source: src/Fragmentation/Fragmentation.cpp@ dcbb5d

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 dcbb5d was ca8bea, checked in by Frederik Heber <heber@…>, 12 years ago

ExportGraph_ToFiles performs now the storing of the generated Graph to files.

  • FragmentMolecule now fills an internal graph.
  • ExportGraph_ToFiles gets graph in cstor and writes the contained KeySets to file on call of operator().
  • Property mode set to 100644
File size: 23.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 * Fragmentation.cpp
25 *
26 * Created on: Oct 18, 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 "Fragmentation.hpp"
37
38#include "CodePatterns/Assert.hpp"
39#include "CodePatterns/Info.hpp"
40#include "CodePatterns/Log.hpp"
41
42#include "Atom/atom.hpp"
43#include "Bond/bond.hpp"
44#include "Descriptors/MoleculeDescriptor.hpp"
45#include "Element/element.hpp"
46#include "Element/periodentafel.hpp"
47#include "Fragmentation/AdaptivityMap.hpp"
48#include "Fragmentation/AtomMask.hpp"
49#include "Fragmentation/fragmentation_helpers.hpp"
50#include "Fragmentation/Graph.hpp"
51#include "Fragmentation/helpers.hpp"
52#include "Fragmentation/KeySet.hpp"
53#include "Fragmentation/PowerSetGenerator.hpp"
54#include "Fragmentation/UniqueFragments.hpp"
55#include "Graph/BondGraph.hpp"
56#include "Graph/CheckAgainstAdjacencyFile.hpp"
57#include "Graph/ListOfLocalAtoms.hpp"
58#include "molecule.hpp"
59#include "World.hpp"
60
61
62/** Constructor of class Fragmentation.
63 *
64 * \param _mol molecule for internal use (looking up atoms)
65 * \param _FileChecker instance contains adjacency parsed from elsewhere
66 * \param _saturation whether to treat hydrogen special and saturate dangling bonds or not
67 */
68Fragmentation::Fragmentation(molecule *_mol, CheckAgainstAdjacencyFile &_FileChecker, const enum HydrogenSaturation _saturation) :
69 mol(_mol),
70 saturation(_saturation),
71 FileChecker(_FileChecker)
72{}
73
74/** Destructor of class Fragmentation.
75 *
76 */
77Fragmentation::~Fragmentation()
78{}
79
80
81/** Performs a many-body bond order analysis for a given bond order.
82 * -# parses adjacency, keysets and orderatsite files
83 * -# RootStack is created for every subgraph (here, later we implement the "update 10 sites with highest energ
84y contribution", and that's why this consciously not done in the following loop)
85 * -# in a loop over all subgraphs
86 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
87 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)
88 * -# combines the generated molecule lists from all subgraphs
89 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files
90 * Note that as we split "this" molecule up into a list of subgraphs, i.e. a MoleculeListClass, we have two sets
91 * of vertex indices: Global always means the index in "this" molecule, whereas local refers to the molecule or
92 * subgraph in the MoleculeListClass.
93 * \param atomids atoms to fragment, used in AtomMask
94 * \param Order up to how many neighbouring bonds a fragment contains in BondOrderScheme::BottumUp scheme
95 * \param prefix prefix string for every fragment file name (may include path)
96 * \param &DFS contains bond structure analysis data
97 * \return 1 - continue, 2 - stop (no fragmentation occured)
98 */
99int Fragmentation::FragmentMolecule(const std::vector<atomId_t> &atomids, int Order, std::string prefix, DepthFirstSearchAnalysis &DFS)
100{
101 std::fstream File;
102 bool FragmentationToDo = true;
103 bool CheckOrder = false;
104 int TotalNumberOfKeySets = 0;
105 AtomMask_t AtomMask(atomids);
106
107 LOG(0, std::endl);
108 switch (saturation) {
109 case DoSaturate:
110 LOG(0, "I will treat hydrogen special and saturate dangling bonds with it.");
111 break;
112 case DontSaturate:
113 LOG(0, "Hydrogen is treated just like the rest of the lot.");
114 break;
115 default:
116 ASSERT(0, "Fragmentation::FragmentMolecule() - there is a saturation setting which I have no idea about.");
117 break;
118 }
119
120 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++
121
122 // ===== 1. Check whether bond structure is same as stored in files ====
123
124 // === compare it with adjacency file ===
125 {
126 const std::vector<atomId_t> globalids = getGlobalIdsFromLocalIds(*mol, atomids);
127 FragmentationToDo = FragmentationToDo && FileChecker(globalids);
128 }
129
130 // ===== 3. if structure still valid, parse key set file and others =====
131 Graph ParsedFragmentList;
132 FragmentationToDo = FragmentationToDo && ParsedFragmentList.ParseKeySetFile(prefix);
133
134 // ===== 4. check globally whether there's something to do actually (first adaptivity check)
135 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(atomids, prefix);
136
137 // =================================== Begin of FRAGMENTATION ===============================
138 // ===== 6a. assign each keyset to its respective subgraph =====
139 ListOfLocalAtoms_t ListOfLocalAtoms;
140 Graph FragmentList;
141 AssignKeySetsToFragment(ParsedFragmentList, ListOfLocalAtoms, FragmentList, true);
142
143 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle
144 KeyStack RootStack;
145 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards
146 bool LoopDoneAlready = false;
147 while ((CheckOrder = CheckOrderAtSite(AtomMask, ParsedFragmentList, Order, prefix, LoopDoneAlready))) {
148 FragmentationToDo = FragmentationToDo || CheckOrder;
149 LoopDoneAlready = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
150 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====
151 FillRootStackForSubgraphs(RootStack, AtomMask);
152
153 // call BOSSANOVA method
154 FragmentBOSSANOVA(mol, FragmentList, RootStack);
155 }
156 LOG(2, "CheckOrder is " << CheckOrder << ".");
157
158 // ==================================== End of FRAGMENTATION ============================================
159
160 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
161 TranslateIndicesToGlobalIDs(FragmentList, TotalNumberOfKeySets, TotalGraph);
162
163 LOG(1, "STATUS: We have created " << TotalGraph.size() << " fragments.");
164
165 // store adaptive orders into file
166 StoreOrderAtSiteFile(prefix);
167
168 LOG(0, "End of bond fragmentation.");
169 return ((int)(!FragmentationToDo)+1); // 1 - continue, 2 - stop (no fragmentation occured)
170};
171
172
173/** Performs BOSSANOVA decomposition at selected sites, increasing the cutoff by one at these sites.
174 * -# constructs a complete keyset of the molecule
175 * -# In a loop over all possible roots from the given rootstack
176 * -# increases order of root site
177 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
178 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset
179as the restricted one and each site in the set as the root)
180 * -# these are merged into a fragment list of keysets
181 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return
182 * Important only is that we create all fragments, it is not important if we create them more than once
183 * as these copies are filtered out via use of the hash table (KeySet).
184 * \param *out output stream for debugging
185 * \param Fragment&*List list of already present keystacks (adaptive scheme) or empty list
186 * \param &RootStack stack with all root candidates (unequal to each atom in complete molecule if adaptive scheme is applied)
187 * \return pointer to Graph list
188 */
189void Fragmentation::FragmentBOSSANOVA(molecule *mol, Graph &FragmentList, KeyStack &RootStack)
190{
191 Info FunctionInfo(__func__);
192 Graph ***FragmentLowerOrdersList = NULL;
193 int NumLevels = 0;
194 int NumMolecules = 0;
195 int TotalNumMolecules = 0;
196 int *NumMoleculesOfOrder = NULL;
197 int Order = 0;
198 int UpgradeCount = RootStack.size();
199 KeyStack FragmentRootStack;
200 int RootKeyNr = 0;
201 int RootNr = 0;
202 UniqueFragments FragmentSearch;
203
204 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)
205 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)
206 NumMoleculesOfOrder = new int[UpgradeCount];
207 FragmentLowerOrdersList = new Graph**[UpgradeCount];
208
209 for(int i=0;i<UpgradeCount;i++) {
210 NumMoleculesOfOrder[i] = 0;
211 FragmentLowerOrdersList[i] = NULL;
212 }
213
214 FragmentSearch.Init(mol->FindAtom(RootKeyNr));
215
216 // Construct the complete KeySet which we need for topmost level only (but for all Roots)
217 KeySet CompleteMolecule;
218 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
219 CompleteMolecule.insert((*iter)->GetTrueFather()->getNr());
220 }
221
222 // this can easily be seen: if Order is 5, then the number of levels for each lower order is the total sum of the number of levels above, as
223 // each has to be split up. E.g. for the second level we have one from 5th, one from 4th, two from 3th (which in turn is one from 5th, one from 4th),
224 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])
225 // with the order along the cells as this: 5433222211111111 for BondOrder 5 needing 16=pow(2,5-1) cells (only we use bit-shifting which is faster)
226 RootNr = 0; // counts through the roots in RootStack
227 while ((RootNr < UpgradeCount) && (!RootStack.empty())) {
228 RootKeyNr = RootStack.front();
229 RootStack.pop_front();
230 atom *Walker = mol->FindAtom(RootKeyNr);
231 // check cyclic lengths
232 //if ((MinimumRingSize[Walker->GetTrueFather()->getNr()] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->getNr()])) {
233 // LOG(0, "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed.");
234 //} else
235 {
236 // increase adaptive order by one
237 Walker->GetTrueFather()->AdaptiveOrder++;
238 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;
239
240 // initialise Order-dependent entries of UniqueFragments structure
241 class PowerSetGenerator PSG(&FragmentSearch, Walker->AdaptiveOrder);
242
243 // allocate memory for all lower level orders in this 1D-array of ptrs
244 NumLevels = 1 << (Order-1); // (int)pow(2,Order);
245 FragmentLowerOrdersList[RootNr] = new Graph*[NumLevels];
246 for (int i=0;i<NumLevels;i++)
247 FragmentLowerOrdersList[RootNr][i] = NULL;
248
249 // create top order where nothing is reduced
250 LOG(0, "==============================================================================================================");
251 LOG(0, "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining."); // , NumLevels is " << NumLevels << "
252
253 // Create list of Graphs of current Bond Order (i.e. F_{ij})
254 FragmentLowerOrdersList[RootNr][0] = new Graph;
255 FragmentSearch.PrepareForPowersetGeneration(1., FragmentLowerOrdersList[RootNr][0], Walker);
256 NumMoleculesOfOrder[RootNr] = PSG(CompleteMolecule, saturation);
257
258 // output resulting number
259 LOG(1, "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << ".");
260 if (NumMoleculesOfOrder[RootNr] != 0) {
261 NumMolecules = 0;
262 } else {
263 Walker->GetTrueFather()->MaxOrder = true;
264 }
265 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder
266 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;
267 TotalNumMolecules += NumMoleculesOfOrder[RootNr];
268// LOG(1, "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << ".");
269 RootStack.push_back(RootKeyNr); // put back on stack
270 RootNr++;
271 }
272 }
273 LOG(0, "==============================================================================================================");
274 LOG(1, "Total number of resulting molecules is: " << TotalNumMolecules << ".");
275 LOG(0, "==============================================================================================================");
276
277 // cleanup FragmentSearch structure
278 FragmentSearch.Cleanup();
279
280 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)
281 // 5433222211111111
282 // 43221111
283 // 3211
284 // 21
285 // 1
286
287 // Subsequently, we combine all into a single list (FragmentList)
288 CombineAllOrderListIntoOne(FragmentList, FragmentLowerOrdersList, RootStack, mol);
289 FreeAllOrdersList(FragmentLowerOrdersList, RootStack, mol);
290 delete[](NumMoleculesOfOrder);
291};
292
293/** Estimates by educated guessing (using upper limit) the expected number of fragments.
294 * The upper limit is
295 * \f[
296 * n = N \cdot C^k
297 * \f]
298 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms.
299 * \param *out output stream for debugging
300 * \param order bond order k
301 * \return number n of fragments
302 */
303int Fragmentation::GuesstimateFragmentCount(int order)
304{
305 size_t c = 0;
306 int FragmentCount;
307 // get maximum bond degree
308 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
309 const BondList& ListOfBonds = (*iter)->getListOfBonds();
310 c = (ListOfBonds.size() > c) ? ListOfBonds.size() : c;
311 }
312 FragmentCount = (saturation == DoSaturate ? mol->getNoNonHydrogen() : mol->getAtomCount()) *(1 << (c*order));
313 LOG(1, "Upper limit for this subgraph is " << FragmentCount << " for "
314 << mol->getNoNonHydrogen() << " non-H atoms with maximum bond degree of " << c << ".");
315 return FragmentCount;
316};
317
318
319/** Checks whether the OrderAtSite is still below \a Order at some site.
320 * \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
321 * \param *GlobalKeySetList list of keysets with global ids (valid in "this" molecule) needed for adaptive increase
322 * \param Order desired Order if positive, desired exponent in threshold criteria if negative (0 is single-step)
323 * \param path path to ENERGYPERFRAGMENT file (may be NULL if Order is non-negative)
324 * \param LoopDoneAlready indicate whether we have done a fragmentation loop already
325 * \return true - needs further fragmentation, false - does not need fragmentation
326 */
327bool Fragmentation::CheckOrderAtSite(AtomMask_t &AtomMask, const Graph &GlobalKeySetList, int Order, std::string path, bool LoopDoneAlready)
328{
329 bool status = false;
330
331 // initialize mask list
332 AtomMask.clear();
333
334 if (Order < 0) { // adaptive increase of BondOrder per site
335 if (LoopDoneAlready) // break after one step
336 return false;
337
338 // transmorph graph keyset list into indexed KeySetList
339 AdaptivityMap * IndexKeySetList = GlobalKeySetList.GraphToAdaptivityMap();
340
341 // parse the EnergyPerFragment file
342 IndexKeySetList->ScanAdaptiveFileIntoMap(path); // (Root No., (Value, Order)) !
343 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)
344 IndexKeySetList->ReMapAdaptiveCriteriaListToValue(mol);
345
346 // pick the ones still below threshold and mark as to be adaptively updated
347 if (IndexKeySetList->IsAdaptiveCriteriaListEmpty()) {
348 ELOG(2, "Unable to parse file, incrementing all.");
349 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
350 if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen
351 {
352 AtomMask.setTrue((*iter)->getNr()); // include all (non-hydrogen) atoms
353 status = true;
354 }
355 }
356 } else {
357 IndexKeySetList->MarkUpdateCandidates(AtomMask, Order, mol);
358 }
359
360 delete[](IndexKeySetList);
361 } else { // global increase of Bond Order
362 for(molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
363 if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen
364 {
365 AtomMask.setTrue((*iter)->getNr()); // include all (non-hydrogen) atoms
366 if ((Order != 0) && ((*iter)->AdaptiveOrder < Order)) // && ((*iter)->AdaptiveOrder < MinimumRingSize[(*iter)->getNr()]))
367 status = true;
368 }
369 }
370 if ((!Order) && (!LoopDoneAlready)) // single stepping, just check
371 status = true;
372
373 if (!status) {
374 if (Order == 0)
375 LOG(1, "Single stepping done.");
376 else
377 LOG(1, "Order at every site is already equal or above desired order " << Order << ".");
378 }
379 }
380
381 PrintAtomMask(AtomMask, mol->getAtomCount()); // for debugging
382
383 return status;
384};
385
386/** Stores pairs (Atom::Nr, Atom::AdaptiveOrder) into file.
387 * Atoms not present in the file get "-1".
388 * \param &path path to file ORDERATSITEFILE
389 * \return true - file writable, false - not writable
390 */
391bool Fragmentation::StoreOrderAtSiteFile(std::string &path)
392{
393 string line;
394 ofstream file;
395
396 line = path + ORDERATSITEFILE;
397 file.open(line.c_str());
398 LOG(1, "Writing OrderAtSite " << ORDERATSITEFILE << " ... ");
399 if (file.good()) {
400 for_each(mol->begin(),mol->end(),bind2nd(mem_fun(&atom::OutputOrder), &file));
401 file.close();
402 LOG(1, "done.");
403 return true;
404 } else {
405 LOG(1, "failed to open file " << line << ".");
406 return false;
407 }
408};
409
410
411/** Parses pairs(Atom::Nr, Atom::AdaptiveOrder) from file and stores in molecule's Atom's.
412 * Atoms not present in the file get "0".
413 * \param atomids atoms to fragment, used in AtomMask
414 * \param &path path to file ORDERATSITEFILEe
415 * \return true - file found and scanned, false - file not found
416 * \sa ParseKeySetFile() and CheckAdjacencyFileAgainstMolecule() as this is meant to be used in conjunction with the two
417 */
418bool Fragmentation::ParseOrderAtSiteFromFile(const std::vector<atomId_t> &atomids, std::string &path)
419{
420 Info FunctionInfo(__func__);
421 typedef unsigned char order_t;
422 typedef std::map<atomId_t, order_t> OrderArray_t;
423 OrderArray_t OrderArray;
424 AtomMask_t MaxArray(atomids);
425 bool status;
426 int AtomNr, value;
427 string line;
428 ifstream file;
429
430 line = path + ORDERATSITEFILE;
431 file.open(line.c_str());
432 if (file.good()) {
433 while (!file.eof()) { // parse from file
434 AtomNr = -1;
435 file >> AtomNr;
436 if (AtomNr != -1) { // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)
437 file >> value;
438 OrderArray[AtomNr] = value;
439 file >> value;
440 MaxArray.setValue(AtomNr, (bool)value);
441 //LOG(2, "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << ".");
442 }
443 }
444 file.close();
445
446 // set atom values
447 for(molecule::iterator iter=mol->begin();iter!=mol->end();++iter){
448 (*iter)->AdaptiveOrder = OrderArray[(*iter)->getNr()];
449 (*iter)->MaxOrder = MaxArray.isTrue((*iter)->getNr());
450 }
451 //SetAtomValueToIndexedArray( OrderArray, &atom::getNr(), &atom::AdaptiveOrder );
452 //SetAtomValueToIndexedArray( MaxArray, &atom::getNr(), &atom::MaxOrder );
453
454 LOG(1, "\t ... done.");
455 status = true;
456 } else {
457 LOG(1, "\t ... failed to open file " << line << ".");
458 status = false;
459 }
460
461 return status;
462};
463
464/** Fills the root stack for sites to be used as root in fragmentation depending on order or adaptivity criteria
465 * Again, as in \sa FillBondStructureFromReference steps recursively through each Leaf in this chain list of molecule's.
466 * \param &RootStack stack to be filled
467 * \param AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site
468 * \return true - stack is non-empty, fragmentation necessary, false - stack is empty, no more sites to update
469 */
470void Fragmentation::FillRootStackForSubgraphs(KeyStack &RootStack, const AtomMask_t &AtomMask)
471{
472 for(molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
473 const atom * const Father = (*iter)->GetTrueFather();
474 if (AtomMask.isTrue(Father->getNr())) // apply mask
475 if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen
476 RootStack.push_front((*iter)->getNr());
477 }
478}
479
480/** The indices per keyset are compared to the respective father's Atom::Nr in each subgraph and thus put into \a **&FragmentList.
481 * \param *KeySetList list with all keysets
482 * \param ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
483 * \param **&FragmentList list to be allocated and returned
484 * \param FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
485 * \retuen true - success, false - failure
486 */
487bool Fragmentation::AssignKeySetsToFragment(Graph &KeySetList, ListOfLocalAtoms_t &ListOfLocalAtoms, Graph &FragmentList, bool FreeList)
488{
489 Info FunctionInfo(__func__);
490 bool status = true;
491 size_t KeySetCounter = 0;
492
493 // fill ListOfLocalAtoms if NULL was given
494 if (!mol->FillListOfLocalAtoms(ListOfLocalAtoms, mol->getAtomCount())) {
495 LOG(1, "Filling of ListOfLocalAtoms failed.");
496 return false;
497 }
498
499 if (KeySetList.size() != 0) { // if there are some scanned keysets at all
500 // assign scanned keysets
501 KeySet TempSet;
502 for (Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { // key sets contain global numbers!
503 if (ListOfLocalAtoms[mol->FindAtom(*((*runner).first.begin()))->getNr()] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set
504 // translate keyset to local numbers
505 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
506 TempSet.insert(ListOfLocalAtoms[mol->FindAtom(*sprinter)->getNr()]->getNr());
507 // insert into FragmentList
508 FragmentList.insert(GraphPair(TempSet, pair<int, double> (KeySetCounter++, (*runner).second.second)));
509 }
510 TempSet.clear();
511 }
512 } else
513 LOG(1, "KeySetList is NULL or empty.");
514
515 if (FreeList) {
516 // free the index lookup list
517 ListOfLocalAtoms.clear();
518 }
519 return status;
520}
521
522/** Translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
523 * \param &FragmentList Graph with local numbers per fragment
524 * \param &TotalNumberOfKeySets global key set counter
525 * \param &TotalGraph Graph to be filled with global numbers
526 */
527void Fragmentation::TranslateIndicesToGlobalIDs(Graph &FragmentList, int &TotalNumberOfKeySets, Graph &TotalGraph)
528{
529 Info FunctionInfo(__func__);
530 for (Graph::iterator runner = FragmentList.begin(); runner != FragmentList.end(); runner++) {
531 KeySet TempSet;
532 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
533 TempSet.insert((mol->FindAtom(*sprinter))->GetTrueFather()->getNr());
534 TotalGraph.insert(GraphPair(TempSet, pair<int, double> (TotalNumberOfKeySets++, (*runner).second.second)));
535 }
536}
537
Note: See TracBrowser for help on using the repository browser.