source: src/Actions/FragmentationAction/FragmentationAutomationAction.cpp@ fbf143

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since fbf143 was fbf143, checked in by Frederik Heber <heber@…>, 12 years ago

Placed Containers, Converter, and SetValues as subfolders into Summation.

  • also libMolecuilderFragmentationSummation is now a shared library, easing linkage to libMolecuilderJobs, and contains all of the three convenience libraries.
  • libMolecuilderFragmentationSetValues is now again convenience, as contained in ..Summation which in turn is shared.
  • KeySetsContainer right now is the link between lib..Summation and lib.. Fragmentation. Hence, we had to extract the module and change it into a shared library, as it is required by libMolecuilderJobs through ..Summation but also by ..Fragmentation that heavily relies on this container.
  • moved parseKeySetFile down into Fragmentation folder to KeySetsContainer, it is also contained in new shared library libMolecuilderFragmentation_ KeySetsContainer.
  • Property mode set to 100644
File size: 16.8 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * FragmentationAutomationAction.cpp
25 *
26 * Created on: May 18, 2012
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include <boost/archive/text_iarchive.hpp>
36// boost asio needs specific operator new
37#include <boost/asio.hpp>
38
39#include "CodePatterns/MemDebug.hpp"
40
41// include headers that implement a archive in simple text format
42#include <boost/archive/text_oarchive.hpp>
43#include <boost/archive/text_iarchive.hpp>
44
45
46#include <boost/mpl/remove.hpp>
47#include <boost/lambda/lambda.hpp>
48
49#include <iostream>
50
51#include "CodePatterns/Assert.hpp"
52#include "CodePatterns/Info.hpp"
53#include "CodePatterns/Log.hpp"
54#include "JobMarket/Jobs/FragmentJob.hpp"
55
56#include "Fragmentation/Automation/FragmentJobQueue.hpp"
57#include "Fragmentation/Automation/MPQCFragmentController.hpp"
58#include "Fragmentation/Automation/VMGDebugGridFragmentController.hpp"
59#include "Fragmentation/Automation/VMGFragmentController.hpp"
60#include "Fragmentation/EnergyMatrix.hpp"
61#include "Fragmentation/ForceMatrix.hpp"
62#include "Fragmentation/Fragmentation.hpp"
63#include "Fragmentation/Homology/HomologyContainer.hpp"
64#include "Fragmentation/Homology/HomologyGraph.hpp"
65#include "Fragmentation/KeySet.hpp"
66#include "Fragmentation/KeySetsContainer.hpp"
67#include "Fragmentation/Summation/IndexSetContainer.hpp"
68#include "Fragmentation/Summation/writeTable.hpp"
69#include "Fragmentation/Summation/Containers/createMatrixNrLookup.hpp"
70#include "Fragmentation/Summation/Containers/extractJobIds.hpp"
71#include "Fragmentation/Summation/Containers/FragmentationChargeDensity.hpp"
72#include "Fragmentation/Summation/Containers/FragmentationLongRangeResults.hpp"
73#include "Fragmentation/Summation/Containers/FragmentationShortRangeResults.hpp"
74#include "Fragmentation/Summation/Containers/MPQCData.hpp"
75#include "Fragmentation/Summation/Containers/MPQCData_printKeyNames.hpp"
76#include "Fragmentation/Summation/SetValues/Fragment.hpp"
77#include "Fragmentation/Summation/SetValues/Histogram.hpp"
78#include "Fragmentation/Summation/SetValues/IndexedVectors.hpp"
79#include "Graph/DepthFirstSearchAnalysis.hpp"
80#include "Jobs/MPQCJob.hpp"
81#ifdef HAVE_VMG
82#include "Fragmentation/Summation/Containers/VMGData.hpp"
83#include "Fragmentation/Summation/Containers/VMGDataFused.hpp"
84#include "Fragmentation/Summation/Containers/VMGDataMap.hpp"
85#include "Fragmentation/Summation/Containers/VMGData_printKeyNames.hpp"
86#include "Jobs/VMGDebugGridJob.hpp"
87#include "Jobs/VMGJob.hpp"
88#endif
89#include "World.hpp"
90
91#include <fstream>
92#include <iostream>
93#include <string>
94#include <vector>
95
96#include <boost/mpl/for_each.hpp>
97
98#include "Actions/FragmentationAction/FragmentationAutomationAction.hpp"
99
100using namespace MoleCuilder;
101
102// and construct the stuff
103#include "FragmentationAutomationAction.def"
104#include "Action_impl_pre.hpp"
105/** =========== define the function ====================== */
106
107class controller_AddOn;
108
109// needs to be defined for using the FragmentController
110controller_AddOn *getAddOn()
111{
112 return NULL;
113}
114
115void writeToFile(const std::string &filename, const std::string contents)
116{
117 std::ofstream tablefile(filename.c_str());
118 tablefile << contents;
119 tablefile.close();
120}
121
122/** Print (short range) energy, forces, and timings from received results.
123 *
124 * @param results summed up results container
125 */
126void printReceivedShortResults(
127 const FragmentationShortRangeResults &results)
128{
129 // print tables (without eigenvalues, they go extra)
130 {
131 typedef boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type
132 MPQCDataEnergyVector_noeigenvalues_t;
133 const std::string energyresult =
134 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
135 results.Result_Energy_fused, results.getMaxLevel());
136 LOG(0, "Energy table is \n" << energyresult);
137 std::string filename;
138 filename += FRAGMENTPREFIX + std::string("_Energy.dat");
139 writeToFile(filename, energyresult);
140 }
141
142 {
143 const std::string eigenvalueresult;
144 LOG(0, "Eigenvalue table is \n" << eigenvalueresult);
145 std::string filename;
146 filename += FRAGMENTPREFIX + std::string("_Eigenvalues.dat");
147 writeToFile(filename, eigenvalueresult);
148 }
149
150 {
151 const std::string forceresult =
152 writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
153 results.Result_Force_fused, results.getMaxLevel());
154 LOG(0, "Force table is \n" << forceresult);
155 std::string filename;
156 filename += FRAGMENTPREFIX + std::string("_Forces.dat");
157 writeToFile(filename, forceresult);
158 }
159 // we don't want to print grid to a table
160 {
161 // print times (without flops for now)
162 typedef boost::mpl::remove<
163 boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_total_flops>::type,
164 MPQCDataFused::times_gather_flops>::type
165 MPQCDataTimeVector_noflops_t;
166 const std::string timesresult =
167 writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
168 results.Result_Time_fused, results.getMaxLevel());
169 LOG(0, "Times table is \n" << timesresult);
170 std::string filename;
171 filename += FRAGMENTPREFIX + std::string("_Times.dat");
172 writeToFile(filename, timesresult);
173 }
174}
175
176
177/** Print long range energy from received results.
178 *
179 * @param results summed up results container
180 */
181void printReceivedFullResults(
182 const FragmentationLongRangeResults &results)
183{
184 // print tables (without eigenvalues, they go extra)
185
186 if (results.Result_LongRange_fused.size() >= (results.getMaxLevel()-2))
187 {
188 const std::string gridresult =
189 writeTable<VMGDataMap_t, VMGDataVector_t >()(
190 results.Result_LongRange_fused, results.getMaxLevel(), 2);
191 LOG(0, "VMG table is \n" << gridresult);
192 std::string filename;
193 filename += FRAGMENTPREFIX + std::string("_VMGEnergy.dat");
194 writeToFile(filename, gridresult);
195 }
196
197 if (results.Result_LongRangeIntegrated_fused.size() >= (results.getMaxLevel()-2))
198 {
199 const std::string gridresult =
200 writeTable<VMGDataLongRangeMap_t, VMGDataLongRangeVector_t >()(
201 results.Result_LongRangeIntegrated_fused, results.getMaxLevel(), 2);
202 LOG(0, "LongRange table is \n" << gridresult);
203 std::string filename;
204 filename += FRAGMENTPREFIX + std::string("_LongRangeEnergy.dat");
205 writeToFile(filename, gridresult);
206 }
207}
208
209bool appendToHomologyFile(
210 const boost::filesystem::path &homology_file,
211 const FragmentationShortRangeResults &shortrangeresults,
212 const FragmentationLongRangeResults &longrangeresults
213 )
214{
215 /// read homology container (if present)
216 HomologyContainer homology_container;
217 if (boost::filesystem::exists(homology_file)) {
218 std::ifstream returnstream(homology_file.string().c_str());
219 if (returnstream.good()) {
220 boost::archive::text_iarchive ia(returnstream);
221 ia >> homology_container;
222 } else {
223 ELOG(2, "Failed to parse from " << homology_file.string() << ".");
224 }
225 returnstream.close();
226 } else {
227 LOG(2, "Could not open " << homology_file.string()
228 << ", creating empty container.");
229 }
230
231 /// append all fragments to a HomologyContainer
232 HomologyContainer::container_t values;
233 const size_t FragmentCounter = shortrangeresults.Result_perIndexSet_Energy.size();
234
235 // convert KeySetContainer to IndexSetContainer
236 IndexSetContainer::ptr ForceContainer(new IndexSetContainer(shortrangeresults.getForceKeySet()));
237 const IndexSetContainer::Container_t &Indices = shortrangeresults.getContainer();
238 const IndexSetContainer::Container_t &ForceIndices = ForceContainer->getContainer();
239 IndexSetContainer::Container_t::const_iterator iter = Indices.begin();
240 IndexSetContainer::Container_t::const_iterator forceiter = ForceIndices.begin();
241 /// go through all fragments
242 for (;iter != Indices.end(); ++iter, ++forceiter) // go through each IndexSet
243 {
244 /// create new graph entry in HomologyContainer which is (key,value) type
245 LOG(1, "INFO: Creating new graph with " << **forceiter << ".");
246 HomologyGraph graph(**forceiter);
247 LOG(2, "DEBUG: Created graph " << graph << ".");
248 const IndexSet::ptr &index = *iter;
249 HomologyContainer::value_t value;
250
251 // obtain fragment as key
252 std::map<IndexSet::ptr, std::pair< MPQCDataFragmentMap_t, MPQCDataFragmentMap_t> >::const_iterator fragmentiter
253 = longrangeresults.Result_perIndexSet_Fragment.find(index);
254 ASSERT( fragmentiter != longrangeresults.Result_perIndexSet_Fragment.end(),
255 "appendToHomologyFile() - cannot find index "+toString(*index)
256 +" in FragmentResults.");
257 value.first = boost::fusion::at_key<MPQCDataFused::fragment>(fragmentiter->second.first);
258
259 // obtain energy as value
260 std::map<IndexSet::ptr, std::pair< MPQCDataEnergyMap_t, MPQCDataEnergyMap_t> >::const_iterator energyiter
261 = shortrangeresults.Result_perIndexSet_Energy.find(index);
262 ASSERT( energyiter != shortrangeresults.Result_perIndexSet_Energy.end(),
263 "appendToHomologyFile() - cannot find index "+toString(*index)
264 +" in FragmentResults.");
265 // value.second = boost::fusion::at_key<MPQCDataFused::energy_total>(energyiter->second.first); // values
266 value.second = boost::fusion::at_key<MPQCDataFused::energy_total>(energyiter->second.second); // contributions
267 values.insert( std::make_pair( graph, value) );
268 }
269 homology_container.insert(values);
270
271 LOG(1, "INFO: Listing all present atomic ids ...");
272 std::stringstream output;
273 for (World::AtomIterator iter = World::getInstance().getAtomIter();
274 iter != World::getInstance().atomEnd(); ++iter)
275 output << (*iter)->getId() << " ";
276 LOG(1, "INFO: { " << output.str() << "} .");
277
278 // for debugging: print container
279 LOG(1, "INFO: Listing all present homologies ...");
280 for (HomologyContainer::container_t::const_iterator iter =
281 homology_container.begin(); iter != homology_container.end(); ++iter) {
282 LOG(1, "INFO: graph " << iter->first << " has Fragment "
283 << iter->second.first << " and associated energy " << iter->second.second << ".");
284 }
285
286 /// store homology container again
287 std::ofstream outputstream(homology_file.string().c_str());
288 if (outputstream.good()) { // check if opened
289 boost::archive::text_oarchive oa(outputstream);
290 oa << homology_container;
291 if (outputstream.fail()) { // check if correctly written
292 LOG(1, "Failed to write to file " << homology_file.string() << ".");
293 return false;
294 } else
295 outputstream.close();
296 } else {
297 LOG(1, "Failed to open file " << homology_file.string()
298 << " for writing.");
299 return false;
300 }
301 return true;
302}
303
304Action::state_ptr FragmentationFragmentationAutomationAction::performCall() {
305 boost::asio::io_service io_service;
306
307 // TODO: Have io_service run in second thread and merge with current again eventually
308
309 size_t Exitflag = 0;
310 std::map<JobId_t, MPQCData> fragmentData;
311 {
312 const size_t NumberJobs = FragmentJobQueue::getInstance().size();
313 MPQCFragmentController mpqccontroller(io_service);
314 mpqccontroller.setHost(params.host.get());
315 mpqccontroller.setPort(params.port.get());
316 // Phase One: obtain ids
317 mpqccontroller.requestIds(NumberJobs);
318
319 // Phase Two: add MPQCJobs and send
320 const size_t NoJobs = mpqccontroller.addJobsFromQueue(
321 params.DoLongrange.get() ? MPQCData::DoSampleDensity : MPQCData::DontSampleDensity);
322 LOG(1, "INFO: Added " << NoJobs << " from FragmentJobsQueue.");
323 mpqccontroller.run();
324
325 // Phase Three: calculate result
326 mpqccontroller.waitforResults(NumberJobs);
327 mpqccontroller.getResults(fragmentData);
328
329 Exitflag += mpqccontroller.getExitflag();
330 }
331
332 FragmentationShortRangeResults shortrangeresults(
333 fragmentData,
334 FragmentJobQueue::getInstance().getKeySets(),
335 FragmentJobQueue::getInstance().getFullKeySets());
336 shortrangeresults(fragmentData);
337 printReceivedShortResults(shortrangeresults);
338
339#ifdef HAVE_VMG
340 if (params.DoLongrange.get()) {
341 if ( World::getInstance().getAllAtoms().size() == 0) {
342 ELOG(1, "Please load the full molecule into the world before starting this action.");
343 return Action::failure;
344 }
345
346 // obtain combined charge density
347 FragmentationChargeDensity summedChargeDensity(
348 fragmentData,
349 FragmentJobQueue::getInstance().getKeySets());
350 const std::vector<SamplingGrid> full_sample = summedChargeDensity.getFullSampledGrid();
351 LOG(1, "INFO: There are " << fragmentData.size() << " short-range and "
352 << full_sample.size() << " level-wise long-range jobs.");
353
354 // Phase Four: obtain more ids
355 std::map<JobId_t, VMGData> longrangeData;
356 {
357 VMGFragmentController vmgcontroller(io_service);
358 vmgcontroller.setHost(params.host.get());
359 vmgcontroller.setPort(params.port.get());
360 const size_t NoJobs = fragmentData.size()+full_sample.size();
361 vmgcontroller.requestIds(NoJobs);
362
363 // Phase Five: create VMGJobs
364 const size_t near_field_cells = params.near_field_cells.get();
365 const size_t interpolation_degree = params.interpolation_degree.get();
366 if (!vmgcontroller.createLongRangeJobs(
367 fragmentData,
368 full_sample,
369 summedChargeDensity.getFragment(),
370 near_field_cells,
371 interpolation_degree))
372 return Action::failure;
373
374 // Phase Six: calculate result
375 vmgcontroller.waitforResults(NoJobs);
376 vmgcontroller.getResults(longrangeData);
377 ASSERT( NoJobs == longrangeData.size(),
378 "FragmentationFragmentationAutomationAction::performCall() - number of MPQCresults+"
379 +toString(full_sample.size())+"="+toString(NoJobs)
380 +" and VMGresults "+toString(longrangeData.size())+" don't match.");
381 Exitflag += vmgcontroller.getExitflag();
382 }
383
384 // remove full solution corresponding to full_sample from map (must be highest ids), has to be treated extra
385 std::map<JobId_t, VMGData>::iterator iter = longrangeData.end();
386 for (size_t i=0;i<full_sample.size();++i)
387 --iter;
388 std::map<JobId_t, VMGData>::iterator remove_iter = iter;
389 std::vector<VMGData> fullsolutionData;
390 for (; iter != longrangeData.end(); ++iter)
391 fullsolutionData.push_back(iter->second);
392 longrangeData.erase(remove_iter, longrangeData.end());
393
394 // Final phase: sum up and print result
395 FragmentationLongRangeResults longrangeresults(
396 fragmentData,
397 longrangeData,
398 FragmentJobQueue::getInstance().getKeySets(),
399 FragmentJobQueue::getInstance().getFullKeySets());
400 longrangeresults(
401 fragmentData,
402 longrangeData,
403 fullsolutionData,
404 full_sample);
405 printReceivedFullResults(longrangeresults);
406
407 // append all keysets to homology file
408 if ((Exitflag == 0) && (!params.homology_file.get().empty())) {
409 const boost::filesystem::path &homology_file = params.homology_file.get();
410 if (homology_file.string() != "") {
411 LOG(1, "INFO: Appending HomologyGraphs to file " << homology_file.string() << ".");
412 if (!appendToHomologyFile(homology_file, shortrangeresults, longrangeresults))
413 Exitflag = 1;
414 }
415 }
416
417 std::map<JobId_t, std::string> debugData;
418 {
419 if (!full_sample.empty()) {
420 // create debug jobs for each level to print the summed-up potential to vtk files
421 VMGDebugGridFragmentController debugcontroller(io_service);
422 debugcontroller.setHost(params.host.get());
423 debugcontroller.setPort(params.port.get());
424 debugcontroller.requestIds(full_sample.size());
425 if (!debugcontroller.createDebugJobs(full_sample))
426 return Action::failure;
427 debugcontroller.waitforResults(full_sample.size());
428 debugcontroller.getResults(debugData);
429 Exitflag += debugcontroller.getExitflag();
430 }
431 }
432 }
433#endif
434
435 // now clear all present jobs as we are done
436 FragmentJobQueue::getInstance().clear();
437
438 return (Exitflag == 0) ? Action::success : Action::failure;
439}
440
441Action::state_ptr FragmentationFragmentationAutomationAction::performUndo(Action::state_ptr _state) {
442 return Action::success;
443}
444
445Action::state_ptr FragmentationFragmentationAutomationAction::performRedo(Action::state_ptr _state){
446 return Action::success;
447}
448
449bool FragmentationFragmentationAutomationAction::canUndo() {
450 return false;
451}
452
453bool FragmentationFragmentationAutomationAction::shouldUndo() {
454 return false;
455}
456/** =========== end of function ====================== */
Note: See TracBrowser for help on using the repository browser.