source: src/Actions/FragmentationAction/AnalyseFragmentationResultsAction.cpp@ ce70d25

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator 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_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions 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 GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since ce70d25 was ce70d25, checked in by Frederik Heber <heber@…>, 8 years ago

Added some asserts and checks in context of SaturatedFragment and appendToHomologies().

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