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

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

We now create one full potential VMGJob of each summed up grid per level.

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