source: src/moleculelist.cpp@ 6f6a8e

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 6f6a8e was 5de3c9, checked in by Frederik Heber <heber@…>, 17 years ago

molecule::CheckOrderAtSite() now interprets negative Orders as adaptive increase by parsing EnergyPerFragment.da
t

positive Order is global increase till all sites have at least this order, Order 0 means single global increase step, negative Order is the exponent in 10{-Order} to give the threshold value: ENERGYPERFRAGMENT is scanned in
to a map (sorted by values) and all fragments still above the threshold are taken into AtomMask for increase. Jo
iner has to write this file with (Root id of Fragment, energy contribution) pairs.

  • Property mode set to 100644
File size: 23.4 KB
Line 
1/** \file MoleculeListClass.cpp
2 *
3 * Function implementations for the class MoleculeListClass.
4 *
5 */
6
7#include "molecules.hpp"
8
9/*********************************** Functions for class MoleculeListClass *************************/
10
11/** Constructor for MoleculeListClass.
12 */
13MoleculeListClass::MoleculeListClass()
14{
15};
16
17/** constructor for MoleculeListClass.
18 * \param NumMolecules number of molecules to allocate for
19 * \param NumAtoms number of atoms to allocate for
20 */
21MoleculeListClass::MoleculeListClass(int NumMolecules, int NumAtoms)
22{
23 ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
24 for (int i=0;i<NumMolecules;i++)
25 ListOfMolecules[i] = NULL;
26 NumberOfMolecules = NumMolecules;
27 NumberOfTopAtoms = NumAtoms;
28};
29
30
31/** Destructor for MoleculeListClass.
32 */
33MoleculeListClass::~MoleculeListClass()
34{
35 cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl;
36 for (int i=0;i<NumberOfMolecules;i++) {
37 if (ListOfMolecules[i] != NULL) { // if NULL don't free
38 cout << Verbose(4) << "ListOfMolecules: Freeing " << ListOfMolecules[i] << "." << endl;
39 delete(ListOfMolecules[i]);
40 ListOfMolecules[i] = NULL;
41 }
42 }
43 cout << Verbose(4) << "Freeing ListOfMolecules." << endl;
44 Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
45};
46
47/** Compare whether two molecules are equal.
48 * \param *a molecule one
49 * \param *n molecule two
50 * \return lexical value (-1, 0, +1)
51 */
52int MolCompare(const void *a, const void *b)
53{
54 int *aList = NULL, *bList = NULL;
55 int Count, Counter, aCounter, bCounter;
56 int flag;
57 atom *aWalker = NULL;
58 atom *bWalker = NULL;
59
60 // sort each atom list and put the numbers into a list, then go through
61 //cout << "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << "." << endl;
62 if ( (**(molecule **)a).AtomCount < (**(molecule **)b).AtomCount ) {
63 return -1;
64 } else { if ((**(molecule **)a).AtomCount > (**(molecule **)b).AtomCount)
65 return +1;
66 else {
67 Count = (**(molecule **)a).AtomCount;
68 aList = (int *) Malloc(sizeof(int)*Count, "MolCompare: *aList");
69 bList = (int *) Malloc(sizeof(int)*Count, "MolCompare: *bList");
70
71 // fill the lists
72 aWalker = (**(molecule **)a).start;
73 bWalker = (**(molecule **)b).start;
74 Counter = 0;
75 aCounter = 0;
76 bCounter = 0;
77 while ((aWalker->next != (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {
78 aWalker = aWalker->next;
79 bWalker = bWalker->next;
80 if (aWalker->GetTrueFather() == NULL)
81 aList[Counter] = Count + (aCounter++);
82 else
83 aList[Counter] = aWalker->GetTrueFather()->nr;
84 if (bWalker->GetTrueFather() == NULL)
85 bList[Counter] = Count + (bCounter++);
86 else
87 bList[Counter] = bWalker->GetTrueFather()->nr;
88 Counter++;
89 }
90 // check if AtomCount was for real
91 flag = 0;
92 if ((aWalker->next == (**(molecule **)a).end) && (bWalker->next != (**(molecule **)b).end)) {
93 flag = -1;
94 } else {
95 if ((aWalker->next != (**(molecule **)a).end) && (bWalker->next == (**(molecule **)b).end))
96 flag = 1;
97 }
98 if (flag == 0) {
99 // sort the lists
100 gsl_heapsort(aList,Count, sizeof(int), CompareDoubles);
101 gsl_heapsort(bList,Count, sizeof(int), CompareDoubles);
102 // compare the lists
103
104 flag = 0;
105 for(int i=0;i<Count;i++) {
106 if (aList[i] < bList[i]) {
107 flag = -1;
108 } else {
109 if (aList[i] > bList[i])
110 flag = 1;
111 }
112 if (flag != 0)
113 break;
114 }
115 }
116 Free((void **)&aList, "MolCompare: *aList");
117 Free((void **)&bList, "MolCompare: *bList");
118 return flag;
119 }
120 }
121 return -1;
122};
123
124/** Simple output of the pointers in ListOfMolecules.
125 * \param *out output stream
126 */
127void MoleculeListClass::Output(ofstream *out)
128{
129 *out<< Verbose(1) << "MoleculeList: ";
130 for (int i=0;i<NumberOfMolecules;i++)
131 *out << ListOfMolecules[i] << "\t";
132 *out << endl;
133};
134
135
136/** Store force indices, i.e. the connection between the nuclear index in the total molecule config and the respective atom in fragment config.
137 * \param *out output stream for debugging
138 * \param *path path to file
139 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
140 * \return true - file written successfully, false - writing failed
141 */
142bool MoleculeListClass::StoreForcesFile(ofstream *out, char *path, int *SortIndex)
143{
144 bool status = true;
145 ofstream ForcesFile;
146 stringstream line;
147 atom *Walker = NULL;
148 element *runner = NULL;
149
150 // open file for the force factors
151 *out << Verbose(1) << "Saving force factors ... ";
152 line << path << "/" << FRAGMENTPREFIX << FORCESFILE;
153 ForcesFile.open(line.str().c_str(), ios::out);
154 if (ForcesFile != NULL) {
155 //cout << Verbose(1) << "Final AtomicForcesList: ";
156 //output << prefix << "Forces" << endl;
157 for(int j=0;j<NumberOfMolecules;j++) {
158 //if (TEList[j] != 0) {
159 runner = ListOfMolecules[j]->elemente->start;
160 while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element
161 runner = runner->next;
162 if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms
163 Walker = ListOfMolecules[j]->start;
164 while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element
165 Walker = Walker->next;
166 if (Walker->type->Z == runner->Z) {
167 if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a rea
168 //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", it
169 ForcesFile << SortIndex[Walker->GetTrueFather()->nr] << "\t";
170 } else // otherwise a -1 to indicate an added saturation hydrogen
171 ForcesFile << "-1\t";
172 }
173 }
174 }
175 }
176 ForcesFile << endl;
177 }
178 ForcesFile.close();
179 *out << Verbose(1) << "done." << endl;
180 } else {
181 status = false;
182 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;
183 }
184 ForcesFile.close();
185
186 return status;
187};
188
189/** Writes a config file for each molecule in the given \a **FragmentList.
190 * \param *out output stream for debugging
191 * \param *configuration standard configuration to attach atoms in fragment molecule to.
192 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
193 * \return true - success (each file was written), false - something went wrong.
194 */
195bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex)
196{
197 ofstream outputFragment;
198 char FragmentName[MAXSTRINGSIZE];
199 char PathBackup[MAXSTRINGSIZE];
200 bool result = true;
201 bool intermediateResult = true;
202 atom *Walker = NULL;
203 vector BoxDimension;
204 char *FragmentNumber;
205 int FragmentCounter = 0;
206 ofstream output;
207
208 // store the fragments as config and as xyz
209 for(int i=0;i<NumberOfMolecules;i++) {
210 // save default path as it is changed for each fragment
211 strcpy(PathBackup, configuration->GetDefaultPath());
212
213 // correct periodic
214 ListOfMolecules[i]->ScanForPeriodicCorrection(out);
215
216 // output xyz file
217 FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
218 sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
219 outputFragment.open(FragmentName, ios::out);
220 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as XYZ ...";
221 if (intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment))
222 *out << " done." << endl;
223 else
224 *out << " failed." << endl;
225 result = result && intermediateResult;
226 outputFragment.close();
227 outputFragment.clear();
228
229 *out << Verbose(2) << "Contained atoms: ";
230 Walker = ListOfMolecules[i]->start;
231 while (Walker->next != ListOfMolecules[i]->end) {
232 Walker = Walker->next;
233 *out << Walker->Name << " ";
234 }
235 *out << endl;
236 // prepare output of config file
237 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
238 outputFragment.open(FragmentName, ios::out);
239 strcpy(PathBackup, configuration->configpath);
240 sprintf(FragmentName, "%s/%s%s/", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
241
242 // center on edge
243 ListOfMolecules[i]->CenterEdge(out, &BoxDimension);
244 ListOfMolecules[i]->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary
245 int j = -1;
246 for (int k=0;k<3;k++) {
247 j += k+1;
248 BoxDimension.x[k] = 5.;
249 ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
250 }
251 ListOfMolecules[i]->Translate(&BoxDimension);
252
253 // also calculate necessary orbitals
254 ListOfMolecules[i]->CountElements(); // this is a bugfix, atoms should should actually be added correctly to this fragment
255 ListOfMolecules[i]->CalculateOrbitals(*configuration);
256
257 // change path in config
258 configuration->SetDefaultPath(FragmentName);
259 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as config ...";
260 if (intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i]))
261 *out << " done." << endl;
262 else
263 *out << " failed." << endl;
264 // restore old config
265 configuration->SetDefaultPath(PathBackup);
266
267 result = result && intermediateResult;
268 outputFragment.close();
269 outputFragment.clear();
270 Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");
271 }
272 cout << " done." << endl;
273
274 // printing final number
275 *out << "Final number of fragments: " << FragmentCounter << "." << endl;
276
277 return result;
278};
279
280/******************************************* Class MoleculeLeafClass ************************************************/
281
282/** Constructor for MoleculeLeafClass root leaf.
283 * \param *Up Leaf on upper level
284 * \param *PreviousLeaf NULL - We are the first leaf on this level, otherwise points to previous in list
285 */
286//MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *Up = NULL, MoleculeLeafClass *Previous = NULL)
287MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
288{
289// if (Up != NULL)
290// if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
291// Up->DownLeaf = this;
292// UpLeaf = Up;
293// DownLeaf = NULL;
294 Leaf = NULL;
295 previous = PreviousLeaf;
296 if (previous != NULL) {
297 MoleculeLeafClass *Walker = previous->next;
298 previous->next = this;
299 next = Walker;
300 } else {
301 next = NULL;
302 }
303};
304
305/** Destructor for MoleculeLeafClass.
306 */
307MoleculeLeafClass::~MoleculeLeafClass()
308{
309// if (DownLeaf != NULL) {// drop leaves further down
310// MoleculeLeafClass *Walker = DownLeaf;
311// MoleculeLeafClass *Next;
312// do {
313// Next = Walker->NextLeaf;
314// delete(Walker);
315// Walker = Next;
316// } while (Walker != NULL);
317// // Last Walker sets DownLeaf automatically to NULL
318// }
319 // remove the leaf itself
320 if (Leaf != NULL) {
321 delete(Leaf);
322 Leaf = NULL;
323 }
324 // remove this Leaf from level list
325 if (previous != NULL)
326 previous->next = next;
327// } else { // we are first in list (connects to UpLeaf->DownLeaf)
328// if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
329// NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node
330// if (UpLeaf != NULL)
331// UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first
332// }
333// UpLeaf = NULL;
334 if (next != NULL) // are we last in list
335 next->previous = previous;
336 next = NULL;
337 previous = NULL;
338};
339
340/** Adds \a molecule leaf to the tree.
341 * \param *ptr ptr to molecule to be added
342 * \param *Previous previous MoleculeLeafClass referencing level and which on the level
343 * \return true - success, false - something went wrong
344 */
345bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous)
346{
347 return false;
348};
349
350/** Fills the bond structure of this chain list subgraphs that are derived from a complete \a *reference molecule.
351 * Calls this routine in each MoleculeLeafClass::next subgraph if it's not NULL.
352 * \param *out output stream for debugging
353 * \param *reference reference molecule with the bond structure to be copied
354 * \param &FragmentCounter Counter needed to address \a **ListOfLocalAtoms
355 * \param ***ListOfLocalAtoms Lookup table for each subgraph and index of each atom in \a *reference, may be NULL on start, then it is filled
356 * \param FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
357 * \return true - success, false - faoilure
358 */
359bool MoleculeLeafClass::FillBondStructureFromReference(ofstream *out, molecule *reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList)
360{
361 atom *Walker = NULL, *OtherWalker = NULL;
362 bond *Binder = NULL;
363 bool status = true;
364 int AtomNo;
365
366 // fill ListOfLocalAtoms if NULL was given
367 if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {
368 *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;
369 return false;
370 }
371
372 if (status) {
373 *out << Verbose(1) << "Creating adjacency list for subgraph " << this << "." << endl;
374 Walker = Leaf->start;
375 while (Walker->next != Leaf->end) {
376 Walker = Walker->next;
377 AtomNo = Walker->father->nr; // global id of the current walker
378 for(int i=0;i<reference->NumberOfBondsPerAtom[AtomNo];i++) { // go through father's bonds and copy them all
379 Binder = reference->ListOfBondsPerAtom[AtomNo][i];
380 OtherWalker = ListOfLocalAtoms[FragmentCounter][Binder->GetOtherAtom(Walker->father)->nr]; // local copy of current bond partner of walker
381 if (OtherWalker != NULL) {
382 if (OtherWalker->nr > Walker->nr)
383 Leaf->AddBond(Walker, OtherWalker, Binder->BondDegree);
384 } else {
385 *out << Verbose(1) << "OtherWalker = ListOfLocalAtoms[" << FragmentCounter << "][" << Binder->GetOtherAtom(Walker->father)->nr << "] is NULL!" << endl;
386 status = false;
387 }
388 }
389 }
390 Leaf->CreateListOfBondsPerAtom(out);
391 FragmentCounter++;
392 if (next != NULL)
393 status = next->FillBondStructureFromReference(out, reference, FragmentCounter, ListOfLocalAtoms);
394 }
395
396 if (FreeList) {
397 // free the index lookup list
398 Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::FillBondStructureFromReference - **ListOfLocalAtoms[]");
399 if (ListOfLocalAtoms[FragmentCounter] == NULL)
400 Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
401 }
402 FragmentCounter--;
403 return status;
404};
405
406/** Fills the root stack for sites to be used as root in fragmentation depending on order or adaptivity criteria
407 * Again, as in \sa FillBondStructureFromReference steps recursively through each Leaf in this chain list of molecule's.
408 * \param *out output stream for debugging
409 * \param *&RootStack stack to be filled
410 * \param *AtomMask defines true/false per global Atom::nr to mask in/out each nuclear site
411 * \param Order desired bond order for all sites
412 * \param &FragmentCounter counts through the fragments in this MoleculeLeafClass
413 * \return true - stack is non-empty, fragmentation necessary, false - stack is empty, no more sites to update
414 */
415bool MoleculeLeafClass::FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, bool *AtomMask, int Order, int &FragmentCounter)
416{
417 atom *Walker = NULL, *Father = NULL;
418
419 if (RootStack != NULL) {
420 if (Order == -1) { // means we want to increase order adaptively
421 cerr << "Adaptive chosing of sites not yet implemented!" << endl;
422 } else { // means we just want to increase it at every site by one
423 // find first root candidates
424 if (&(RootStack[FragmentCounter]) != NULL) {
425 RootStack[FragmentCounter].clear();
426 Walker = Leaf->start;
427 while (Walker->next != Leaf->end) { // go through all (non-hydrogen) atoms
428 Walker = Walker->next;
429 Father = Walker->GetTrueFather();
430 if (AtomMask[Father->nr]) // apply mask
431 #ifdef ADDHYDROGEN
432 if (Walker->type->Z != 1) // skip hydrogen
433 #endif
434 if (Father->AdaptiveOrder < Order) // only if Order is still greater
435 RootStack[FragmentCounter].push_front(Walker->nr);
436 }
437 if (next != NULL)
438 next->FillRootStackForSubgraphs(out, RootStack, AtomMask, Order, ++FragmentCounter);
439 } else {
440 *out << Verbose(1) << "Rootstack[" << FragmentCounter << "] is NULL." << endl;
441 return false;
442 }
443 }
444 FragmentCounter--;
445 return true;
446 } else {
447 *out << Verbose(1) << "Rootstack is NULL." << endl;
448 return false;
449 }
450};
451
452/** Fills a lookup list of father's Atom::nr -> atom for each subgraph.
453 * \param *out output stream fro debugging
454 * \param ***ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
455 * \param &FragmentCounter counts the fragments as we move along the list
456 * \param GlobalAtomCount number of atoms in the complete molecule
457 * \param &FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
458 * \return true - succes, false - failure
459 */
460bool MoleculeLeafClass::FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, int &FragmentCounter, int GlobalAtomCount, bool &FreeList)
461{
462 bool status = true;
463
464 int Counter = Count();
465 if (ListOfLocalAtoms == NULL) { // allocated initial pointer
466 // allocate and set each field to NULL
467 ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **)*Counter, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
468 if (ListOfLocalAtoms != NULL) {
469 for (int i=0;i<Counter;i++)
470 ListOfLocalAtoms[i] = NULL;
471 FreeList = FreeList && true;
472 } else
473 status = false;
474 }
475
476 if ((ListOfLocalAtoms != NULL) && (ListOfLocalAtoms[FragmentCounter] == NULL)) { // allocate and fill list of this fragment/subgraph
477 status = status && CreateFatherLookupTable(out, Leaf->start, Leaf->end, ListOfLocalAtoms[FragmentCounter], GlobalAtomCount);
478 FreeList = FreeList && true;
479 }
480
481 return status;
482};
483
484/** The indices per keyset are compared to the respective father's Atom::nr in each subgraph and thus put into \a **&FragmentList.
485 * \param *out output stream fro debugging
486 * \param *reference reference molecule with the bond structure to be copied
487 * \param *KeySetList list with all keysets
488 * \param ***ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
489 * \param **&FragmentList list to be allocated and returned
490 * \param &FragmentCounter counts the fragments as we move along the list
491 * \param FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
492 * \retuen true - success, false - failure
493 */
494bool MoleculeLeafClass::AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList)
495{
496 bool status = true;
497 int KeySetCounter = 0;
498
499 // fill ListOfLocalAtoms if NULL was given
500 if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {
501 *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;
502 return false;
503 }
504
505 // allocate fragment list
506 if (FragmentList == NULL) {
507 KeySetCounter = Count();
508 FragmentList = (Graph **) Malloc(sizeof(Graph *)*KeySetCounter, "MoleculeLeafClass::AssignKeySetsToFragment - **FragmentList");
509 for(int i=0;i<KeySetCounter;i++)
510 FragmentList[i] = NULL;
511 KeySetCounter = 0;
512 }
513
514 if ((KeySetList != NULL) && (KeySetList->size() != 0)) { // if there are some scanned keysets at all
515 // assign scanned keysets
516 if (FragmentList[FragmentCounter] == NULL)
517 FragmentList[FragmentCounter] = new Graph;
518 KeySet *TempSet = new KeySet;
519 for(Graph::iterator runner = KeySetList->begin();runner != KeySetList->end(); runner++) { // key sets contain global numbers!
520 if ( ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*((*runner).first.begin()))->nr]->nr != -1) {// as we may assume that that bond structure is unchanged, we only test the first key in each set
521 // translate keyset to local numbers
522 for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
523 TempSet->insert(ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*sprinter)->nr]->nr);
524 // insert into FragmentList
525 FragmentList[FragmentCounter]->insert(GraphPair (*TempSet, pair<int,double>(KeySetCounter++, (*runner).second.second)));
526 }
527 TempSet->clear();
528 }
529 delete(TempSet);
530 if (KeySetCounter == 0) {// if there are no keysets, delete the list
531 *out << Verbose(1) << "KeySetCounter is zero, deleting FragmentList." << endl;
532 delete(FragmentList[FragmentCounter]);
533 } else
534 *out << Verbose(1) << KeySetCounter << " keysets were assigned to subgraph " << FragmentCounter << "." << endl;
535 FragmentCounter++;
536 if (next != NULL)
537 next->AssignKeySetsToFragment(out, reference, KeySetList, ListOfLocalAtoms, FragmentList, FragmentCounter, FreeList);
538 FragmentCounter--;
539 } else
540 *out << Verbose(1) << "KeySetList is NULL or empty." << endl;
541
542 return status;
543};
544
545/** Translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
546 * \param *out output stream for debugging
547 * \param **FragmentList Graph with local numbers per fragment
548 * \param &FragmentCounter counts the fragments as we move along the list
549 * \param &TotalNumberOfKeySets global key set counter
550 * \param &TotalGraph Graph to be filled with global numbers
551 */
552void MoleculeLeafClass::TranslateIndicesToGlobalIDs(ofstream *out, Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph)
553{
554 KeySet *TempSet = new KeySet;
555 for(Graph::iterator runner = FragmentList[FragmentCounter]->begin(); runner != FragmentList[FragmentCounter]->end(); runner++) {
556 for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
557 TempSet->insert((Leaf->FindAtom(*sprinter))->GetTrueFather()->nr);
558 TotalGraph.insert(GraphPair(*TempSet, pair<int,double>(TotalNumberOfKeySets++, (*runner).second.second)));
559 TempSet->clear();
560 }
561 delete(TempSet);
562 if (next != NULL)
563 next->TranslateIndicesToGlobalIDs(out, FragmentList, ++FragmentCounter, TotalNumberOfKeySets, TotalGraph);
564 FragmentCounter--;
565};
566
567/** Simply counts the number of items in the list, from given MoleculeLeafClass.
568 * \return number of items
569 */
570int MoleculeLeafClass::Count() const
571{
572 if (next != NULL)
573 return next->Count()+1;
574 else
575 return 1;
576};
Note: See TracBrowser for help on using the repository browser.