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

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

Added VMGDebugGridJob that just prints given sampled grid as VTK grid.

  • this is to allow inspecting the potential on the various summed levels.
  • added to FragmentationAutomationAction::performCall().
  • Property mode set to 100644
File size: 27.0 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 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 = boost::fusion::at_key<MPQCDataFused::sampled_grid>(Result_Grid_fused.back());
289 full_fragment = boost::fusion::at_key<MPQCDataFused::fragment>(Result_Fragment_fused.back());
290
291 return true;
292}
293
294/** Print MPQCData from received results.
295 *
296 * @param fragmentData MPQCData resulting from the jobs, associated to job id
297 * @param KeySetFilename filename with keysets to associate forces correctly
298 * @param NoAtoms total number of atoms
299 * @param full_sample summed up charge from fragments on return
300 */
301bool printReceivedMPQCResults(
302 const std::map<JobId_t, MPQCData> &fragmentData,
303 const std::string &KeySetFilename,
304 size_t NoAtoms,
305 SamplingGrid &full_sample)
306{
307 // create a vector of all job ids
308 std::vector<JobId_t> jobids;
309 std::transform(fragmentData.begin(),fragmentData.end(),
310 std::back_inserter(jobids),
311 boost::bind( &std::map<JobId_t,MPQCData>::value_type::first, boost::lambda::_1 )
312 );
313
314 // create lookup from job nr to fragment number
315 size_t FragmentCounter = 0;
316 const std::map< JobId_t, size_t > MatrixNrLookup=
317 createMatrixNrLookup(jobids, FragmentCounter);
318
319 // place results into maps
320 EnergyMatrix Energy;
321 ForceMatrix Force;
322 if (!putResultsintoMatrices(fragmentData, MatrixNrLookup, FragmentCounter, NoAtoms, Energy, Force))
323 return false;
324
325 // initialise keysets
326 KeySetsContainer KeySet;
327 KeySetsContainer ForceKeySet;
328 if (!Energy.InitialiseIndices()) return false;
329
330 if (!Force.ParseIndices(KeySetFilename.c_str())) return false;
331
332 {
333 // else needs keysets without hydrogens
334 std::stringstream filename;
335 filename << FRAGMENTPREFIX << KEYSETFILE;
336 if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
337 }
338
339 {
340 // forces need keysets including hydrogens
341 std::stringstream filename;
342 filename << FRAGMENTPREFIX << FORCESFILE;
343 if (!ForceKeySet.ParseKeySets(KeySetFilename, filename.str(), FragmentCounter)) return false;
344 }
345
346 /// prepare for OrthogonalSummation
347
348 // convert KeySetContainer to IndexSetContainer
349 IndexSetContainer::ptr container(new IndexSetContainer(KeySet));
350 // create the map of all keysets
351 SubsetMap::ptr subsetmap(new SubsetMap(*container));
352
353 /// convert all MPQCData to MPQCDataMap_t
354 {
355 ASSERT( ForceKeySet.KeySets.size() == fragmentData.size(),
356 "FragmentationAutomationAction::performCall() - ForceKeySet's KeySets and fragmentData differ in size.");
357
358 typedef boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type MPQCDataEnergyVector_noeigenvalues_t;
359 std::vector<MPQCDataEnergyMap_t> Result_Energy_fused(
360 OrthogonalSumUpPerLevel<MPQCDataEnergyMap_t, MPQCDataEnergyVector_t>(
361 fragmentData, MatrixNrLookup, container, subsetmap));
362 std::vector<MPQCDataGridMap_t> Result_Grid_fused(
363 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCDataGridVector_t>(
364 fragmentData, MatrixNrLookup, container, subsetmap));
365 std::vector<MPQCDataTimeMap_t> Result_Time_fused(
366 SumUpPerLevel<MPQCDataTimeMap_t, MPQCDataTimeVector_t>(
367 fragmentData, MatrixNrLookup, container, subsetmap));
368
369 // force has extra converter
370 std::map<JobId_t, MPQCDataForceMap_t> MPQCData_Force_fused;
371 convertMPQCDatatoForceMap(fragmentData, ForceKeySet, MPQCData_Force_fused);
372 std::vector<MPQCDataForceMap_t> Result_Force_fused(subsetmap->getMaximumSubsetLevel());
373 AllLevelOrthogonalSummator<MPQCDataForceMap_t> forceSummer(
374 subsetmap,
375 MPQCData_Force_fused,
376 container->getContainer(),
377 MatrixNrLookup,
378 Result_Force_fused);
379 boost::mpl::for_each<MPQCDataForceVector_t>(boost::ref(forceSummer));
380
381 // obtain full grid
382 full_sample = boost::fusion::at_key<MPQCDataFused::sampled_grid>(Result_Grid_fused.back());
383
384 // print tables (without eigenvalues, they go extra)
385 const size_t MaxLevel = subsetmap->getMaximumSubsetLevel();
386 const std::string energyresult =
387 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
388 Result_Energy_fused, MaxLevel);
389 LOG(0, "Energy table is \n" << energyresult);
390 const std::string eigenvalueresult;
391
392 LOG(0, "Eigenvalue table is \n" << eigenvalueresult);
393 const std::string forceresult =
394 writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
395 Result_Force_fused, MaxLevel);
396 LOG(0, "Force table is \n" << forceresult);
397 // we don't want to print grid to a table
398 // print times (without flops for now)
399 typedef boost::mpl::remove<
400 boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_total_flops>::type,
401 MPQCDataFused::times_gather_flops>::type
402 MPQCDataTimeVector_noflops_t;
403 const std::string timesresult =
404 writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
405 Result_Time_fused, MaxLevel);
406 LOG(0, "Times table is \n" << timesresult);
407 }
408
409 // combine all found data
410 if (!KeySet.ParseManyBodyTerms()) return false;
411
412 EnergyMatrix EnergyFragments;
413 ForceMatrix ForceFragments;
414 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return false;
415 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return false;
416
417 if(!Energy.SetLastMatrix(0., 0)) return false;
418 if(!Force.SetLastMatrix(0., 2)) return false;
419
420 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
421 // --------- sum up energy --------------------
422 LOG(1, "INFO: Summing energy of order " << BondOrder+1 << " ...");
423 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return false;
424 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return false;
425
426 // --------- sum up Forces --------------------
427 LOG(1, "INFO: Summing forces of order " << BondOrder+1 << " ...");
428 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return false;
429 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return false;
430 }
431
432 // for debugging print resulting energy and forces
433 LOG(1, "INFO: Resulting energy is " << Energy.Matrix[ FragmentCounter ][0][0]);
434 std::stringstream output;
435 for (int i=0; i< Force.RowCounter[FragmentCounter]; ++i) {
436 for (int j=0; j< Force.ColumnCounter[FragmentCounter]; ++j)
437 output << Force.Matrix[ FragmentCounter ][i][j] << " ";
438 output << "\n";
439 }
440 LOG(1, "INFO: Resulting forces are " << std::endl << output.str());
441
442 return true;
443}
444
445template <typename T>
446std::vector<JobId_t> extractJobIds(const std::map<JobId_t, T> &iddata)
447{
448 // create a vector of all job ids
449 std::vector<JobId_t> jobids;
450 std::transform(iddata.begin(),iddata.end(),
451 std::back_inserter(jobids),
452 boost::bind(&std::map<JobId_t,T>::value_type::first, boost::lambda::_1 )
453 );
454 return jobids;
455}
456
457/** Print MPQCData from received results.
458 *
459 * @param fragmentData MPQCData resulting from the jobs
460 * @param longrangeData VMGData resulting from long-range jobs
461 * @param fullsolutionData VMGData resulting from long-range of full problem
462 * @param KeySetFilename filename with keysets to associate forces correctly
463 * @param NoAtoms total number of atoms
464 * @param full_sample summed up charge from fragments on return
465 */
466bool printReceivedFullResults(
467 const std::map<JobId_t,MPQCData> &fragmentData,
468 const std::map<JobId_t,VMGData> &longrangeData,
469 const VMGData &fullsolutionData,
470 const std::string &KeySetFilename,
471 size_t NoAtoms,
472 SamplingGrid &full_sample)
473{
474 // create lookup from job nr to fragment number
475 size_t MPQCFragmentCounter = 0;
476 const std::vector<JobId_t> mpqcjobids = extractJobIds<MPQCData>(fragmentData);
477 const std::map< JobId_t, size_t > MPQCMatrixNrLookup =
478 createMatrixNrLookup(mpqcjobids, MPQCFragmentCounter);
479
480 size_t VMGFragmentCounter = 0;
481 const std::vector<JobId_t> vmgjobids = extractJobIds<VMGData>(longrangeData);
482 const std::map< JobId_t, size_t > VMGMatrixNrLookup =
483 createMatrixNrLookup(vmgjobids, VMGFragmentCounter);
484
485 // initialise keysets
486 KeySetsContainer KeySet;
487 KeySetsContainer ForceKeySet;
488 {
489 // else needs keysets without hydrogens
490 std::stringstream filename;
491 filename << FRAGMENTPREFIX << KEYSETFILE;
492 if (!KeySet.ParseKeySets(KeySetFilename, filename.str(), MPQCFragmentCounter)) return false;
493 }
494
495 {
496 // forces need keysets including hydrogens
497 std::stringstream filename;
498 filename << FRAGMENTPREFIX << FORCESFILE;
499 if (!ForceKeySet.ParseKeySets(KeySetFilename, filename.str(), MPQCFragmentCounter)) return false;
500 }
501
502 /// prepare for OrthogonalSummation
503
504 // convert KeySetContainer to IndexSetContainer
505 IndexSetContainer::ptr container(new IndexSetContainer(KeySet));
506 // create the map of all keysets
507 SubsetMap::ptr subsetmap(new SubsetMap(*container));
508
509 /// convert all MPQCData to MPQCDataMap_t
510 {
511 typedef boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type MPQCDataEnergyVector_noeigenvalues_t;
512 std::vector<MPQCDataEnergyMap_t> Result_Energy_fused(
513 OrthogonalSumUpPerLevel<MPQCDataEnergyMap_t, MPQCDataEnergyVector_t>(
514 fragmentData, MPQCMatrixNrLookup, container, subsetmap));
515 std::vector<MPQCDataGridMap_t> Result_Grid_fused(
516 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCDataGridVector_t>(
517 fragmentData, MPQCMatrixNrLookup, container, subsetmap));
518 std::vector<MPQCDataTimeMap_t> Result_Time_fused(
519 SumUpPerLevel<MPQCDataTimeMap_t, MPQCDataTimeVector_t>(
520 fragmentData, MPQCMatrixNrLookup, container, subsetmap));
521 std::vector<MPQCDataFragmentMap_t> Result_Fragment_fused(
522 OrthogonalSumUpPerLevel<MPQCDataFragmentMap_t, MPQCDataFragmentVector_t>(
523 fragmentData, MPQCMatrixNrLookup, container, subsetmap));
524
525 // force has extra converter
526 std::map<JobId_t, MPQCDataForceMap_t> MPQCData_Force_fused;
527 convertMPQCDatatoForceMap(fragmentData, ForceKeySet, MPQCData_Force_fused);
528 std::vector<MPQCDataForceMap_t> Result_Force_fused(subsetmap->getMaximumSubsetLevel());
529 AllLevelOrthogonalSummator<MPQCDataForceMap_t> forceSummer(
530 subsetmap,
531 MPQCData_Force_fused,
532 container->getContainer(),
533 MPQCMatrixNrLookup,
534 Result_Force_fused);
535 boost::mpl::for_each<MPQCDataForceVector_t>(boost::ref(forceSummer));
536
537 // obtain full grid
538 std::map<JobId_t, VMGDataMap_t> VMGData_Potential_fused;
539 convertDataTo<VMGData, VMGDataMap_t>(longrangeData, VMGData_Potential_fused);
540 OrthogonalFullSummator<VMGDataMap_t, VMGDataFused::sampled_potential> potentialSummer(
541 subsetmap,
542 VMGData_Potential_fused,
543 container->getContainer(),
544 VMGMatrixNrLookup);
545 potentialSummer(subsetmap->getMaximumSubsetLevel());
546 OrthogonalFullSummator<VMGDataMap_t, VMGDataFused::energy_potential> epotentialSummer(
547 subsetmap,
548 VMGData_Potential_fused,
549 container->getContainer(),
550 VMGMatrixNrLookup);
551 epotentialSummer(subsetmap->getMaximumSubsetLevel());
552 SamplingGrid full_sample_solution = fullsolutionData.sampled_potential;
553// LOG(0, "Remaining long-range energy from energy_potential is " << full_sample_solution.integral()-epotentialSummer.getFullContribution() << ".");
554 full_sample_solution -= potentialSummer.getFullContribution();
555 // multiply element-wise with charge distribution
556 LOG(0, "Remaining long-range potential integral is " << full_sample_solution.integral() << ".");
557 full_sample_solution *= full_sample;
558 LOG(0, "Remaining long-range energy from potential integral is " << full_sample_solution.integral() << ".");
559
560 // TODO: Extract long-range corrections to forces
561 // NOTE: potential is in atomic length units, NOT IN ANGSTROEM!
562
563 OrthogonalFullSummator<VMGDataMap_t, VMGDataFused::energy_long> elongSummer(
564 subsetmap,
565 VMGData_Potential_fused,
566 container->getContainer(),
567 VMGMatrixNrLookup);
568 elongSummer(subsetmap->getMaximumSubsetLevel());
569 double e_long = fullsolutionData.e_long;
570 e_long -= elongSummer.getFullContribution();
571 LOG(0, "Remaining long-range energy is " << e_long << ".");
572
573 // print tables (without eigenvalues, they go extra)
574 const size_t MaxLevel = subsetmap->getMaximumSubsetLevel();
575 const std::string energyresult =
576 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
577 Result_Energy_fused, MaxLevel);
578 LOG(0, "Energy table is \n" << energyresult);
579 const std::string eigenvalueresult;
580
581 LOG(0, "Eigenvalue table is \n" << eigenvalueresult);
582 const std::string forceresult =
583 writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
584 Result_Force_fused, MaxLevel);
585 LOG(0, "Force table is \n" << forceresult);
586 // we don't want to print grid to a table
587 // print times (without flops for now)
588 typedef boost::mpl::remove<
589 boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_total_flops>::type,
590 MPQCDataFused::times_gather_flops>::type
591 MPQCDataTimeVector_noflops_t;
592 const std::string timesresult =
593 writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
594 Result_Time_fused, MaxLevel);
595 LOG(0, "Times table is \n" << timesresult);
596 }
597
598 return true;
599}
600
601
602Action::state_ptr FragmentationFragmentationAutomationAction::performCall() {
603 boost::asio::io_service io_service;
604 MPQCFragmentController mpqccontroller(io_service);
605 mpqccontroller.setHost(params.host.get());
606 mpqccontroller.setPort(params.port.get());
607 mpqccontroller.setLevel(params.level.get());
608 VMGFragmentController vmgcontroller(io_service);
609 vmgcontroller.setHost(params.host.get());
610 vmgcontroller.setPort(params.port.get());
611 VMGDebugGridFragmentController debugcontroller(io_service);
612 debugcontroller.setHost(params.host.get());
613 debugcontroller.setPort(params.port.get());
614
615 // TODO: Have io_service run in second thread and merge with current again eventually
616
617 // Phase One: obtain ids
618 std::vector< boost::filesystem::path > jobfiles = params.jobfiles.get();
619 mpqccontroller.requestIds(jobfiles.size());
620
621 // Phase Two: create and add MPQCJobs
622 if (!mpqccontroller.addJobsFromFiles(params.executable.get().string(), jobfiles))
623 return Action::failure;
624
625 // Phase Three: calculate result
626 mpqccontroller.waitforResults(jobfiles.size());
627 std::map<JobId_t, MPQCData> fragmentData;
628 mpqccontroller.getResults(fragmentData);
629
630#ifdef HAVE_VMG
631 if (params.DoLongrange.get()) {
632 ASSERT( World::getInstance().getAllAtoms().size() != 0,
633 "FragmentationFragmentationAutomationAction::performCall() - please load the full molecule into the World before.");
634
635 // obtain combined charge density
636 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
637 SamplingGrid full_sample;
638 Fragment full_fragment;
639 sumUpChargeDensity(
640 fragmentData,
641 params.path.get(),
642 full_sample,
643 full_fragment);
644
645 // Phase Four: obtain more ids
646 vmgcontroller.requestIds(fragmentData.size()+1);
647
648 // Phase Five: create VMGJobs
649 const size_t near_field_cells = params.near_field_cells.get();
650 if (!vmgcontroller.createLongRangeJobs(fragmentData, full_sample, full_fragment, near_field_cells))
651 return Action::failure;
652
653 // Phase Six: calculate result
654 vmgcontroller.waitforResults(fragmentData.size()+1);
655 std::map<JobId_t, VMGData> longrangeData;
656 vmgcontroller.getResults(longrangeData);
657 ASSERT( fragmentData.size()+1 == longrangeData.size(),
658 "FragmentationFragmentationAutomationAction::performCall() - number of MPQCresults+1 "
659 +toString(fragmentData.size()+1)+" and VMGresults "+toString(longrangeData.size())+" don't match.");
660
661 // remove full solution from map (must be highest id), has to be treated extra
662 VMGData fullsolutionData = (--longrangeData.end())->second;
663 longrangeData.erase(--longrangeData.end());
664
665 // Final phase: print result
666 {
667 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
668 printReceivedFullResults(
669 fragmentData,
670 longrangeData,
671 fullsolutionData,
672 params.path.get(),
673 getNoAtomsFromAdjacencyFile(params.path.get()),
674 full_sample);
675
676 // create debug jobs to print the summed-up potential to vtk files
677 debugcontroller.requestIds(1);
678 if (!debugcontroller.createDebugJobs(std::vector<SamplingGrid>(1,full_sample)))
679 return Action::failure;
680 debugcontroller.waitforResults(1);
681 std::map<JobId_t, std::string> debugData;
682 debugcontroller.getResults(debugData);
683 }
684 }
685#else
686 // Final phase: print result
687 {
688 LOG(1, "INFO: Parsing fragment files from " << params.path.get() << ".");
689 printReceivedMPQCResults(
690 fragmentData,
691 params.path.get(),
692 getNoAtomsFromAdjacencyFile(params.path.get()),
693 full_sample);
694 }
695#endif
696 size_t Exitflag = vmgcontroller.getExitflag() + mpqccontroller.getExitflag();
697
698 return (Exitflag == 0) ? Action::success : Action::failure;
699}
700
701Action::state_ptr FragmentationFragmentationAutomationAction::performUndo(Action::state_ptr _state) {
702 return Action::success;
703}
704
705Action::state_ptr FragmentationFragmentationAutomationAction::performRedo(Action::state_ptr _state){
706 return Action::success;
707}
708
709bool FragmentationFragmentationAutomationAction::canUndo() {
710 return false;
711}
712
713bool FragmentationFragmentationAutomationAction::shouldUndo() {
714 return false;
715}
716/** =========== end of function ====================== */
Note: See TracBrowser for help on using the repository browser.