source: src/moleculelist.cpp@ d2a294

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

new function FillListOfLocalAtoms() checks whether List needs filling or is already present, Count() const

Count() is now Count() const
new function FillListOfLocalAtoms() checks for NULL pointers and if found fills the list by calling CreateFatherLookupTable()

  • Property mode set to 100644
File size: 21.9 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 Order desired bond order for all sites
411 * \param &FragmentCounter counts through the fragments in this MoleculeLeafClass
412 * \return true - stack is non-empty, fragmentation necessary, false - stack is empty, no more sites to update
413 */
414bool MoleculeLeafClass::FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, int Order, int &FragmentCounter)
415{
416 atom *Walker = NULL;
417
418 if (RootStack != NULL) {
419 if (Order == -1) { // means we want to increase order adaptively
420 cerr << "Adaptive chosing of sites not yet implemented!" << endl;
421 } else { // means we just want to increase it at every site by one
422 // find first root candidates
423 if (&(RootStack[FragmentCounter]) != NULL) {
424 RootStack[FragmentCounter].clear();
425 Walker = Leaf->start;
426 while (Walker->next != Leaf->end) { // go through all (non-hydrogen) atoms
427 Walker = Walker->next;
428 #ifdef ADDHYDROGEN
429 if (Walker->type->Z != 1) // skip hydrogen
430 #endif
431 if (Walker->GetTrueFather()->AdaptiveOrder < Order) // only if Order is still greater
432 RootStack[FragmentCounter].push_front(Walker->nr);
433 }
434 if (next != NULL)
435 next->FillRootStackForSubgraphs(out, RootStack, Order, ++FragmentCounter);
436 } else {
437 *out << Verbose(1) << "Rootstack[" << FragmentCounter << "] is NULL." << endl;
438 return false;
439 }
440 }
441 FragmentCounter--;
442 return true;
443 } else {
444 *out << Verbose(1) << "Rootstack is NULL." << endl;
445 return false;
446 }
447};
448
449/** Fills a lookup list of father's Atom::nr -> atom for each subgraph.
450 * \param *out output stream fro debugging
451 * \param ***ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
452 * \param &FragmentCounter counts the fragments as we move along the list
453 * \param GlobalAtomCount number of atoms in the complete molecule
454 * \param &FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
455 * \return true - succes, false - failure
456 */
457bool MoleculeLeafClass::FillListOfLocalAtoms(ofstream *out, atom ***&ListOfLocalAtoms, int &FragmentCounter, int GlobalAtomCount, bool &FreeList)
458{
459 bool status = true;
460
461 int Counter = Count();
462 if (ListOfLocalAtoms == NULL) { // allocated initial pointer
463 // allocate and set each field to NULL
464 ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **)*Counter, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
465 if (ListOfLocalAtoms != NULL) {
466 for (int i=0;i<Counter;i++)
467 ListOfLocalAtoms[i] = NULL;
468 FreeList = FreeList && true;
469 } else
470 status = false;
471 }
472
473 if ((ListOfLocalAtoms != NULL) && (ListOfLocalAtoms[FragmentCounter] == NULL)) { // allocate and fill list of this fragment/subgraph
474 status = status && CreateFatherLookupTable(out, Leaf->start, Leaf->end, ListOfLocalAtoms[FragmentCounter], GlobalAtomCount);
475 FreeList = FreeList && true;
476 }
477
478 return status;
479};
480
481/** The indices per keyset are compared to the respective father's Atom::nr in each subgraph and thus put into \a **&FragmentList.
482 * \param *out output stream fro debugging
483 * \param *reference reference molecule with the bond structure to be copied
484 * \param *KeySetList list with all keysets
485 * \param ***ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
486 * \param **&FragmentList list to be allocated and returned
487 * \param &FragmentCounter counts the fragments as we move along the list
488 * \param FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
489 * \retuen true - success, false - failure
490 */
491bool MoleculeLeafClass::AssignKeySetsToFragment(ofstream *out, molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList)
492{
493 bool status = true;
494 int KeySetCounter = 0;
495
496 // fill ListOfLocalAtoms if NULL was given
497 if (!FillListOfLocalAtoms(out, ListOfLocalAtoms, FragmentCounter, reference->AtomCount, FreeList)) {
498 *out << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl;
499 return false;
500 }
501
502 // allocate fragment list
503 if (FragmentList == NULL) {
504 KeySetCounter = Count();
505 FragmentList = (Graph **) Malloc(sizeof(Graph *)*KeySetCounter, "molecule::FragmentMolecule - **BondFragments");
506 for(int i=0;i<KeySetCounter;i++)
507 FragmentList[i] = NULL;
508 KeySetCounter = 0;
509 }
510
511 if ((KeySetList != NULL) && (KeySetList->size() != 0)) { // if there are some scanned keysets at all
512 // assign scanned keysets
513 if (FragmentList[FragmentCounter] == NULL)
514 FragmentList[FragmentCounter] = new Graph;
515 KeySet *TempSet = new KeySet;
516 for(Graph::iterator runner = KeySetList->begin();runner != KeySetList->end(); runner++) { // key sets contain global numbers!
517 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
518 // translate keyset to local numbers
519 for(KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
520 TempSet->insert(ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*sprinter)->nr]->nr);
521 // insert into FragmentList
522 FragmentList[FragmentCounter]->insert(GraphPair (*TempSet, pair<int,double>(KeySetCounter++, (*runner).second.second)));
523 }
524 TempSet->clear();
525 }
526 delete(TempSet);
527 if (KeySetCounter == 0) {// if there are no keysets, delete the list
528 *out << Verbose(1) << "KeySetCounter is zero, deleting FragmentList." << endl;
529 delete(FragmentList[FragmentCounter]);
530 } else
531 *out << Verbose(1) << KeySetCounter << " keysets were assigned to subgraph " << FragmentCounter << "." << endl;
532 FragmentCounter++;
533 if (next != NULL)
534 next->AssignKeySetsToFragment(out, reference, KeySetList, ListOfLocalAtoms, FragmentList, FragmentCounter, FreeList);
535 FragmentCounter--;
536 } else
537 *out << Verbose(1) << "KeySetList is NULL or empty." << endl;
538
539 return status;
540};
541
542/** Simply counts the number of items in the list, from given MoleculeLeafClass.
543 * \return number of items
544 */
545int MoleculeLeafClass::Count() const
546{
547 if (next != NULL)
548 return next->Count()+1;
549 else
550 return 1;
551};
Note: See TracBrowser for help on using the repository browser.