source: molecuilder/src/moleculelist.cpp@ 255d13

Last change on this file since 255d13 was 255d13, checked in by Frederik Heber <heber@…>, 17 years ago

FillBondStructureFromReference: previous == NULL was bad idea, new functions Count() and FillRootStackForSubgraphs()

FillBondStructureFromReference: checking previous == NULL if we are the first is bad due to starting node (with mpty leaf) being actual previous, hence we decrease FragmentCounter before return, thus climb up the ladder and then down again and free in this course. Initial list pointer is free'd if FragmentCounter == 0: much better!
Count: simply counts the number of further leaves in the chain list, also by the neat recursive trick
FillRootStackForSubgraphs: Fills a rootstack by going through the leaves of a subgraph and checking on their atom's father's atom::AdaptiveOrder against given Order. This is further abstraction for molecule::FragmentMolecule()

  • Property mode set to 100644
File size: 17.7 KB
RevLine 
[a0bcf1]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");
[c75363]24 for (int i=0;i<NumMolecules;i++)
[a0bcf1]25 ListOfMolecules[i] = NULL;
26 NumberOfMolecules = NumMolecules;
27 NumberOfTopAtoms = NumAtoms;
28};
29
30
31/** Destructor for MoleculeListClass.
32 */
33MoleculeListClass::~MoleculeListClass()
34{
[c75363]35 cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl;
[a0bcf1]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
[c75363]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 */
[a0bcf1]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
[115bf4]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
[a0bcf1]189/** Writes a config file for each molecule in the given \a **FragmentList.
[c75363]190 * \param *out output stream for debugging
[a0bcf1]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 */
[c75363]195bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex)
[a0bcf1]196{
197 ofstream outputFragment;
[c510a7]198 char FragmentName[MAXSTRINGSIZE];
199 char PathBackup[MAXSTRINGSIZE];
[a0bcf1]200 bool result = true;
201 bool intermediateResult = true;
202 atom *Walker = NULL;
203 vector BoxDimension;
204 char *FragmentNumber;
205 int FragmentCounter = 0;
[23409a]206 ofstream output;
[a0bcf1]207
208 // store the fragments as config and as xyz
209 for(int i=0;i<NumberOfMolecules;i++) {
[c75363]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 << " ";
[a0bcf1]234 }
[c75363]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.;
[a0bcf1]250 }
[c75363]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");
[a0bcf1]271 }
[115bf4]272 cout << " done." << endl;
[a0bcf1]273
274 // printing final number
[c75363]275 *out << "Final number of fragments: " << FragmentCounter << "." << endl;
[a0bcf1]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};
[b8eb3a]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 if (ListOfLocalAtoms == NULL) { // allocated initial pointer
367 // count the number of fragments
368 MoleculeLeafClass *MolecularWalker = this;
369 while (MolecularWalker->next != NULL) {
370 MolecularWalker = MolecularWalker->next;
371 FragmentCounter++;
372 }
373 // allocate and set each field to NULL
374 ListOfLocalAtoms = (atom ***) Malloc(sizeof(atom **)*(FragmentCounter+1), "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
375 if (ListOfLocalAtoms == NULL)
376 return false;
377 for (int i=0;i<=FragmentCounter;i++)
378 ListOfLocalAtoms[i] = NULL;
379 FragmentCounter = 0;
380 FreeList = FreeList && true;
381 }
382 if (ListOfLocalAtoms[FragmentCounter] == NULL) { // allocate and fill list of this fragment/subgraph
383 status = status && CreateFatherLookupTable(out, Leaf->start, Leaf->end, ListOfLocalAtoms[FragmentCounter], reference->AtomCount);
384 FreeList = FreeList && true;
385 }
386
387 if (status) {
388 *out << Verbose(1) << "Creating adjacency list for subgraph " << this << "." << endl;
389 Walker = Leaf->start;
390 while (Walker->next != Leaf->end) {
391 Walker = Walker->next;
392 AtomNo = Walker->father->nr; // global id of the current walker
393 for(int i=0;i<reference->NumberOfBondsPerAtom[AtomNo];i++) { // go through father's bonds and copy them all
394 Binder = reference->ListOfBondsPerAtom[AtomNo][i];
395 OtherWalker = ListOfLocalAtoms[FragmentCounter][Binder->GetOtherAtom(Walker->father)->nr]; // local copy of current bond partner of walker
396 if (OtherWalker != NULL) {
397 if (OtherWalker->nr > Walker->nr)
398 Leaf->AddBond(Walker, OtherWalker, Binder->BondDegree);
399 } else {
400 *out << Verbose(1) << "OtherWalker = ListOfLocalAtoms[" << FragmentCounter << "][" << Binder->GetOtherAtom(Walker->father)->nr << "] is NULL!" << endl;
401 status = false;
402 }
403 }
404 }
405 Leaf->CreateListOfBondsPerAtom(out);
406 FragmentCounter++;
407 if (next != NULL)
408 status = next->FillBondStructureFromReference(out, reference, FragmentCounter, ListOfLocalAtoms);
409 }
410
411 if (FreeList) {
412 // free the index lookup list
[255d13]413 Free((void **)&ListOfLocalAtoms[FragmentCounter], "MoleculeLeafClass::FillBondStructureFromReference - **ListOfLocalAtoms[]");
414 if (ListOfLocalAtoms[FragmentCounter] == NULL)
[b8eb3a]415 Free((void **)&ListOfLocalAtoms, "MoleculeLeafClass::FillBondStructureFromReference - ***ListOfLocalAtoms");
416 }
[255d13]417 FragmentCounter--;
[b8eb3a]418 return status;
419};
420
[255d13]421/** Fills the root stack for sites to be used as root in fragmentation depending on order or adaptivity criteria
422 * Again, as in \sa FillBondStructureFromReference steps recursively through each Leaf in this chain list of molecule's.
423 * \param *out output stream for debugging
424 * \param *&RootStack stack to be filled
425 * \param Order desired bond order for all sites
426 * \param &FragmentCounter counts through the fragments in this MoleculeLeafClass
427 * \return true - stack is non-empty, fragmentation necessary, false - stack is empty, no more sites to update
428 */
429bool MoleculeLeafClass::FillRootStackForSubgraphs(ofstream *out, KeyStack *&RootStack, int Order, int &FragmentCounter)
430{
431 atom *Walker = NULL;
432
433 if (RootStack != NULL) {
434 if (Order == -1) { // means we want to increase order adaptively
435 cerr << "Adaptive chosing of sites not yet implemented!" << endl;
436 } else { // means we just want to increase it at every site by one
437 // find first root candidates
438 if (&(RootStack[FragmentCounter]) != NULL) {
439 RootStack[FragmentCounter].clear();
440 Walker = Leaf->start;
441 while (Walker->next != Leaf->end) { // go through all (non-hydrogen) atoms
442 Walker = Walker->next;
443 #ifdef ADDHYDROGEN
444 if (Walker->type->Z != 1) // skip hydrogen
445 #endif
446 if (Walker->GetTrueFather()->AdaptiveOrder < Order) // only if Order is still greater
447 RootStack[FragmentCounter].push_front(Walker->nr);
448 }
449 if (next != NULL)
450 next->FillRootStackForSubgraphs(out, RootStack, Order, ++FragmentCounter);
451 } else
452 return false;
453 }
454 return true;
455 } else
456 return false;
457};
[b8eb3a]458
[255d13]459/** Simply counts the number of items in the list, from given MoleculeLeafClass.
460 * \return number of items
461 */
462int MoleculeLeafClass::Count()
463{
464 if (next != NULL)
465 return next->Count()+1;
466 else
467 return 1;
468};
Note: See TracBrowser for help on using the repository browser.