source: src/moleculelist.cpp@ bbbad5

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 bbbad5 was 61951b, checked in by Frederik Heber <heber@…>, 15 years ago

Removed molecule merging functions from MoleculeListClass.

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