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

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

Extracted template function extractJobIds() into own header file.

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