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

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 ffe057 was ffe057, checked in by Frederik Heber <heber@…>, 12 years ago

Added SpecificFragmentController and subclasses that contain functions to add type-specific jobs.

  • Property mode set to 100644
File size: 25.7 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#include <boost/lambda/lambda.hpp>
43
44#include "CodePatterns/Assert.hpp"
45#include "CodePatterns/Info.hpp"
46#include "CodePatterns/Log.hpp"
47#include "JobMarket/Jobs/FragmentJob.hpp"
48
49#include "Fragmentation/Automation/MPQCFragmentController.hpp"
50#include "Fragmentation/Automation/VMGFragmentController.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/OrthogonalSumUpPerLevel.hpp"
61#include "Fragmentation/Summation/SumUpPerLevel.hpp"
62#include "Fragmentation/Summation/OrthogonalFullSummator.hpp"
63#include "Fragmentation/Summation/writeTable.hpp"
64#include "Graph/DepthFirstSearchAnalysis.hpp"
65#include "Helpers/defs.hpp"
66#include "Jobs/MPQCJob.hpp"
67#include "Jobs/MPQCData.hpp"
68#include "Jobs/MPQCData_printKeyNames.hpp"
69#include "Jobs/Grid/SamplingGrid.hpp"
70#ifdef HAVE_VMG
71#include "Jobs/VMGJob.hpp"
72#include "Jobs/VMGData.hpp"
73#include "Jobs/VMGDataFused.hpp"
74#include "Jobs/VMGDataMap.hpp"
75#include "Jobs/VMGData_printKeyNames.hpp"
76#endif
77#include "World.hpp"
78
79#include <iostream>
80#include <string>
81#include <vector>
82
83#include <boost/mpl/for_each.hpp>
84
85#include "Actions/FragmentationAction/FragmentationAutomationAction.hpp"
86
87using namespace MoleCuilder;
88
89// and construct the stuff
90#include "FragmentationAutomationAction.def"
91#include "Action_impl_pre.hpp"
92/** =========== define the function ====================== */
93
94class controller_AddOn;
95
96// needs to be defined for using the FragmentController
97controller_AddOn *getAddOn()
98{
99 return NULL;
100}
101
102/** Helper function to get number of atoms somehow.
103 *
104 * Here, we just parse the number of lines in the adjacency file as
105 * it should correspond to the number of atoms, except when some atoms
106 * are not bonded, but then fragmentation makes no sense.
107 *
108 * @param path path to the adjacency file
109 */
110size_t getNoAtomsFromAdjacencyFile(const std::string &path)
111{
112 size_t NoAtoms = 0;
113
114 // parse in special file to get atom count (from line count)
115 std::string filename(path);
116 filename += FRAGMENTPREFIX;
117 filename += ADJACENCYFILE;
118 std::ifstream adjacency(filename.c_str());
119 if (adjacency.fail()) {
120 LOG(0, endl << "getNoAtomsFromAdjacencyFile() - Unable to open " << filename << ", is the directory correct?");
121 return false;
122 }
123 std::string buffer;
124 while (getline(adjacency, buffer))
125 NoAtoms++;
126 LOG(1, "INFO: There are " << NoAtoms << " atoms.");
127
128 return NoAtoms;
129}
130
131
132/** Creates a lookup from FragmentJob::id to the true fragment number.
133 *
134 * @param jobids vector with job ids
135 * @param FragmentCounter total number of fragments on return
136 * @return Lookup up-map
137 */
138std::map< JobId_t, size_t > createMatrixNrLookup(
139 const std::vector<JobId_t> &jobids,
140 size_t &FragmentCounter)
141{
142 // align fragments
143 std::map< JobId_t, size_t > MatrixNrLookup;
144 FragmentCounter = 0;
145 for (std::vector<JobId_t>::const_iterator iter = jobids.begin();
146 iter != jobids.end(); ++iter) {
147 LOG(3, "DEBUG: Inserting (" << *iter << "," << FragmentCounter << ").");
148#ifndef NDEBUG
149 std::pair< std::map< JobId_t, size_t >::iterator, bool> inserter =
150#endif
151 MatrixNrLookup.insert( std::make_pair(*iter, FragmentCounter++) );
152 ASSERT( inserter.second,
153 "createMatrixNrLookup() - two results have same id "
154 +toString(*iter)+".");
155 }
156 LOG(1, "INFO: There are " << FragmentCounter << " fragments.");
157 return MatrixNrLookup;
158}
159
160/** Place results from FragmentResult into EnergyMatrix and ForceMatrix.
161 *
162 * @param fragmentData MPQCData resulting from the jobs
163 * @param MatrixNrLookup Lookup up-map from job id to fragment number
164 * @param FragmentCounter total number of fragments
165 * @param NoAtoms total number of atoms
166 * @param Energy energy matrix to be filled on return
167 * @param Force force matrix to be filled on return
168 * @return true - everything ok, false - else
169 */
170bool putResultsintoMatrices(
171 const std::map<JobId_t, MPQCData> &fragmentData,
172 const std::map< JobId_t, size_t > &MatrixNrLookup,
173 const size_t FragmentCounter,
174 const size_t NoAtoms,
175 EnergyMatrix &Energy,
176 ForceMatrix &Force)
177{
178 for (std::map<JobId_t, MPQCData>::const_iterator dataiter = fragmentData.begin();
179 dataiter != fragmentData.end(); ++dataiter) {
180 const MPQCData &extractedData = dataiter->second;
181 const JobId_t &jobid = dataiter->first;
182 std::map< JobId_t, size_t >::const_iterator nriter = MatrixNrLookup.find(jobid);
183 ASSERT( nriter != MatrixNrLookup.end(),
184 "putResultsintoMatrices() - MatrixNrLookup does not contain id "
185 +toString(jobid)+".");
186 // place results into EnergyMatrix ...
187 {
188 MatrixContainer::MatrixArray matrix;
189 matrix.resize(1);
190 matrix[0].resize(1, extractedData.energies.total);
191 if (!Energy.AddMatrix(
192 std::string("MPQCJob ")+toString(jobid),
193 matrix,
194 nriter->second)) {
195 ELOG(1, "Adding energy matrix failed.");
196 return false;
197 }
198 }
199 // ... and ForceMatrix (with two empty columns in front)
200 {
201 MatrixContainer::MatrixArray matrix;
202 const size_t rows = extractedData.forces.size();
203 matrix.resize(rows);
204 for (size_t i=0;i<rows;++i) {
205 const size_t columns = 2+extractedData.forces[i].size();
206 matrix[i].resize(columns, 0.);
207 // for (size_t j=0;j<2;++j)
208 // matrix[i][j] = 0.;
209 for (size_t j=2;j<columns;++j)
210 matrix[i][j] = extractedData.forces[i][j-2];
211 }
212 if (!Force.AddMatrix(
213 std::string("MPQCJob ")+toString(jobid),
214 matrix,
215 nriter->second)) {
216 ELOG(1, "Adding force matrix failed.");
217 return false;
218 }
219 }
220 }
221 // add one more matrix (not required for energy)
222 MatrixContainer::MatrixArray matrix;
223 matrix.resize(1);
224 matrix[0].resize(1, 0.);
225 if (!Energy.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter))
226 return false;
227 // but for energy because we need to know total number of atoms
228 matrix.resize(NoAtoms);
229 for (size_t i = 0; i< NoAtoms; ++i)
230 matrix[i].resize(2+NDIM, 0.);
231 if (!Force.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter))
232 return false;
233
234 return true;
235}
236/** Print MPQCData from received results.
237 *
238 * @param fragmentData MPQCData resulting from the jobs, each associated to a job
239 * @param KeySetFilename filename with keysets to associate forces correctly
240 * @param NoAtoms total number of atoms
241 * @param full_sample summed up charge density of electrons from fragments on return
242 * @param full_fragment summed up positions and charges of nuclei from fragments on return
243 */
244bool sumUpChargeDensity(
245 const std::map<JobId_t,MPQCData> &fragmentData,
246 const std::string &KeySetFilename,
247 SamplingGrid &full_sample,
248 Fragment &full_fragment)
249{
250 // create a vector of all job ids
251 std::vector<JobId_t> jobids;
252 std::transform(fragmentData.begin(),fragmentData.end(),
253 std::back_inserter(jobids),
254 boost::bind( &std::map<JobId_t,MPQCData>::value_type::first, boost::lambda::_1 )
255 );
256
257 // create lookup from job nr to fragment number
258 size_t FragmentCounter = 0;
259 const std::map< JobId_t, size_t > MatrixNrLookup =
260 createMatrixNrLookup(jobids, FragmentCounter);
261
262 // initialise keysets
263 KeySetsContainer KeySet;
264 {
265 // else needs keysets without hydrogens
266 std::stringstream filename;
267 filename << FRAGMENTPREFIX << KEYSETFILE;
268 if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
269 }
270
271 /// prepare for OrthogonalSummation
272
273 // convert KeySetContainer to IndexSetContainer
274 IndexSetContainer::ptr container(new IndexSetContainer(KeySet));
275 // create the map of all keysets
276 SubsetMap::ptr subsetmap(new SubsetMap(*container));
277
278 /// convert all MPQCData to MPQCDataMap_t
279 std::vector<MPQCDataGridMap_t> Result_Grid_fused(
280 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCDataGridVector_t>(
281 fragmentData, MatrixNrLookup, container, subsetmap));
282 std::vector<MPQCDataFragmentMap_t> Result_Fragment_fused(
283 OrthogonalSumUpPerLevel<MPQCDataFragmentMap_t, MPQCDataFragmentVector_t>(
284 fragmentData, MatrixNrLookup, container, subsetmap));
285 // obtain full grid
286 full_sample = boost::fusion::at_key<MPQCDataFused::sampled_grid>(Result_Grid_fused.back());
287 full_fragment = boost::fusion::at_key<MPQCDataFused::fragment>(Result_Fragment_fused.back());
288
289 return true;
290}
291
292/** Print MPQCData from received results.
293 *
294 * @param fragmentData MPQCData resulting from the jobs, associated to job id
295 * @param KeySetFilename filename with keysets to associate forces correctly
296 * @param NoAtoms total number of atoms
297 * @param full_sample summed up charge from fragments on return
298 */
299bool printReceivedMPQCResults(
300 const std::map<JobId_t, MPQCData> &fragmentData,
301 const std::string &KeySetFilename,
302 size_t NoAtoms,
303 SamplingGrid &full_sample)
304{
305 // create a vector of all job ids
306 std::vector<JobId_t> jobids;
307 std::transform(fragmentData.begin(),fragmentData.end(),
308 std::back_inserter(jobids),
309 boost::bind( &std::map<JobId_t,MPQCData>::value_type::first, boost::lambda::_1 )
310 );
311
312 // create lookup from job nr to fragment number
313 size_t FragmentCounter = 0;
314 const std::map< JobId_t, size_t > MatrixNrLookup=
315 createMatrixNrLookup(jobids, FragmentCounter);
316
317 // place results into maps
318 EnergyMatrix Energy;
319 ForceMatrix Force;
320 if (!putResultsintoMatrices(fragmentData, MatrixNrLookup, FragmentCounter, NoAtoms, Energy, Force))
321 return false;
322
323 // initialise keysets
324 KeySetsContainer KeySet;
325 KeySetsContainer ForceKeySet;
326 if (!Energy.InitialiseIndices()) return false;
327
328 if (!Force.ParseIndices(KeySetFilename.c_str())) return false;
329
330 {
331 // else needs keysets without hydrogens
332 std::stringstream filename;
333 filename << FRAGMENTPREFIX << KEYSETFILE;
334 if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
335 }
336
337 {
338 // forces need keysets including hydrogens
339 std::stringstream filename;
340 filename << FRAGMENTPREFIX << FORCESFILE;
341 if (!ForceKeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
342 }
343
344 /// prepare for OrthogonalSummation
345
346 // convert KeySetContainer to IndexSetContainer
347 IndexSetContainer::ptr container(new IndexSetContainer(KeySet));
348 // create the map of all keysets
349 SubsetMap::ptr subsetmap(new SubsetMap(*container));
350
351 /// convert all MPQCData to MPQCDataMap_t
352 {
353 ASSERT( ForceKeySet.KeySets.size() == fragmentData.size(),
354 "FragmentationAutomationAction::performCall() - ForceKeySet's KeySets and fragmentData differ in size.");
355
356 typedef boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type MPQCDataEnergyVector_noeigenvalues_t;
357 std::vector<MPQCDataEnergyMap_t> Result_Energy_fused(
358 OrthogonalSumUpPerLevel<MPQCDataEnergyMap_t, MPQCDataEnergyVector_t>(
359 fragmentData, MatrixNrLookup, container, subsetmap));
360 std::vector<MPQCDataGridMap_t> Result_Grid_fused(
361 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCDataGridVector_t>(
362 fragmentData, MatrixNrLookup, container, subsetmap));
363 std::vector<MPQCDataTimeMap_t> Result_Time_fused(
364 SumUpPerLevel<MPQCDataTimeMap_t, MPQCDataTimeVector_t>(
365 fragmentData, MatrixNrLookup, container, subsetmap));
366
367 // force has extra converter
368 std::map<JobId_t, MPQCDataForceMap_t> MPQCData_Force_fused;
369 convertMPQCDatatoForceMap(fragmentData, ForceKeySet, MPQCData_Force_fused);
370 std::vector<MPQCDataForceMap_t> Result_Force_fused(subsetmap->getMaximumSubsetLevel());
371 AllLevelOrthogonalSummator<MPQCDataForceMap_t> forceSummer(
372 subsetmap,
373 MPQCData_Force_fused,
374 container->getContainer(),
375 MatrixNrLookup,
376 Result_Force_fused);
377 boost::mpl::for_each<MPQCDataForceVector_t>(boost::ref(forceSummer));
378
379 // obtain full grid
380 full_sample = boost::fusion::at_key<MPQCDataFused::sampled_grid>(Result_Grid_fused.back());
381
382 // print tables (without eigenvalues, they go extra)
383 const size_t MaxLevel = subsetmap->getMaximumSubsetLevel();
384 const std::string energyresult =
385 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
386 Result_Energy_fused, MaxLevel);
387 LOG(0, "Energy table is \n" << energyresult);
388 const std::string eigenvalueresult;
389
390 LOG(0, "Eigenvalue table is \n" << eigenvalueresult);
391 const std::string forceresult =
392 writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
393 Result_Force_fused, MaxLevel);
394 LOG(0, "Force table is \n" << forceresult);
395 // we don't want to print grid to a table
396 // print times (without flops for now)
397 typedef boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_flops>::type MPQCDataTimeVector_noflops_t;
398 const std::string timesresult =
399 writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
400 Result_Time_fused, MaxLevel);
401 LOG(0, "Times table is \n" << timesresult);
402 }
403
404 // combine all found data
405 if (!KeySet.ParseManyBodyTerms()) return false;
406
407 EnergyMatrix EnergyFragments;
408 ForceMatrix ForceFragments;
409 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return false;
410 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return false;
411
412 if(!Energy.SetLastMatrix(0., 0)) return false;
413 if(!Force.SetLastMatrix(0., 2)) return false;
414
415 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
416 // --------- sum up energy --------------------
417 LOG(1, "INFO: Summing energy of order " << BondOrder+1 << " ...");
418 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return false;
419 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return false;
420
421 // --------- sum up Forces --------------------
422 LOG(1, "INFO: Summing forces of order " << BondOrder+1 << " ...");
423 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return false;
424 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return false;
425 }
426
427 // for debugging print resulting energy and forces
428 LOG(1, "INFO: Resulting energy is " << Energy.Matrix[ FragmentCounter ][0][0]);
429 std::stringstream output;
430 for (int i=0; i< Force.RowCounter[FragmentCounter]; ++i) {
431 for (int j=0; j< Force.ColumnCounter[FragmentCounter]; ++j)
432 output << Force.Matrix[ FragmentCounter ][i][j] << " ";
433 output << "\n";
434 }
435 LOG(1, "INFO: Resulting forces are " << std::endl << output.str());
436
437 return true;
438}
439
440template <typename T>
441std::vector<JobId_t> extractJobIds(const std::map<JobId_t, T> &iddata)
442{
443 // create a vector of all job ids
444 std::vector<JobId_t> jobids;
445 std::transform(iddata.begin(),iddata.end(),
446 std::back_inserter(jobids),
447 boost::bind(&std::map<JobId_t,T>::value_type::first, boost::lambda::_1 )
448 );
449 return jobids;
450}
451
452/** Print MPQCData from received results.
453 *
454 * @param fragmentData MPQCData resulting from the jobs
455 * @param longrangeData VMGData resulting from long-range jobs
456 * @param fullsolutionData VMGData resulting from long-range of full problem
457 * @param KeySetFilename filename with keysets to associate forces correctly
458 * @param NoAtoms total number of atoms
459 * @param full_sample summed up charge from fragments on return
460 */
461bool printReceivedFullResults(
462 const std::map<JobId_t,MPQCData> &fragmentData,
463 const std::map<JobId_t,VMGData> &longrangeData,
464 const VMGData &fullsolutionData,
465 const std::string &KeySetFilename,
466 size_t NoAtoms,
467 SamplingGrid &full_sample)
468{
469 // create lookup from job nr to fragment number
470 size_t MPQCFragmentCounter = 0;
471 const std::vector<JobId_t> mpqcjobids = extractJobIds<MPQCData>(fragmentData);
472 const std::map< JobId_t, size_t > MPQCMatrixNrLookup =
473 createMatrixNrLookup(mpqcjobids, MPQCFragmentCounter);
474
475 size_t VMGFragmentCounter = 0;
476 const std::vector<JobId_t> vmgjobids = extractJobIds<VMGData>(longrangeData);
477 const std::map< JobId_t, size_t > VMGMatrixNrLookup =
478 createMatrixNrLookup(vmgjobids, VMGFragmentCounter);
479
480 // initialise keysets
481 KeySetsContainer KeySet;
482 KeySetsContainer ForceKeySet;
483 {
484 // else needs keysets without hydrogens
485 std::stringstream filename;
486 filename << FRAGMENTPREFIX << KEYSETFILE;
487 if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), MPQCFragmentCounter)) return false;
488 }
489
490 {
491 // forces need keysets including hydrogens
492 std::stringstream filename;
493 filename << FRAGMENTPREFIX << FORCESFILE;
494 if (!ForceKeySet.ParseKeySets(KeySetFilename, filename.str(), MPQCFragmentCounter)) return false;
495 }
496
497 /// prepare for OrthogonalSummation
498
499 // convert KeySetContainer to IndexSetContainer
500 IndexSetContainer::ptr container(new IndexSetContainer(KeySet));
501 // create the map of all keysets
502 SubsetMap::ptr subsetmap(new SubsetMap(*container));
503
504 /// convert all MPQCData to MPQCDataMap_t
505 {
506 typedef boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type MPQCDataEnergyVector_noeigenvalues_t;
507 std::vector<MPQCDataEnergyMap_t> Result_Energy_fused(
508 OrthogonalSumUpPerLevel<MPQCDataEnergyMap_t, MPQCDataEnergyVector_t>(
509 fragmentData, MPQCMatrixNrLookup, container, subsetmap));
510 std::vector<MPQCDataGridMap_t> Result_Grid_fused(
511 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCDataGridVector_t>(
512 fragmentData, MPQCMatrixNrLookup, container, subsetmap));
513 std::vector<MPQCDataTimeMap_t> Result_Time_fused(
514 SumUpPerLevel<MPQCDataTimeMap_t, MPQCDataTimeVector_t>(
515 fragmentData, MPQCMatrixNrLookup, container, subsetmap));
516 std::vector<MPQCDataFragmentMap_t> Result_Fragment_fused(
517 OrthogonalSumUpPerLevel<MPQCDataFragmentMap_t, MPQCDataFragmentVector_t>(
518 fragmentData, MPQCMatrixNrLookup, container, subsetmap));
519
520 // force has extra converter
521 std::map<JobId_t, MPQCDataForceMap_t> MPQCData_Force_fused;
522 convertMPQCDatatoForceMap(fragmentData, ForceKeySet, MPQCData_Force_fused);
523 std::vector<MPQCDataForceMap_t> Result_Force_fused(subsetmap->getMaximumSubsetLevel());
524 AllLevelOrthogonalSummator<MPQCDataForceMap_t> forceSummer(
525 subsetmap,
526 MPQCData_Force_fused,
527 container->getContainer(),
528 MPQCMatrixNrLookup,
529 Result_Force_fused);
530 boost::mpl::for_each<MPQCDataForceVector_t>(boost::ref(forceSummer));
531
532 // obtain full grid
533 std::map<JobId_t, VMGDataMap_t> VMGData_Potential_fused;
534 convertDataTo<VMGData, VMGDataMap_t>(longrangeData, VMGData_Potential_fused);
535 OrthogonalFullSummator<VMGDataMap_t, VMGDataFused::sampled_potential> potentialSummer(
536 subsetmap,
537 VMGData_Potential_fused,
538 container->getContainer(),
539 VMGMatrixNrLookup);
540 potentialSummer(subsetmap->getMaximumSubsetLevel());
541 OrthogonalFullSummator<VMGDataMap_t, VMGDataFused::energy_potential> epotentialSummer(
542 subsetmap,
543 VMGData_Potential_fused,
544 container->getContainer(),
545 VMGMatrixNrLookup);
546 epotentialSummer(subsetmap->getMaximumSubsetLevel());
547 SamplingGrid full_sample = fullsolutionData.sampled_potential;
548 LOG(0, "Remaining long-range energy from energy_potential is " << full_sample.integral()-epotentialSummer.getFullContribution() << ".");
549 full_sample -= potentialSummer.getFullContribution();
550 LOG(0, "Remaining long-range energy from potential integral is " << full_sample.integral() << ".");
551
552
553 OrthogonalFullSummator<VMGDataMap_t, VMGDataFused::energy_long> elongSummer(
554 subsetmap,
555 VMGData_Potential_fused,
556 container->getContainer(),
557 VMGMatrixNrLookup);
558 elongSummer(subsetmap->getMaximumSubsetLevel());
559 double e_long = fullsolutionData.e_long;
560 e_long -= elongSummer.getFullContribution();
561 LOG(0, "Remaining long-range energy is " << e_long << ".");
562
563 // print tables (without eigenvalues, they go extra)
564 const size_t MaxLevel = subsetmap->getMaximumSubsetLevel();
565 const std::string energyresult =
566 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
567 Result_Energy_fused, MaxLevel);
568 LOG(0, "Energy table is \n" << energyresult);
569 const std::string eigenvalueresult;
570
571 LOG(0, "Eigenvalue table is \n" << eigenvalueresult);
572 const std::string forceresult =
573 writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
574 Result_Force_fused, MaxLevel);
575 LOG(0, "Force table is \n" << forceresult);
576 // we don't want to print grid to a table
577 // print times (without flops for now)
578 typedef boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_flops>::type MPQCDataTimeVector_noflops_t;
579 const std::string timesresult =
580 writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
581 Result_Time_fused, MaxLevel);
582 LOG(0, "Times table is \n" << timesresult);
583 }
584
585 return true;
586}
587
588
589Action::state_ptr FragmentationFragmentationAutomationAction::performCall() {
590 boost::asio::io_service io_service;
591 MPQCFragmentController mpqccontroller(io_service);
592 mpqccontroller.setHost(params.host.get());
593 mpqccontroller.setPort(params.port.get());
594 VMGFragmentController vmgcontroller(io_service);
595 vmgcontroller.setHost(params.host.get());
596 vmgcontroller.setPort(params.port.get());
597
598 // TODO: Have io_service run in second thread and merge with current again eventually
599
600 // Phase One: obtain ids
601 std::vector< boost::filesystem::path > jobfiles = params.jobfiles.get();
602 mpqccontroller.requestIds(jobfiles.size());
603
604 // Phase Two: create and add MPQCJobs
605 if (!mpqccontroller.addJobsFromFiles(params.executable.get().string(), jobfiles))
606 return Action::failure;
607
608 // Phase Three: calculate result
609 mpqccontroller.waitforResults(jobfiles.size());
610 std::map<JobId_t, MPQCData> fragmentData;
611 mpqccontroller.getResults(fragmentData);
612
613#ifdef HAVE_VMG
614 if (params.DoLongrange.get()) {
615 ASSERT( World::getInstance().getAllAtoms().size() != 0,
616 "FragmentationFragmentationAutomationAction::performCall() - please load the full molecule into the World before.");
617
618 // obtain combined charge density
619 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
620 SamplingGrid full_sample;
621 Fragment full_fragment;
622 sumUpChargeDensity(
623 fragmentData,
624 params.path.get(),
625 full_sample,
626 full_fragment);
627
628 // Phase Four: obtain more ids
629 vmgcontroller.requestIds(fragmentData.size()+1);
630
631 // Phase Five: create VMGJobs
632 if (!vmgcontroller.createLongRangeJobs(fragmentData, full_sample, full_fragment))
633 return Action::failure;
634
635 // Phase Six: calculate result
636 vmgcontroller.waitforResults(fragmentData.size()+1);
637 std::map<JobId_t, VMGData> longrangeData;
638 vmgcontroller.getResults(longrangeData);
639 ASSERT( fragmentData.size()+1 == longrangeData.size(),
640 "FragmentationFragmentationAutomationAction::performCall() - number of MPQCresults+1 "
641 +toString(fragmentData.size()+1)+" and VMGresults "+toString(longrangeData.size())+" don't match.");
642
643 // remove full solution from map (must be highest id), has to be treated extra
644 VMGData fullsolutionData = (--longrangeData.end())->second;
645 longrangeData.erase(--longrangeData.end());
646
647 // Final phase: print result
648 {
649 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
650 printReceivedFullResults(
651 fragmentData,
652 longrangeData,
653 fullsolutionData,
654 params.path.get(),
655 getNoAtomsFromAdjacencyFile(params.path.get()),
656 full_sample);
657 }
658 }
659#else
660 // Final phase: print result
661 {
662 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
663 printReceivedMPQCResults(
664 fragmentData,
665 params.path.get(),
666 getNoAtomsFromAdjacencyFile(params.path.get()),
667 full_sample);
668 }
669#endif
670 size_t Exitflag = vmgcontroller.getExitflag() + mpqccontroller.getExitflag();
671
672 return (Exitflag == 0) ? Action::success : Action::failure;
673}
674
675Action::state_ptr FragmentationFragmentationAutomationAction::performUndo(Action::state_ptr _state) {
676 return Action::success;
677}
678
679Action::state_ptr FragmentationFragmentationAutomationAction::performRedo(Action::state_ptr _state){
680 return Action::success;
681}
682
683bool FragmentationFragmentationAutomationAction::canUndo() {
684 return false;
685}
686
687bool FragmentationFragmentationAutomationAction::shouldUndo() {
688 return false;
689}
690/** =========== end of function ====================== */
Note: See TracBrowser for help on using the repository browser.