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 | */
|
---|
13 | MoleculeListClass::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 | */
|
---|
21 | MoleculeListClass::MoleculeListClass(int NumMolecules, int NumAtoms)
|
---|
22 | {
|
---|
23 | TEList = (double*) Malloc(sizeof(double)*NumMolecules, "MoleculeListClass:MoleculeListClass: *TEList");
|
---|
24 | ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
|
---|
25 | for (int i=0;i<NumMolecules;i++) {
|
---|
26 | TEList[i] = 0.;
|
---|
27 | ListOfMolecules[i] = NULL;
|
---|
28 | }
|
---|
29 | NumberOfMolecules = NumMolecules;
|
---|
30 | NumberOfTopAtoms = NumAtoms;
|
---|
31 | };
|
---|
32 |
|
---|
33 |
|
---|
34 | /** Destructor for MoleculeListClass.
|
---|
35 | */
|
---|
36 | MoleculeListClass::~MoleculeListClass()
|
---|
37 | {
|
---|
38 | cout << Verbose(3) << this << ": Freeing ListOfMolcules and TEList." << endl;
|
---|
39 | for (int i=0;i<NumberOfMolecules;i++) {
|
---|
40 | if (ListOfMolecules[i] != NULL) { // if NULL don't free
|
---|
41 | cout << Verbose(4) << "ListOfMolecules: Freeing " << ListOfMolecules[i] << "." << endl;
|
---|
42 | delete(ListOfMolecules[i]);
|
---|
43 | ListOfMolecules[i] = NULL;
|
---|
44 | }
|
---|
45 | }
|
---|
46 | cout << Verbose(4) << "Freeing ListOfMolecules." << endl;
|
---|
47 | Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules");
|
---|
48 | cout << Verbose(4) << "Freeing TEList." << endl;
|
---|
49 | Free((void **)&TEList, "MoleculeListClass:MoleculeListClass: *TEList");
|
---|
50 | };
|
---|
51 |
|
---|
52 | int 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 | /** Returns an allocated index list which fragment should remain and which are doubly appearing.
|
---|
125 | * Again, we use linked cell however not with \a threshold which in most cases is too small and would
|
---|
126 | * generate too many cells, but a too be specified \a celldistance which should e.g. be chosen in
|
---|
127 | * the magnitude of the typical bond distance. In order to avoid so far the need of a vector list,
|
---|
128 | * we simply use the molecule structure and the vector sitting in the atom structure.
|
---|
129 | * \param *out output stream for debugging
|
---|
130 | * \param **MapList empty but allocated(MoleculeListClass::NumberOfMolecules), containing on return mapping of for which equal molecule which atoms corresponds to which one (needed for ForceFactors)
|
---|
131 | * \param threshold threshold value for molecule::IsEqualToWithinThreshold()
|
---|
132 | * \param cell_size 6 entries specifying the unit cell vectors (matrix is symmetric)
|
---|
133 | * \param celldistance needed for linked-cell technique to find possible equals
|
---|
134 | * \return allocated index list with \a Num entries.
|
---|
135 | */
|
---|
136 | int * MoleculeListClass::GetMappingToUniqueFragments(ofstream *out, double threshold, double *cell_size, double celldistance)
|
---|
137 | {
|
---|
138 | int j, UniqueIndex, HighestNumber;
|
---|
139 | //int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index;
|
---|
140 | int Counter;
|
---|
141 | //molecule **CellList;
|
---|
142 | int *MapList = NULL;
|
---|
143 | size_t *SortMap = NULL;
|
---|
144 | //atom *Walker = NULL, *OtherWalker = NULL;
|
---|
145 | //molecule *LinkedCellContainer = new molecule(NULL); // container for all the center of gravities stored as atoms
|
---|
146 |
|
---|
147 | /// Allocated MapList with range NumberOfMolecules.
|
---|
148 | MapList = (int *) Malloc(sizeof(int)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *MapList");
|
---|
149 | SortMap = (size_t *) Malloc(sizeof(size_t)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *MapList");
|
---|
150 | for (j=0;j<NumberOfMolecules;j++) {
|
---|
151 | if (ListOfMolecules[j] == NULL)
|
---|
152 | cerr << "ERROR: Molecule " << j << " is NULL!" << endl;
|
---|
153 | //else
|
---|
154 | //cerr << "ERROR: Molecule " << j << " is " << ListOfMolecules[j] << " with count " << ListOfMolecules[j]->AtomCount << "." << endl;
|
---|
155 | MapList[j] = -1;
|
---|
156 | SortMap[j] = 0;
|
---|
157 | }
|
---|
158 | *out << Verbose(1) << "Get mapping to unique fragments with " << NumberOfMolecules << " fragments total." << endl;
|
---|
159 |
|
---|
160 | // sort the list with heapsort according to sort function
|
---|
161 | gsl_heapsort_index(SortMap, ListOfMolecules, NumberOfMolecules, sizeof(molecule *), MolCompare);
|
---|
162 | // check next neighbours and remap
|
---|
163 | Counter = 0;
|
---|
164 | MapList[SortMap[0]] = Counter++;
|
---|
165 | for(int i=1;i<NumberOfMolecules;i++) {
|
---|
166 | if (MolCompare(&ListOfMolecules[SortMap[i]], &ListOfMolecules[SortMap[i-1]]) == 0)
|
---|
167 | MapList[SortMap[i]] = MapList[SortMap[i-1]];
|
---|
168 | else
|
---|
169 | MapList[SortMap[i]] = Counter++;
|
---|
170 | }
|
---|
171 | Free((void **)&SortMap, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");
|
---|
172 |
|
---|
173 | *out << Verbose(2) << "Map: ";
|
---|
174 | for(int i=0;i<NumberOfMolecules;i++)
|
---|
175 | *out << MapList[i] << " ";
|
---|
176 | *out << endl;
|
---|
177 |
|
---|
178 | // bring MapList indices into an ascending order
|
---|
179 | HighestNumber = Counter;
|
---|
180 | *out << Verbose(3) << "HighestNumber: " << HighestNumber << "." << endl;
|
---|
181 | SortMap = (size_t *) Malloc(sizeof(size_t)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");
|
---|
182 | for(int i=0;i<NumberOfMolecules;i++)
|
---|
183 | SortMap[i] = HighestNumber; // is the first number that will not appear anymore in list
|
---|
184 | UniqueIndex = 0;
|
---|
185 | for(int i=0;i<NumberOfMolecules;i++)
|
---|
186 | if (MapList[i] != -1) {
|
---|
187 | if ((unsigned int)SortMap[MapList[i]] == (unsigned int)HighestNumber)
|
---|
188 | SortMap[MapList[i]] = UniqueIndex++;
|
---|
189 | MapList[i] = SortMap[MapList[i]];
|
---|
190 | } else {
|
---|
191 | MapList[i] = -1;
|
---|
192 | }
|
---|
193 | *out << Verbose(2) << "Ascending Map: ";
|
---|
194 | for(int i=0;i<NumberOfMolecules;i++)
|
---|
195 | *out << MapList[i] << " ";
|
---|
196 | *out << endl;
|
---|
197 | Free((void **)&SortMap, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");
|
---|
198 |
|
---|
199 | /// Return the constructed list.
|
---|
200 | return MapList;
|
---|
201 | };
|
---|
202 |
|
---|
203 |
|
---|
204 | /** Takes a list of molecules and returns the list with doubles removed.
|
---|
205 | * Checks by using molecule::IsEqualToWithinThreshold() whether fragments within the list
|
---|
206 | * are actually doubles. If not, the pointer are copied to a new list, if so,
|
---|
207 | * they are dropped. The new list is then copied back to the reallocated \a **FragmentList
|
---|
208 | * and the new number of elements therein returned.
|
---|
209 | * \param *out output stream for debugging
|
---|
210 | * \param *Map mapping of which index goes on which (from molecule::GetMappingToUniqueFragments())
|
---|
211 | * \return number of molecules in the new realloacted **FragmentList
|
---|
212 | */
|
---|
213 | int MoleculeListClass::ReduceFragmentToUniqueOnes(ofstream *out, int *Map)
|
---|
214 | {
|
---|
215 | *out << Verbose(2) << "Begin of ReduceFragmentToUniqueOnes" << endl;
|
---|
216 | /// Allocate temporary lists of size \a Num.
|
---|
217 | molecule **NewMolList = (molecule **) Malloc(sizeof(molecule *)*NumberOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: NewList");
|
---|
218 | double *NewTEList = (double *) Malloc(sizeof(double)*NumberOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewTEList");
|
---|
219 | for(int i=0;i<NumberOfMolecules;i++) {
|
---|
220 | NewTEList[i] = 0;
|
---|
221 | NewMolList[i] = NULL;
|
---|
222 | }
|
---|
223 | int ReducedNum = 0, j;
|
---|
224 | *out << Verbose(3) << "Reducing TE and Forces lists." << endl;
|
---|
225 | for(int i=0;i<NumberOfMolecules;i++) { /// Count new reduced number of molecules ...
|
---|
226 | //*out << Verbose(4) << i << "th TE Value " << " goes to " << Map[i] << ": " << TEList[i] << "." << endl;
|
---|
227 | NewTEList[Map[i]] += TEList[i];
|
---|
228 | if (Map[i] == i) { /// ... by checking if Map[i] != i, then Fragment[i] is double of Fragment[Map[i]].
|
---|
229 | *out << Verbose(4) << "Copying molecule " << i << " as it is unique so far ... " << ListOfMolecules[i]<< endl;
|
---|
230 | NewMolList[ReducedNum++] = ListOfMolecules[i]; /// ..., whilst copying each value to temporary list, ...
|
---|
231 | } else { // else free molecule cause it appears doubly
|
---|
232 | *out << Verbose(4) << "Removing molecule " << i << "." << endl;
|
---|
233 | delete(ListOfMolecules[i]);
|
---|
234 | ListOfMolecules[i] = NULL;
|
---|
235 | }
|
---|
236 | }
|
---|
237 | /// Reallocate \a **FragmentList ...
|
---|
238 | *out << Verbose(3) << "Reallocating to Unique Fragments:" << endl;
|
---|
239 | if ((ReducedNum != 0) && (TEList != 0)) {
|
---|
240 | // factor list
|
---|
241 | *out << Verbose(4) << "Reallocating TEList [" << TEList << "] to " << ReducedNum << endl;
|
---|
242 | TEList = (double *) ReAlloc(TEList, sizeof(double)*ReducedNum, "MoleculeListClass::ReduceFragmentToUniqueOnes: *TEList");
|
---|
243 |
|
---|
244 | *out << Verbose(4) << "Copying values to new list: " << endl;
|
---|
245 | j = 0; // is ReducedNum index
|
---|
246 | for(int i=0;i<NumberOfMolecules;i++) {/// copy value from temporary to return list
|
---|
247 | if (Map[i] == i) {
|
---|
248 | //if (fabs(NewTEList[i]) > MYEPSILON) { // this is a good check also, if TEList[i] = 0 then fragment cancels and may be dropped!
|
---|
249 | TEList[j] = NewTEList[i];
|
---|
250 | *out << Verbose(5) << "TE [i" << i << "<->j" << j << "]:" << NewTEList[i] << "->" << TEList[j];
|
---|
251 | j++;
|
---|
252 | }
|
---|
253 | *out << endl;
|
---|
254 | }
|
---|
255 | if (j != ReducedNum)
|
---|
256 | *out << "Panic: j " << j << " != ReducedNum " << ReducedNum << "." << endl;
|
---|
257 |
|
---|
258 |
|
---|
259 | // molecule list
|
---|
260 | *out << Verbose(4) << "Reallocating ListOfMolecules ... " << endl;
|
---|
261 | ListOfMolecules = (molecule **) ReAlloc(ListOfMolecules, sizeof(molecule *)*ReducedNum, "MoleculeListClass::ReduceFragmentToUniqueOnes: ListOfMolecules");
|
---|
262 | NumberOfMolecules = ReducedNum;
|
---|
263 | /// ... and copy the reduced number back
|
---|
264 | *out << Verbose(5) << "Transfering to ListOfMolecules ... ";
|
---|
265 | for(int i=0;i<ReducedNum;i++) {
|
---|
266 | ListOfMolecules[i] = NewMolList[i];
|
---|
267 | *out << NewMolList[i] << " -> " << ListOfMolecules[i] << "\t";
|
---|
268 | }
|
---|
269 | *out << endl;
|
---|
270 |
|
---|
271 |
|
---|
272 | } else {
|
---|
273 | Free((void **)&ListOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: ListOfMolecules");
|
---|
274 | NumberOfMolecules = ReducedNum;
|
---|
275 | *out << Verbose(3) << "ReducedNum is " << ReducedNum << ", Number of Molecules is " << NumberOfMolecules << "." << endl;
|
---|
276 | }
|
---|
277 | // free all the lists again
|
---|
278 | *out << Verbose(3) << "Freeing temporary lists." << endl;
|
---|
279 | Free((void **)&NewTEList, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewTEList"); /// free temporary list again
|
---|
280 | Free((void **)&NewMolList, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewMolList");
|
---|
281 | *out << Verbose(2) << "End of ReduceFragmentToUniqueOnes" << endl;
|
---|
282 | return(ReducedNum);
|
---|
283 | };
|
---|
284 |
|
---|
285 | /** Simple output of the pointers in ListOfMolecules.
|
---|
286 | * \param *out output stream
|
---|
287 | */
|
---|
288 | void MoleculeListClass::Output(ofstream *out)
|
---|
289 | {
|
---|
290 | *out<< Verbose(1) << "MoleculeList: ";
|
---|
291 | for (int i=0;i<NumberOfMolecules;i++)
|
---|
292 | *out << ListOfMolecules[i] << "\t";
|
---|
293 | *out << endl;
|
---|
294 | };
|
---|
295 |
|
---|
296 | /** Writes a config file for each molecule in the given \a **FragmentList.
|
---|
297 | * Note that molecules with a TEList factor of 0 are not stored!
|
---|
298 | * \param *prefix prefix for the file name
|
---|
299 | * \param *configuration standard configuration to attach atoms in fragment molecule to.
|
---|
300 | * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
|
---|
301 | * \return true - success (each file was written), false - something went wrong.
|
---|
302 | */
|
---|
303 | bool MoleculeListClass::OutputConfigForListOfFragments(char *prefix, config *configuration, int *SortIndex)
|
---|
304 | {
|
---|
305 | ofstream outputFragment;
|
---|
306 | char FragmentName[255];
|
---|
307 | char PathBackup[255];
|
---|
308 | bool result = true;
|
---|
309 | bool intermediateResult = true;
|
---|
310 | atom *Walker = NULL;
|
---|
311 | vector BoxDimension;
|
---|
312 | char TEFilename[255];
|
---|
313 | char *FragmentNumber;
|
---|
314 | int FragmentCounter = 0;
|
---|
315 | ofstream TEFile;
|
---|
316 | ofstream ForcesFile;
|
---|
317 | ofstream KeySetFile;
|
---|
318 | element *runner = NULL;
|
---|
319 |
|
---|
320 | // store the fragments as config and as xyz
|
---|
321 | for(int i=0;i<NumberOfMolecules;i++) {
|
---|
322 | //if (TEList[i] != 0) {
|
---|
323 | strcpy(PathBackup, configuration->GetDefaultPath());
|
---|
324 |
|
---|
325 | // scan all atoms in the current molecule for their fathers and write each vertex index to forces file
|
---|
326 |
|
---|
327 | // correct periodic
|
---|
328 | ListOfMolecules[i]->ScanForPeriodicCorrection((ofstream *)&cout);
|
---|
329 |
|
---|
330 | // output xyz file
|
---|
331 | FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
|
---|
332 | sprintf(FragmentName, "%s/%s%s.conf.xyz", PathBackup, prefix, FragmentNumber);
|
---|
333 | outputFragment.open(FragmentName, ios::out);
|
---|
334 | cout << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as XYZ ...";
|
---|
335 | if (intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment))
|
---|
336 | cout << " done." << endl;
|
---|
337 | else
|
---|
338 | cout << " failed." << endl;
|
---|
339 | result = result && intermediateResult;
|
---|
340 | outputFragment.close();
|
---|
341 | outputFragment.clear();
|
---|
342 |
|
---|
343 | cout << Verbose(2) << "Contained atoms: ";
|
---|
344 | Walker = ListOfMolecules[i]->start;
|
---|
345 | while (Walker->next != ListOfMolecules[i]->end) {
|
---|
346 | Walker = Walker->next;
|
---|
347 | cout << Walker->Name << " ";
|
---|
348 | }
|
---|
349 | cout << endl;
|
---|
350 | // prepare output of config file
|
---|
351 | sprintf(FragmentName, "%s/%s%s.conf", PathBackup, prefix, FragmentNumber);
|
---|
352 | outputFragment.open(FragmentName, ios::out);
|
---|
353 | strcpy(PathBackup, configuration->GetDefaultPath());
|
---|
354 | sprintf(FragmentName, "%s/%s%s/", PathBackup, prefix, FragmentNumber);
|
---|
355 |
|
---|
356 | // center on edge
|
---|
357 | ListOfMolecules[i]->CenterEdge((ofstream *)&cout, &BoxDimension);
|
---|
358 | ListOfMolecules[i]->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary
|
---|
359 | int j = -1;
|
---|
360 | for (int k=0;k<3;k++) {
|
---|
361 | j += k+1;
|
---|
362 | BoxDimension.x[k] = 5.;
|
---|
363 | ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
|
---|
364 | }
|
---|
365 | ListOfMolecules[i]->Translate(&BoxDimension);
|
---|
366 |
|
---|
367 | // also calculate necessary orbitals
|
---|
368 | ListOfMolecules[i]->CountElements(); // this is a bugfix, atoms should should actually be added correctly to this fragment
|
---|
369 | ListOfMolecules[i]->CalculateOrbitals(*configuration);
|
---|
370 |
|
---|
371 | // change path in config
|
---|
372 | configuration->SetDefaultPath(FragmentName);
|
---|
373 | cout << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as config ...";
|
---|
374 | if (intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i]))
|
---|
375 | cout << " done." << endl;
|
---|
376 | else
|
---|
377 | cout << " failed." << endl;
|
---|
378 | // restore old config
|
---|
379 | configuration->SetDefaultPath(PathBackup);
|
---|
380 |
|
---|
381 | result = result && intermediateResult;
|
---|
382 | outputFragment.close();
|
---|
383 | outputFragment.clear();
|
---|
384 | Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");
|
---|
385 | }
|
---|
386 |
|
---|
387 | strcpy(PathBackup, configuration->GetDefaultPath());
|
---|
388 | // open file for the total energy factor
|
---|
389 | sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, "TE-Factors.dat");
|
---|
390 | TEFile.open(TEFilename, ios::out);
|
---|
391 | // output TEList (later to file AtomicTEList.dat)
|
---|
392 | cout << Verbose(2) << "Saving " << prefix << " energy factors ...";
|
---|
393 | //cout << Verbose(1) << "Final ATEList: ";
|
---|
394 | //less TEFile << prefix << "TE\t";
|
---|
395 | for(int i=0;i<NumberOfMolecules;i++) {
|
---|
396 | //cout << TEList[i] << "\t";
|
---|
397 | //if (TEList[i] != 0)
|
---|
398 | TEFile << TEList[i] << "\t";
|
---|
399 | }
|
---|
400 | //cout << endl;
|
---|
401 | TEFile << endl;
|
---|
402 | TEFile.close();
|
---|
403 | cout << " done." << endl;
|
---|
404 |
|
---|
405 | // open file for the force factors
|
---|
406 | sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, "Forces-Factors.dat");
|
---|
407 | ForcesFile.open(TEFilename, ios::out);
|
---|
408 | //cout << Verbose(1) << "Final AtomicForcesList: ";
|
---|
409 | cout << Verbose(2) << "Saving " << prefix << " force factors ...";
|
---|
410 | //ForcesFile << prefix << "Forces" << endl;
|
---|
411 | for(int j=0;j<NumberOfMolecules;j++) {
|
---|
412 | //if (TEList[j] != 0) {
|
---|
413 | runner = ListOfMolecules[j]->elemente->start;
|
---|
414 | while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element
|
---|
415 | runner = runner->next;
|
---|
416 | if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms
|
---|
417 | Walker = ListOfMolecules[j]->start;
|
---|
418 | while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element
|
---|
419 | Walker = Walker->next;
|
---|
420 | if (Walker->type->Z == runner->Z) {
|
---|
421 | if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a real father, prints its index
|
---|
422 | cerr << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", its number " << Walker->GetTrueFather()->nr << " and index " << SortIndex[Walker->GetTrueFather()->nr] << "." << endl;
|
---|
423 | ForcesFile << SortIndex[Walker->GetTrueFather()->nr] << "\t";
|
---|
424 | } else // otherwise a -1 to indicate an added saturation hydrogen
|
---|
425 | ForcesFile << "-1\t";
|
---|
426 | }
|
---|
427 | }
|
---|
428 | }
|
---|
429 | }
|
---|
430 | //cout << endl << endl;
|
---|
431 | ForcesFile << endl;
|
---|
432 | }
|
---|
433 | ForcesFile.close();
|
---|
434 | cout << " done." << endl;
|
---|
435 |
|
---|
436 | // open KeySet file
|
---|
437 | sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, "KeySets.dat");
|
---|
438 | KeySetFile.open(TEFilename, ios::out);
|
---|
439 | cout << Verbose(2) << "Saving " << prefix << " key sets of each subgraph ...";
|
---|
440 | for(int j=0;j<NumberOfMolecules;j++) {
|
---|
441 | //if (TEList[j] != 0) {
|
---|
442 | Walker = ListOfMolecules[j]->start;
|
---|
443 | while(Walker->next != ListOfMolecules[j]->end) {
|
---|
444 | Walker = Walker->next;
|
---|
445 | #ifdef ADDHYDROGEN
|
---|
446 | if ((Walker->GetTrueFather() != NULL) && (Walker->type->Z != 1)) // if there is a real father, prints its index
|
---|
447 | #else
|
---|
448 | if ((Walker->GetTrueFather() != NULL)) // if there is a real father, prints its index
|
---|
449 | #endif
|
---|
450 | KeySetFile << Walker->GetTrueFather()->nr << "\t";
|
---|
451 | #ifdef ADDHYDROGEN
|
---|
452 | else // otherwise a -1 to indicate an added saturation hydrogen
|
---|
453 | KeySetFile << "-1\t";
|
---|
454 | #endif
|
---|
455 | }
|
---|
456 | //cout << endl << endl;
|
---|
457 | KeySetFile << endl;
|
---|
458 | }
|
---|
459 | KeySetFile.close();
|
---|
460 | cout << " done." << endl;
|
---|
461 |
|
---|
462 | // printing final number
|
---|
463 | cout << "Final number of fragments: " << FragmentCounter << "." << endl;
|
---|
464 |
|
---|
465 | return result;
|
---|
466 | };
|
---|
467 |
|
---|
468 | /** Reduce the list of molecules to unique pieces.
|
---|
469 | * molecule::IsEqualToWithinThreshold() is used by GetMappingToUniqueFragments() to provide a mapping for
|
---|
470 | * ReduceFragmentToUniqueOnes().
|
---|
471 | * \param *out output stream for debugging
|
---|
472 | * \param cell_size 6 entries specifying the unit cell vectors (matrix is symmetric) for getting the map
|
---|
473 | * \param celldistance needed for linked-cell technique when getting the map
|
---|
474 | */
|
---|
475 | void MoleculeListClass::ReduceToUniqueList(ofstream *out, double *cell_size, double celldistance)
|
---|
476 | {
|
---|
477 | int *ReduceMapping = NULL;
|
---|
478 |
|
---|
479 | *out << Verbose(0) << "Begin of ReduceToUniqueList." << endl;
|
---|
480 | // again, check whether there are equal fragments by ReduceToUniqueOnes
|
---|
481 | *out << Verbose(1) << "Get reduce mapping." << endl;
|
---|
482 | ReduceMapping = GetMappingToUniqueFragments(out, 0.05, cell_size, celldistance);
|
---|
483 | *out << Verbose(1) << "MapList: ";
|
---|
484 | for(int i=0;i<NumberOfMolecules;i++)
|
---|
485 | *out << ReduceMapping[i] << " ";
|
---|
486 | *out << endl << endl;
|
---|
487 | *out << Verbose(1) << "Apply reduce mapping." << endl;
|
---|
488 | ReduceFragmentToUniqueOnes(out, ReduceMapping);
|
---|
489 | Free((void **)&ReduceMapping, "MoleculeListClass::FragmentTopDown: *ReduceMapping"); // free map after reduce
|
---|
490 | *out << Verbose(1) << "Number of Fragments after Reducing is " << NumberOfMolecules << "." << endl;
|
---|
491 | *out << Verbose(0) << "End of ReduceToUniqueList." << endl;
|
---|
492 | };
|
---|
493 |
|
---|
494 | /** Fragments a molecule and resulting pieces recursively until the number of bonds
|
---|
495 | * Here the idea is similar to the FragmentBottomUp() approach, only that we split up the molecule
|
---|
496 | * bond per bond into left and right fragments and this recursively also with each yielded
|
---|
497 | * fragment until there is no fragment with continuous number of bonds greater than \a BondDegree.
|
---|
498 | * are below the given \a BondDegree.
|
---|
499 | * \param *out output stream for debugging
|
---|
500 | * \param BondDegree maximum number of continuous bonds in a fragment
|
---|
501 | * \param bonddistance typical bond distance
|
---|
502 | * \param *configuration configuration for writing config files for each fragment
|
---|
503 | * \param CutCyclic cut cyclic bonds (saturate with hydrogen) or add
|
---|
504 | * \return pointer to MoleculeListClass with all the fragments or NULL if something went wrong.
|
---|
505 | * \todo so far we volontarily mix up the above BondDegree definition and molecule::NoNonBonds
|
---|
506 | *
|
---|
507 | * \bug FragmentTopDown does not work right now due to NULL being given as cell_size to ReduceToUniqueOnes()
|
---|
508 | */
|
---|
509 | MoleculeListClass * MoleculeListClass::FragmentTopDown(ofstream *out, int BondDegree, double bonddistance, config *configuration, enum CutCyclicBond CutCyclic)
|
---|
510 | {
|
---|
511 | int Num, No, Cyclic, NoBonds;
|
---|
512 | MoleculeListClass *ReturnList = NULL;
|
---|
513 | MoleculeListClass **FragmentsList = NULL;
|
---|
514 | molecule *CurrentMolecule = NULL;
|
---|
515 | bond *Binder = NULL;
|
---|
516 |
|
---|
517 | *out << Verbose(0) << "Begin of FragmentTopDown:" << this << "." << endl;
|
---|
518 | Num = 0;
|
---|
519 | FragmentsList = (MoleculeListClass **) Malloc(sizeof(MoleculeListClass *)*NumberOfMolecules, "MoleculeListClass::FragmentTopDown: **FragmentsList");
|
---|
520 | // fragment each molecule into its own MoleculeListClass
|
---|
521 | for(int i=0;i<NumberOfMolecules;i++) {
|
---|
522 | CurrentMolecule = ListOfMolecules[i];
|
---|
523 | CurrentMolecule->CountAtoms(out);
|
---|
524 | Cyclic = CurrentMolecule->CountCyclicBonds(out);
|
---|
525 | NoBonds =
|
---|
526 | #ifdef ADDHYDROGEN
|
---|
527 | CurrentMolecule->NoNonBonds
|
---|
528 | #else
|
---|
529 | CurrentMolecule->BondCount
|
---|
530 | #endif
|
---|
531 | - ((CutCyclic == KeepBond) ? Cyclic : 0);
|
---|
532 | // check if NoNonBonds < BondDegree, then don't split any further: Here, correct for greatest continuous bond length!
|
---|
533 | *out << Verbose(0) << "Checking on Number of true Bonds " << NoBonds << " (i.e. no -H, if chosen no cyclic) greater than " << BondDegree << "." << endl;
|
---|
534 | if (NoBonds > BondDegree) {
|
---|
535 | //cerr << Verbose(1) << "TopDown Level of Molecule " << CurrentMolecule << ": " << (CurrentMolecule->NoNonBonds - BondDegree) << "." << endl;
|
---|
536 | *out << Verbose(1) << "Breaking up molecule " << i << " in fragment list." << endl;
|
---|
537 | CurrentMolecule->CreateListOfBondsPerAtom(out);
|
---|
538 | // Get atomic fragments for the list
|
---|
539 | *out << Verbose(1) << "Getting Atomic fragments for molecule " << i << "." << endl;
|
---|
540 | MoleculeListClass *AtomicFragments = CurrentMolecule->GetAtomicFragments(out, NumberOfTopAtoms, configuration->GetIsAngstroem(), TEList[i]/(1. - NoBonds), CutCyclic);
|
---|
541 |
|
---|
542 | // build the atomic part of the list of molecules
|
---|
543 | *out << Verbose(1) << "Putting atomic fragment into list of molecules." << endl;
|
---|
544 |
|
---|
545 | // cutting cyclic bonds yields only a single fragment, not two as non-cyclic!
|
---|
546 | No = (CutCyclic == KeepBond) ? ((
|
---|
547 | #ifdef ADDHYDROGEN
|
---|
548 | CurrentMolecule->NoNonBonds - Cyclic)*2) : CurrentMolecule->NoNonBonds*2 - Cyclic;
|
---|
549 | #else
|
---|
550 | CurrentMolecule->BondCount - Cyclic)*2) : CurrentMolecule->BondCount*2 - Cyclic;
|
---|
551 | #endif
|
---|
552 |
|
---|
553 | if (AtomicFragments != NULL) {
|
---|
554 | ReturnList = new MoleculeListClass(No+AtomicFragments->NumberOfMolecules, NumberOfTopAtoms);
|
---|
555 | for (int j=0;j<AtomicFragments->NumberOfMolecules;j++) { // shift all Atomic Fragments into this one here
|
---|
556 | ReturnList->ListOfMolecules[j+No] = AtomicFragments->ListOfMolecules[j];
|
---|
557 | AtomicFragments->ListOfMolecules[j] = NULL;
|
---|
558 | ReturnList->ListOfMolecules[j+No]->NoNonBonds = 0;
|
---|
559 | ReturnList->ListOfMolecules[j+No]->NoNonHydrogen = 1;
|
---|
560 | ReturnList->TEList[j+No] = AtomicFragments->TEList[j];
|
---|
561 | }
|
---|
562 | *out << Verbose(3) << "Freeing Atomic memory" << endl;
|
---|
563 | delete(AtomicFragments);
|
---|
564 | AtomicFragments = NULL;
|
---|
565 | } else {
|
---|
566 | *out << Verbose(2) << "AtomicFragments is NULL, filling list with whole molecule only." << endl;
|
---|
567 | ReturnList = new MoleculeListClass(No, NumberOfTopAtoms);
|
---|
568 | }
|
---|
569 |
|
---|
570 | // build the side pieces part of the list of molecules
|
---|
571 | *out << Verbose(1) << "Building side piece fragments and putting into list of molecules." << endl;
|
---|
572 | No = 0;
|
---|
573 | Binder = CurrentMolecule->first;
|
---|
574 | while(Binder->next != CurrentMolecule->last) {
|
---|
575 | Binder = Binder->next;
|
---|
576 | #ifdef ADDHYDROGEN
|
---|
577 | if (Binder->HydrogenBond == 0)
|
---|
578 | #endif
|
---|
579 | if ((CutCyclic == SaturateBond) || (!Binder->Cyclic)) {
|
---|
580 | // split each bond into left and right side piece
|
---|
581 | if (Binder->Cyclic) {
|
---|
582 | molecule *dummy = NULL; // we lazily hand FragmentMoleculeByBond() a dummy as second fragment and ...
|
---|
583 | *out << Verbose(1) << "Breaking up " << Binder->nr << "th and " << No << "th non-hydrogen, CYCLIC bond " << *Binder << " of molecule " << i << " [" << CurrentMolecule << "] into a single pieces." << endl;
|
---|
584 | CurrentMolecule->FragmentMoleculeByBond(out, Binder, &(ReturnList->ListOfMolecules[No]), &(dummy), configuration->GetIsAngstroem(), CutCyclic);
|
---|
585 | delete(dummy); // ... free the dummy which is due to the cyclic bond the exacy same fragment
|
---|
586 | *out << Verbose(1) << "Single fragment is " << ReturnList->ListOfMolecules[No] << "." << endl;
|
---|
587 |
|
---|
588 | // write down the necessary TE-summation in order to regain TE of whole molecule
|
---|
589 | *out << Verbose(2) << "Creating TEList for Fragment " << i << " of Bond " << No << "." << endl;
|
---|
590 | #ifdef ADDHYDROGEN
|
---|
591 | ReturnList->TEList[No] = -TEList[i]/(1. -CurrentMolecule->NoNonBonds);
|
---|
592 | #else
|
---|
593 | ReturnList->TEList[No] = -TEList[i]/(1. -CurrentMolecule->BondCount);
|
---|
594 | #endif
|
---|
595 | } else {
|
---|
596 | *out << Verbose(1) << "Breaking up " << Binder->nr << "th and " << No << "th non-hydrogen, non-cyclic bond " << *Binder << " of molecule " << i << " [" << CurrentMolecule << "] into left and right side pieces." << endl;
|
---|
597 | CurrentMolecule->FragmentMoleculeByBond(out, Binder, &(ReturnList->ListOfMolecules[No]), &(ReturnList->ListOfMolecules[No+1]), configuration->GetIsAngstroem(), CutCyclic);
|
---|
598 | *out << Verbose(1) << "Left Fragment is " << ReturnList->ListOfMolecules[No] << ", right Fragment is " << ReturnList->ListOfMolecules[No+1] << "." << endl;
|
---|
599 |
|
---|
600 | // write down the necessary TE-summation in order to regain TE of whole molecule
|
---|
601 | *out << Verbose(2) << "Creating TEList for Fragment " << i << " of Bond " << No << "." << endl;
|
---|
602 | ReturnList->TEList[No] = -TEList[i]/(1. - NoBonds);
|
---|
603 | ReturnList->TEList[No+1] = -TEList[i]/(1. - NoBonds);
|
---|
604 | }
|
---|
605 | No += ((Binder->Cyclic) ? 1 : 2);
|
---|
606 | }
|
---|
607 | }
|
---|
608 |
|
---|
609 | // Reduce this list
|
---|
610 | ReturnList->ReduceToUniqueList(out, NULL, bonddistance);
|
---|
611 |
|
---|
612 | // recurse and receive List
|
---|
613 | *out << Verbose(1) << "Calling TopDown " << ReturnList<< " with filled list: ";
|
---|
614 | ReturnList->Output(out);
|
---|
615 | FragmentsList[i] = ReturnList->FragmentTopDown(out, BondDegree, bonddistance, configuration, CutCyclic);
|
---|
616 | *out << Verbose(1) << "Returning from TopDown " << ReturnList<< " with filled list: ";
|
---|
617 | ReturnList->Output(out);
|
---|
618 |
|
---|
619 | // remove list after we're done
|
---|
620 | *out << Verbose(2) << "Removing caller list." << endl;
|
---|
621 | delete(ReturnList);
|
---|
622 | ReturnList = NULL;
|
---|
623 |
|
---|
624 | } else { // create a list with only a single molecule inside, transfer everything from "this" list to return list
|
---|
625 | *out << Verbose(1) << "Not breaking up molecule " << i << " in fragment list." << endl;
|
---|
626 | FragmentsList[i] = new MoleculeListClass(1, NumberOfTopAtoms);
|
---|
627 | FragmentsList[i]->ListOfMolecules[0] = ListOfMolecules[i];
|
---|
628 | ListOfMolecules[i] = NULL;
|
---|
629 | FragmentsList[i]->TEList[0] = TEList[i];
|
---|
630 | }
|
---|
631 | Num += FragmentsList[i]->NumberOfMolecules;
|
---|
632 | }
|
---|
633 |
|
---|
634 | // now, we have a list of MoleculeListClasses: combine all fragments list into one single list
|
---|
635 | *out << Verbose(2) << "Combining to a list of " << Num << " molecules and Memory cleanup of old list of lists." << endl;
|
---|
636 | ReturnList = new MoleculeListClass(Num, NumberOfTopAtoms);
|
---|
637 | No = 0;
|
---|
638 | for(int i=0;i<NumberOfMolecules;i++) {
|
---|
639 | for(int j=0;j<FragmentsList[i]->NumberOfMolecules;j++) {
|
---|
640 | // transfer molecule
|
---|
641 | ReturnList->ListOfMolecules[No] = FragmentsList[i]->ListOfMolecules[j];
|
---|
642 | FragmentsList[i]->ListOfMolecules[j] = NULL;
|
---|
643 | // transfer TE factor
|
---|
644 | ReturnList->TEList[No] = FragmentsList[i]->TEList[j];
|
---|
645 | No++;
|
---|
646 | }
|
---|
647 | delete(FragmentsList[i]);
|
---|
648 | FragmentsList[i] = NULL;
|
---|
649 | }
|
---|
650 | Free((void **)&FragmentsList, "MoleculeListClass::FragmentTopDown: **FragmentsList");
|
---|
651 |
|
---|
652 | // Reduce the list to unique fragments
|
---|
653 | ReturnList->ReduceToUniqueList(out, NULL, bonddistance);
|
---|
654 |
|
---|
655 | // return pointer to list
|
---|
656 | *out << Verbose(0) << "Return with filled list: ";
|
---|
657 | ReturnList->Output(out);
|
---|
658 |
|
---|
659 | *out << Verbose(0) << "End of FragmentTopDown:" << this << "." << endl;
|
---|
660 | return (ReturnList);
|
---|
661 | };
|
---|
662 |
|
---|
663 | /******************************************* Class MoleculeLeafClass ************************************************/
|
---|
664 |
|
---|
665 | /** Constructor for MoleculeLeafClass root leaf.
|
---|
666 | * \param *Up Leaf on upper level
|
---|
667 | * \param *PreviousLeaf NULL - We are the first leaf on this level, otherwise points to previous in list
|
---|
668 | */
|
---|
669 | //MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *Up = NULL, MoleculeLeafClass *Previous = NULL)
|
---|
670 | MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
|
---|
671 | {
|
---|
672 | // if (Up != NULL)
|
---|
673 | // if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
|
---|
674 | // Up->DownLeaf = this;
|
---|
675 | // UpLeaf = Up;
|
---|
676 | // DownLeaf = NULL;
|
---|
677 | Leaf = NULL;
|
---|
678 | previous = PreviousLeaf;
|
---|
679 | if (previous != NULL) {
|
---|
680 | MoleculeLeafClass *Walker = previous->next;
|
---|
681 | previous->next = this;
|
---|
682 | next = Walker;
|
---|
683 | } else {
|
---|
684 | next = NULL;
|
---|
685 | }
|
---|
686 | };
|
---|
687 |
|
---|
688 | /** Destructor for MoleculeLeafClass.
|
---|
689 | */
|
---|
690 | MoleculeLeafClass::~MoleculeLeafClass()
|
---|
691 | {
|
---|
692 | // if (DownLeaf != NULL) {// drop leaves further down
|
---|
693 | // MoleculeLeafClass *Walker = DownLeaf;
|
---|
694 | // MoleculeLeafClass *Next;
|
---|
695 | // do {
|
---|
696 | // Next = Walker->NextLeaf;
|
---|
697 | // delete(Walker);
|
---|
698 | // Walker = Next;
|
---|
699 | // } while (Walker != NULL);
|
---|
700 | // // Last Walker sets DownLeaf automatically to NULL
|
---|
701 | // }
|
---|
702 | // remove the leaf itself
|
---|
703 | if (Leaf != NULL) {
|
---|
704 | delete(Leaf);
|
---|
705 | Leaf = NULL;
|
---|
706 | }
|
---|
707 | // remove this Leaf from level list
|
---|
708 | if (previous != NULL)
|
---|
709 | previous->next = next;
|
---|
710 | // } else { // we are first in list (connects to UpLeaf->DownLeaf)
|
---|
711 | // if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
|
---|
712 | // NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node
|
---|
713 | // if (UpLeaf != NULL)
|
---|
714 | // UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first
|
---|
715 | // }
|
---|
716 | // UpLeaf = NULL;
|
---|
717 | if (next != NULL) // are we last in list
|
---|
718 | next->previous = previous;
|
---|
719 | next = NULL;
|
---|
720 | previous = NULL;
|
---|
721 | };
|
---|
722 |
|
---|
723 | /** Adds \a molecule leaf to the tree.
|
---|
724 | * \param *ptr ptr to molecule to be added
|
---|
725 | * \param *Previous previous MoleculeLeafClass referencing level and which on the level
|
---|
726 | * \return true - success, false - something went wrong
|
---|
727 | */
|
---|
728 | bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous)
|
---|
729 | {
|
---|
730 | return false;
|
---|
731 | };
|
---|