source: molecuilder/src/moleculelist.cpp@ cffff8

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

HUGE REWRITE to allow for adaptive increase of the bond order, first working commit

Lots of code was thrown out:
-BottomUp, TopDown and GetAtomicFragments
-TEFactors are now used as "CreationCounters", i.e. the count how often a fragment as been created (ideal would be only once)
-ReduceToUniqueOnes and stuff all thrown out, since they are out-dated since use of hash table
Other changes:
-CreateListofUniqueFragments renamed to PowerSetGenerator
-PowerSetGenerator goes not over all reachable roots, but one given by calling function FragmentBOSSANOVA
-FragmentBOSSANOVA loops over all possible root sites and hands this over to PowerSetGenerator
-by the virtue of the hash table it is not important anymore whether created keysets are unique or not, as this is recognized in log(n). Hence, the label < label is not important anymore (and not applicable in an adaptive scheme with old, parsed keysets and unknown labels) (THIS IS HOWEVER NOT DONE YET!)
The setup is then as follows:

  1. FragmentMolecule
    1. parses adjacency, keysets and orderatsite files
    2. performs DFS to find connected subgraphs (to leave this in was a design decision: might be useful later)
    3. a RootStack is created for every subgraph (here, later we implement the "update 10 sites with highest energy contribution", and that's why this consciously not done in the following loop)
    4. in a loop over all subgraphs

d1. calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure
d2. creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)

  1. combines the generated molecule lists from all subgraphs
  2. saves to disk: fragment configs, adjacency, orderatsite, keyset files
  1. FragmentBOSSANOVA
    1. constructs a complete keyset of the molecule
    2. In a loop over all possible roots from the given rootstack

b1. increases order of root site
b2. calls PowerSetGenerator with this order, the complete keyset and the rootkeynr
b3. for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset as the restricted one and each site in the set as the root)
b4. these are merged into a fragment list of keysets

  1. All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return
  1. PowerSetGenerator
    1. initialises UniqueFragments structure
    2. fills edge list via BFS
    3. creates the fragment by calling recursive function SPFragmentGenerator with UniqueFragments structure, 0 as root distance, the edge set, its dimension and the current suborder
    4. Free'ing structure
  2. SPFragmentGenerator (nothing much has changed here)
    1. loops over every possible combination (2dimension of edge set)

a1. inserts current set, if there's still space left

a11. yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root distance+1
a12. no: stores fragment into keyset list by calling InsertFragmentIntoGraph

a2. removes all items added into the snake stack (in UniqueFragments structure) added during level (root distance) and current set

  • Property mode set to 100644
File size: 11.1 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/** Writes a config file for each molecule in the given \a **FragmentList.
136 * \param *out output stream for debugging
137 * \param *configuration standard configuration to attach atoms in fragment molecule to.
138 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
139 * \return true - success (each file was written), false - something went wrong.
140 */
141bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex)
142{
143 ofstream outputFragment;
144 char FragmentName[MAXSTRINGSIZE];
145 char PathBackup[MAXSTRINGSIZE];
146 bool result = true;
147 bool intermediateResult = true;
148 atom *Walker = NULL;
149 vector BoxDimension;
150 char *FragmentNumber;
151 int FragmentCounter = 0;
152 ofstream output;
153
154 // store the fragments as config and as xyz
155 for(int i=0;i<NumberOfMolecules;i++) {
156 // save default path as it is changed for each fragment
157 strcpy(PathBackup, configuration->GetDefaultPath());
158
159 // correct periodic
160 ListOfMolecules[i]->ScanForPeriodicCorrection(out);
161
162 // output xyz file
163 FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
164 sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
165 outputFragment.open(FragmentName, ios::out);
166 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as XYZ ...";
167 if (intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment))
168 *out << " done." << endl;
169 else
170 *out << " failed." << endl;
171 result = result && intermediateResult;
172 outputFragment.close();
173 outputFragment.clear();
174
175 *out << Verbose(2) << "Contained atoms: ";
176 Walker = ListOfMolecules[i]->start;
177 while (Walker->next != ListOfMolecules[i]->end) {
178 Walker = Walker->next;
179 *out << Walker->Name << " ";
180 }
181 *out << endl;
182 // prepare output of config file
183 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
184 outputFragment.open(FragmentName, ios::out);
185 strcpy(PathBackup, configuration->configpath);
186 sprintf(FragmentName, "%s/%s%s/", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
187
188 // center on edge
189 ListOfMolecules[i]->CenterEdge(out, &BoxDimension);
190 ListOfMolecules[i]->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary
191 int j = -1;
192 for (int k=0;k<3;k++) {
193 j += k+1;
194 BoxDimension.x[k] = 5.;
195 ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
196 }
197 ListOfMolecules[i]->Translate(&BoxDimension);
198
199 // also calculate necessary orbitals
200 ListOfMolecules[i]->CountElements(); // this is a bugfix, atoms should should actually be added correctly to this fragment
201 ListOfMolecules[i]->CalculateOrbitals(*configuration);
202
203 // change path in config
204 configuration->SetDefaultPath(FragmentName);
205 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as config ...";
206 if (intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i]))
207 *out << " done." << endl;
208 else
209 *out << " failed." << endl;
210 // restore old config
211 configuration->SetDefaultPath(PathBackup);
212
213 result = result && intermediateResult;
214 outputFragment.close();
215 outputFragment.clear();
216 Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");
217 }
218
219 // open KeySet file
220 sprintf(FragmentName, "%s/%s%s", configuration->configpath, FRAGMENTPREFIX , KEYSETFILE);
221 output.open(FragmentName, ios::out);
222 *out << Verbose(2) << "Saving " << FRAGMENTPREFIX << " key sets of each subgraph ...";
223 for(int j=0;j<NumberOfMolecules;j++) {
224 Walker = ListOfMolecules[j]->start;
225 while(Walker->next != ListOfMolecules[j]->end) {
226 Walker = Walker->next;
227#ifdef ADDHYDROGEN
228 if ((Walker->GetTrueFather() != NULL) && (Walker->type->Z != 1)) // if there is a real father, prints its index
229#else
230 if ((Walker->GetTrueFather() != NULL)) // if there is a real father, prints its index
231#endif
232 output << Walker->GetTrueFather()->nr << "\t";
233#ifdef ADDHYDROGEN
234 else // otherwise a -1 to indicate an added saturation hydrogen
235 output << "-1\t";
236#endif
237 }
238 output << endl;
239 }
240 output.close();
241 *out << " done." << endl;
242
243 // printing final number
244 *out << "Final number of fragments: " << FragmentCounter << "." << endl;
245
246 return result;
247};
248
249/******************************************* Class MoleculeLeafClass ************************************************/
250
251/** Constructor for MoleculeLeafClass root leaf.
252 * \param *Up Leaf on upper level
253 * \param *PreviousLeaf NULL - We are the first leaf on this level, otherwise points to previous in list
254 */
255//MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *Up = NULL, MoleculeLeafClass *Previous = NULL)
256MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
257{
258// if (Up != NULL)
259// if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
260// Up->DownLeaf = this;
261// UpLeaf = Up;
262// DownLeaf = NULL;
263 Leaf = NULL;
264 previous = PreviousLeaf;
265 if (previous != NULL) {
266 MoleculeLeafClass *Walker = previous->next;
267 previous->next = this;
268 next = Walker;
269 } else {
270 next = NULL;
271 }
272};
273
274/** Destructor for MoleculeLeafClass.
275 */
276MoleculeLeafClass::~MoleculeLeafClass()
277{
278// if (DownLeaf != NULL) {// drop leaves further down
279// MoleculeLeafClass *Walker = DownLeaf;
280// MoleculeLeafClass *Next;
281// do {
282// Next = Walker->NextLeaf;
283// delete(Walker);
284// Walker = Next;
285// } while (Walker != NULL);
286// // Last Walker sets DownLeaf automatically to NULL
287// }
288 // remove the leaf itself
289 if (Leaf != NULL) {
290 delete(Leaf);
291 Leaf = NULL;
292 }
293 // remove this Leaf from level list
294 if (previous != NULL)
295 previous->next = next;
296// } else { // we are first in list (connects to UpLeaf->DownLeaf)
297// if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
298// NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node
299// if (UpLeaf != NULL)
300// UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first
301// }
302// UpLeaf = NULL;
303 if (next != NULL) // are we last in list
304 next->previous = previous;
305 next = NULL;
306 previous = NULL;
307};
308
309/** Adds \a molecule leaf to the tree.
310 * \param *ptr ptr to molecule to be added
311 * \param *Previous previous MoleculeLeafClass referencing level and which on the level
312 * \return true - success, false - something went wrong
313 */
314bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous)
315{
316 return false;
317};
Note: See TracBrowser for help on using the repository browser.