source: src/Actions/FragmentationAction/AnalyseFragmentationResultsAction.cpp@ 5cf341

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 5cf341 was ff347f, checked in by Frederik Heber <heber@…>, 9 years ago

Added gathering of full and longrange forces into extra file.

  • added new structs to VMGDataFusedMap for summation.
  • tempcommit: we do not have the full index set available, hence it just accumulated all indices from all fragments into a sorted set and use this in lieu of the full index set. We need to check how the full solution is constructed and how indices to the particles and their force vectors can be assigned.
  • extended printFullSolution() by another table with short- and long-range forces.
  • Property mode set to 100644
File size: 27.7 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * AnalyseFragmentationResultsAction.cpp
26 *
27 * Created on: Mar 8, 2013
28 * Author: heber
29 */
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36// include headers that implement a archive in simple text format
37// and before MemDebug due to placement new
38#include <boost/archive/text_oarchive.hpp>
39#include <boost/archive/text_iarchive.hpp>
40
41#include "CodePatterns/MemDebug.hpp"
42
43#include <boost/foreach.hpp>
44#include <boost/lambda/lambda.hpp>
45#include <boost/mpl/remove.hpp>
46
47#include <algorithm>
48#include <fstream>
49#include <iostream>
50//#include <numeric>
51#include <string>
52#include <vector>
53
54#include "CodePatterns/Assert.hpp"
55#include "CodePatterns/Log.hpp"
56
57#ifdef HAVE_JOBMARKET
58#include "JobMarket/types.hpp"
59#else
60typedef size_t JobId_t;
61#endif
62
63#include "Descriptors/AtomIdDescriptor.hpp"
64#include "Fragmentation/Summation/Containers/FragmentationChargeDensity.hpp"
65#include "Fragmentation/Summation/Containers/FragmentationResultContainer.hpp"
66#include "Fragmentation/Summation/Containers/FragmentationShortRangeResults.hpp"
67#include "Fragmentation/Summation/Containers/MPQCData.hpp"
68#include "Fragmentation/Summation/Containers/MPQCData_printKeyNames.hpp"
69#include "Fragmentation/Homology/HomologyContainer.hpp"
70#include "Fragmentation/Homology/HomologyGraph.hpp"
71#include "Fragmentation/KeySetsContainer.hpp"
72#include "Fragmentation/Summation/SetValues/Eigenvalues.hpp"
73#include "Fragmentation/Summation/SetValues/Fragment.hpp"
74#include "Fragmentation/Summation/SetValues/FragmentForces.hpp"
75#include "Fragmentation/Summation/SetValues/Histogram.hpp"
76#include "Fragmentation/Summation/SetValues/IndexedVectors.hpp"
77#include "Fragmentation/Summation/IndexSetContainer.hpp"
78#include "Fragmentation/Summation/writeIndexedTable.hpp"
79#include "Fragmentation/Summation/writeTable.hpp"
80#if defined(HAVE_JOBMARKET) && defined(HAVE_VMG)
81#include "Fragmentation/Summation/Containers/FragmentationLongRangeResults.hpp"
82#include "Fragmentation/Summation/Containers/VMGData.hpp"
83#include "Fragmentation/Summation/Containers/VMGDataFused.hpp"
84#include "Fragmentation/Summation/Containers/VMGDataMap.hpp"
85#include "Fragmentation/Summation/Containers/VMGData_printKeyNames.hpp"
86#endif
87#include "Helpers/defs.hpp"
88#include "World.hpp"
89
90#include "Actions/FragmentationAction/AnalyseFragmentationResultsAction.hpp"
91
92using namespace MoleCuilder;
93
94// and construct the stuff
95#include "AnalyseFragmentationResultsAction.def"
96#include "Action_impl_pre.hpp"
97/** =========== define the function ====================== */
98
99void writeToFile(const std::string &filename, const std::string contents)
100{
101 std::ofstream tablefile(filename.c_str());
102 tablefile << contents;
103 tablefile.close();
104}
105
106/** Print cycle correction from received results.
107 *
108 * @param results summed up results container
109 */
110void printReceivedCycleResults(
111 const FragmentationShortRangeResults &results)
112{
113 typedef boost::mpl::remove<
114 boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type,
115 MPQCDataFused::energy_eigenhistogram>::type
116 MPQCDataEnergyVector_noeigenvalues_t;
117 const std::string energyresult =
118 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
119 results.Result_Energy_fused, results.getMaxLevel());
120 LOG(2, "DEBUG: Energy table is \n" << energyresult);
121 std::string filename;
122 filename += FRAGMENTPREFIX + std::string("_CycleEnergy.dat");
123 writeToFile(filename, energyresult);
124}
125
126/** Print (short range) energy, forces, and timings from received results per index set.
127 *
128 * @param results summed up results container
129 */
130void printReceivedShortResultsPerIndex(
131 const FragmentationShortRangeResults &results)
132{
133 // print tables per keyset(without eigenvalues, they go extra)
134 typedef boost::mpl::remove<
135 boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type,
136 MPQCDataFused::energy_eigenhistogram>::type
137 MPQCDataEnergyVector_noeigenvalues_t;
138 const std::string energyresult =
139 writeIndexedTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
140 results.Result_perIndexSet_Energy, results.getMaxLevel());
141 LOG(2, "DEBUG: Indexed Energy table is \n" << energyresult);
142 std::string filename;
143 filename += FRAGMENTPREFIX + std::string("_IndexedEnergy.dat");
144 writeToFile(filename, energyresult);
145}
146
147/** Print (short range) energy, forces, and timings from received results.
148 *
149 * @param results summed up results container
150 */
151void printReceivedShortResults(
152 const FragmentationShortRangeResults &results)
153{
154 // print tables (without eigenvalues, they go extra)
155 {
156 typedef boost::mpl::remove<
157 boost::mpl::remove<MPQCDataEnergyVector_t, MPQCDataFused::energy_eigenvalues>::type,
158 MPQCDataFused::energy_eigenhistogram>::type
159 MPQCDataEnergyVector_noeigenvalues_t;
160 const std::string energyresult =
161 writeTable<MPQCDataEnergyMap_t, MPQCDataEnergyVector_noeigenvalues_t >()(
162 results.Result_Energy_fused, results.getMaxLevel());
163 LOG(2, "DEBUG: Energy table is \n" << energyresult);
164 std::string filename;
165 filename += FRAGMENTPREFIX + std::string("_Energy.dat");
166 writeToFile(filename, energyresult);
167 }
168
169 {
170 typedef boost::mpl::list<
171 MPQCDataFused::energy_eigenvalues
172 > MPQCDataEigenvalues_t;
173 const std::string eigenvalueresult =
174 writeTable<MPQCDataEnergyMap_t, MPQCDataEigenvalues_t >()(
175 results.Result_Energy_fused, results.getMaxLevel());
176 LOG(2, "DEBUG: Eigenvalue table is \n" << eigenvalueresult);
177 std::string filename;
178 filename += FRAGMENTPREFIX + std::string("_Eigenvalues.dat");
179 writeToFile(filename, eigenvalueresult);
180 }
181
182 {
183 typedef boost::mpl::list<
184 MPQCDataFused::energy_eigenhistogram
185 > MPQCDataEigenhistogram_t;
186 const std::string eigenhistogramresult =
187 writeTable<MPQCDataEnergyMap_t, MPQCDataEigenhistogram_t >()(
188 results.Result_Energy_fused, results.getMaxLevel());
189 LOG(2, "DEBUG: Eigenhistogram table is \n" << eigenhistogramresult);
190 std::string filename;
191 filename += FRAGMENTPREFIX + std::string("_Eigenhistogram.dat");
192 writeToFile(filename, eigenhistogramresult);
193 }
194
195 {
196 typedef boost::mpl::list<
197 MPQCDataFused::energy_eigenvalues
198 > MPQCDataEigenvalues_t;
199 const std::string eigenvalueresult =
200 writeTable<MPQCDataEnergyMap_t, MPQCDataEigenvalues_t >()(
201 results.Result_Energy_fused, results.getMaxLevel());
202 LOG(2, "DEBUG: Eigenvalue table is \n" << eigenvalueresult);
203 std::string filename;
204 filename += FRAGMENTPREFIX + std::string("_Eigenvalues.dat");
205 writeToFile(filename, eigenvalueresult);
206 }
207
208 {
209 const std::string forceresult =
210 writeTable<MPQCDataForceMap_t, MPQCDataForceVector_t>()(
211 results.Result_Force_fused, results.getMaxLevel());
212 LOG(2, "DEBUG: Force table is \n" << forceresult);
213 std::string filename;
214 filename += FRAGMENTPREFIX + std::string("_Forces.dat");
215 writeToFile(filename, forceresult);
216 }
217 // we don't want to print grid to a table
218 {
219 // print times (without flops for now)
220 typedef boost::mpl::remove<
221 boost::mpl::remove<MPQCDataTimeVector_t, MPQCDataFused::times_total_flops>::type,
222 MPQCDataFused::times_gather_flops>::type
223 MPQCDataTimeVector_noflops_t;
224 const std::string timesresult =
225 writeTable<MPQCDataTimeMap_t, MPQCDataTimeVector_noflops_t >()(
226 results.Result_Time_fused, results.getMaxLevel());
227 LOG(2, "DEBUG: Times table is \n" << timesresult);
228 std::string filename;
229 filename += FRAGMENTPREFIX + std::string("_Times.dat");
230 writeToFile(filename, timesresult);
231 }
232}
233
234
235#if defined(HAVE_JOBMARKET) && defined(HAVE_VMG)
236/** Print long range energy from received results.
237 *
238 * @param results summed up results container
239 */
240void printReceivedFullResults(
241 const FragmentationLongRangeResults &results)
242{
243 // print tables per keyset(without grids, they go extra)
244
245 {
246 const std::string gridresult =
247 writeTable<VMGDataMap_t, VMGDataVector_t >()(
248 results.Result_LongRange_fused, results.getMaxLevel(), 1);
249 LOG(2, "DEBUG: VMG table is \n" << gridresult);
250 std::string filename;
251 filename += FRAGMENTPREFIX + std::string("_VMGEnergy.dat");
252 writeToFile(filename, gridresult);
253 }
254
255 if (results.hasLongRangeForces()) {
256 const std::string forceresult =
257 writeTable<VMGDataForceMap_t, VMGDataForceVector_t>()(
258 results.Result_ForceLongRange_fused, results.getMaxLevel());
259 LOG(2, "DEBUG: Force table is \n" << forceresult);
260 std::string filename;
261 filename += FRAGMENTPREFIX + std::string("_VMGForces.dat");
262 writeToFile(filename, forceresult);
263 }
264
265 {
266 const std::string gridresult =
267 writeTable<VMGDataLongRangeMap_t, VMGDataLongRangeVector_t >()(
268 results.Result_LongRangeIntegrated_fused, results.getMaxLevel(), 1);
269 LOG(2, "DEBUG: LongRange table is \n" << gridresult);
270 std::string filename;
271 filename += FRAGMENTPREFIX + std::string("_LongRangeEnergy.dat");
272 writeToFile(filename, gridresult);
273 }
274
275 if (results.hasLongRangeForces()) {
276 const std::string forceresult =
277 writeTable<VMGDataLongRangeForceMap_t, VMGDataLongRangeForceVector_t >()(
278 results.Result_ForcesLongRangeIntegrated_fused, results.getMaxLevel(), 1);
279 LOG(2, "DEBUG: ForcesLongRange table is \n" << forceresult);
280 std::string filename;
281 filename += FRAGMENTPREFIX + std::string("_LongRangeForces.dat");
282 writeToFile(filename, forceresult);
283 }
284}
285#endif
286
287void appendToHomologies(
288 const FragmentationShortRangeResults &shortrangeresults,
289#if defined(HAVE_JOBMARKET) && defined(HAVE_VMG)
290 const FragmentationLongRangeResults &longrangeresults,
291#endif
292 const bool storeGrids
293 )
294{
295 /// read homology container (if present)
296 HomologyContainer &homology_container = World::getInstance().getHomologies();
297
298 /// append all fragments to a HomologyContainer
299 HomologyContainer::container_t values;
300
301 // convert KeySetContainer to IndexSetContainer
302 IndexSetContainer::ptr ForceContainer(new IndexSetContainer(shortrangeresults.getForceKeySet()));
303 const IndexSetContainer::Container_t &Indices = shortrangeresults.getContainer();
304 const IndexSetContainer::Container_t &ForceIndices = ForceContainer->getContainer();
305 IndexSetContainer::Container_t::const_iterator iter = Indices.begin();
306 IndexSetContainer::Container_t::const_iterator forceiter = ForceIndices.begin();
307
308 /// go through all fragments
309 for (;iter != Indices.end(); ++iter, ++forceiter) // go through each IndexSet
310 {
311 /// create new graph entry in HomologyContainer which is (key,value) type
312 LOG(1, "INFO: Creating new graph with " << **forceiter << ".");
313 HomologyGraph graph(**forceiter);
314 LOG(2, "DEBUG: Created graph " << graph << ".");
315 const IndexSet::ptr &index = *iter;
316
317 /// we fill the value structure
318 HomologyContainer::value_t value;
319 value.containsGrids = storeGrids;
320 // obtain fragment
321 std::map<IndexSet::ptr, std::pair< MPQCDataFragmentMap_t, MPQCDataFragmentMap_t> >::const_iterator fragmentiter
322 = shortrangeresults.Result_perIndexSet_Fragment.find(index);
323 ASSERT( fragmentiter != shortrangeresults.Result_perIndexSet_Fragment.end(),
324 "appendToHomologyFile() - cannot find index "+toString(*index)
325 +" in FragmentResults.");
326 value.fragment = boost::fusion::at_key<MPQCDataFused::fragment>(fragmentiter->second.first);
327
328 // obtain energy
329 std::map<IndexSet::ptr, std::pair< MPQCDataEnergyMap_t, MPQCDataEnergyMap_t> >::const_iterator energyiter
330 = shortrangeresults.Result_perIndexSet_Energy.find(index);
331 ASSERT( energyiter != shortrangeresults.Result_perIndexSet_Energy.end(),
332 "appendToHomologyFile() - cannot find index "+toString(*index)
333 +" in FragmentResults.");
334 value.energy = boost::fusion::at_key<MPQCDataFused::energy_total>(energyiter->second.second); // contributions
335
336 // only store sampled grids if desired
337 if (storeGrids) {
338#if defined(HAVE_JOBMARKET) && defined(HAVE_VMG)
339 // obtain charge distribution
340 std::map<IndexSet::ptr, std::pair< MPQCDataGridMap_t, MPQCDataGridMap_t> >::const_iterator chargeiter
341 = longrangeresults.Result_perIndexSet_Grid.find(index);
342 ASSERT( chargeiter != longrangeresults.Result_perIndexSet_Grid.end(),
343 "appendToHomologyFile() - cannot find index "+toString(*index)
344 +" in FragmentResults.");
345 value.charge_distribution = boost::fusion::at_key<MPQCDataFused::sampled_grid>(chargeiter->second.second); // contributions
346
347 // obtain potential distribution
348 std::map<IndexSet::ptr, std::pair< VMGDataGridMap_t, VMGDataGridMap_t> >::const_iterator potentialiter
349 = longrangeresults.Result_perIndexSet_LongRange_Grid.find(index);
350 ASSERT( potentialiter != longrangeresults.Result_perIndexSet_LongRange_Grid.end(),
351 "appendToHomologyFile() - cannot find index "+toString(*index)
352 +" in FragmentResults.");
353 // add e+n potentials
354 value.potential_distribution =
355 boost::fusion::at_key<VMGDataFused::both_sampled_potential>(potentialiter->second.second); // contributions
356// // and re-average to zero (integral is times volume_element which we don't need here)
357// const double sum =
358// std::accumulate(
359// value.potential_distribution.sampled_grid.begin(),
360// value.potential_distribution.sampled_grid.end(),
361// 0.);
362// const double offset = sum/(double)value.potential_distribution.sampled_grid.size();
363// for (SamplingGrid::sampledvalues_t::iterator iter = value.potential_distribution.sampled_grid.begin();
364// iter != value.potential_distribution.sampled_grid.end();
365// ++iter)
366// *iter -= offset;
367#else
368 ELOG(1, "Long-range information in homology desired but long-range analysis capability not compiled in.");
369#endif
370 }
371 values.insert( std::make_pair( graph, value) );
372 }
373 homology_container.insert(values);
374
375 if (DoLog(2)) {
376 LOG(2, "DEBUG: Listing all present atomic ids ...");
377 std::stringstream output;
378 for (World::AtomIterator iter = World::getInstance().getAtomIter();
379 iter != World::getInstance().atomEnd(); ++iter)
380 output << (*iter)->getId() << " ";
381 LOG(2, "DEBUG: { " << output.str() << "} .");
382 }
383
384 // for debugging: print container
385 if (DoLog(2)) {
386 LOG(2, "DEBUG: Listing all present homologies ...");
387 for (HomologyContainer::container_t::const_iterator iter =
388 homology_container.begin(); iter != homology_container.end(); ++iter) {
389 std::stringstream output;
390 output << "DEBUG: graph " << iter->first
391 << " has Fragment " << iter->second.fragment
392 << ", associated energy " << iter->second.energy;
393 if (iter->second.containsGrids)
394#if defined(HAVE_JOBMARKET) && defined(HAVE_VMG)
395 output << ", and sampled grid integral " << iter->second.charge_distribution.integral();
396#else
397 output << ", and there are sampled grids but capability not compiled in";
398#endif
399 output << ".";
400 LOG(2, output.str());
401 }
402 }
403}
404
405// this it taken from
406// http://stackoverflow.com/questions/2291802/is-there-a-c-iterator-that-can-iterate-over-a-file-line-by-line
407namespace detail
408{
409 /** Extend the string class by a friend function.
410 *
411 */
412 class Line : public std::string
413 {
414 friend std::istream & operator>>(std::istream & is, Line & line)
415 {
416 return std::getline(is, line);
417 }
418 };
419}
420
421/** Parse the given stream line-by-line, passing each to \a dest.
422 *
423 * \param is stream to parse line-wise
424 * \param dest output iterator
425 */
426template<class OutIt>
427void read_lines(std::istream& is, OutIt dest)
428{
429 typedef std::istream_iterator<detail::Line> InIt;
430 std::copy(InIt(is), InIt(), dest);
431}
432
433
434/** Determines the largest cycle in the container and returns its size.
435 *
436 * \param cycles set of cycles
437 * \return size if largest cycle
438 */
439size_t getMaxCycleSize(const KeySetsContainer &cycles)
440{
441 // gather cycle sizes
442 std::vector<size_t> cyclesizes(cycles.KeySets.size());
443 std::transform(
444 cycles.KeySets.begin(), cycles.KeySets.end(),
445 cyclesizes.begin(),
446 boost::bind(&KeySetsContainer::IntVector::size, boost::lambda::_1)
447 );
448 // get maximum
449 std::vector<size_t>::const_iterator maximum_size =
450 std::max_element(cyclesizes.begin(), cyclesizes.end());
451 if (maximum_size != cyclesizes.end())
452 return *maximum_size;
453 else
454 return 0;
455}
456
457void calculateCycleFullContribution(
458 const std::map<JobId_t, MPQCData> &shortrangedata,
459 const KeySetsContainer &keysets,
460 const KeySetsContainer &forcekeysets,
461 const KeySetsContainer &cycles,
462 const FragmentationShortRangeResults &shortrangeresults)
463{
464 // copy the shortrangeresults such that private MaxLevel is set in
465 // FragmentationShortRangeResults
466 FragmentationShortRangeResults cycleresults(shortrangeresults);
467 // get largest size
468 const size_t maximum_size = getMaxCycleSize(cycles);
469
470 /// The idea here is that (Orthogonal)Summation will place a result
471 /// consisting of level 1,2, and 3 fragment and a level 6 ring nonetheless
472 /// in level 6. If we want to have this result already at level 3, we
473 /// have to specifically inhibit all fragments from later levels but the
474 /// cycles and then pick the result from the last level and placing it at
475 /// the desired one
476
477 // loop from level 1 to max ring size and gather contributions
478 for (size_t level = 1; level <= maximum_size; ++level) {
479 // create ValueMask for this level by stepping through each keyset and checking size
480 std::vector<bool> localValueMask(shortrangedata.size(), false);
481 size_t index=0;
482 // TODO: if only KeySetsContainer was usable as a compliant STL container, might be able to use set_difference or alike.
483 KeySetsContainer::ArrayOfIntVectors::const_iterator keysetsiter = keysets.KeySets.begin();
484 KeySetsContainer::ArrayOfIntVectors::const_iterator cyclesiter = cycles.KeySets.begin();
485 for (; (keysetsiter != keysets.KeySets.end()) && (cyclesiter != cycles.KeySets.end());) {
486 if (cyclesiter->size() > keysetsiter->size()) {
487 // add if not greater than level in size
488 if ((*keysetsiter).size() <= level)
489 localValueMask[index] = true;
490 ++keysetsiter;
491 ++index;
492 } else if (cyclesiter->size() < keysetsiter->size()) {
493 ++cyclesiter;
494 } else { // both sets have same size
495 if (*cyclesiter > *keysetsiter) {
496 // add if not greater than level in size
497 if ((*keysetsiter).size() <= level)
498 localValueMask[index] = true;
499 ++keysetsiter;
500 ++index;
501 } else if (*cyclesiter < *keysetsiter) {
502 ++cyclesiter;
503 } else {
504 // also always add all cycles
505 localValueMask[index] = true;
506 ++cyclesiter;
507 ++keysetsiter;
508 ++index;
509 }
510 }
511 }
512 // activate rest if desired by level
513 for (; keysetsiter != keysets.KeySets.end(); ++keysetsiter) {
514 if ((*keysetsiter).size() <= level)
515 localValueMask[index] = true;
516 ++index;
517 }
518 LOG(2, "DEBUG: ValueMask for cycle correction at level " << level << " is "
519 << localValueMask << ".");
520 // create FragmentationShortRangeResults
521 FragmentationShortRangeResults localresults(shortrangedata, keysets, forcekeysets, localValueMask);
522 // and perform summation
523 localresults(shortrangedata);
524 // finally, extract the corrections from last level
525 cycleresults.Result_Energy_fused[level-1] =
526 localresults.Result_Energy_fused.back();
527 cycleresults.Result_Time_fused[level-1] =
528 localresults.Result_Time_fused.back();
529 cycleresults.Result_Force_fused[level-1] =
530 localresults.Result_Force_fused.back();
531 }
532 printReceivedCycleResults(cycleresults);
533}
534
535ActionState::ptr FragmentationAnalyseFragmentationResultsAction::performCall() {
536
537 /// if file is given, parse from file into ResultsContainer
538 FragmentationResultContainer& container = FragmentationResultContainer::getInstance();
539 if (!params.resultsfile.get().empty()) {
540 boost::filesystem::path resultsfile = params.resultsfile.get();
541 if (boost::filesystem::exists(resultsfile)) {
542 LOG(1, "INFO: Parsing results from " << resultsfile.string() << ".");
543 std::ifstream returnstream(resultsfile.string().c_str());
544 if (returnstream.good()) {
545 boost::archive::text_iarchive ia(returnstream);
546 ia >> container;
547 }
548 } else {
549 ELOG(1, "Given file" << resultsfile.string() << " does not exist.");
550 }
551 }
552
553 /// get data and keysets from ResultsContainer
554 const std::map<JobId_t, MPQCData> &shortrangedata = container.getShortRangeResults();
555 const KeySetsContainer &keysets = container.getKeySets();
556 const KeySetsContainer &forcekeysets = container.getForceKeySets();
557 const bool DoLongrange = container.areFullRangeResultsPresent();
558 const bool IsAngstroem = true;
559
560 if (keysets.KeySets.empty()) {
561 STATUS("There are no results in the container.");
562 return Action::failure;
563 }
564
565 /// calculate normal contributions with (if present) cycles coming at their
566 /// respective bond order.
567 std::vector<bool> ValueMask(shortrangedata.size(), true);
568 FragmentationShortRangeResults shortrangeresults(shortrangedata, keysets, forcekeysets, ValueMask);
569 shortrangeresults(shortrangedata);
570 printReceivedShortResults(shortrangeresults);
571 printReceivedShortResultsPerIndex(shortrangeresults);
572 // add summed results to container
573 container.addShortRangeSummedResults(shortrangeresults.getSummedShortRangeResults());
574
575 /// now do we need to calculate the cycle contribution
576 // check whether there are cycles in container or else in file
577 KeySetsContainer cycles = container.getCycles();
578 if (cycles.KeySets.empty()) {
579 // parse from file if cycles is empty
580 boost::filesystem::path filename(
581 params.prefix.get() + std::string(CYCLEKEYSETFILE));
582 if (boost::filesystem::exists(filename)) {
583 LOG(1, "INFO: Parsing cycles file " << filename.string() << ".");
584 // parse file line by line
585 std::ifstream File;
586 File.open(filename.string().c_str());
587 typedef std::istream_iterator<detail::Line> InIt;
588 for (InIt iter = InIt(File); iter != InIt(); ++iter) {
589 KeySetsContainer::IntVector cycle;
590 std::stringstream line(*iter);
591 while (line.good()) {
592 int id;
593 line >> id >> ws;
594 cycle.push_back(id);
595 }
596 if (!cycle.empty()) {
597 LOG(2, "DEBUG: Adding cycle " << cycle << ".");
598 cycles.insert( cycle, cycle.size());
599 }
600 }
601 File.close();
602 } else {
603 LOG(1, "INFO: Cycles file not found at " << filename.string() << ".");
604 }
605 }
606
607 // calculate energy if cycles are calculated fully at each level already
608 if (!cycles.KeySets.empty()) {
609 calculateCycleFullContribution(
610 shortrangedata,
611 keysets,
612 forcekeysets,
613 cycles,
614 shortrangeresults);
615 }
616
617 // adding obtained forces
618 if ( const_cast<const World &>(World::getInstance()).getAllAtoms().size() != 0) {
619 const IndexedVectors::indexedvectors_t forces =
620 boost::fusion::at_key<MPQCDataFused::forces>(
621 shortrangeresults.Result_Force_fused.back()
622 ).getVectors();
623 ;
624 for(IndexedVectors::indexedvectors_t::const_iterator iter = forces.begin();
625 iter != forces.end(); ++iter) {
626 const IndexedVectors::index_t &index = iter->first;
627 const IndexedVectors::vector_t &forcevector = iter->second;
628 ASSERT( forcevector.size() == NDIM,
629 "printReceivedShortResults() - obtained force vector has incorrect dimension.");
630 // note that mpqc calculates a gradient, hence force pointing into opposite direction
631 // we have to mind different units here: MPQC has a_o, while we may have angstroem
632 Vector ForceVector(-forcevector[0], -forcevector[1], -forcevector[2]);
633 if (IsAngstroem)
634 for (size_t i=0;i<NDIM;++i)
635 ForceVector[i] *= AtomicLengthToAngstroem;
636 atom *_atom = World::getInstance().getAtom(AtomById(index));
637 if(_atom != NULL)
638 _atom->setAtomicForce(_atom->getAtomicForce() + ForceVector);
639 else
640 ELOG(2, "Could not find atom to id " << index << ".");
641 }
642 } else {
643 LOG(1, "INFO: Full molecule not loaded, hence will not add forces to atoms.");
644 }
645
646#if defined(HAVE_JOBMARKET) && defined(HAVE_VMG)
647 if (DoLongrange) {
648 if ( const_cast<const World &>(World::getInstance()).getAllAtoms().size() == 0) {
649 STATUS("Please load the full molecule into std::map<JobId_t, VMGData> longrangeData the world before starting this action.");
650 return Action::failure;
651 }
652
653 FragmentationChargeDensity summedChargeDensity(shortrangedata,keysets);
654 const std::vector<SamplingGrid> full_sample = summedChargeDensity.getFullSampledGrid();
655
656 std::map<JobId_t, VMGData> longrangeData = container.getLongRangeResults();
657 // remove full solution corresponding to full_sample from map (must be highest ids), has to be treated extra
658 std::map<JobId_t, VMGData>::iterator iter = longrangeData.end();
659 std::advance(iter, -full_sample.size());
660 std::map<JobId_t, VMGData>::iterator remove_iter = iter;
661 std::vector<VMGData> fullsolutionData;
662 for (; iter != longrangeData.end(); ++iter)
663 fullsolutionData.push_back(iter->second);
664 if (longrangeData.size() > 1) // when there's just a single fragment, it corresponds to full solution
665 longrangeData.erase(remove_iter, longrangeData.end());
666
667 // Final phase: sum up and print result
668 FragmentationLongRangeResults longrangeresults(
669 shortrangedata,longrangeData,keysets, forcekeysets);
670 longrangeresults(
671 shortrangedata,
672 longrangeData,
673 fullsolutionData,
674 full_sample);
675 printReceivedFullResults(longrangeresults);
676
677 // append all keysets to homology file
678 appendToHomologies(shortrangeresults, longrangeresults, params.DoStoreGrids.get());
679 } else {
680 // append all keysets to homology file with short-range info only (without grids)
681 std::map<JobId_t, VMGData> longrangeData;
682 FragmentationLongRangeResults longrangeresults(
683 shortrangedata,longrangeData,keysets, forcekeysets);
684 appendToHomologies(shortrangeresults, longrangeresults, false);
685 }
686#else
687 if (DoLongrange) {
688 ELOG(2, "File contains long-range information but long-range analysis capability not compiled in.");
689 }
690
691 // append all keysets to homology file with short-range info only (without grids)
692 appendToHomologies(shortrangeresults, false);
693#endif
694
695 // we no longer clear the container
696// container.clear();
697
698 return Action::success;
699}
700
701ActionState::ptr FragmentationAnalyseFragmentationResultsAction::performUndo(ActionState::ptr _state) {
702 return Action::success;
703}
704
705ActionState::ptr FragmentationAnalyseFragmentationResultsAction::performRedo(ActionState::ptr _state){
706 return Action::success;
707}
708
709bool FragmentationAnalyseFragmentationResultsAction::canUndo() {
710 return false;
711}
712
713bool FragmentationAnalyseFragmentationResultsAction::shouldUndo() {
714 return false;
715}
716/** =========== end of function ====================== */
Note: See TracBrowser for help on using the repository browser.