source: src/moleculelist.cpp@ 0de7e8

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 0de7e8 was bd6bfa, checked in by Frederik Heber <heber@…>, 15 years ago

Fixes after first,last removal.

  • BUGFIX: molecule::OutputGraphInfoPerBond() - had removal loop, not go-through-each-loop.
  • BUGFIX: MoleculeListClass::~MoleculeListClass() - did falsely destroy molecules too although this is done by World.
  • new function MoleculeListClass::erase() - handles signing off molecule as observer and removes from list.
  • FIX: MoleculeListClass::DissectMoleculeIntoConnectedSubgraphs()
    • all molecules are removed from MoleculeListClass and also from World.
    • all bonds are removed, by going through all atoms of World.
    • molecule::getAtomCount() - calls doCountAtoms() which re-numbers and -labels atoms. This confused stuff.
  • TESTFIX: Molecules/6 and Molecules/7 had wrong (old) ordering in their test.conf
  • Property mode set to 100755
File size: 47.6 KB
Line 
1/** \file MoleculeListClass.cpp
2 *
3 * Function implementations for the class MoleculeListClass.
4 *
5 */
6
7#include <cstring>
8
9#include "World.hpp"
10#include "atom.hpp"
11#include "bond.hpp"
12#include "boundary.hpp"
13#include "config.hpp"
14#include "element.hpp"
15#include "helpers.hpp"
16#include "linkedcell.hpp"
17#include "lists.hpp"
18#include "log.hpp"
19#include "molecule.hpp"
20#include "memoryallocator.hpp"
21#include "periodentafel.hpp"
22#include "Helpers/Assert.hpp"
23
24#include "Helpers/Assert.hpp"
25
26/*********************************** Functions for class MoleculeListClass *************************/
27
28/** Constructor for MoleculeListClass.
29 */
30MoleculeListClass::MoleculeListClass(World *_world) :
31 world(_world)
32{
33 // empty lists
34 ListOfMolecules.clear();
35 MaxIndex = 1;
36};
37
38/** Destructor for MoleculeListClass.
39 */
40MoleculeListClass::~MoleculeListClass()
41{
42 DoLog(4) && (Log() << Verbose(4) << "Clearing ListOfMolecules." << endl);
43 for(MoleculeList::iterator MolRunner = ListOfMolecules.begin(); MolRunner != ListOfMolecules.end(); ++MolRunner)
44 (*MolRunner)->signOff(this);
45 ListOfMolecules.clear(); // empty list
46};
47
48/** Insert a new molecule into the list and set its number.
49 * \param *mol molecule to add to list.
50 */
51void MoleculeListClass::insert(molecule *mol)
52{
53 OBSERVE;
54 mol->IndexNr = MaxIndex++;
55 ListOfMolecules.push_back(mol);
56 mol->signOn(this);
57};
58
59/** Erases a molecule from the list.
60 * \param *mol molecule to add to list.
61 */
62void MoleculeListClass::erase(molecule *mol)
63{
64 OBSERVE;
65 mol->signOff(this);
66 ListOfMolecules.remove(mol);
67};
68
69/** Compare whether two molecules are equal.
70 * \param *a molecule one
71 * \param *n molecule two
72 * \return lexical value (-1, 0, +1)
73 */
74int MolCompare(const void *a, const void *b)
75{
76 int *aList = NULL, *bList = NULL;
77 int Count, Counter, aCounter, bCounter;
78 int flag;
79
80 // sort each atom list and put the numbers into a list, then go through
81 //Log() << Verbose(0) << "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << "." << endl;
82 // Yes those types are awkward... but check it for yourself it checks out this way
83 molecule *const *mol1_ptr= static_cast<molecule *const *>(a);
84 molecule *mol1 = *mol1_ptr;
85 molecule *const *mol2_ptr= static_cast<molecule *const *>(b);
86 molecule *mol2 = *mol2_ptr;
87 if (mol1->getAtomCount() < mol2->getAtomCount()) {
88 return -1;
89 } else {
90 if (mol1->getAtomCount() > mol2->getAtomCount())
91 return +1;
92 else {
93 Count = mol1->getAtomCount();
94 aList = new int[Count];
95 bList = new int[Count];
96
97 // fill the lists
98 Counter = 0;
99 aCounter = 0;
100 bCounter = 0;
101 molecule::const_iterator aiter = mol1->begin();
102 molecule::const_iterator biter = mol2->begin();
103 for (;(aiter != mol1->end()) && (biter != mol2->end());
104 ++aiter, ++biter) {
105 if ((*aiter)->GetTrueFather() == NULL)
106 aList[Counter] = Count + (aCounter++);
107 else
108 aList[Counter] = (*aiter)->GetTrueFather()->nr;
109 if ((*biter)->GetTrueFather() == NULL)
110 bList[Counter] = Count + (bCounter++);
111 else
112 bList[Counter] = (*biter)->GetTrueFather()->nr;
113 Counter++;
114 }
115 // check if AtomCount was for real
116 flag = 0;
117 if ((aiter == mol1->end()) && (biter != mol2->end())) {
118 flag = -1;
119 } else {
120 if ((aiter != mol1->end()) && (biter == mol2->end()))
121 flag = 1;
122 }
123 if (flag == 0) {
124 // sort the lists
125 gsl_heapsort(aList, Count, sizeof(int), CompareDoubles);
126 gsl_heapsort(bList, Count, sizeof(int), CompareDoubles);
127 // compare the lists
128
129 flag = 0;
130 for (int i = 0; i < Count; i++) {
131 if (aList[i] < bList[i]) {
132 flag = -1;
133 } else {
134 if (aList[i] > bList[i])
135 flag = 1;
136 }
137 if (flag != 0)
138 break;
139 }
140 }
141 delete[] (aList);
142 delete[] (bList);
143 return flag;
144 }
145 }
146 return -1;
147};
148
149/** Output of a list of all molecules.
150 * \param *out output stream
151 */
152void MoleculeListClass::Enumerate(ostream *out)
153{
154 periodentafel *periode = World::getInstance().getPeriode();
155 std::map<atomicNumber_t,unsigned int> counts;
156 double size=0;
157 Vector Origin;
158
159 // header
160 (*out) << "Index\tName\t\tAtoms\tFormula\tCenter\tSize" << endl;
161 (*out) << "-----------------------------------------------" << endl;
162 if (ListOfMolecules.size() == 0)
163 (*out) << "\tNone" << endl;
164 else {
165 Origin.Zero();
166 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
167 // count atoms per element and determine size of bounding sphere
168 size=0.;
169 for (molecule::const_iterator iter = (*ListRunner)->begin(); iter != (*ListRunner)->end(); ++iter) {
170 counts[(*iter)->type->getNumber()]++;
171 if ((*iter)->x.DistanceSquared(Origin) > size)
172 size = (*iter)->x.DistanceSquared(Origin);
173 }
174 // output Index, Name, number of atoms, chemical formula
175 (*out) << ((*ListRunner)->ActiveFlag ? "*" : " ") << (*ListRunner)->IndexNr << "\t" << (*ListRunner)->name << "\t\t" << (*ListRunner)->getAtomCount() << "\t";
176
177 std::map<atomicNumber_t,unsigned int>::reverse_iterator iter;
178 for(iter=counts.rbegin(); iter!=counts.rend();++iter){
179 atomicNumber_t Z =(*iter).first;
180 (*out) << periode->FindElement(Z)->getSymbol() << (*iter).second;
181 }
182 // Center and size
183 (*out) << "\t" << (*ListRunner)->Center << "\t" << sqrt(size) << endl;
184 }
185 }
186};
187
188/** Returns the molecule with the given index \a index.
189 * \param index index of the desired molecule
190 * \return pointer to molecule structure, NULL if not found
191 */
192molecule * MoleculeListClass::ReturnIndex(int index)
193{
194 for(MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
195 if ((*ListRunner)->IndexNr == index)
196 return (*ListRunner);
197 return NULL;
198};
199
200/** Simple merge of two molecules into one.
201 * \param *mol destination molecule
202 * \param *srcmol source molecule
203 * \return true - merge successful, false - merge failed (probably due to non-existant indices
204 */
205bool MoleculeListClass::SimpleMerge(molecule *mol, molecule *srcmol)
206{
207 if (srcmol == NULL)
208 return false;
209
210 // put all molecules of src into mol
211 molecule::iterator runner;
212 for (molecule::iterator iter = srcmol->begin(); iter != srcmol->end(); ++iter) {
213 runner = iter++;
214 srcmol->UnlinkAtom((*runner));
215 mol->AddAtom((*runner));
216 }
217
218 // remove src
219 ListOfMolecules.remove(srcmol);
220 World::getInstance().destroyMolecule(srcmol);
221 return true;
222};
223
224/** Simple add of one molecules into another.
225 * \param *mol destination molecule
226 * \param *srcmol source molecule
227 * \return true - merge successful, false - merge failed (probably due to non-existant indices
228 */
229bool MoleculeListClass::SimpleAdd(molecule *mol, molecule *srcmol)
230{
231 if (srcmol == NULL)
232 return false;
233
234 // put all molecules of src into mol
235 atom *Walker = NULL;
236 for (molecule::iterator iter = srcmol->begin(); iter != srcmol->end(); ++iter) {
237 Walker = mol->AddCopyAtom((*iter));
238 Walker->father = Walker;
239 }
240
241 return true;
242};
243
244/** Simple merge of a given set of molecules into one.
245 * \param *mol destination molecule
246 * \param *src index of set of source molecule
247 * \param N number of source molecules
248 * \return true - merge successful, false - some merges failed (probably due to non-existant indices)
249 */
250bool MoleculeListClass::SimpleMultiMerge(molecule *mol, int *src, int N)
251{
252 bool status = true;
253 // check presence of all source molecules
254 for (int i=0;i<N;i++) {
255 molecule *srcmol = ReturnIndex(src[i]);
256 status = status && SimpleMerge(mol, srcmol);
257 }
258 return status;
259};
260
261/** Simple add of a given set of molecules into one.
262 * \param *mol destination molecule
263 * \param *src index of set of source molecule
264 * \param N number of source molecules
265 * \return true - merge successful, false - some merges failed (probably due to non-existant indices)
266 */
267bool MoleculeListClass::SimpleMultiAdd(molecule *mol, int *src, int N)
268{
269 bool status = true;
270 // check presence of all source molecules
271 for (int i=0;i<N;i++) {
272 molecule *srcmol = ReturnIndex(src[i]);
273 status = status && SimpleAdd(mol, srcmol);
274 }
275 return status;
276};
277
278/** Scatter merge of a given set of molecules into one.
279 * Scatter merge distributes the molecules in such a manner that they don't overlap.
280 * \param *mol destination molecule
281 * \param *src index of set of source molecule
282 * \param N number of source molecules
283 * \return true - merge successful, false - merge failed (probably due to non-existant indices
284 * \TODO find scatter center for each src molecule
285 */
286bool MoleculeListClass::ScatterMerge(molecule *mol, int *src, int N)
287{
288 // check presence of all source molecules
289 for (int i=0;i<N;i++) {
290 // get pointer to src molecule
291 molecule *srcmol = ReturnIndex(src[i]);
292 if (srcmol == NULL)
293 return false;
294 }
295 // adapt each Center
296 for (int i=0;i<N;i++) {
297 // get pointer to src molecule
298 molecule *srcmol = ReturnIndex(src[i]);
299 //srcmol->Center.Zero();
300 srcmol->Translate(&srcmol->Center);
301 }
302 // perform a simple multi merge
303 SimpleMultiMerge(mol, src, N);
304 return true;
305};
306
307/** Embedding merge of a given set of molecules into one.
308 * Embedding merge inserts one molecule into the other.
309 * \param *mol destination molecule (fixed one)
310 * \param *srcmol source molecule (variable one, where atoms are taken from)
311 * \return true - merge successful, false - merge failed (probably due to non-existant indices)
312 * \TODO linked cell dimensions for boundary points has to be as big as inner diameter!
313 */
314bool MoleculeListClass::EmbedMerge(molecule *mol, molecule *srcmol)
315{
316 LinkedCell *LCList = NULL;
317 Tesselation *TesselStruct = NULL;
318 if ((srcmol == NULL) || (mol == NULL)) {
319 DoeLog(1) && (eLog()<< Verbose(1) << "Either fixed or variable molecule is given as NULL." << endl);
320 return false;
321 }
322
323 // calculate envelope for *mol
324 LCList = new LinkedCell(mol, 8.);
325 FindNonConvexBorder(mol, TesselStruct, (const LinkedCell *&)LCList, 4., NULL);
326 if (TesselStruct == NULL) {
327 DoeLog(1) && (eLog()<< Verbose(1) << "Could not tesselate the fixed molecule." << endl);
328 return false;
329 }
330 delete(LCList);
331 LCList = new LinkedCell(TesselStruct, 8.); // re-create with boundary points only!
332
333 // prepare index list for bonds
334 atom ** CopyAtoms = new atom*[srcmol->getAtomCount()];
335 for(int i=0;i<srcmol->getAtomCount();i++)
336 CopyAtoms[i] = NULL;
337
338 // for each of the source atoms check whether we are in- or outside and add copy atom
339 int nr=0;
340 for (molecule::const_iterator iter = srcmol->begin(); iter != srcmol->end(); ++iter) {
341 DoLog(2) && (Log() << Verbose(2) << "INFO: Current Walker is " << **iter << "." << endl);
342 if (!TesselStruct->IsInnerPoint((*iter)->x, LCList)) {
343 CopyAtoms[(*iter)->nr] = (*iter)->clone();
344 mol->AddAtom(CopyAtoms[(*iter)->nr]);
345 nr++;
346 } else {
347 // do nothing
348 }
349 }
350 DoLog(1) && (Log() << Verbose(1) << nr << " of " << srcmol->getAtomCount() << " atoms have been merged.");
351
352 // go through all bonds and add as well
353 for(molecule::iterator AtomRunner = srcmol->begin(); AtomRunner != srcmol->end(); ++AtomRunner)
354 for(BondList::iterator BondRunner = (*AtomRunner)->ListOfBonds.begin(); BondRunner != (*AtomRunner)->ListOfBonds.end(); ++BondRunner)
355 if ((*BondRunner)->leftatom == *AtomRunner) {
356 DoLog(3) && (Log() << Verbose(3) << "Adding Bond between " << *CopyAtoms[(*BondRunner)->leftatom->nr] << " and " << *CopyAtoms[(*BondRunner)->rightatom->nr]<< "." << endl);
357 mol->AddBond(CopyAtoms[(*BondRunner)->leftatom->nr], CopyAtoms[(*BondRunner)->rightatom->nr], (*BondRunner)->BondDegree);
358 }
359 delete(LCList);
360 return true;
361};
362
363/** Simple output of the pointers in ListOfMolecules.
364 * \param *out output stream
365 */
366void MoleculeListClass::Output(ofstream *out)
367{
368 DoLog(1) && (Log() << Verbose(1) << "MoleculeList: ");
369 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
370 DoLog(0) && (Log() << Verbose(0) << *ListRunner << "\t");
371 DoLog(0) && (Log() << Verbose(0) << endl);
372};
373
374/** Calculates necessary hydrogen correction due to unwanted interaction between saturated ones.
375 * If for a pair of two hydrogen atoms a and b, at least is a saturated one, and a and b are not
376 * bonded to the same atom, then we add for this pair a correction term constructed from a Morse
377 * potential function fit to QM calculations with respecting to the interatomic hydrogen distance.
378 * \param *out output stream for debugging
379 * \param *path path to file
380 */
381bool MoleculeListClass::AddHydrogenCorrection(char *path)
382{
383 bond *Binder = NULL;
384 double ***FitConstant = NULL, **correction = NULL;
385 int a, b;
386 ofstream output;
387 ifstream input;
388 string line;
389 stringstream zeile;
390 double distance;
391 char ParsedLine[1023];
392 double tmp;
393 char *FragmentNumber = NULL;
394
395 DoLog(1) && (Log() << Verbose(1) << "Saving hydrogen saturation correction ... ");
396 // 0. parse in fit constant files that should have the same dimension as the final energy files
397 // 0a. find dimension of matrices with constants
398 line = path;
399 line.append("/");
400 line += FRAGMENTPREFIX;
401 line += "1";
402 line += FITCONSTANTSUFFIX;
403 input.open(line.c_str());
404 if (input == NULL) {
405 DoLog(1) && (Log() << Verbose(1) << endl << "Unable to open " << line << ", is the directory correct?" << endl);
406 return false;
407 }
408 a = 0;
409 b = -1; // we overcount by one
410 while (!input.eof()) {
411 input.getline(ParsedLine, 1023);
412 zeile.str(ParsedLine);
413 int i = 0;
414 while (!zeile.eof()) {
415 zeile >> distance;
416 i++;
417 }
418 if (i > a)
419 a = i;
420 b++;
421 }
422 DoLog(0) && (Log() << Verbose(0) << "I recognized " << a << " columns and " << b << " rows, ");
423 input.close();
424
425 // 0b. allocate memory for constants
426 FitConstant = new double**[3];
427 for (int k = 0; k < 3; k++) {
428 FitConstant[k] = new double*[a];
429 for (int i = a; i--;) {
430 FitConstant[k][i] = new double[b];
431 for (int j = b; j--;) {
432 FitConstant[k][i][j] = 0.;
433 }
434 }
435 }
436 // 0c. parse in constants
437 for (int i = 0; i < 3; i++) {
438 line = path;
439 line.append("/");
440 line += FRAGMENTPREFIX;
441 sprintf(ParsedLine, "%d", i + 1);
442 line += ParsedLine;
443 line += FITCONSTANTSUFFIX;
444 input.open(line.c_str());
445 if (input == NULL) {
446 DoeLog(0) && (eLog()<< Verbose(0) << endl << "Unable to open " << line << ", is the directory correct?" << endl);
447 performCriticalExit();
448 return false;
449 }
450 int k = 0, l;
451 while ((!input.eof()) && (k < b)) {
452 input.getline(ParsedLine, 1023);
453 //Log() << Verbose(0) << "Current Line: " << ParsedLine << endl;
454 zeile.str(ParsedLine);
455 zeile.clear();
456 l = 0;
457 while ((!zeile.eof()) && (l < a)) {
458 zeile >> FitConstant[i][l][k];
459 //Log() << Verbose(0) << FitConstant[i][l][k] << "\t";
460 l++;
461 }
462 //Log() << Verbose(0) << endl;
463 k++;
464 }
465 input.close();
466 }
467 for (int k = 0; k < 3; k++) {
468 DoLog(0) && (Log() << Verbose(0) << "Constants " << k << ":" << endl);
469 for (int j = 0; j < b; j++) {
470 for (int i = 0; i < a; i++) {
471 DoLog(0) && (Log() << Verbose(0) << FitConstant[k][i][j] << "\t");
472 }
473 DoLog(0) && (Log() << Verbose(0) << endl);
474 }
475 DoLog(0) && (Log() << Verbose(0) << endl);
476 }
477
478 // 0d. allocate final correction matrix
479 correction = new double*[a];
480 for (int i = a; i--;)
481 correction[i] = new double[b];
482
483 // 1a. go through every molecule in the list
484 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
485 // 1b. zero final correction matrix
486 for (int k = a; k--;)
487 for (int j = b; j--;)
488 correction[k][j] = 0.;
489 // 2. take every hydrogen that is a saturated one
490 for (molecule::const_iterator iter = (*ListRunner)->begin(); iter != (*ListRunner)->end(); ++iter) {
491 //Log() << Verbose(1) << "(*iter): " << *(*iter) << " with first bond " << *((*iter)->ListOfBonds.begin()) << "." << endl;
492 if (((*iter)->type->Z == 1) && (((*iter)->father == NULL)
493 || ((*iter)->father->type->Z != 1))) { // if it's a hydrogen
494 for (molecule::const_iterator runner = (*ListRunner)->begin(); runner != (*ListRunner)->end(); ++runner) {
495 //Log() << Verbose(2) << "Runner: " << *(*runner) << " with first bond " << *((*iter)->ListOfBonds.begin()) << "." << endl;
496 // 3. take every other hydrogen that is the not the first and not bound to same bonding partner
497 Binder = *((*runner)->ListOfBonds.begin());
498 if (((*runner)->type->Z == 1) && ((*runner)->nr > (*iter)->nr) && (Binder->GetOtherAtom((*runner)) != Binder->GetOtherAtom((*iter)))) { // (hydrogens have only one bonding partner!)
499 // 4. evaluate the morse potential for each matrix component and add up
500 distance = (*runner)->x.distance((*iter)->x);
501 //Log() << Verbose(0) << "Fragment " << (*ListRunner)->name << ": " << *(*runner) << "<= " << distance << "=>" << *(*iter) << ":" << endl;
502 for (int k = 0; k < a; k++) {
503 for (int j = 0; j < b; j++) {
504 switch (k) {
505 case 1:
506 case 7:
507 case 11:
508 tmp = pow(FitConstant[0][k][j] * (1. - exp(-FitConstant[1][k][j] * (distance - FitConstant[2][k][j]))), 2);
509 break;
510 default:
511 tmp = FitConstant[0][k][j] * pow(distance, FitConstant[1][k][j]) + FitConstant[2][k][j];
512 };
513 correction[k][j] -= tmp; // ground state is actually lower (disturbed by additional interaction)
514 //Log() << Verbose(0) << tmp << "\t";
515 }
516 //Log() << Verbose(0) << endl;
517 }
518 //Log() << Verbose(0) << endl;
519 }
520 }
521 }
522 }
523 // 5. write final matrix to file
524 line = path;
525 line.append("/");
526 line += FRAGMENTPREFIX;
527 FragmentNumber = FixedDigitNumber(ListOfMolecules.size(), (*ListRunner)->IndexNr);
528 line += FragmentNumber;
529 delete[] (FragmentNumber);
530 line += HCORRECTIONSUFFIX;
531 output.open(line.c_str());
532 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;
533 for (int j = 0; j < b; j++) {
534 for (int i = 0; i < a; i++)
535 output << correction[i][j] << "\t";
536 output << endl;
537 }
538 output.close();
539 }
540 for (int i = a; i--;)
541 delete[](correction[i]);
542 delete[](correction);
543
544 line = path;
545 line.append("/");
546 line += HCORRECTIONSUFFIX;
547 output.open(line.c_str());
548 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;
549 for (int j = 0; j < b; j++) {
550 for (int i = 0; i < a; i++)
551 output << 0 << "\t";
552 output << endl;
553 }
554 output.close();
555 // 6. free memory of parsed matrices
556 for (int k = 0; k < 3; k++) {
557 for (int i = a; i--;) {
558 delete[](FitConstant[k][i]);
559 }
560 delete[](FitConstant[k]);
561 }
562 delete[](FitConstant);
563 DoLog(0) && (Log() << Verbose(0) << "done." << endl);
564 return true;
565};
566
567/** Store force indices, i.e. the connection between the nuclear index in the total molecule config and the respective atom in fragment config.
568 * \param *out output stream for debugging
569 * \param *path path to file
570 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
571 * \return true - file written successfully, false - writing failed
572 */
573bool MoleculeListClass::StoreForcesFile(char *path,
574 int *SortIndex)
575{
576 bool status = true;
577 ofstream ForcesFile;
578 stringstream line;
579 periodentafel *periode=World::getInstance().getPeriode();
580
581 // open file for the force factors
582 DoLog(1) && (Log() << Verbose(1) << "Saving force factors ... ");
583 line << path << "/" << FRAGMENTPREFIX << FORCESFILE;
584 ForcesFile.open(line.str().c_str(), ios::out);
585 if (ForcesFile != NULL) {
586 //Log() << Verbose(1) << "Final AtomicForcesList: ";
587 //output << prefix << "Forces" << endl;
588 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
589 periodentafel::const_iterator elemIter;
590 for(elemIter=periode->begin();elemIter!=periode->end();++elemIter){
591 if ((*ListRunner)->ElementsInMolecule[(*elemIter).first]) { // if this element got atoms
592 for(molecule::iterator atomIter = (*ListRunner)->begin(); atomIter !=(*ListRunner)->end();++atomIter){
593 if ((*atomIter)->type->getNumber() == (*elemIter).first) {
594 if (((*atomIter)->GetTrueFather() != NULL) && ((*atomIter)->GetTrueFather() != (*atomIter))) {// if there is a rea
595 //Log() << Verbose(0) << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", it
596 ForcesFile << SortIndex[(*atomIter)->GetTrueFather()->nr] << "\t";
597 } else
598 // otherwise a -1 to indicate an added saturation hydrogen
599 ForcesFile << "-1\t";
600 }
601 }
602 }
603 }
604 ForcesFile << endl;
605 }
606 ForcesFile.close();
607 DoLog(1) && (Log() << Verbose(1) << "done." << endl);
608 } else {
609 status = false;
610 DoLog(1) && (Log() << Verbose(1) << "failed to open file " << line.str() << "." << endl);
611 }
612 ForcesFile.close();
613
614 return status;
615};
616
617/** Writes a config file for each molecule in the given \a **FragmentList.
618 * \param *out output stream for debugging
619 * \param *configuration standard configuration to attach atoms in fragment molecule to.
620 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
621 * \return true - success (each file was written), false - something went wrong.
622 */
623bool MoleculeListClass::OutputConfigForListOfFragments(config *configuration, int *SortIndex)
624{
625 ofstream outputFragment;
626 char FragmentName[MAXSTRINGSIZE];
627 char PathBackup[MAXSTRINGSIZE];
628 bool result = true;
629 bool intermediateResult = true;
630 Vector BoxDimension;
631 char *FragmentNumber = NULL;
632 char *path = NULL;
633 int FragmentCounter = 0;
634 ofstream output;
635 double cell_size_backup[6];
636 double * const cell_size = World::getInstance().getDomain();
637
638 // backup cell_size
639 for (int i=0;i<6;i++)
640 cell_size_backup[i] = cell_size[i];
641 // store the fragments as config and as xyz
642 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
643 // save default path as it is changed for each fragment
644 path = configuration->GetDefaultPath();
645 if (path != NULL)
646 strcpy(PathBackup, path);
647 else {
648 DoeLog(0) && (eLog()<< Verbose(0) << "OutputConfigForListOfFragments: NULL default path obtained from config!" << endl);
649 performCriticalExit();
650 }
651
652 // correct periodic
653 (*ListRunner)->ScanForPeriodicCorrection();
654
655 // output xyz file
656 FragmentNumber = FixedDigitNumber(ListOfMolecules.size(), FragmentCounter++);
657 sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
658 outputFragment.open(FragmentName, ios::out);
659 DoLog(2) && (Log() << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter - 1 << " as XYZ ...");
660 if ((intermediateResult = (*ListRunner)->OutputXYZ(&outputFragment)))
661 DoLog(0) && (Log() << Verbose(0) << " done." << endl);
662 else
663 DoLog(0) && (Log() << Verbose(0) << " failed." << endl);
664 result = result && intermediateResult;
665 outputFragment.close();
666 outputFragment.clear();
667
668 // list atoms in fragment for debugging
669 DoLog(2) && (Log() << Verbose(2) << "Contained atoms: ");
670 for (molecule::const_iterator iter = (*ListRunner)->begin(); iter != (*ListRunner)->end(); ++iter) {
671 DoLog(0) && (Log() << Verbose(0) << (*iter)->getName() << " ");
672 }
673 DoLog(0) && (Log() << Verbose(0) << endl);
674
675 // center on edge
676 (*ListRunner)->CenterEdge(&BoxDimension);
677 (*ListRunner)->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary
678 int j = -1;
679 for (int k = 0; k < NDIM; k++) {
680 j += k + 1;
681 BoxDimension[k] = 2.5 * (configuration->GetIsAngstroem() ? 1. : 1. / AtomicLengthToAngstroem);
682 cell_size[j] = BoxDimension[k] * 2.;
683 }
684 (*ListRunner)->Translate(&BoxDimension);
685
686 // also calculate necessary orbitals
687 (*ListRunner)->CountElements(); // this is a bugfix, atoms should shoulds actually be added correctly to this fragment
688 (*ListRunner)->CalculateOrbitals(*configuration);
689
690 // change path in config
691 //strcpy(PathBackup, configuration->configpath);
692 sprintf(FragmentName, "%s/%s%s/", PathBackup, FRAGMENTPREFIX, FragmentNumber);
693 configuration->SetDefaultPath(FragmentName);
694
695 // and save as config
696 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
697 DoLog(2) && (Log() << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter - 1 << " as config ...");
698 if ((intermediateResult = configuration->Save(FragmentName, (*ListRunner)->elemente, (*ListRunner))))
699 DoLog(0) && (Log() << Verbose(0) << " done." << endl);
700 else
701 DoLog(0) && (Log() << Verbose(0) << " failed." << endl);
702 result = result && intermediateResult;
703
704 // restore old config
705 configuration->SetDefaultPath(PathBackup);
706
707 // and save as mpqc input file
708 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber);
709 DoLog(2) && (Log() << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter - 1 << " as mpqc input ...");
710 if ((intermediateResult = configuration->SaveMPQC(FragmentName, (*ListRunner))))
711 DoLog(2) && (Log() << Verbose(2) << " done." << endl);
712 else
713 DoLog(0) && (Log() << Verbose(0) << " failed." << endl);
714
715 result = result && intermediateResult;
716 //outputFragment.close();
717 //outputFragment.clear();
718 delete[](FragmentNumber);
719 }
720 DoLog(0) && (Log() << Verbose(0) << " done." << endl);
721
722 // printing final number
723 DoLog(2) && (Log() << Verbose(2) << "Final number of fragments: " << FragmentCounter << "." << endl);
724
725 // restore cell_size
726 for (int i=0;i<6;i++)
727 cell_size[i] = cell_size_backup[i];
728
729 return result;
730};
731
732/** Counts the number of molecules with the molecule::ActiveFlag set.
733 * \return number of molecules with ActiveFlag set to true.
734 */
735int MoleculeListClass::NumberOfActiveMolecules()
736{
737 int count = 0;
738 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
739 count += ((*ListRunner)->ActiveFlag ? 1 : 0);
740 return count;
741};
742
743/** Dissects given \a *mol into connected subgraphs and inserts them as new molecules but with old atoms into \a this.
744 * \param *out output stream for debugging
745 * \param *periode periodentafel
746 * \param *configuration config with BondGraph
747 */
748void MoleculeListClass::DissectMoleculeIntoConnectedSubgraphs(const periodentafel * const periode, config * const configuration)
749{
750 // 0a. remove all present molecules
751 vector<molecule *> allmolecules = World::getInstance().getAllMolecules();
752 for (vector<molecule *>::iterator MolRunner = allmolecules.begin(); MolRunner != allmolecules.end(); ++MolRunner) {
753 erase(*MolRunner);
754 World::getInstance().destroyMolecule(*MolRunner);
755 }
756 // 0b. remove all bonds
757 molecule *mol = World::getInstance().createMolecule();
758 vector <atom *> allatoms = World::getInstance().getAllAtoms();
759 for(vector<atom *>::iterator AtomRunner = allatoms.begin(); AtomRunner != allatoms.end(); ++AtomRunner) {
760 for(BondList::iterator BondRunner = (*AtomRunner)->ListOfBonds.begin(); !(*AtomRunner)->ListOfBonds.empty(); BondRunner = (*AtomRunner)->ListOfBonds.begin())
761 delete(*BondRunner);
762 mol->AddAtom(*AtomRunner);
763 }
764
765 // 1. dissect the molecule into connected subgraphs
766 if (!configuration->BG->ConstructBondGraph(mol)) {
767 World::getInstance().destroyMolecule(mol);
768 DoeLog(1) && (eLog()<< Verbose(1) << "There are no bonds." << endl);
769 return;
770 }
771
772 // 2. scan for connected subgraphs
773 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis
774 class StackClass<bond *> *BackEdgeStack = NULL;
775 Subgraphs = mol->DepthFirstSearchAnalysis(BackEdgeStack);
776 delete(BackEdgeStack);
777 if ((Subgraphs == NULL) || (Subgraphs->next == NULL)) {
778 World::getInstance().destroyMolecule(mol);
779 DoeLog(1) && (eLog()<< Verbose(1) << "There are no atoms." << endl);
780 return;
781 }
782
783 // 3. dissect (the following construct is needed to have the atoms not in the order of the DFS, but in
784 // the original one as parsed in)
785 // TODO: Optimize this, when molecules just contain pointer list of global atoms!
786
787 // 4a. create array of molecules to fill
788 const int MolCount = Subgraphs->next->Count();
789 char number[MAXSTRINGSIZE];
790 molecule **molecules = new molecule *[MolCount];
791 for (int i=0;i<MolCount;i++) {
792 molecules[i] = World::getInstance().createMolecule();
793 molecules[i]->ActiveFlag = true;
794 strncpy(molecules[i]->name, mol->name, MAXSTRINGSIZE);
795 if (MolCount > 1) {
796 sprintf(number, "-%d", i+1);
797 strncat(molecules[i]->name, number, MAXSTRINGSIZE - strlen(mol->name) - 1);
798 }
799 DoLog(1) && (Log() << Verbose(1) << "MolName is " << molecules[i]->name << endl);
800 insert(molecules[i]);
801 }
802
803 // 4b. create and fill map of which atom is associated to which connected molecule (note, counting starts at 1)
804 int FragmentCounter = 0;
805 int *MolMap = new int[mol->getAtomCount()];
806 for (int i=0;i<mol->getAtomCount();i++)
807 MolMap[i] = 0;
808 MoleculeLeafClass *MolecularWalker = Subgraphs;
809 while (MolecularWalker->next != NULL) {
810 MolecularWalker = MolecularWalker->next;
811 for (molecule::const_iterator iter = MolecularWalker->Leaf->begin(); iter != MolecularWalker->Leaf->end(); ++iter) {
812 MolMap[(*iter)->GetTrueFather()->nr] = FragmentCounter+1;
813 }
814 FragmentCounter++;
815 }
816
817 // 4c. relocate atoms to new molecules and remove from Leafs
818 for (molecule::iterator iter = mol->begin(); !mol->empty(); iter = mol->begin()) {
819 const int count = mol->getAtomCount();
820 if (((*iter)->nr <0) || ((*iter)->nr >= count)) {
821 DoeLog(0) && (eLog()<< Verbose(0) << "Index " << (*iter)->nr << " of atom " << **iter << " in molecule of " << count << " atoms is invalid!" << endl);
822 performCriticalExit();
823 }
824 const int Index = MolMap[(*iter)->nr];
825 if (Index != 0) {
826 DoLog(3) && (Log() << Verbose(3) << "Re-linking " << **iter << "..." << endl);
827 molecules[Index-1]->AddAtom((*iter)); // counting starts at 1
828 mol->erase(iter);
829 } else {
830 DoeLog(0) && (eLog()<< Verbose(0) << "Atom " << **iter << " not associated to molecule!" << endl);
831 performCriticalExit();
832 }
833 }
834 // 4d. we don't need to redo bonds, as they are connected subgraphs and still maintain their ListOfBonds, but we have to remove them from first..last list
835 // TODO: check whether this is really not needed anymore
836 // 4e. free Leafs
837 MolecularWalker = Subgraphs;
838 while (MolecularWalker->next != NULL) {
839 MolecularWalker = MolecularWalker->next;
840 delete(MolecularWalker->previous);
841 }
842 delete(MolecularWalker);
843 delete[](MolMap);
844 delete[](molecules);
845 DoLog(1) && (Log() << Verbose(1) << "I scanned " << FragmentCounter << " molecules." << endl);
846};
847
848/** Count all atoms in each molecule.
849 * \return number of atoms in the MoleculeListClass.
850 * TODO: the inner loop should be done by some (double molecule::CountAtom()) function
851 */
852int MoleculeListClass::CountAllAtoms() const
853{
854 int AtomNo = 0;
855 for (MoleculeList::const_iterator MolWalker = ListOfMolecules.begin(); MolWalker != ListOfMolecules.end(); MolWalker++) {
856 AtomNo += (*MolWalker)->size();
857 }
858 return AtomNo;
859}
860
861/***********
862 * Methods Moved here from the menus
863 */
864
865void MoleculeListClass::flipChosen() {
866 int j;
867 Log() << Verbose(0) << "Enter index of molecule: ";
868 cin >> j;
869 for(MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
870 if ((*ListRunner)->IndexNr == j)
871 (*ListRunner)->ActiveFlag = !(*ListRunner)->ActiveFlag;
872}
873
874void MoleculeListClass::createNewMolecule(periodentafel *periode) {
875 OBSERVE;
876 molecule *mol = NULL;
877 mol = World::getInstance().createMolecule();
878 insert(mol);
879};
880
881void MoleculeListClass::loadFromXYZ(periodentafel *periode){
882 molecule *mol = NULL;
883 Vector center;
884 char filename[MAXSTRINGSIZE];
885 Log() << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
886 mol = World::getInstance().createMolecule();
887 do {
888 Log() << Verbose(0) << "Enter file name: ";
889 cin >> filename;
890 } while (!mol->AddXYZFile(filename));
891 mol->SetNameFromFilename(filename);
892 // center at set box dimensions
893 mol->CenterEdge(&center);
894 World::getInstance().getDomain()[0] = center[0];
895 World::getInstance().getDomain()[1] = 0;
896 World::getInstance().getDomain()[2] = center[1];
897 World::getInstance().getDomain()[3] = 0;
898 World::getInstance().getDomain()[4] = 0;
899 World::getInstance().getDomain()[5] = center[2];
900 insert(mol);
901}
902
903void MoleculeListClass::setMoleculeFilename() {
904 char filename[MAXSTRINGSIZE];
905 int nr;
906 molecule *mol = NULL;
907 do {
908 Log() << Verbose(0) << "Enter index of molecule: ";
909 cin >> nr;
910 mol = ReturnIndex(nr);
911 } while (mol == NULL);
912 Log() << Verbose(0) << "Enter name: ";
913 cin >> filename;
914 mol->SetNameFromFilename(filename);
915}
916
917void MoleculeListClass::parseXYZIntoMolecule(){
918 char filename[MAXSTRINGSIZE];
919 int nr;
920 molecule *mol = NULL;
921 mol = NULL;
922 do {
923 Log() << Verbose(0) << "Enter index of molecule: ";
924 cin >> nr;
925 mol = ReturnIndex(nr);
926 } while (mol == NULL);
927 Log() << Verbose(0) << "Format should be XYZ with: ShorthandOfElement\tX\tY\tZ" << endl;
928 do {
929 Log() << Verbose(0) << "Enter file name: ";
930 cin >> filename;
931 } while (!mol->AddXYZFile(filename));
932 mol->SetNameFromFilename(filename);
933};
934
935void MoleculeListClass::eraseMolecule(){
936 int nr;
937 molecule *mol = NULL;
938 Log() << Verbose(0) << "Enter index of molecule: ";
939 cin >> nr;
940 for(MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
941 if (nr == (*ListRunner)->IndexNr) {
942 mol = *ListRunner;
943 ListOfMolecules.erase(ListRunner);
944 World::getInstance().destroyMolecule(mol);
945 break;
946 }
947};
948
949
950/******************************************* Class MoleculeLeafClass ************************************************/
951
952/** Constructor for MoleculeLeafClass root leaf.
953 * \param *Up Leaf on upper level
954 * \param *PreviousLeaf NULL - We are the first leaf on this level, otherwise points to previous in list
955 */
956//MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *Up = NULL, MoleculeLeafClass *Previous = NULL)
957MoleculeLeafClass::MoleculeLeafClass(MoleculeLeafClass *PreviousLeaf = NULL)
958{
959 // if (Up != NULL)
960 // if (Up->DownLeaf == NULL) // are we the first down leaf for the upper leaf?
961 // Up->DownLeaf = this;
962 // UpLeaf = Up;
963 // DownLeaf = NULL;
964 Leaf = NULL;
965 previous = PreviousLeaf;
966 if (previous != NULL) {
967 MoleculeLeafClass *Walker = previous->next;
968 previous->next = this;
969 next = Walker;
970 } else {
971 next = NULL;
972 }
973};
974
975/** Destructor for MoleculeLeafClass.
976 */
977MoleculeLeafClass::~MoleculeLeafClass()
978{
979 // if (DownLeaf != NULL) {// drop leaves further down
980 // MoleculeLeafClass *Walker = DownLeaf;
981 // MoleculeLeafClass *Next;
982 // do {
983 // Next = Walker->NextLeaf;
984 // delete(Walker);
985 // Walker = Next;
986 // } while (Walker != NULL);
987 // // Last Walker sets DownLeaf automatically to NULL
988 // }
989 // remove the leaf itself
990 if (Leaf != NULL) {
991 World::getInstance().destroyMolecule(Leaf);
992 Leaf = NULL;
993 }
994 // remove this Leaf from level list
995 if (previous != NULL)
996 previous->next = next;
997 // } else { // we are first in list (connects to UpLeaf->DownLeaf)
998 // if ((NextLeaf != NULL) && (NextLeaf->UpLeaf == NULL))
999 // NextLeaf->UpLeaf = UpLeaf; // either null as we are top level or the upleaf of the first node
1000 // if (UpLeaf != NULL)
1001 // UpLeaf->DownLeaf = NextLeaf; // either null as we are only leaf or NextLeaf if we are just the first
1002 // }
1003 // UpLeaf = NULL;
1004 if (next != NULL) // are we last in list
1005 next->previous = previous;
1006 next = NULL;
1007 previous = NULL;
1008};
1009
1010/** Adds \a molecule leaf to the tree.
1011 * \param *ptr ptr to molecule to be added
1012 * \param *Previous previous MoleculeLeafClass referencing level and which on the level
1013 * \return true - success, false - something went wrong
1014 */
1015bool MoleculeLeafClass::AddLeaf(molecule *ptr, MoleculeLeafClass *Previous)
1016{
1017 return false;
1018};
1019
1020/** Fills the bond structure of this chain list subgraphs that are derived from a complete \a *reference molecule.
1021 * Calls this routine in each MoleculeLeafClass::next subgraph if it's not NULL.
1022 * \param *out output stream for debugging
1023 * \param *reference reference molecule with the bond structure to be copied
1024 * \param &FragmentCounter Counter needed to address \a **ListOfLocalAtoms
1025 * \param ***ListOfLocalAtoms Lookup table for each subgraph and index of each atom in \a *reference, may be NULL on start, then it is filled
1026 * \param FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
1027 * \return true - success, false - faoilure
1028 */
1029bool MoleculeLeafClass::FillBondStructureFromReference(const molecule * const reference, int &FragmentCounter, atom ***&ListOfLocalAtoms, bool FreeList)
1030{
1031 atom *OtherWalker = NULL;
1032 atom *Father = NULL;
1033 bool status = true;
1034 int AtomNo;
1035
1036 DoLog(1) && (Log() << Verbose(1) << "Begin of FillBondStructureFromReference." << endl);
1037 // fill ListOfLocalAtoms if NULL was given
1038 if (!FillListOfLocalAtoms(ListOfLocalAtoms, FragmentCounter, reference->getAtomCount(), FreeList)) {
1039 DoLog(1) && (Log() << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl);
1040 return false;
1041 }
1042
1043 if (status) {
1044 DoLog(1) && (Log() << Verbose(1) << "Creating adjacency list for subgraph " << Leaf << "." << endl);
1045 // remove every bond from the list
1046 for(molecule::iterator AtomRunner = Leaf->begin(); AtomRunner != Leaf->end(); ++AtomRunner)
1047 for(BondList::iterator BondRunner = (*AtomRunner)->ListOfBonds.begin(); !(*AtomRunner)->ListOfBonds.empty(); BondRunner = (*AtomRunner)->ListOfBonds.begin())
1048 if ((*BondRunner)->leftatom == *AtomRunner)
1049 delete((*BondRunner));
1050
1051 for(molecule::const_iterator iter = Leaf->begin(); iter != Leaf->end(); ++iter) {
1052 Father = (*iter)->GetTrueFather();
1053 AtomNo = Father->nr; // global id of the current walker
1054 for (BondList::const_iterator Runner = Father->ListOfBonds.begin(); Runner != Father->ListOfBonds.end(); (++Runner)) {
1055 OtherWalker = ListOfLocalAtoms[FragmentCounter][(*Runner)->GetOtherAtom((*iter)->GetTrueFather())->nr]; // local copy of current bond partner of walker
1056 if (OtherWalker != NULL) {
1057 if (OtherWalker->nr > (*iter)->nr)
1058 Leaf->AddBond((*iter), OtherWalker, (*Runner)->BondDegree);
1059 } else {
1060 DoLog(1) && (Log() << Verbose(1) << "OtherWalker = ListOfLocalAtoms[" << FragmentCounter << "][" << (*Runner)->GetOtherAtom((*iter)->GetTrueFather())->nr << "] is NULL!" << endl);
1061 status = false;
1062 }
1063 }
1064 }
1065 }
1066
1067 if ((FreeList) && (ListOfLocalAtoms != NULL)) {
1068 // free the index lookup list
1069 delete[](ListOfLocalAtoms[FragmentCounter]);
1070 if (FragmentCounter == 0) // first fragments frees the initial pointer to list
1071 delete[](ListOfLocalAtoms);
1072 }
1073 DoLog(1) && (Log() << Verbose(1) << "End of FillBondStructureFromReference." << endl);
1074 return status;
1075};
1076
1077/** Fills the root stack for sites to be used as root in fragmentation depending on order or adaptivity criteria
1078 * Again, as in \sa FillBondStructureFromReference steps recursively through each Leaf in this chain list of molecule's.
1079 * \param *out output stream for debugging
1080 * \param *&RootStack stack to be filled
1081 * \param *AtomMask defines true/false per global Atom::nr to mask in/out each nuclear site
1082 * \param &FragmentCounter counts through the fragments in this MoleculeLeafClass
1083 * \return true - stack is non-empty, fragmentation necessary, false - stack is empty, no more sites to update
1084 */
1085bool MoleculeLeafClass::FillRootStackForSubgraphs(KeyStack *&RootStack, bool *AtomMask, int &FragmentCounter)
1086{
1087 atom *Father = NULL;
1088
1089 if (RootStack != NULL) {
1090 // find first root candidates
1091 if (&(RootStack[FragmentCounter]) != NULL) {
1092 RootStack[FragmentCounter].clear();
1093 for(molecule::const_iterator iter = Leaf->begin(); iter != Leaf->end(); ++iter) {
1094 Father = (*iter)->GetTrueFather();
1095 if (AtomMask[Father->nr]) // apply mask
1096#ifdef ADDHYDROGEN
1097 if ((*iter)->type->Z != 1) // skip hydrogen
1098#endif
1099 RootStack[FragmentCounter].push_front((*iter)->nr);
1100 }
1101 if (next != NULL)
1102 next->FillRootStackForSubgraphs(RootStack, AtomMask, ++FragmentCounter);
1103 } else {
1104 DoLog(1) && (Log() << Verbose(1) << "Rootstack[" << FragmentCounter << "] is NULL." << endl);
1105 return false;
1106 }
1107 FragmentCounter--;
1108 return true;
1109 } else {
1110 DoLog(1) && (Log() << Verbose(1) << "Rootstack is NULL." << endl);
1111 return false;
1112 }
1113};
1114
1115/** Fills a lookup list of father's Atom::nr -> atom for each subgraph.
1116 * \param *out output stream from debugging
1117 * \param ***ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
1118 * \param FragmentCounter counts the fragments as we move along the list
1119 * \param GlobalAtomCount number of atoms in the complete molecule
1120 * \param &FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
1121 * \return true - success, false - failure
1122 */
1123bool MoleculeLeafClass::FillListOfLocalAtoms(atom ***&ListOfLocalAtoms, const int FragmentCounter, const int GlobalAtomCount, bool &FreeList)
1124{
1125 bool status = true;
1126
1127 if (ListOfLocalAtoms == NULL) { // allocated initial pointer
1128 // allocate and set each field to NULL
1129 const int Counter = Count();
1130 ASSERT(FragmentCounter < Counter, "FillListOfLocalAtoms: FragmenCounter greater than present fragments.");
1131 ListOfLocalAtoms = new atom**[Counter];
1132 if (ListOfLocalAtoms == NULL) {
1133 FreeList = FreeList && false;
1134 status = false;
1135 }
1136 for (int i=0;i<Counter;i++)
1137 ListOfLocalAtoms[i] = NULL;
1138 }
1139
1140 if ((ListOfLocalAtoms != NULL) && (ListOfLocalAtoms[FragmentCounter] == NULL)) { // allocate and fill list of this fragment/subgraph
1141 status = status && Leaf->CreateFatherLookupTable(ListOfLocalAtoms[FragmentCounter], GlobalAtomCount);
1142 FreeList = FreeList && true;
1143 }
1144
1145 return status;
1146};
1147
1148/** The indices per keyset are compared to the respective father's Atom::nr in each subgraph and thus put into \a **&FragmentList.
1149 * \param *out output stream fro debugging
1150 * \param *reference reference molecule with the bond structure to be copied
1151 * \param *KeySetList list with all keysets
1152 * \param ***ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
1153 * \param **&FragmentList list to be allocated and returned
1154 * \param &FragmentCounter counts the fragments as we move along the list
1155 * \param FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
1156 * \retuen true - success, false - failure
1157 */
1158bool MoleculeLeafClass::AssignKeySetsToFragment(molecule *reference, Graph *KeySetList, atom ***&ListOfLocalAtoms, Graph **&FragmentList, int &FragmentCounter, bool FreeList)
1159{
1160 bool status = true;
1161 int KeySetCounter = 0;
1162
1163 DoLog(1) && (Log() << Verbose(1) << "Begin of AssignKeySetsToFragment." << endl);
1164 // fill ListOfLocalAtoms if NULL was given
1165 if (!FillListOfLocalAtoms(ListOfLocalAtoms, FragmentCounter, reference->getAtomCount(), FreeList)) {
1166 DoLog(1) && (Log() << Verbose(1) << "Filling of ListOfLocalAtoms failed." << endl);
1167 return false;
1168 }
1169
1170 // allocate fragment list
1171 if (FragmentList == NULL) {
1172 KeySetCounter = Count();
1173 FragmentList = new Graph*[KeySetCounter];
1174 for (int i=0;i<KeySetCounter;i++)
1175 FragmentList[i] = NULL;
1176 KeySetCounter = 0;
1177 }
1178
1179 if ((KeySetList != NULL) && (KeySetList->size() != 0)) { // if there are some scanned keysets at all
1180 // assign scanned keysets
1181 if (FragmentList[FragmentCounter] == NULL)
1182 FragmentList[FragmentCounter] = new Graph;
1183 KeySet *TempSet = new KeySet;
1184 for (Graph::iterator runner = KeySetList->begin(); runner != KeySetList->end(); runner++) { // key sets contain global numbers!
1185 if (ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*((*runner).first.begin()))->nr] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set
1186 // translate keyset to local numbers
1187 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
1188 TempSet->insert(ListOfLocalAtoms[FragmentCounter][reference->FindAtom(*sprinter)->nr]->nr);
1189 // insert into FragmentList
1190 FragmentList[FragmentCounter]->insert(GraphPair(*TempSet, pair<int, double> (KeySetCounter++, (*runner).second.second)));
1191 }
1192 TempSet->clear();
1193 }
1194 delete (TempSet);
1195 if (KeySetCounter == 0) {// if there are no keysets, delete the list
1196 DoLog(1) && (Log() << Verbose(1) << "KeySetCounter is zero, deleting FragmentList." << endl);
1197 delete (FragmentList[FragmentCounter]);
1198 } else
1199 DoLog(1) && (Log() << Verbose(1) << KeySetCounter << " keysets were assigned to subgraph " << FragmentCounter << "." << endl);
1200 FragmentCounter++;
1201 if (next != NULL)
1202 next->AssignKeySetsToFragment(reference, KeySetList, ListOfLocalAtoms, FragmentList, FragmentCounter, FreeList);
1203 FragmentCounter--;
1204 } else
1205 DoLog(1) && (Log() << Verbose(1) << "KeySetList is NULL or empty." << endl);
1206
1207 if ((FreeList) && (ListOfLocalAtoms != NULL)) {
1208 // free the index lookup list
1209 delete[](ListOfLocalAtoms[FragmentCounter]);
1210 if (FragmentCounter == 0) // first fragments frees the initial pointer to list
1211 delete[](ListOfLocalAtoms);
1212 }
1213 DoLog(1) && (Log() << Verbose(1) << "End of AssignKeySetsToFragment." << endl);
1214 return status;
1215};
1216
1217/** Translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
1218 * \param *out output stream for debugging
1219 * \param **FragmentList Graph with local numbers per fragment
1220 * \param &FragmentCounter counts the fragments as we move along the list
1221 * \param &TotalNumberOfKeySets global key set counter
1222 * \param &TotalGraph Graph to be filled with global numbers
1223 */
1224void MoleculeLeafClass::TranslateIndicesToGlobalIDs(Graph **FragmentList, int &FragmentCounter, int &TotalNumberOfKeySets, Graph &TotalGraph)
1225{
1226 DoLog(1) && (Log() << Verbose(1) << "Begin of TranslateIndicesToGlobalIDs." << endl);
1227 KeySet *TempSet = new KeySet;
1228 if (FragmentList[FragmentCounter] != NULL) {
1229 for (Graph::iterator runner = FragmentList[FragmentCounter]->begin(); runner != FragmentList[FragmentCounter]->end(); runner++) {
1230 for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
1231 TempSet->insert((Leaf->FindAtom(*sprinter))->GetTrueFather()->nr);
1232 TotalGraph.insert(GraphPair(*TempSet, pair<int, double> (TotalNumberOfKeySets++, (*runner).second.second)));
1233 TempSet->clear();
1234 }
1235 delete (TempSet);
1236 } else {
1237 DoLog(1) && (Log() << Verbose(1) << "FragmentList is NULL." << endl);
1238 }
1239 if (next != NULL)
1240 next->TranslateIndicesToGlobalIDs(FragmentList, ++FragmentCounter, TotalNumberOfKeySets, TotalGraph);
1241 FragmentCounter--;
1242 DoLog(1) && (Log() << Verbose(1) << "End of TranslateIndicesToGlobalIDs." << endl);
1243};
1244
1245/** Simply counts the number of items in the list, from given MoleculeLeafClass.
1246 * \return number of items
1247 */
1248int MoleculeLeafClass::Count() const
1249{
1250 if (next != NULL)
1251 return next->Count() + 1;
1252 else
1253 return 1;
1254};
1255
Note: See TracBrowser for help on using the repository browser.