source: src/Fragmentation/Summation/Containers/FragmentationLongRangeResults.cpp@ 3b6956

Last change on this file since 3b6956 was ff347f, checked in by Frederik Heber <heber@…>, 10 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: 12.8 KB
RevLine 
[376a3b]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
[5aaa43]5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
[376a3b]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/*
[0cd8cf]25 * FragmentationLongRangeResults.cpp
[376a3b]26 *
27 * Created on: Aug 31, 2012
28 * Author: heber
29 */
30
31
32// include config.h
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36
37#include "CodePatterns/MemDebug.hpp"
38
[0cd8cf]39#include "FragmentationLongRangeResults.hpp"
[376a3b]40
41#include <boost/mpl/for_each.hpp>
42#include <boost/mpl/remove.hpp>
43#include <sstream>
44
45#include "CodePatterns/Assert.hpp"
46#include "CodePatterns/Log.hpp"
47
48#include "Fragmentation/KeySetsContainer.hpp"
[fbf143]49#include "Fragmentation/parseKeySetFile.hpp"
50#include "Fragmentation/Summation/Converter/DataConverter.hpp"
51#include "Fragmentation/Summation/Containers/createMatrixNrLookup.hpp"
52#include "Fragmentation/Summation/Containers/extractJobIds.hpp"
[376a3b]53#include "Fragmentation/Summation/AllLevelOrthogonalSummator.hpp"
54#include "Fragmentation/Summation/IndexSetContainer.hpp"
55#include "Fragmentation/Summation/OrthogonalSumUpPerLevel.hpp"
56#include "Fragmentation/Summation/SubsetMap.hpp"
57#include "Fragmentation/Summation/SumUpPerLevel.hpp"
58
59#include "Helpers/defs.hpp"
60
[0cd8cf]61FragmentationLongRangeResults::FragmentationLongRangeResults(
[376a3b]62 const std::map<JobId_t,MPQCData> &fragmentData,
[5a5196]63 std::map<JobId_t,VMGData> &longrangeData,
[bae7bc]64 const KeySetsContainer& _KeySet,
65 const KeySetsContainer& _ForceKeySet) :
66 KeySet(_KeySet),
[94db13]67 ForceKeySet(_ForceKeySet),
68 hasForces((!longrangeData.empty()) && (longrangeData.begin()->second.hasForces))
[5281ff]69{
70 initLookups(fragmentData, longrangeData);
71
72 // convert KeySetContainer to IndexSetContainer
73 container.reset(new IndexSetContainer(KeySet));
74 // create the map of all keysets
75 subsetmap.reset(new SubsetMap(*container));
76}
77
78void FragmentationLongRangeResults::initLookups(
79 const std::map<JobId_t,MPQCData> &fragmentData,
80 std::map<JobId_t,VMGData> &longrangeData
81 )
[376a3b]82{
83 // create lookup from job nr to fragment number
[e0ae58d]84 {
85 size_t MPQCFragmentCounter = 0;
86 std::vector<bool> ValueMask(fragmentData.size(), true);
87 const std::vector<JobId_t> mpqcjobids = extractJobIds<MPQCData>(fragmentData);
88 MPQCMatrixNrLookup =
89 createMatrixNrLookup(mpqcjobids, MPQCFragmentCounter, ValueMask);
90 }
[376a3b]91
[e0ae58d]92 {
93 size_t VMGFragmentCounter = 0;
94 std::vector<bool> ValueMask(longrangeData.size(), true);
95 const std::vector<JobId_t> vmgjobids = extractJobIds<VMGData>(longrangeData);
96 VMGMatrixNrLookup =
97 createMatrixNrLookup(vmgjobids, VMGFragmentCounter, ValueMask);
98 }
[2dd305]99}
[376a3b]100
[0cd8cf]101void FragmentationLongRangeResults::operator()(
[2dd305]102 const std::map<JobId_t,MPQCData> &fragmentData,
103 std::map<JobId_t,VMGData> &longrangeData,
104 const std::vector<VMGData> &fullsolutionData,
105 const std::vector<SamplingGrid> &full_sample)
106{
[19c50e]107 MaxLevel = subsetmap->getMaximumSetLevel();
108 LOG(1, "INFO: Summing up results till level " << MaxLevel << ".");
[376a3b]109 /// convert all MPQCData to MPQCDataMap_t
110 {
111 ASSERT( ForceKeySet.KeySets.size() == fragmentData.size(),
[0cd8cf]112 "FragmentationLongRangeResults::FragmentationLongRangeResults() - ForceKeySet's KeySets and fragmentData differ in size.");
[376a3b]113
[b8f0b25]114 OrthogonalSumUpPerLevel<MPQCDataGridMap_t, MPQCData, MPQCDataGridVector_t>(
115 fragmentData, MPQCMatrixNrLookup, container, subsetmap,
116 Result_Grid_fused, Result_perIndexSet_Grid);
[5a5196]117
118 // multiply each short-range potential with the respective charge
119 std::map<JobId_t,MPQCData>::const_iterator mpqciter = fragmentData.begin();
120 std::map<JobId_t,VMGData>::iterator vmgiter = longrangeData.begin();
121 for (; vmgiter != longrangeData.end(); ++mpqciter, ++vmgiter) {
122 vmgiter->second.sampled_potential *= mpqciter->second.sampled_grid;
123 }
124 // then sum up
[b8f0b25]125 OrthogonalSumUpPerLevel<VMGDataMap_t, VMGData, VMGDataVector_t>(
126 longrangeData, VMGMatrixNrLookup, container, subsetmap,
127 Result_LongRange_fused, Result_perIndexSet_LongRange);
[376a3b]128
[ff347f]129 IndexedVectors::indices_t fullindices;
[94db13]130 if (hasLongRangeForces()) {
131 // force has extra data converter (this is similar to MPQCData's forces
132 std::map<JobId_t, VMGDataForceMap_t> VMGData_Force_fused;
133 convertDatatoForceMap<VMGData, VMGDataForceMap_t, VMGDataFused>(
134 longrangeData, ForceKeySet, VMGData_Force_fused);
135 Result_ForceLongRange_fused.resize(MaxLevel); // we need the results of correct size already
136 AllLevelOrthogonalSummator<VMGDataForceMap_t> forceSummer(
137 subsetmap,
138 VMGData_Force_fused,
139 container->getContainer(),
140 VMGMatrixNrLookup,
141 Result_ForceLongRange_fused,
142 Result_perIndexSet_LongRange_Force);
143 boost::mpl::for_each<VMGDataForceVector_t>(boost::ref(forceSummer));
[ff347f]144 // build full force index set
145 KeySetsContainer::ArrayOfIntVectors::const_iterator arrayiter = ForceKeySet.KeySets.begin();
146 std::set<IndexedVectors::index_t> sorted_indices;
147 for (;arrayiter != ForceKeySet.KeySets.end(); ++arrayiter) {
148 sorted_indices.insert(arrayiter->begin(), arrayiter->end());
149 }
150 sorted_indices.erase(-1);
151 fullindices.insert(fullindices.begin(), sorted_indices.begin(), sorted_indices.end());
[94db13]152 }
153
[83a425]154 // then sum up
155 OrthogonalSumUpPerLevel<VMGDataGridMap_t, VMGData, VMGDataGridVector_t>(
156 longrangeData, VMGMatrixNrLookup, container, subsetmap,
157 Result_GridLongRange_fused, Result_perIndexSet_LongRange_Grid);
158
[376a3b]159 Result_LongRangeIntegrated_fused.reserve(MaxLevel);
[d29b31]160 // NOTE: potential for level 1 is wrongly calculated within a molecule
161 // as saturation hydrogen are not removed on this level yet
162 for (size_t level = 1; level <= MaxLevel; ++level) {
[e2925fd]163 // We have calculated three different contributions: e-e, e-n+n-n, and n-n.
164 // And we want to have e-e+e-n, n-n+n-e (where e-n = n-e).
165 // For each of these three contributions we have a full solution and summed
166 // up short range solutions.
167
168 // first we obtain the full e-e energy as potential times charge on the
169 // respective level.
[376a3b]170 const SamplingGrid &charge_weight =
171 boost::fusion::at_key<MPQCDataFused::sampled_grid>(Result_Grid_fused[level-1]);
[d29b31]172 SamplingGrid full_sample_solution = fullsolutionData[level-1].sampled_potential;
[67fec1]173 full_sample_solution *= charge_weight;
[e2925fd]174 double electron_solution_energy = full_sample_solution.integral();
175
176 // then we subtract the summed-up short-range e-e interaction energy from
177 // the full solution.
[376a3b]178 const SamplingGrid &short_range_correction =
[83a425]179 boost::fusion::at_key<VMGDataFused::sampled_potential>(Result_GridLongRange_fused[level-1]);
[e2925fd]180 double electron_short_range_energy = short_range_correction.integral();
[376a3b]181 full_sample_solution -= short_range_correction;
[e2925fd]182 electron_solution_energy -= electron_short_range_energy;
183 ASSERT( fabs(electron_solution_energy - full_sample_solution.integral()) < 1e-7,
184 "FragmentationLongRangeResults::operator() - integral and energy are not exchangeable.");
185
186 // then, we obtain the e-n+n-n full solution in the same way
[d29b31]187 double nuclei_solution_energy = fullsolutionData[level-1].nuclei_long;
[e2925fd]188 double nuclei_short_range_energy =
189 boost::fusion::at_key<VMGDataFused::nuclei_long>(Result_LongRange_fused[level-1]);
190 nuclei_solution_energy -= nuclei_short_range_energy;
191
192 // and also the e-n full solution
[d29b31]193 double both_solution_energy = fullsolutionData[level-1].electron_long;
[e2925fd]194 double both_short_range_energy =
195 boost::fusion::at_key<VMGDataFused::electron_long>(Result_LongRange_fused[level-1]);
196 both_solution_energy -= both_short_range_energy;
197
198 // energies from interpolation at nuclei position has factor of 1/2 already
199 electron_solution_energy *= .5;
200 electron_short_range_energy *= .5;
201
202 // At last, we subtract e-n from n-n+e-n for full solution and short-range
203 // correction.
204 nuclei_solution_energy -= both_solution_energy;
205 nuclei_short_range_energy -= both_short_range_energy;
[376a3b]206
207 VMGDataLongRangeMap_t instance;
[e2925fd]208 boost::fusion::at_key<VMGDataFused::electron_longrange>(instance) = electron_solution_energy;
[67fec1]209// LOG(0, "Remaining long-range potential integral of level " << level << " is "
210// << full_sample_solution.integral() << ".");
[e2925fd]211 boost::fusion::at_key<VMGDataFused::electron_shortrange>(instance) = electron_short_range_energy;
[67fec1]212// LOG(0, "Short-range correction potential integral of level " << level << " is "
213// << short_range_correction.integral() << ".");
[e2925fd]214 boost::fusion::at_key<VMGDataFused::mixed_longrange>(instance) = both_solution_energy;
215// LOG(0, "Remaining long-range energy from potential integral of level " << level << " is "
216// << full_solution_energy << ".");
217 boost::fusion::at_key<VMGDataFused::mixed_shortrange>(instance) = both_short_range_energy;
218// LOG(0, "Short-range correction energy from potential integral of level " << level << " is "
219// << short_range_energy << ".");
220 boost::fusion::at_key<VMGDataFused::nuclei_longrange>(instance) = nuclei_solution_energy;
[67fec1]221// LOG(0, "Remaining long-range energy from potential integral of level " << level << " is "
222// << full_solution_energy << ".");
[e2925fd]223 boost::fusion::at_key<VMGDataFused::nuclei_shortrange>(instance) = nuclei_short_range_energy;
[67fec1]224// LOG(0, "Short-range correction energy from potential integral of level " << level << " is "
225// << short_range_energy << ".");
226 boost::fusion::at_key<VMGDataFused::total_longrange>(instance) =
[e2925fd]227 boost::fusion::at_key<VMGDataFused::electron_longrange>(instance)
228 + 2.*boost::fusion::at_key<VMGDataFused::mixed_longrange>(instance)
229 + boost::fusion::at_key<VMGDataFused::nuclei_longrange>(instance);
[67fec1]230 boost::fusion::at_key<VMGDataFused::total_shortrange>(instance) =
[e2925fd]231 boost::fusion::at_key<VMGDataFused::electron_shortrange>(instance)
232 + 2.*boost::fusion::at_key<VMGDataFused::mixed_shortrange>(instance)
233 + boost::fusion::at_key<VMGDataFused::nuclei_shortrange>(instance);
[376a3b]234 Result_LongRangeIntegrated_fused.push_back(instance);
[ff347f]235
236 if (hasLongRangeForces()) {
237 VMGDataLongRangeForceMap_t forceinstance;
238 IndexedVectors fullforces( fullindices, fullsolutionData[level-1].forces);
239 IndexedVectors longrangeforces =
240 boost::fusion::at_key<VMGDataFused::forces>(Result_ForceLongRange_fused[level-1]);
241 boost::fusion::at_key<VMGDataFused::forces_shortrange>(forceinstance) =
242 fullforces;
243 fullforces -= longrangeforces;
244 boost::fusion::at_key<VMGDataFused::forces_longrange>(forceinstance) =
245 fullforces;
246 Result_ForcesLongRangeIntegrated_fused.push_back(forceinstance);
247 }
[376a3b]248 }
249// {
250// // LOG(0, "Remaining long-range energy from energy_potential is " << full_sample_solution.integral()-epotentialSummer.getFullContribution() << ".");
251// SamplingGrid full_sample_solution = fullsolutionData.back().sampled_potential;
252// const SamplingGrid &short_range_correction =
[83a425]253// boost::fusion::at_key<VMGDataFused::sampled_potential>(Result_GridLongRange_fused.back()).getFullContribution();
[376a3b]254// full_sample_solution -= short_range_correction;
255// // multiply element-wise with charge distribution
256// LOG(0, "Remaining long-range potential integral is " << full_sample_solution.integral() << ".");
257// LOG(0, "Short-range correction potential integral of level is " << short_range_correction.integral() << ".");
258// LOG(0, "Remaining long-range energy from potential integral is "
259// << full_sample_solution.integral(full_sample.back()) << ".");
260// LOG(0, "Short-range correction energy from potential integral is "
261// << short_range_correction.integral(full_sample.back()) << ".");
262//
263// double e_long = fullsolutionData.back().e_long;
264// e_long -= boost::fusion::at_key<VMGDataFused::energy_long>(Result_LongRange_fused.back()).getFullContribution();
265// LOG(0, "Remaining long-range energy is " << e_long << ".");
266// }
267
268 // TODO: Extract long-range corrections to forces
269 // NOTE: potential is in atomic length units, NOT IN ANGSTROEM!
270
271 }
272}
Note: See TracBrowser for help on using the repository browser.