source: src/Fragmentation/fragmentation_helpers.cpp@ 75363b

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 Candidate_v1.7.0 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 75363b was 75363b, checked in by Frederik Heber <heber@…>, 14 years ago

Extracted functions from fragmentation_helpers and placed them in KeySet or Graph class.

  • Property mode set to 100644
File size: 12.0 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * fragmentation_helpers.cpp
10 *
11 * Created on: Oct 18, 2011
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "CodePatterns/MemDebug.hpp"
21
22#include "fragmentation_helpers.hpp"
23
24#include <sstream>
25
26#include "CodePatterns/Log.hpp"
27
28#include "atom.hpp"
29#include "Bond/bond.hpp"
30#include "Element/element.hpp"
31#include "Fragmentation/Graph.hpp"
32#include "Fragmentation/KeySet.hpp"
33#include "Helpers/defs.hpp"
34#include "Helpers/helpers.hpp"
35#include "molecule.hpp"
36
37using namespace std;
38
39/** Inserts a (\a No, \a value) pair into the list, overwriting present one.
40 * Note if values are equal, No will decided on which is first
41 * \param *out output stream for debugging
42 * \param &AdaptiveCriteriaList list to insert into
43 * \param &IndexedKeySetList list to find key set for a given index \a No
44 * \param FragOrder current bond order of fragment
45 * \param No index of keyset
46 * \param value energy value
47 */
48void InsertIntoAdaptiveCriteriaList(std::map<int, pair<double,int> > *AdaptiveCriteriaList, std::map<int,KeySet> &IndexKeySetList, int FragOrder, int No, double Value)
49{
50 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No.
51 if (marker != IndexKeySetList.end()) { // if found
52 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes them not equal without changing anything actually
53 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask
54 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList->insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
55 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
56 if (!InsertedElement.second) { // this root is already present
57 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term
58 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase)
59 { // if value is smaller, update value and order
60 (*PresentItem).second.first = fabs(Value);
61 (*PresentItem).second.second = FragOrder;
62 DoLog(2) && (Log() << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl);
63 } else {
64 DoLog(2) && (Log() << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl);
65 }
66 } else {
67 DoLog(2) && (Log() << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl);
68 }
69 } else {
70 DoLog(1) && (Log() << Verbose(1) << "No Fragment under No. " << No << "found." << endl);
71 }
72};
73
74/** Counts lines in file.
75 * Note we are scanning lines from current position, not from beginning.
76 * \param InputFile file to be scanned.
77 */
78int CountLinesinFile(std::ifstream &InputFile)
79{
80 char *buffer = new char[MAXSTRINGSIZE];
81 int lines=0;
82
83 int PositionMarker = InputFile.tellg(); // not needed as Inputfile is copied, given by value, not by ref
84 // count the number of lines, i.e. the number of fragments
85 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
86 InputFile.getline(buffer, MAXSTRINGSIZE);
87 while(!InputFile.eof()) {
88 InputFile.getline(buffer, MAXSTRINGSIZE);
89 lines++;
90 }
91 InputFile.seekg(PositionMarker, ios::beg);
92 delete[](buffer);
93 return lines;
94};
95
96
97/** Scans the adaptive order file and insert (index, value) into map.
98 * \param &path path to ENERGYPERFRAGMENT file (may be NULL if Order is non-negative)
99 * \param &IndexedKeySetList list to find key set for a given index \a No
100 * \return adaptive criteria list from file
101 */
102std::map<int, std::pair<double,int> > * ScanAdaptiveFileIntoMap(std::string &path, std::map<int,KeySet> &IndexKeySetList)
103{
104 map<int, pair<double,int> > *AdaptiveCriteriaList = new map<int, pair<double,int> >;
105 int No = 0, FragOrder = 0;
106 double Value = 0.;
107 char buffer[MAXSTRINGSIZE];
108 string filename = path + ENERGYPERFRAGMENT;
109 ifstream InputFile(filename.c_str());
110
111 if (InputFile.fail()) {
112 DoeLog(1) && (eLog() << Verbose(1) << "Cannot find file " << filename << "." << endl);
113 return AdaptiveCriteriaList;
114 }
115
116 if (CountLinesinFile(InputFile) > 0) {
117 // each line represents a fragment root (Atom::Nr) id and its energy contribution
118 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
119 InputFile.getline(buffer, MAXSTRINGSIZE);
120 while(!InputFile.eof()) {
121 InputFile.getline(buffer, MAXSTRINGSIZE);
122 if (strlen(buffer) > 2) {
123 //Log() << Verbose(2) << "Scanning: " << buffer << endl;
124 stringstream line(buffer);
125 line >> FragOrder;
126 line >> ws >> No;
127 line >> ws >> Value; // skip time entry
128 line >> ws >> Value;
129 No -= 1; // indices start at 1 in file, not 0
130 //Log() << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;
131
132 // clean the list of those entries that have been superceded by higher order terms already
133 InsertIntoAdaptiveCriteriaList(AdaptiveCriteriaList, IndexKeySetList, FragOrder, No, Value);
134 }
135 }
136 // close and done
137 InputFile.close();
138 InputFile.clear();
139 }
140
141 return AdaptiveCriteriaList;
142};
143
144/** Maps adaptive criteria list back onto (Value, (Root Nr., Order))
145 * (i.e. sorted by value to pick the highest ones)
146 * \param *out output stream for debugging
147 * \param &AdaptiveCriteriaList list to insert into
148 * \param *mol molecule with atoms
149 * \return remapped list
150 */
151std::map<double, std::pair<int,int> > * ReMapAdaptiveCriteriaListToValue(std::map<int, std::pair<double,int> > *AdaptiveCriteriaList, molecule *mol)
152{
153 atom *Walker = NULL;
154 map<double, pair<int,int> > *FinalRootCandidates = new map<double, pair<int,int> > ;
155 DoLog(1) && (Log() << Verbose(1) << "Root candidate list is: " << endl);
156 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList->begin(); runner != AdaptiveCriteriaList->end(); runner++) {
157 Walker = mol->FindAtom((*runner).first);
158 if (Walker != NULL) {
159 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
160 if (!Walker->MaxOrder) {
161 DoLog(2) && (Log() << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl);
162 FinalRootCandidates->insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
163 } else {
164 DoLog(2) && (Log() << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl);
165 }
166 } else {
167 DoeLog(0) && (eLog()<< Verbose(0) << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl);
168 performCriticalExit();
169 }
170 }
171 return FinalRootCandidates;
172};
173
174/** Marks all candidate sites for update if below adaptive threshold.
175 * Picks a given number of highest values and set *AtomMask to true.
176 * \param *out output stream for debugging
177 * \param *AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site, used to activate given number of site to increment order adaptively
178 * \param FinalRootCandidates list candidates to check
179 * \param Order desired order
180 * \param *mol molecule with atoms
181 * \return true - if update is necessary, false - not
182 */
183bool MarkUpdateCandidates(bool *AtomMask, std::map<double, std::pair<int,int> > &FinalRootCandidates, int Order, molecule *mol)
184{
185 atom *Walker = NULL;
186 int No = -1;
187 bool status = false;
188 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {
189 No = (*runner).second.first;
190 Walker = mol->FindAtom(No);
191 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->getNr()]) {
192 DoLog(2) && (Log() << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl);
193 AtomMask[No] = true;
194 status = true;
195 //} else
196 //Log() << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->getNr()] << " does not allow further adaptive increase." << endl;
197 }
198 return status;
199};
200
201/** print atom mask for debugging.
202 * \param *out output stream for debugging
203 * \param *AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site, used to activate given number of site to increment order adaptively
204 * \param AtomCount number of entries in \a *AtomMask
205 */
206void PrintAtomMask(bool *AtomMask, int AtomCount)
207{
208 DoLog(2) && (Log() << Verbose(2) << " ");
209 for(int i=0;i<AtomCount;i++)
210 DoLog(0) && (Log() << Verbose(0) << (i % 10));
211 DoLog(0) && (Log() << Verbose(0) << endl);
212 DoLog(2) && (Log() << Verbose(2) << "Atom mask is: ");
213 for(int i=0;i<AtomCount;i++)
214 DoLog(0) && (Log() << Verbose(0) << (AtomMask[i] ? "t" : "f"));
215 DoLog(0) && (Log() << Verbose(0) << endl);
216};
217
218/** Combines all KeySets from all orders into single ones (with just unique entries).
219 * \param *out output stream for debugging
220 * \param *&FragmentList list to fill
221 * \param ***FragmentLowerOrdersList
222 * \param &RootStack stack with all root candidates (unequal to each atom in complete molecule if adaptive scheme is applied)
223 * \param *mol molecule with atoms and bonds
224 */
225int CombineAllOrderListIntoOne(Graph *&FragmentList, Graph ***FragmentLowerOrdersList, KeyStack &RootStack, molecule *mol)
226{
227 int RootNr = 0;
228 int RootKeyNr = 0;
229 int StartNr = 0;
230 int counter = 0;
231 int NumLevels = 0;
232 atom *Walker = NULL;
233
234 DoLog(0) && (Log() << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl);
235 if (FragmentList == NULL) {
236 FragmentList = new Graph;
237 counter = 0;
238 } else {
239 counter = FragmentList->size();
240 }
241
242 StartNr = RootStack.back();
243 do {
244 RootKeyNr = RootStack.front();
245 RootStack.pop_front();
246 Walker = mol->FindAtom(RootKeyNr);
247 NumLevels = 1 << (Walker->AdaptiveOrder - 1);
248 for(int i=0;i<NumLevels;i++) {
249 if (FragmentLowerOrdersList[RootNr][i] != NULL) {
250 (*FragmentList).InsertGraph((*FragmentLowerOrdersList[RootNr][i]), &counter);
251 }
252 }
253 RootStack.push_back(Walker->getNr());
254 RootNr++;
255 } while (RootKeyNr != StartNr);
256 return counter;
257};
258
259/** Free's memory allocated for all KeySets from all orders.
260 * \param *out output stream for debugging
261 * \param ***FragmentLowerOrdersList
262 * \param &RootStack stack with all root candidates (unequal to each atom in complete molecule if adaptive scheme is applied)
263 * \param *mol molecule with atoms and bonds
264 */
265void FreeAllOrdersList(Graph ***FragmentLowerOrdersList, KeyStack &RootStack, molecule *mol)
266{
267 DoLog(1) && (Log() << Verbose(1) << "Free'ing the lists of all orders per order." << endl);
268 int RootNr = 0;
269 int RootKeyNr = 0;
270 int NumLevels = 0;
271 atom *Walker = NULL;
272 while (!RootStack.empty()) {
273 RootKeyNr = RootStack.front();
274 RootStack.pop_front();
275 Walker = mol->FindAtom(RootKeyNr);
276 NumLevels = 1 << (Walker->AdaptiveOrder - 1);
277 for(int i=0;i<NumLevels;i++) {
278 if (FragmentLowerOrdersList[RootNr][i] != NULL) {
279 delete(FragmentLowerOrdersList[RootNr][i]);
280 }
281 }
282 delete[](FragmentLowerOrdersList[RootNr]);
283 RootNr++;
284 }
285 delete[](FragmentLowerOrdersList);
286};
287
Note: See TracBrowser for help on using the repository browser.