source: src/moleculelist.cpp@ 14de469

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

-initial commit
-Minimum set of files needed from ESPACK SVN repository
-Switch to three tantamount package parts instead of all relating to pcp (as at some time Ralf's might find inclusion as well)

  • Property mode set to 100644
File size: 32.6 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 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 */
36MoleculeListClass::~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
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/** 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 */
136int * 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 */
213int 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 */
288void 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 */
303bool 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 */
475void 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 */
509MoleculeListClass * 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
527CurrentMolecule->NoNonBonds
528#else
529CurrentMolecule->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
548CurrentMolecule->NoNonBonds - Cyclic)*2) : CurrentMolecule->NoNonBonds*2 - Cyclic;
549#else
550CurrentMolecule->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)
670MoleculeLeafClass::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 */
690MoleculeLeafClass::~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 */
728bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous)
729{
730 return false;
731};
Note: See TracBrowser for help on using the repository browser.