source: src/moleculelist.cpp@ 260934

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

char lengths of 255 and MAXDUMMYSTRING replaced with define MAXSTRINGSIZE in molecuilder and pcp

  • Property mode set to 100644
File size: 32.5 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[MAXSTRINGSIZE];
307 char PathBackup[MAXSTRINGSIZE];
308 bool result = true;
309 bool intermediateResult = true;
310 atom *Walker = NULL;
311 vector BoxDimension;
312 char TEFilename[MAXSTRINGSIZE];
313 char *FragmentNumber;
314 int FragmentCounter = 0;
315 ofstream output;
316 element *runner = NULL;
317
318 // store the fragments as config and as xyz
319 for(int i=0;i<NumberOfMolecules;i++) {
320 //if (TEList[i] != 0) {
321 strcpy(PathBackup, configuration->configpath);
322
323 // scan all atoms in the current molecule for their fathers and write each vertex index to forces file
324
325 // correct periodic
326 ListOfMolecules[i]->ScanForPeriodicCorrection((ofstream *)&cout);
327
328 // output xyz file
329 FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++);
330 sprintf(FragmentName, "%s/%s%s.conf.xyz", PathBackup, prefix, FragmentNumber);
331 outputFragment.open(FragmentName, ios::out);
332 cout << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as XYZ ...";
333 if (intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment))
334 cout << " done." << endl;
335 else
336 cout << " failed." << endl;
337 result = result && intermediateResult;
338 outputFragment.close();
339 outputFragment.clear();
340
341 cout << Verbose(2) << "Contained atoms: ";
342 Walker = ListOfMolecules[i]->start;
343 while (Walker->next != ListOfMolecules[i]->end) {
344 Walker = Walker->next;
345 cout << Walker->Name << " ";
346 }
347 cout << endl;
348 // prepare output of config file
349 sprintf(FragmentName, "%s/%s%s.conf", PathBackup, prefix, FragmentNumber);
350 outputFragment.open(FragmentName, ios::out);
351 strcpy(PathBackup, configuration->configpath);
352 sprintf(FragmentName, "%s/%s%s/", PathBackup, prefix, FragmentNumber);
353
354 // center on edge
355 ListOfMolecules[i]->CenterEdge((ofstream *)&cout, &BoxDimension);
356 ListOfMolecules[i]->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary
357 int j = -1;
358 for (int k=0;k<3;k++) {
359 j += k+1;
360 BoxDimension.x[k] = 5.;
361 ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.;
362 }
363 ListOfMolecules[i]->Translate(&BoxDimension);
364
365 // also calculate necessary orbitals
366 ListOfMolecules[i]->CountElements(); // this is a bugfix, atoms should should actually be added correctly to this fragment
367 ListOfMolecules[i]->CalculateOrbitals(*configuration);
368
369 // change path in config
370 configuration->SetDefaultPath(FragmentName);
371 cout << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as config ...";
372 if (intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i]))
373 cout << " done." << endl;
374 else
375 cout << " failed." << endl;
376 // restore old config
377 configuration->SetDefaultPath(PathBackup);
378
379 result = result && intermediateResult;
380 outputFragment.close();
381 outputFragment.clear();
382 Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber");
383 }
384
385 strcpy(PathBackup, configuration->configpath);
386 // open file for the total energy factor
387 sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, TEFACTORSFILE);
388 output.open(TEFilename, ios::out);
389 // output TEList (later to file AtomicTEList.dat)
390 cout << Verbose(2) << "Saving " << prefix << " energy factors ...";
391 //cout << Verbose(1) << "Final ATEList: ";
392 //less output << prefix << "TE\t";
393 for(int i=0;i<NumberOfMolecules;i++) {
394 //cout << TEList[i] << "\t";
395 //if (TEList[i] != 0)
396 output << TEList[i] << "\t";
397 }
398 //cout << endl;
399 output << endl;
400 output.close();
401 cout << " done." << endl;
402
403 // open file for the force factors
404 sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, FORCESFILE);
405 output.open(TEFilename, ios::out);
406 //cout << Verbose(1) << "Final AtomicForcesList: ";
407 cout << Verbose(2) << "Saving " << prefix << " force factors ...";
408 //output << prefix << "Forces" << endl;
409 for(int j=0;j<NumberOfMolecules;j++) {
410 //if (TEList[j] != 0) {
411 runner = ListOfMolecules[j]->elemente->start;
412 while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element
413 runner = runner->next;
414 if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms
415 Walker = ListOfMolecules[j]->start;
416 while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element
417 Walker = Walker->next;
418 if (Walker->type->Z == runner->Z) {
419 if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a real father, prints its index
420 //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", its number " << Walker->GetTrueFather()->nr << " and index " << SortIndex[Walker->GetTrueFather()->nr] << "." << endl;
421 output << SortIndex[Walker->GetTrueFather()->nr] << "\t";
422 } else // otherwise a -1 to indicate an added saturation hydrogen
423 output << "-1\t";
424 }
425 }
426 }
427 }
428 //cout << endl << endl;
429 output << endl;
430 }
431 output.close();
432 cout << " done." << endl;
433
434 // open KeySet file
435 sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, "KeySets.dat");
436 output.open(TEFilename, ios::out);
437 cout << Verbose(2) << "Saving " << prefix << " key sets of each subgraph ...";
438 for(int j=0;j<NumberOfMolecules;j++) {
439 //if (TEList[j] != 0) {
440 Walker = ListOfMolecules[j]->start;
441 while(Walker->next != ListOfMolecules[j]->end) {
442 Walker = Walker->next;
443#ifdef ADDHYDROGEN
444 if ((Walker->GetTrueFather() != NULL) && (Walker->type->Z != 1)) // if there is a real father, prints its index
445#else
446 if ((Walker->GetTrueFather() != NULL)) // if there is a real father, prints its index
447#endif
448 output << Walker->GetTrueFather()->nr << "\t";
449#ifdef ADDHYDROGEN
450 else // otherwise a -1 to indicate an added saturation hydrogen
451 output << "-1\t";
452#endif
453 }
454 //cout << endl << endl;
455 output << endl;
456 }
457 output.close();
458 cout << " done." << endl;
459
460 // printing final number
461 cout << "Final number of fragments: " << FragmentCounter << "." << endl;
462
463 return result;
464};
465
466/** Reduce the list of molecules to unique pieces.
467 * molecule::IsEqualToWithinThreshold() is used by GetMappingToUniqueFragments() to provide a mapping for
468 * ReduceFragmentToUniqueOnes().
469 * \param *out output stream for debugging
470 * \param cell_size 6 entries specifying the unit cell vectors (matrix is symmetric) for getting the map
471 * \param celldistance needed for linked-cell technique when getting the map
472 */
473void MoleculeListClass::ReduceToUniqueList(ofstream *out, double *cell_size, double celldistance)
474{
475 int *ReduceMapping = NULL;
476
477 *out << Verbose(0) << "Begin of ReduceToUniqueList." << endl;
478 // again, check whether there are equal fragments by ReduceToUniqueOnes
479 *out << Verbose(1) << "Get reduce mapping." << endl;
480 ReduceMapping = GetMappingToUniqueFragments(out, 0.05, cell_size, celldistance);
481 *out << Verbose(1) << "MapList: ";
482 for(int i=0;i<NumberOfMolecules;i++)
483 *out << ReduceMapping[i] << " ";
484 *out << endl << endl;
485 *out << Verbose(1) << "Apply reduce mapping." << endl;
486 ReduceFragmentToUniqueOnes(out, ReduceMapping);
487 Free((void **)&ReduceMapping, "MoleculeListClass::FragmentTopDown: *ReduceMapping"); // free map after reduce
488 *out << Verbose(1) << "Number of Fragments after Reducing is " << NumberOfMolecules << "." << endl;
489 *out << Verbose(0) << "End of ReduceToUniqueList." << endl;
490};
491
492/** Fragments a molecule and resulting pieces recursively until the number of bonds
493 * Here the idea is similar to the FragmentBottomUp() approach, only that we split up the molecule
494 * bond per bond into left and right fragments and this recursively also with each yielded
495 * fragment until there is no fragment with continuous number of bonds greater than \a BondDegree.
496 * are below the given \a BondDegree.
497 * \param *out output stream for debugging
498 * \param BondDegree maximum number of continuous bonds in a fragment
499 * \param bonddistance typical bond distance
500 * \param *configuration configuration for writing config files for each fragment
501 * \param CutCyclic cut cyclic bonds (saturate with hydrogen) or add
502 * \return pointer to MoleculeListClass with all the fragments or NULL if something went wrong.
503 * \todo so far we volontarily mix up the above BondDegree definition and molecule::NoNonBonds
504 *
505 * \bug FragmentTopDown does not work right now due to NULL being given as cell_size to ReduceToUniqueOnes()
506 */
507MoleculeListClass * MoleculeListClass::FragmentTopDown(ofstream *out, int BondDegree, double bonddistance, config *configuration, enum CutCyclicBond CutCyclic)
508{
509 int Num, No, Cyclic, NoBonds;
510 MoleculeListClass *ReturnList = NULL;
511 MoleculeListClass **FragmentsList = NULL;
512 molecule *CurrentMolecule = NULL;
513 bond *Binder = NULL;
514
515 *out << Verbose(0) << "Begin of FragmentTopDown:" << this << "." << endl;
516 Num = 0;
517 FragmentsList = (MoleculeListClass **) Malloc(sizeof(MoleculeListClass *)*NumberOfMolecules, "MoleculeListClass::FragmentTopDown: **FragmentsList");
518 // fragment each molecule into its own MoleculeListClass
519 for(int i=0;i<NumberOfMolecules;i++) {
520 CurrentMolecule = ListOfMolecules[i];
521 CurrentMolecule->CountAtoms(out);
522 Cyclic = CurrentMolecule->CountCyclicBonds(out);
523 NoBonds =
524#ifdef ADDHYDROGEN
525CurrentMolecule->NoNonBonds
526#else
527CurrentMolecule->BondCount
528#endif
529 - ((CutCyclic == KeepBond) ? Cyclic : 0);
530 // check if NoNonBonds < BondDegree, then don't split any further: Here, correct for greatest continuous bond length!
531 *out << Verbose(0) << "Checking on Number of true Bonds " << NoBonds << " (i.e. no -H, if chosen no cyclic) greater than " << BondDegree << "." << endl;
532 if (NoBonds > BondDegree) {
533 //cerr << Verbose(1) << "TopDown Level of Molecule " << CurrentMolecule << ": " << (CurrentMolecule->NoNonBonds - BondDegree) << "." << endl;
534 *out << Verbose(1) << "Breaking up molecule " << i << " in fragment list." << endl;
535 CurrentMolecule->CreateListOfBondsPerAtom(out);
536 // Get atomic fragments for the list
537 *out << Verbose(1) << "Getting Atomic fragments for molecule " << i << "." << endl;
538 MoleculeListClass *AtomicFragments = CurrentMolecule->GetAtomicFragments(out, NumberOfTopAtoms, configuration->GetIsAngstroem(), TEList[i]/(1. - NoBonds), CutCyclic);
539
540 // build the atomic part of the list of molecules
541 *out << Verbose(1) << "Putting atomic fragment into list of molecules." << endl;
542
543 // cutting cyclic bonds yields only a single fragment, not two as non-cyclic!
544 No = (CutCyclic == KeepBond) ? ((
545#ifdef ADDHYDROGEN
546CurrentMolecule->NoNonBonds - Cyclic)*2) : CurrentMolecule->NoNonBonds*2 - Cyclic;
547#else
548CurrentMolecule->BondCount - Cyclic)*2) : CurrentMolecule->BondCount*2 - Cyclic;
549#endif
550
551 if (AtomicFragments != NULL) {
552 ReturnList = new MoleculeListClass(No+AtomicFragments->NumberOfMolecules, NumberOfTopAtoms);
553 for (int j=0;j<AtomicFragments->NumberOfMolecules;j++) { // shift all Atomic Fragments into this one here
554 ReturnList->ListOfMolecules[j+No] = AtomicFragments->ListOfMolecules[j];
555 AtomicFragments->ListOfMolecules[j] = NULL;
556 ReturnList->ListOfMolecules[j+No]->NoNonBonds = 0;
557 ReturnList->ListOfMolecules[j+No]->NoNonHydrogen = 1;
558 ReturnList->TEList[j+No] = AtomicFragments->TEList[j];
559 }
560 *out << Verbose(3) << "Freeing Atomic memory" << endl;
561 delete(AtomicFragments);
562 AtomicFragments = NULL;
563 } else {
564 *out << Verbose(2) << "AtomicFragments is NULL, filling list with whole molecule only." << endl;
565 ReturnList = new MoleculeListClass(No, NumberOfTopAtoms);
566 }
567
568 // build the side pieces part of the list of molecules
569 *out << Verbose(1) << "Building side piece fragments and putting into list of molecules." << endl;
570 No = 0;
571 Binder = CurrentMolecule->first;
572 while(Binder->next != CurrentMolecule->last) {
573 Binder = Binder->next;
574#ifdef ADDHYDROGEN
575 if (Binder->HydrogenBond == 0)
576#endif
577 if ((CutCyclic == SaturateBond) || (!Binder->Cyclic)) {
578 // split each bond into left and right side piece
579 if (Binder->Cyclic) {
580 molecule *dummy = NULL; // we lazily hand FragmentMoleculeByBond() a dummy as second fragment and ...
581 *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;
582 CurrentMolecule->FragmentMoleculeByBond(out, Binder, &(ReturnList->ListOfMolecules[No]), &(dummy), configuration->GetIsAngstroem(), CutCyclic);
583 delete(dummy); // ... free the dummy which is due to the cyclic bond the exacy same fragment
584 *out << Verbose(1) << "Single fragment is " << ReturnList->ListOfMolecules[No] << "." << endl;
585
586 // write down the necessary TE-summation in order to regain TE of whole molecule
587 *out << Verbose(2) << "Creating TEList for Fragment " << i << " of Bond " << No << "." << endl;
588#ifdef ADDHYDROGEN
589 ReturnList->TEList[No] = -TEList[i]/(1. -CurrentMolecule->NoNonBonds);
590#else
591 ReturnList->TEList[No] = -TEList[i]/(1. -CurrentMolecule->BondCount);
592#endif
593 } else {
594 *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;
595 CurrentMolecule->FragmentMoleculeByBond(out, Binder, &(ReturnList->ListOfMolecules[No]), &(ReturnList->ListOfMolecules[No+1]), configuration->GetIsAngstroem(), CutCyclic);
596 *out << Verbose(1) << "Left Fragment is " << ReturnList->ListOfMolecules[No] << ", right Fragment is " << ReturnList->ListOfMolecules[No+1] << "." << endl;
597
598 // write down the necessary TE-summation in order to regain TE of whole molecule
599 *out << Verbose(2) << "Creating TEList for Fragment " << i << " of Bond " << No << "." << endl;
600 ReturnList->TEList[No] = -TEList[i]/(1. - NoBonds);
601 ReturnList->TEList[No+1] = -TEList[i]/(1. - NoBonds);
602 }
603 No += ((Binder->Cyclic) ? 1 : 2);
604 }
605 }
606
607 // Reduce this list
608 ReturnList->ReduceToUniqueList(out, NULL, bonddistance);
609
610 // recurse and receive List
611 *out << Verbose(1) << "Calling TopDown " << ReturnList<< " with filled list: ";
612 ReturnList->Output(out);
613 FragmentsList[i] = ReturnList->FragmentTopDown(out, BondDegree, bonddistance, configuration, CutCyclic);
614 *out << Verbose(1) << "Returning from TopDown " << ReturnList<< " with filled list: ";
615 ReturnList->Output(out);
616
617 // remove list after we're done
618 *out << Verbose(2) << "Removing caller list." << endl;
619 delete(ReturnList);
620 ReturnList = NULL;
621
622 } else { // create a list with only a single molecule inside, transfer everything from "this" list to return list
623 *out << Verbose(1) << "Not breaking up molecule " << i << " in fragment list." << endl;
624 FragmentsList[i] = new MoleculeListClass(1, NumberOfTopAtoms);
625 FragmentsList[i]->ListOfMolecules[0] = ListOfMolecules[i];
626 ListOfMolecules[i] = NULL;
627 FragmentsList[i]->TEList[0] = TEList[i];
628 }
629 Num += FragmentsList[i]->NumberOfMolecules;
630 }
631
632 // now, we have a list of MoleculeListClasses: combine all fragments list into one single list
633 *out << Verbose(2) << "Combining to a list of " << Num << " molecules and Memory cleanup of old list of lists." << endl;
634 ReturnList = new MoleculeListClass(Num, NumberOfTopAtoms);
635 No = 0;
636 for(int i=0;i<NumberOfMolecules;i++) {
637 for(int j=0;j<FragmentsList[i]->NumberOfMolecules;j++) {
638 // transfer molecule
639 ReturnList->ListOfMolecules[No] = FragmentsList[i]->ListOfMolecules[j];
640 FragmentsList[i]->ListOfMolecules[j] = NULL;
641 // transfer TE factor
642 ReturnList->TEList[No] = FragmentsList[i]->TEList[j];
643 No++;
644 }
645 delete(FragmentsList[i]);
646 FragmentsList[i] = NULL;
647 }
648 Free((void **)&FragmentsList, "MoleculeListClass::FragmentTopDown: **FragmentsList");
649
650 // Reduce the list to unique fragments
651 ReturnList->ReduceToUniqueList(out, NULL, bonddistance);
652
653 // return pointer to list
654 *out << Verbose(0) << "Return with filled list: ";
655 ReturnList->Output(out);
656
657 *out << Verbose(0) << "End of FragmentTopDown:" << this << "." << endl;
658 return (ReturnList);
659};
660
661/******************************************* Class MoleculeLeafClass ************************************************/
662
663/** Constructor for MoleculeLeafClass root leaf.
664 * \param *Up Leaf on upper level
665 * \param *PreviousLeaf NULL - We are the first leaf on this level, otherwise points to previous in list
666 */
667//MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *Up = NULL, MoleculeLeafClass *Previous = NULL)
668MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
669{
670// if (Up != NULL)
671// if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
672// Up->DownLeaf = this;
673// UpLeaf = Up;
674// DownLeaf = NULL;
675 Leaf = NULL;
676 previous = PreviousLeaf;
677 if (previous != NULL) {
678 MoleculeLeafClass *Walker = previous->next;
679 previous->next = this;
680 next = Walker;
681 } else {
682 next = NULL;
683 }
684};
685
686/** Destructor for MoleculeLeafClass.
687 */
688MoleculeLeafClass::~MoleculeLeafClass()
689{
690// if (DownLeaf != NULL) {// drop leaves further down
691// MoleculeLeafClass *Walker = DownLeaf;
692// MoleculeLeafClass *Next;
693// do {
694// Next = Walker->NextLeaf;
695// delete(Walker);
696// Walker = Next;
697// } while (Walker != NULL);
698// // Last Walker sets DownLeaf automatically to NULL
699// }
700 // remove the leaf itself
701 if (Leaf != NULL) {
702 delete(Leaf);
703 Leaf = NULL;
704 }
705 // remove this Leaf from level list
706 if (previous != NULL)
707 previous->next = next;
708// } else { // we are first in list (connects to UpLeaf->DownLeaf)
709// if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
710// NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node
711// if (UpLeaf != NULL)
712// UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first
713// }
714// UpLeaf = NULL;
715 if (next != NULL) // are we last in list
716 next->previous = previous;
717 next = NULL;
718 previous = NULL;
719};
720
721/** Adds \a molecule leaf to the tree.
722 * \param *ptr ptr to molecule to be added
723 * \param *Previous previous MoleculeLeafClass referencing level and which on the level
724 * \return true - success, false - something went wrong
725 */
726bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous)
727{
728 return false;
729};
Note: See TracBrowser for help on using the repository browser.