source: src/Fragmentation/AdaptivityMap.cpp@ 6d551c

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

FIX: As we use GSL internally, we are as of now required to use GPL v2 license.

  • GNU Scientific Library is used at every place in the code, especially the sub-package LinearAlgebra is based on it which in turn is used really everywhere in the remainder of MoleCuilder. Hence, we have to use the GPL license for the whole of MoleCuilder. In effect, GPL's COPYING was present all along and stated the terms of the GPL v2 license.
  • Hence, I added the default GPL v2 disclaimer to every source file and removed the note about a (actually missing) LICENSE file.
  • also, I added a help-redistribute action which again gives the disclaimer of the GPL v2.
  • also, I changed in the disclaimer that is printed at every program start in builder_init.cpp.
  • TEST: Added check on GPL statement present in every module to test CodeChecks project-disclaimer.
  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * AdaptivityMap.cpp
25 *
26 * Created on: Oct 20, 2011
27 * Author: heber
28 */
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#include "CodePatterns/MemDebug.hpp"
35
36#include "AdaptivityMap.hpp"
37
38#include <fstream>
39
40#include "CodePatterns/Assert.hpp"
41#include "CodePatterns/Log.hpp"
42
43#include "Atom/atom.hpp"
44#include "Helpers/defs.hpp"
45#include "Helpers/helpers.hpp"
46#include "molecule.hpp"
47
48/** Constructor of class AdaptivityMap.
49 *
50 */
51AdaptivityMap::AdaptivityMap()
52{}
53
54/** Destructor of class AdaptivityMap.
55 *
56 */
57AdaptivityMap::~AdaptivityMap()
58{}
59
60/** Inserts a (\a No, \a value) pair into the list, overwriting present one.
61 * Note if values are equal, No will decided on which is first
62 * \param *out output stream for debugging
63 * \param &AdaptiveCriteriaList list to insert into
64 * \param &IndexedKeySetList list to find key set for a given index \a No
65 * \param FragOrder current bond order of fragment
66 * \param No index of keyset
67 * \param value energy value
68 */
69void AdaptivityMap::InsertIntoAdaptiveCriteriaList(int FragOrder, int No, double Value)
70{
71 ASSERT( AdaptiveCriteriaList != NULL,
72 "AdaptivityMap::InsertIntoAdaptiveCriteriaList() - AdaptiveCriteriaList is not allocated yet.");
73 const_iterator marker = find(No); // find keyset to Frag No.
74 if (marker != end()) { // if found
75 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes them not equal without changing anything actually
76 // 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
77 std::pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList->insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
78 std::map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
79 if (!InsertedElement.second) { // this root is already present
80 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term
81 //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)
82 { // if value is smaller, update value and order
83 (*PresentItem).second.first = fabs(Value);
84 (*PresentItem).second.second = FragOrder;
85 LOG(2, "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "]).");
86 } else {
87 LOG(2, "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << ".");
88 }
89 } else {
90 LOG(2, "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "]).");
91 }
92 } else {
93 LOG(1, "No Fragment under No. " << No << "found.");
94 }
95};
96
97
98/** Scans the adaptive order file and insert (index, value) into map.
99 * \param &path path to ENERGYPERFRAGMENT file (may be NULL if Order is non-negative)
100 */
101void AdaptivityMap::ScanAdaptiveFileIntoMap(std::string &path)
102{
103 int No = 0, FragOrder = 0;
104 double Value = 0.;
105 char buffer[MAXSTRINGSIZE];
106 std::string filename = path + ENERGYPERFRAGMENT;
107 std::ifstream InputFile(filename.c_str());
108
109 if (InputFile.fail()) {
110 ELOG(1, "Cannot find file " << filename << ".");
111 return;
112 }
113
114 if (CountLinesinFile(InputFile) > 0) {
115 // each line represents a fragment root (Atom::Nr) id and its energy contribution
116 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
117 InputFile.getline(buffer, MAXSTRINGSIZE);
118 while(!InputFile.eof()) {
119 InputFile.getline(buffer, MAXSTRINGSIZE);
120 if (strlen(buffer) > 2) {
121 //LOG(2, "Scanning: " << buffer);
122 stringstream line(buffer);
123 line >> FragOrder;
124 line >> ws >> No;
125 line >> ws >> Value; // skip time entry
126 line >> ws >> Value;
127 No -= 1; // indices start at 1 in file, not 0
128 //LOG(2, " - yields (" << No << "," << Value << ", " << FragOrder << ")");
129
130 // clean the list of those entries that have been superceded by higher order terms already
131 InsertIntoAdaptiveCriteriaList(FragOrder, No, Value);
132 }
133 }
134 // close and done
135 InputFile.close();
136 InputFile.clear();
137 }
138};
139
140/** Maps adaptive criteria list back onto (Value, (Root Nr., Order))
141 * (i.e. sorted by value to pick the highest ones)
142 * \param *mol molecule with atoms
143 * \return remapped list
144 */
145void AdaptivityMap::ReMapAdaptiveCriteriaListToValue(molecule *mol)
146{
147 atom *Walker = NULL;
148 ASSERT( AdaptiveCriteriaList != NULL,
149 "AdaptivityMap::ReMapAdaptiveCriteriaListToValue() - AdaptiveCriteriaList is not allocated yet.");
150 FinalRootCandidates = new AdaptiveCriteriaValueMap;
151 LOG(1, "Root candidate list is: ");
152 for(AdaptiveCriteriaIndexMap::const_iterator runner = AdaptiveCriteriaList->begin(); runner != AdaptiveCriteriaList->end(); runner++) {
153 Walker = mol->FindAtom((*runner).first);
154 if (Walker != NULL) {
155 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
156 if (!Walker->MaxOrder) {
157 LOG(2, "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])");
158 FinalRootCandidates->insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
159 } else {
160 LOG(2, "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order.");
161 }
162 } else {
163 ELOG(0, "Atom No. " << (*runner).second.first << " was not found in this molecule.");
164 performCriticalExit();
165 }
166 }
167};
168
169/** Counts lines in file.
170 * Note we are scanning lines from current position, not from beginning.
171 * \param InputFile file to be scanned.
172 */
173int AdaptivityMap::CountLinesinFile(std::ifstream &InputFile) const
174{
175 char *buffer = new char[MAXSTRINGSIZE];
176 int lines=0;
177
178 int PositionMarker = InputFile.tellg(); // not needed as Inputfile is copied, given by value, not by ref
179 // count the number of lines, i.e. the number of fragments
180 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
181 InputFile.getline(buffer, MAXSTRINGSIZE);
182 while(!InputFile.eof()) {
183 InputFile.getline(buffer, MAXSTRINGSIZE);
184 lines++;
185 }
186 InputFile.seekg(PositionMarker, ios::beg);
187 delete[](buffer);
188 return lines;
189};
190
191/** Marks all candidate sites for update if below adaptive threshold.
192 * Picks a given number of highest values and set *AtomMask to true.
193 * \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
194 * \param Order desired order
195 * \param *mol molecule with atoms
196 * \return true - if update is necessary, false - not
197 */
198bool AdaptivityMap::MarkUpdateCandidates(bool *AtomMask, int Order, molecule *mol) const
199{
200 atom *Walker = NULL;
201 int No = -1;
202 bool status = false;
203 ASSERT( FinalRootCandidates != NULL,
204 "AdaptivityMap::MarkUpdateCandidates() - FinalRootCandidates is not allocated yet.");
205 for(AdaptiveCriteriaValueMap::const_iterator runner = FinalRootCandidates->upper_bound(pow(10.,Order)); runner != FinalRootCandidates->end(); runner++) {
206 No = (*runner).second.first;
207 Walker = mol->FindAtom(No);
208 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->getNr()]) {
209 LOG(2, "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true.");
210 AtomMask[No] = true;
211 status = true;
212 //} else
213 //LOG(2, "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->getNr()] << " does not allow further adaptive increase.");
214 }
215 return status;
216};
217
218/** Checks whether there are any adaptive items currently.
219 *
220 * @return true - there are items for adaptive refinement, false - there are none
221 */
222bool AdaptivityMap::IsAdaptiveCriteriaListEmpty() const
223{
224 ASSERT( AdaptiveCriteriaList != NULL,
225 "AdaptivityMap::ReMapAdaptiveCriteriaListToValue() - AdaptiveCriteriaList is not allocated yet.");
226 return AdaptiveCriteriaList->empty();
227}
Note: See TracBrowser for help on using the repository browser.