source: src/Actions/FragmentationAction/FragmentationAutomationAction.cpp@ 358ddb

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 Candidate_v1.7.0 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 358ddb was 358ddb, checked in by Frederik Heber <heber@…>, 13 years ago

FragmentationAutomationAction now also sums up potential and obtain long-range energy.

  • this does not yet seem to be fully working but all the pieces are in place and the failure might also be connected to various issues (e.g. bohr radii) of mpqc.
  • Property mode set to 100644
File size: 40.3 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 <boost/mpl/remove.hpp>
42
43#include "CodePatterns/Assert.hpp"
44#include "CodePatterns/Info.hpp"
45#include "CodePatterns/Log.hpp"
46#include "JobMarket/Controller/FragmentController.hpp"
47#include "JobMarket/Jobs/FragmentJob.hpp"
48
49#include "Atom/atom.hpp"
50#include "Box.hpp"
51#include "Fragmentation/EnergyMatrix.hpp"
52#include "Fragmentation/ForceMatrix.hpp"
53#include "Fragmentation/Fragmentation.hpp"
54#include "Fragmentation/SetValues/Fragment.hpp"
55#include "Fragmentation/SetValues/Histogram.hpp"
56#include "Fragmentation/SetValues/IndexedVectors.hpp"
57#include "Fragmentation/HydrogenSaturation_enum.hpp"
58#include "Fragmentation/KeySet.hpp"
59#include "Fragmentation/KeySetsContainer.hpp"
60#include "Fragmentation/Summation/AllLevelOrthogonalSummator.hpp"
61#include "Fragmentation/Summation/AllLevelSummator.hpp"
62#include "Fragmentation/Summation/OrthogonalFullSummator.hpp"
63#include "Fragmentation/Summation/OrthogonalSummation.hpp"
64#include "Fragmentation/Summation/writeTable.hpp"
65#include "Graph/DepthFirstSearchAnalysis.hpp"
66#include "Helpers/defs.hpp"
67#include "Jobs/MPQCJob.hpp"
68#include "Jobs/MPQCData.hpp"
69#include "Jobs/MPQCData_printKeyNames.hpp"
70#include "Jobs/Grid/SamplingGrid.hpp"
71#include "LinearAlgebra/RealSpaceMatrix.hpp"
72#ifdef HAVE_VMG
73#include "Jobs/VMGJob.hpp"
74#include "Jobs/VMGData.hpp"
75#include "Jobs/VMGDataFused.hpp"
76#include "Jobs/VMGDataMap.hpp"
77#include "Jobs/VMGData_printKeyNames.hpp"
78#endif
79#include "molecule.hpp"
80#include "World.hpp"
81
82#include <iostream>
83#include <string>
84#include <vector>
85
86#include <boost/mpl/for_each.hpp>
87
88#include "Actions/FragmentationAction/FragmentationAutomationAction.hpp"
89
90using namespace MoleCuilder;
91
92// and construct the stuff
93#include "FragmentationAutomationAction.def"
94#include "Action_impl_pre.hpp"
95/** =========== define the function ====================== */
96
97class controller_AddOn;
98
99// needs to be defined for using the FragmentController
100controller_AddOn *getAddOn()
101{
102 return NULL;
103}
104
105const int LEVEL = 5;
106
107/** Creates a MPQCCommandJob with argument \a filename.
108 *
109 * @param jobs created job is added to this vector
110 * @param command mpqc command to execute
111 * @param filename filename being argument to job
112 * @param nextid id for this job
113 */
114void parsejob(
115 std::vector<FragmentJob::ptr> &jobs,
116 const std::string &command,
117 const std::string &filename,
118 const JobId_t nextid)
119{
120 std::ifstream file;
121 file.open(filename.c_str());
122 ASSERT( file.good(), "parsejob() - file "+filename+" does not exist.");
123 std::string output((std::istreambuf_iterator<char>(file)),
124 std::istreambuf_iterator<char>());
125 double begin[NDIM] = { 0., 0., 0. };
126 const RealSpaceMatrix& M = World::getInstance().getDomain().getM();
127 const double size = M.at(0,0);
128 ASSERT( M.determinant() == size*size*size,
129 "parsejob() - current domain matrix "+toString(M)+" is not cubic.");
130 const int level = LEVEL;
131 FragmentJob::ptr testJob( new MPQCJob(nextid, output, begin, size, level) );
132 jobs.push_back(testJob);
133 file.close();
134 LOG(1, "INFO: Added MPQCCommandJob from file "+filename+".");
135}
136
137/** Helper function to get number of atoms somehow.
138 *
139 * Here, we just parse the number of lines in the adjacency file as
140 * it should correspond to the number of atoms, except when some atoms
141 * are not bonded, but then fragmentation makes no sense.
142 *
143 * @param path path to the adjacency file
144 */
145size_t getNoAtomsFromAdjacencyFile(const std::string &path)
146{
147 size_t NoAtoms = 0;
148
149 // parse in special file to get atom count (from line count)
150 std::string filename(path);
151 filename += FRAGMENTPREFIX;
152 filename += ADJACENCYFILE;
153 std::ifstream adjacency(filename.c_str());
154 if (adjacency.fail()) {
155 LOG(0, endl << "getNoAtomsFromAdjacencyFile() - Unable to open " << filename << ", is the directory correct?");
156 return false;
157 }
158 std::string buffer;
159 while (getline(adjacency, buffer))
160 NoAtoms++;
161 LOG(1, "INFO: There are " << NoAtoms << " atoms.");
162
163 return NoAtoms;
164}
165
166/** Extracts MPQCData from received vector of FragmentResults.
167 *
168 * @param results results to extract MPQCData from
169 * @param fragmentData on return array filled with extracted MPQCData
170 */
171template <typename T>
172void ConvertFragmentResultTo(
173 const std::vector<FragmentResult::ptr> &results,
174 std::vector<T> &fragmentData)
175{
176 // extract results
177 fragmentData.clear();
178 fragmentData.reserve(results.size());
179
180 LOG(2, "DEBUG: Parsing now through " << results.size() << " results.");
181 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
182 iter != results.end(); ++iter) {
183 //LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
184 T extractedData;
185 std::stringstream inputstream((*iter)->result);
186 LOG(2, "DEBUG: First 50 characters FragmentResult's string: "+(*iter)->result.substr(0, 50));
187 boost::archive::text_iarchive ia(inputstream);
188 ia >> extractedData;
189 LOG(1, "INFO: extracted data is " << extractedData << ".");
190 fragmentData.push_back(extractedData);
191 }
192
193 ASSERT( results.size() == fragmentData.size(),
194 "ConvertFragmentResultTo() - the number of extracted data differs from the number of results.");
195}
196
197/** Creates a lookup from FragmentJob::id to the true fragment number.
198 *
199 * @param results result with job ids
200 * @param MatrixNrLookup Lookup up-map, filled on return
201 * @param FragmentCounter total number of fragments on return
202 */
203void createMatrixNrLookup(
204 const std::vector<FragmentResult::ptr> &results,
205 std::map< JobId_t, size_t > &MatrixNrLookup,
206 size_t &FragmentCounter)
207{
208 // align fragments
209 MatrixNrLookup.clear();
210 FragmentCounter = 0;
211 {
212 // bring ids in order ...
213 typedef std::map< JobId_t, FragmentResult::ptr> IdResultMap_t;
214 IdResultMap_t IdResultMap;
215 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
216 iter != results.end(); ++iter) {
217 #ifndef NDEBUG
218 std::pair< IdResultMap_t::iterator, bool> inserter =
219 #endif
220 IdResultMap.insert( make_pair((*iter)->getId(), *iter) );
221 ASSERT( inserter.second,
222 "ExtractMPQCDataFromResults() - two results have same id "
223 +toString((*iter)->getId())+".");
224 }
225 // ... and fill lookup
226 for(IdResultMap_t::const_iterator iter = IdResultMap.begin();
227 iter != IdResultMap.end(); ++iter)
228 MatrixNrLookup.insert( make_pair(iter->first, FragmentCounter++) );
229 }
230 LOG(1, "INFO: There are " << FragmentCounter << " fragments.");
231}
232
233/** Place results from FragmentResult into EnergyMatrix and ForceMatrix.
234 *
235 * @param results results with ids to associate with fragment number
236 * @param fragmentData MPQCData resulting from the jobs
237 * @param MatrixNrLookup Lookup up-map from job id to fragment number
238 * @param FragmentCounter total number of fragments
239 * @param NoAtoms total number of atoms
240 * @param Energy energy matrix to be filled on return
241 * @param Force force matrix to be filled on return
242 * @return true - everything ok, false - else
243 */
244bool putResultsintoMatrices(
245 const std::vector<FragmentResult::ptr> &results,
246 const std::vector<MPQCData> &fragmentData,
247 std::map< JobId_t, size_t > &MatrixNrLookup,
248 const size_t FragmentCounter,
249 const size_t NoAtoms,
250 EnergyMatrix &Energy,
251 ForceMatrix &Force)
252{
253 ASSERT( results.size() == fragmentData.size(),
254 "printReceivedMPQCResults() - results and fragmentData differ in size.");
255 std::vector<MPQCData>::const_iterator dataiter = fragmentData.begin();
256 std::vector<FragmentResult::ptr>::const_iterator resultiter = results.begin();
257 for (; dataiter != fragmentData.end(); ++dataiter, ++resultiter) {
258 const MPQCData &extractedData = *dataiter;
259 // place results into EnergyMatrix ...
260 {
261 MatrixContainer::MatrixArray matrix;
262 matrix.resize(1);
263 matrix[0].resize(1, extractedData.energies.total);
264 if (!Energy.AddMatrix(
265 std::string("MPQCJob ")+toString((*resultiter)->getId()),
266 matrix,
267 MatrixNrLookup[(*resultiter)->getId()])) {
268 ELOG(1, "Adding energy matrix failed.");
269 return false;
270 }
271 }
272 // ... and ForceMatrix (with two empty columns in front)
273 {
274 MatrixContainer::MatrixArray matrix;
275 const size_t rows = extractedData.forces.size();
276 matrix.resize(rows);
277 for (size_t i=0;i<rows;++i) {
278 const size_t columns = 2+extractedData.forces[i].size();
279 matrix[i].resize(columns, 0.);
280 // for (size_t j=0;j<2;++j)
281 // matrix[i][j] = 0.;
282 for (size_t j=2;j<columns;++j)
283 matrix[i][j] = extractedData.forces[i][j-2];
284 }
285 if (!Force.AddMatrix(
286 std::string("MPQCJob ")+toString((*resultiter)->getId()),
287 matrix,
288 MatrixNrLookup[(*resultiter)->getId()])) {
289 ELOG(1, "Adding force matrix failed.");
290 return false;
291 }
292 }
293 }
294 // add one more matrix (not required for energy)
295 MatrixContainer::MatrixArray matrix;
296 matrix.resize(1);
297 matrix[0].resize(1, 0.);
298 if (!Energy.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter))
299 return false;
300 // but for energy because we need to know total number of atoms
301 matrix.resize(NoAtoms);
302 for (size_t i = 0; i< NoAtoms; ++i)
303 matrix[i].resize(2+NDIM, 0.);
304 if (!Force.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter))
305 return false;
306
307 return true;
308}
309
310template <typename source, typename dest>
311void convertDataTo(
312 const std::vector<source> &fragmentData,
313 std::vector<dest> &MPQCData_fused)
314{
315 MPQCData_fused.clear();
316}
317
318template <>
319void convertDataTo<MPQCData, MPQCDataEnergyMap_t>(
320 const std::vector<MPQCData> &fragmentData,
321 std::vector<MPQCDataEnergyMap_t> &MPQCData_Energy_fused)
322{
323 // energy_t
324 MPQCData_Energy_fused.clear();
325 MPQCData_Energy_fused.reserve(fragmentData.size());
326 for(std::vector<MPQCData>::const_iterator dataiter = fragmentData.begin();
327 dataiter != fragmentData.end(); ++dataiter) {
328 const MPQCData &extractedData = *dataiter;
329 LOG(2, "DEBUG: Current extracted Data is " << extractedData << ".");
330 MPQCDataEnergyMap_t instance;
331 boost::fusion::at_key<MPQCDataFused::energy_total>(instance) = extractedData.energies.total;
332 boost::fusion::at_key<MPQCDataFused::energy_nuclear_repulsion>(instance) = extractedData.energies.nuclear_repulsion;
333 boost::fusion::at_key<MPQCDataFused::energy_electron_coulomb>(instance) = extractedData.energies.electron_coulomb;
334 boost::fusion::at_key<MPQCDataFused::energy_electron_exchange>(instance) = extractedData.energies.electron_exchange;
335 boost::fusion::at_key<MPQCDataFused::energy_correlation>(instance) = extractedData.energies.correlation;
336 boost::fusion::at_key<MPQCDataFused::energy_overlap>(instance) = extractedData.energies.overlap;
337 boost::fusion::at_key<MPQCDataFused::energy_kinetic>(instance) = extractedData.energies.kinetic;
338 boost::fusion::at_key<MPQCDataFused::energy_hcore>(instance) = extractedData.energies.hcore;
339 boost::fusion::at_key<MPQCDataFused::energy_eigenvalues>(instance) = extractedData.energies.eigenvalues;
340 MPQCData_Energy_fused.push_back(instance);
341 }
342}
343
344template <>
345void convertDataTo<VMGData, VMGDataMap_t>(
346 const std::vector<VMGData> &longrangeData,
347 std::vector<VMGDataMap_t> &VMGData_fused)
348{
349 // energy_t
350 VMGData_fused.clear();
351 VMGData_fused.reserve(longrangeData.size());
352 for(std::vector<VMGData>::const_iterator dataiter = longrangeData.begin();
353 dataiter != longrangeData.end(); ++dataiter) {
354 const VMGData &extractedData = *dataiter;
355 LOG(2, "DEBUG: Current extracted Data is " << extractedData << ".");
356 VMGDataMap_t instance;
357 boost::fusion::at_key<VMGDataFused::sampled_potential>(instance) = extractedData.sampled_potential;
358 boost::fusion::at_key<VMGDataFused::energy_long>(instance) = extractedData.e_long;
359 VMGData_fused.push_back(instance);
360 }
361}
362
363void convertMPQCDatatoForceMap(
364 const std::vector<MPQCData> &fragmentData,
365 const KeySetsContainer &ForceKeySet,
366 std::vector<MPQCDataForceMap_t> &MPQCData_Force_fused)
367{
368 // forces
369 ASSERT( ForceKeySet.KeySets.size() == fragmentData.size(),
370 "FragmentationAutomationAction::performCall() - indices and fragmentData differ in size.");
371 MPQCData_Force_fused.clear();
372 MPQCData_Force_fused.reserve(fragmentData.size());
373 std::vector<MPQCData>::const_iterator dataiter = fragmentData.begin();
374 KeySetsContainer::ArrayOfIntVectors::const_iterator arrayiter = ForceKeySet.KeySets.begin();
375 for(;dataiter != fragmentData.end(); ++dataiter, ++arrayiter) {
376 const MPQCData &extractedData = *dataiter;
377 LOG(2, "DEBUG: Current extracted Data is " << extractedData << ".");
378 MPQCDataForceMap_t instance;
379 // must convert int to index_t
380 IndexedVectors::indices_t indices(arrayiter->begin(), arrayiter->end());
381 boost::fusion::at_key<MPQCDataFused::forces>(instance) =
382 IndexedVectors(indices, extractedData.forces);
383 MPQCData_Force_fused.push_back(instance);
384 }
385}
386
387template <>
388void convertDataTo<MPQCData, MPQCDataGridMap_t>(
389 const std::vector<MPQCData> &fragmentData,
390 std::vector<MPQCDataGridMap_t> &MPQCData_Grid_fused)
391{
392 // sampled_grid
393 MPQCData_Grid_fused.clear();
394 MPQCData_Grid_fused.reserve(fragmentData.size());
395 for(std::vector<MPQCData>::const_iterator dataiter = fragmentData.begin();
396 dataiter != fragmentData.end(); ++dataiter) {
397 const MPQCData &extractedData = *dataiter;
398 LOG(2, "DEBUG: Current extracted Data is " << extractedData << ".");
399 MPQCDataGridMap_t instance;
400 boost::fusion::at_key<MPQCDataFused::sampled_grid>(instance) = extractedData.sampled_grid;
401 MPQCData_Grid_fused.push_back(instance);
402 }
403}
404
405template <>
406void convertDataTo<MPQCData, MPQCDataFragmentMap_t>(
407 const std::vector<MPQCData> &fragmentData,
408 std::vector<MPQCDataFragmentMap_t> &MPQCData_Fragment_fused)
409{
410 // fragment
411 MPQCData_Fragment_fused.clear();
412 MPQCData_Fragment_fused.reserve(fragmentData.size());
413 for(std::vector<MPQCData>::const_iterator dataiter = fragmentData.begin();
414 dataiter != fragmentData.end(); ++dataiter) {
415 const MPQCData &extractedData = *dataiter;
416 LOG(2, "DEBUG: Current extracted Data is " << extractedData << ".");
417 MPQCDataFragmentMap_t instance;
418 boost::fusion::at_key<MPQCDataFused::fragment>(instance) =
419 Fragment(extractedData.positions, extractedData.charges);
420 MPQCData_Fragment_fused.push_back(instance);
421 }
422}
423
424template <>
425void convertDataTo<MPQCData, MPQCDataTimeMap_t>(
426 const std::vector<MPQCData> &fragmentData,
427 std::vector<MPQCDataTimeMap_t> &MPQCData_Time_fused)
428{
429 // times
430 MPQCData_Time_fused.clear();
431 MPQCData_Time_fused.reserve(fragmentData.size());
432 for(std::vector<MPQCData>::const_iterator dataiter = fragmentData.begin();
433 dataiter != fragmentData.end(); ++dataiter) {
434 const MPQCData &extractedData = *dataiter;
435 LOG(2, "DEBUG: Current extracted Data is " << extractedData << ".");
436 MPQCDataTimeMap_t instance;
437 boost::fusion::at_key<MPQCDataFused::times_walltime>(instance) = extractedData.times.walltime;
438 boost::fusion::at_key<MPQCDataFused::times_cputime>(instance) = extractedData.times.cputime;
439 boost::fusion::at_key<MPQCDataFused::times_flops>(instance) = extractedData.times.flops;
440 MPQCData_Time_fused.push_back(instance);
441 }
442}
443
444template <typename TypeMap, typename TypeVector>
445std::vector<TypeMap> SumUpPerLevel(
446 const std::vector<MPQCData> &fragmentData,
447 const std::vector<JobId_t> &jobids,
448 std::map< JobId_t, size_t > &MatrixNrLookup,
449 const IndexSetContainer::ptr &container,
450 SubsetMap::ptr &subsetmap
451 )
452{
453 // place data into boost::fusion::map instance
454 std::vector<TypeMap> MPQCData_fused;
455 convertDataTo<MPQCData, TypeMap>(fragmentData, MPQCData_fused);
456 // instantiate summator
457 std::vector<TypeMap> Result_fused(subsetmap->getMaximumSubsetLevel());
458 AllLevelSummator<TypeMap> Summer(
459 subsetmap,
460 MPQCData_fused,
461 jobids,
462 container->getContainer(),
463 MatrixNrLookup,
464 Result_fused);
465 // sum up for each type key in TypeVector
466 boost::mpl::for_each<TypeVector>(boost::ref(Summer));
467 return Result_fused;
468}
469
470template <typename TypeMap, typename TypeVector>
471std::vector<TypeMap> OrthogonalSumUpPerLevel(
472 const std::vector<MPQCData> &fragmentData,
473 const std::vector<JobId_t> &jobids,
474 std::map< JobId_t, size_t > &MatrixNrLookup,
475 const IndexSetContainer::ptr &container,
476 SubsetMap::ptr &subsetmap
477 )
478{
479 // place data into boost::fusion::map instance
480 std::vector<TypeMap> MPQCData_fused;
481 convertDataTo<MPQCData, TypeMap>(fragmentData, MPQCData_fused);
482 // instantiate summator
483 std::vector<TypeMap> Result_fused(subsetmap->getMaximumSubsetLevel());
484 AllLevelOrthogonalSummator<TypeMap> Summer(
485 subsetmap,
486 MPQCData_fused,
487 jobids,
488 container->getContainer(),
489 MatrixNrLookup,
490 Result_fused);
491 // sum up for each type key in TypeVector
492 boost::mpl::for_each<TypeVector>(boost::ref(Summer));
493 return Result_fused;
494}
495
496/** Print MPQCData from received results.
497 *
498 * @param results results with ids to associate with fragment number
499 * @param fragmentData MPQCData resulting from the jobs
500 * @param KeySetFilename filename with keysets to associate forces correctly
501 * @param NoAtoms total number of atoms
502 * @param full_sample summed up charge density of electrons from fragments on return
503 * @param full_fragment summed up positions and charges of nuclei from fragments on return
504 */
505bool sumUpChargeDensity(
506 const std::vector<FragmentResult::ptr> &results,
507 const std::vector<MPQCData> &fragmentData,
508 const std::string &KeySetFilename,
509 SamplingGrid &full_sample,
510 Fragment &full_fragment)
511{
512 // create lookup from job nr to fragment number
513 std::map< JobId_t, size_t > MatrixNrLookup;
514 size_t FragmentCounter = 0;
515 createMatrixNrLookup(results, MatrixNrLookup, FragmentCounter);
516
517 // initialise keysets
518 KeySetsContainer KeySet;
519 {
520 // else needs keysets without hydrogens
521 std::stringstream filename;
522 filename << FRAGMENTPREFIX << KEYSETFILE;
523 if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
524 }
525
526 /// prepare for OrthogonalSummation
527
528 // convert KeySetContainer to IndexSetContainer
529 IndexSetContainer::ptr container(new IndexSetContainer(KeySet));
530 // create the map of all keysets
531 SubsetMap::ptr subsetmap(new SubsetMap(*container));
532
533 // create a vector of all job ids
534 std::vector<JobId_t> jobids(results.size(), JobId::IllegalJob);
535 std::transform(results.begin(), results.end(), jobids.begin(),
536 boost::bind(&FragmentResult::getId,
537 boost::bind(&FragmentResult::ptr::operator->, _1)));
538
539 /// convert all MPQCData to MPQCDataMap_t
540 std::vector<MPQCDataGridMap_t> Result_Grid_fused(
541 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCDataGridVector_t>(
542 fragmentData, jobids, MatrixNrLookup, container, subsetmap));
543 std::vector<MPQCDataFragmentMap_t> Result_Fragment_fused(
544 OrthogonalSumUpPerLevel<MPQCDataFragmentMap_t, MPQCDataFragmentVector_t>(
545 fragmentData, jobids, MatrixNrLookup, container, subsetmap));
546 // obtain full grid
547 full_sample = boost::fusion::at_key<MPQCDataFused::sampled_grid>(Result_Grid_fused.back());
548 full_fragment = boost::fusion::at_key<MPQCDataFused::fragment>(Result_Fragment_fused.back());
549
550 return true;
551}
552
553
554/** Print MPQCData from received results.
555 *
556 * @param results results with ids to associate with fragment number
557 * @param fragmentData MPQCData resulting from the jobs
558 * @param KeySetFilename filename with keysets to associate forces correctly
559 * @param NoAtoms total number of atoms
560 * @param full_sample summed up charge from fragments on return
561 */
562bool printReceivedMPQCResults(
563 const std::vector<FragmentResult::ptr> &results,
564 const std::vector<MPQCData> &fragmentData,
565 const std::string &KeySetFilename,
566 size_t NoAtoms,
567 SamplingGrid &full_sample)
568{
569 // create lookup from job nr to fragment number
570 std::map< JobId_t, size_t > MatrixNrLookup;
571 size_t FragmentCounter = 0;
572 createMatrixNrLookup(results, MatrixNrLookup, FragmentCounter);
573
574 // place results into maps
575 EnergyMatrix Energy;
576 ForceMatrix Force;
577 if (!putResultsintoMatrices(results, fragmentData, MatrixNrLookup, FragmentCounter, NoAtoms, Energy, Force))
578 return false;
579
580 // initialise keysets
581 KeySetsContainer KeySet;
582 KeySetsContainer ForceKeySet;
583 if (!Energy.InitialiseIndices()) return false;
584
585 if (!Force.ParseIndices(KeySetFilename.c_str())) return false;
586
587 {
588 // else needs keysets without hydrogens
589 std::stringstream filename;
590 filename << FRAGMENTPREFIX << KEYSETFILE;
591 if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
592 }
593
594 {
595 // forces need keysets including hydrogens
596 std::stringstream filename;
597 filename << FRAGMENTPREFIX << FORCESFILE;
598 if (!ForceKeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
599 }
600
601 /// prepare for OrthogonalSummation
602
603 // convert KeySetContainer to IndexSetContainer
604 IndexSetContainer::ptr container(new IndexSetContainer(KeySet));
605 // create the map of all keysets
606 SubsetMap::ptr subsetmap(new SubsetMap(*container));
607
608 // create a vector of all job ids
609 std::vector<JobId_t> jobids(results.size(), JobId::IllegalJob);
610 std::transform(results.begin(), results.end(), jobids.begin(),
611 boost::bind(&FragmentResult::getId,
612 boost::bind(&FragmentResult::ptr::operator->, _1)));
613
614 /// convert all MPQCData to MPQCDataMap_t
615 {
616 ASSERT( ForceKeySet.KeySets.size() == fragmentData.size(),
617 "FragmentationAutomationAction::performCall() - ForceKeySet's KeySets and fragmentData differ in size.");
618
619 typedef boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type MPQCDataEnergyVector_noeigenvalues_t;
620 std::vector<MPQCDataEnergyMap_t> Result_Energy_fused(
621 OrthogonalSumUpPerLevel<MPQCDataEnergyMap_t, MPQCDataEnergyVector_t>(
622 fragmentData, jobids, MatrixNrLookup, container, subsetmap));
623 std::vector<MPQCDataGridMap_t> Result_Grid_fused(
624 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCDataGridVector_t>(
625 fragmentData, jobids, MatrixNrLookup, container, subsetmap));
626 std::vector<MPQCDataTimeMap_t> Result_Time_fused(
627 SumUpPerLevel<MPQCDataTimeMap_t, MPQCDataTimeVector_t>(
628 fragmentData, jobids, MatrixNrLookup, container, subsetmap));
629
630 // force has extra converter
631 std::vector<MPQCDataForceMap_t> MPQCData_Force_fused;
632 convertMPQCDatatoForceMap(fragmentData, ForceKeySet, MPQCData_Force_fused);
633 std::vector<MPQCDataForceMap_t> Result_Force_fused(subsetmap->getMaximumSubsetLevel());
634 AllLevelOrthogonalSummator<MPQCDataForceMap_t> forceSummer(
635 subsetmap,
636 MPQCData_Force_fused,
637 jobids,
638 container->getContainer(),
639 MatrixNrLookup,
640 Result_Force_fused);
641 boost::mpl::for_each<MPQCDataForceVector_t>(boost::ref(forceSummer));
642
643 // obtain full grid
644 full_sample = boost::fusion::at_key<MPQCDataFused::sampled_grid>(Result_Grid_fused.back());
645
646 // print tables (without eigenvalues, they go extra)
647 const size_t MaxLevel = subsetmap->getMaximumSubsetLevel();
648 const std::string energyresult =
649 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
650 Result_Energy_fused, MaxLevel);
651 LOG(0, "Energy table is \n" << energyresult);
652 const std::string eigenvalueresult;
653
654 LOG(0, "Eigenvalue table is \n" << eigenvalueresult);
655 const std::string forceresult =
656 writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
657 Result_Force_fused, MaxLevel);
658 LOG(0, "Force table is \n" << forceresult);
659 // we don't want to print grid to a table
660 // print times (without flops for now)
661 typedef boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_flops>::type MPQCDataTimeVector_noflops_t;
662 const std::string timesresult =
663 writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
664 Result_Time_fused, MaxLevel);
665 LOG(0, "Times table is \n" << timesresult);
666 }
667
668 // combine all found data
669 if (!KeySet.ParseManyBodyTerms()) return false;
670
671 EnergyMatrix EnergyFragments;
672 ForceMatrix ForceFragments;
673 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return false;
674 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return false;
675
676 if(!Energy.SetLastMatrix(0., 0)) return false;
677 if(!Force.SetLastMatrix(0., 2)) return false;
678
679 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
680 // --------- sum up energy --------------------
681 LOG(1, "INFO: Summing energy of order " << BondOrder+1 << " ...");
682 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return false;
683 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return false;
684
685 // --------- sum up Forces --------------------
686 LOG(1, "INFO: Summing forces of order " << BondOrder+1 << " ...");
687 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return false;
688 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return false;
689 }
690
691 // for debugging print resulting energy and forces
692 LOG(1, "INFO: Resulting energy is " << Energy.Matrix[ FragmentCounter ][0][0]);
693 std::stringstream output;
694 for (int i=0; i< Force.RowCounter[FragmentCounter]; ++i) {
695 for (int j=0; j< Force.ColumnCounter[FragmentCounter]; ++j)
696 output << Force.Matrix[ FragmentCounter ][i][j] << " ";
697 output << "\n";
698 }
699 LOG(1, "INFO: Resulting forces are " << std::endl << output.str());
700
701 return true;
702}
703
704/** Print MPQCData from received results.
705 *
706 * @param fragmentresults results with short-range job ids to associate with fragment number
707 * @param longrangeresults results with long-range job ids to associate with fragment number
708 * @param fragmentData MPQCData resulting from the jobs
709 * @param longrangeData VMGData resulting from long-range jobs
710 * @param KeySetFilename filename with keysets to associate forces correctly
711 * @param NoAtoms total number of atoms
712 * @param full_sample summed up charge from fragments on return
713 */
714bool printReceivedFullResults(
715 const std::vector<FragmentResult::ptr> &fragmentresults,
716 const std::vector<FragmentResult::ptr> &longrangeresults,
717 const std::vector<MPQCData> &fragmentData,
718 const std::vector<VMGData> &longrangeData,
719 const std::string &KeySetFilename,
720 size_t NoAtoms,
721 SamplingGrid &full_sample)
722{
723 // create lookup from job nr to fragment number
724 std::map< JobId_t, size_t > MatrixNrLookup;
725 size_t FragmentCounter = 0;
726 createMatrixNrLookup(fragmentresults, MatrixNrLookup, FragmentCounter);
727 std::map< JobId_t, size_t > extraMatrixNrLookup;
728 size_t extraFragmentCounter = 0;
729 createMatrixNrLookup(longrangeresults, extraMatrixNrLookup, extraFragmentCounter);
730
731 // initialise keysets
732 KeySetsContainer KeySet;
733 KeySetsContainer ForceKeySet;
734 {
735 // else needs keysets without hydrogens
736 std::stringstream filename;
737 filename << FRAGMENTPREFIX << KEYSETFILE;
738 if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
739 }
740
741 {
742 // forces need keysets including hydrogens
743 std::stringstream filename;
744 filename << FRAGMENTPREFIX << FORCESFILE;
745 if (!ForceKeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
746 }
747
748 /// prepare for OrthogonalSummation
749
750 // convert KeySetContainer to IndexSetContainer
751 IndexSetContainer::ptr container(new IndexSetContainer(KeySet));
752 // create the map of all keysets
753 SubsetMap::ptr subsetmap(new SubsetMap(*container));
754
755 // create a vector of all job ids from short-range
756 std::vector<JobId_t> jobids(fragmentresults.size(), JobId::IllegalJob);
757 std::transform(fragmentresults.begin(), fragmentresults.end(), jobids.begin(),
758 boost::bind(&FragmentResult::getId,
759 boost::bind(&FragmentResult::ptr::operator->, _1)));
760 // create a vector of all job ids from long-range
761 std::vector<JobId_t> extrajobids(longrangeresults.size(), JobId::IllegalJob);
762 std::transform(longrangeresults.begin(), longrangeresults.end(), extrajobids.begin(),
763 boost::bind(&FragmentResult::getId,
764 boost::bind(&FragmentResult::ptr::operator->, _1)));
765
766 /// convert all MPQCData to MPQCDataMap_t
767 {
768 typedef boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type MPQCDataEnergyVector_noeigenvalues_t;
769 std::vector<MPQCDataEnergyMap_t> Result_Energy_fused(
770 OrthogonalSumUpPerLevel<MPQCDataEnergyMap_t, MPQCDataEnergyVector_t>(
771 fragmentData, jobids, MatrixNrLookup, container, subsetmap));
772 std::vector<MPQCDataGridMap_t> Result_Grid_fused(
773 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCDataGridVector_t>(
774 fragmentData, jobids, MatrixNrLookup, container, subsetmap));
775 std::vector<MPQCDataTimeMap_t> Result_Time_fused(
776 SumUpPerLevel<MPQCDataTimeMap_t, MPQCDataTimeVector_t>(
777 fragmentData, jobids, MatrixNrLookup, container, subsetmap));
778
779 // force has extra converter
780 std::vector<MPQCDataForceMap_t> MPQCData_Force_fused;
781 convertMPQCDatatoForceMap(fragmentData, ForceKeySet, MPQCData_Force_fused);
782 std::vector<MPQCDataForceMap_t> Result_Force_fused(subsetmap->getMaximumSubsetLevel());
783 AllLevelOrthogonalSummator<MPQCDataForceMap_t> forceSummer(
784 subsetmap,
785 MPQCData_Force_fused,
786 jobids,
787 container->getContainer(),
788 MatrixNrLookup,
789 Result_Force_fused);
790 boost::mpl::for_each<MPQCDataForceVector_t>(boost::ref(forceSummer));
791
792 // obtain full grid
793 std::vector<VMGDataMap_t> VMGData_Potential_fused;
794 convertDataTo<VMGData, VMGDataMap_t>(longrangeData, VMGData_Potential_fused);
795 OrthogonalFullSummator<VMGDataMap_t, VMGDataFused::sampled_potential> potentialSummer(
796 subsetmap,
797 VMGData_Potential_fused,
798 extrajobids,
799 container->getContainer(),
800 extraMatrixNrLookup);
801 potentialSummer(subsetmap->getMaximumSubsetLevel());
802 full_sample = potentialSummer.getFullContribution();
803 LOG(0, "Remaining long-range energy from potential integral is " << full_sample.integral() << ".");
804
805 OrthogonalFullSummator<VMGDataMap_t, VMGDataFused::energy_long> elongSummer(
806 subsetmap,
807 VMGData_Potential_fused,
808 extrajobids,
809 container->getContainer(),
810 extraMatrixNrLookup);
811 elongSummer(subsetmap->getMaximumSubsetLevel());
812 const double e_long = elongSummer.getFullContribution();
813 LOG(0, "Remaining long-range energy is " << e_long << ".");
814
815 // print tables (without eigenvalues, they go extra)
816 const size_t MaxLevel = subsetmap->getMaximumSubsetLevel();
817 const std::string energyresult =
818 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
819 Result_Energy_fused, MaxLevel);
820 LOG(0, "Energy table is \n" << energyresult);
821 const std::string eigenvalueresult;
822
823 LOG(0, "Eigenvalue table is \n" << eigenvalueresult);
824 const std::string forceresult =
825 writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
826 Result_Force_fused, MaxLevel);
827 LOG(0, "Force table is \n" << forceresult);
828 // we don't want to print grid to a table
829 // print times (without flops for now)
830 typedef boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_flops>::type MPQCDataTimeVector_noflops_t;
831 const std::string timesresult =
832 writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
833 Result_Time_fused, MaxLevel);
834 LOG(0, "Times table is \n" << timesresult);
835 }
836
837 return true;
838}
839
840
841void RunService(
842 boost::asio::io_service &io_service,
843 std::string message)
844{
845 message = std::string("io_service: ") + message;
846 io_service.reset();
847 Info info(message.c_str());
848 io_service.run();
849}
850
851void requestIds(
852 FragmentController &controller,
853 const FragmentationFragmentationAutomationAction::FragmentationFragmentationAutomationParameters &params,
854 const size_t numberjobs)
855{
856 controller.requestIds(params.host.get(), params.port.get(), numberjobs);
857}
858
859bool createJobsFromFiles(
860 FragmentController &controller,
861 const FragmentationFragmentationAutomationAction::FragmentationFragmentationAutomationParameters &params,
862 const std::vector< boost::filesystem::path > &jobfiles)
863{
864 std::vector<FragmentJob::ptr> jobs;
865 for (std::vector< boost::filesystem::path >::const_iterator iter = jobfiles.begin();
866 iter != jobfiles .end(); ++iter) {
867 const std::string &filename = (*iter).string();
868 if (boost::filesystem::exists(filename)) {
869 const JobId_t next_id = controller.getAvailableId();
870 LOG(1, "INFO: Creating MPQCCommandJob with filename'"
871 +filename+"', and id "+toString(next_id)+".");
872 parsejob(jobs, params.executable.get().string(), filename, next_id);
873 } else {
874 ELOG(1, "Fragment job "+filename+" does not exist.");
875 return false;
876 }
877 }
878 controller.addJobs(jobs);
879 controller.sendJobs(params.host.get(), params.port.get());
880 return true;
881}
882
883#ifdef HAVE_VMG
884bool createLongRangeJobs(
885 FragmentController &controller,
886 const FragmentationFragmentationAutomationAction::FragmentationFragmentationAutomationParameters &params,
887 const std::vector<MPQCData> &fragmentData,
888 const SamplingGrid &full_sampled_grid,
889 const Fragment &full_fragment)
890{
891 std::vector<FragmentJob::ptr> jobs;
892 // add one job for each fragment as the short-range correction which we need
893 // to subtract from the obtained full potential to get the long-range part only
894 for (std::vector<MPQCData>::const_iterator iter = fragmentData.begin();
895 iter != fragmentData.end(); ++iter) {
896 const JobId_t next_id = controller.getAvailableId();
897 LOG(1, "INFO: Creating VMGJob with " << iter->sampled_grid.sampled_grid.size()
898 << " gridpoints and " << iter->charges.size() << " particle charges.");
899 FragmentJob::ptr testJob(
900 new VMGJob(next_id, iter->sampled_grid, iter->positions, iter->charges) );
901 jobs.push_back(testJob);
902 }
903
904 {
905// const int level = LEVEL;
906// const int GRID = pow(2, level);
907// double begin[NDIM] = { 0., 0., 0. };
908// const RealSpaceMatrix& M = World::getInstance().getDomain().getM();
909// const double size = M.at(0,0);
910// ASSERT( M.determinant() == size*size*size,
911// "createLongRangeJobs() - current domain matrix "+toString(M)+" is not cubic.");
912 const std::vector< std::vector<double> > positions(full_fragment.getPositions());
913 const std::vector<double> charges(full_fragment.getCharges());
914 const JobId_t next_id = controller.getAvailableId();
915 LOG(1, "INFO: Creating full VMGJob with " << full_sampled_grid.sampled_grid.size()
916 << " gridpoints and " << charges.size() << " particle charges.");
917 FragmentJob::ptr testJob(
918 new VMGJob(next_id, full_sampled_grid, positions, charges) );
919 jobs.push_back(testJob);
920 }
921
922 // then send jobs to controller
923 controller.addJobs(jobs);
924 controller.sendJobs(params.host.get(), params.port.get());
925 return true;
926}
927#endif
928
929void WaitforResults(
930 boost::asio::io_service &io_service,
931 FragmentController &controller,
932 const FragmentationFragmentationAutomationAction::FragmentationFragmentationAutomationParameters &params,
933 const size_t NoExpectedResults
934 )
935{
936 size_t NoCalculatedResults = 0;
937 while (NoCalculatedResults != NoExpectedResults) {
938 // wait a bit
939 boost::asio::deadline_timer timer(io_service);
940 timer.expires_from_now(boost::posix_time::milliseconds(500));
941 timer.wait();
942 // then request status
943 controller.checkResults(params.host.get(), params.port.get());
944 RunService(io_service, "Checking on results");
945
946 const std::pair<size_t, size_t> JobStatus = controller.getJobStatus();
947 LOG(1, "INFO: #" << JobStatus.first << " are waiting in the queue and #" << JobStatus.second << " jobs are calculated so far.");
948 NoCalculatedResults = JobStatus.second;
949 }
950}
951
952
953Action::state_ptr FragmentationFragmentationAutomationAction::performCall() {
954 boost::asio::io_service io_service;
955 FragmentController controller(io_service);
956
957 // TODO: Have io_service run in second thread and merge with current again eventually
958
959 // Phase One: obtain ids
960 std::vector< boost::filesystem::path > jobfiles = params.jobfiles.get();
961 requestIds(controller, params, jobfiles.size());
962 RunService(io_service, "Requesting ids");
963
964 // Phase Two: create and add MPQCJobs
965 if (!createJobsFromFiles(controller, params, jobfiles))
966 return Action::failure;
967 RunService(io_service, "Adding MPQCJobs");
968
969 // Phase Three: calculate result
970 WaitforResults(io_service, controller, params, jobfiles.size());
971 controller.receiveResults(params.host.get(), params.port.get());
972 RunService(io_service, "Requesting short-range results");
973 std::vector<FragmentResult::ptr> MPQCresults = controller.getReceivedResults();
974 std::vector<MPQCData> fragmentData;
975 ConvertFragmentResultTo<MPQCData>(MPQCresults, fragmentData);
976
977#ifdef HAVE_VMG
978 if (params.DoLongrange.get()) {
979 // obtain combined charge density
980 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
981 SamplingGrid full_sample;
982 Fragment full_fragment;
983 sumUpChargeDensity(
984 MPQCresults,
985 fragmentData,
986 params.path.get(),
987 full_sample,
988 full_fragment);
989
990 // Phase Four: obtain more ids
991 requestIds(controller, params, fragmentData.size()+1);
992 RunService(io_service, "Requesting ids");
993
994 // Phase Five: create VMGJobs
995 if (!createLongRangeJobs(controller, params, fragmentData, full_sample, full_fragment))
996 return Action::failure;
997 RunService(io_service, "Adding VMGJobs");
998
999 // Phase Six: calculate result
1000 WaitforResults(io_service, controller, params, fragmentData.size()+1);
1001 controller.receiveResults(params.host.get(), params.port.get());
1002 RunService(io_service, "Requesting long-range results");
1003 std::vector<FragmentResult::ptr> VMGresults = controller.getReceivedResults();
1004 ASSERT( MPQCresults.size()+1 == VMGresults.size(),
1005 "FragmentationFragmentationAutomationAction::performCall() - number of MPQCresultd and VMGresults don't match.");
1006
1007 std::vector<VMGData> longrangeData;
1008 ConvertFragmentResultTo<VMGData>(VMGresults, longrangeData);
1009
1010 // Final phase: print result
1011 {
1012 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
1013 printReceivedFullResults(
1014 MPQCresults,
1015 VMGresults,
1016 fragmentData,
1017 longrangeData,
1018 params.path.get(),
1019 getNoAtomsFromAdjacencyFile(params.path.get()),
1020 full_sample);
1021 }
1022 }
1023#else
1024 // Final phase: print result
1025 {
1026 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
1027 printReceivedMPQCResults(
1028 MPQCresults,
1029 fragmentData,
1030 params.path.get(),
1031 getNoAtomsFromAdjacencyFile(params.path.get()),
1032 full_sample);
1033 }
1034#endif
1035 size_t Exitflag = controller.getExitflag();
1036
1037 return (Exitflag == 0) ? Action::success : Action::failure;
1038}
1039
1040Action::state_ptr FragmentationFragmentationAutomationAction::performUndo(Action::state_ptr _state) {
1041 return Action::success;
1042}
1043
1044Action::state_ptr FragmentationFragmentationAutomationAction::performRedo(Action::state_ptr _state){
1045 return Action::success;
1046}
1047
1048bool FragmentationFragmentationAutomationAction::canUndo() {
1049 return false;
1050}
1051
1052bool FragmentationFragmentationAutomationAction::shouldUndo() {
1053 return false;
1054}
1055/** =========== end of function ====================== */
Note: See TracBrowser for help on using the repository browser.