source: src/moleculelist.cpp@ c8302f3

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 c8302f3 was 88c8ec, checked in by Frederik Heber <heber@…>, 12 years ago

REFACTOR: Replaced all "bond *" appearances by bond::ptr.

  • this is preparatory for making bond::ptr a boost::shared_ptr of bond.
  • NOTE: We had to remove a const prefix at four or five places and forward declarations had to be replaced by the true inclusion of bond.hpp at tne or so files. Apart from that, the replacement has been very smooth.
  • Property mode set to 100755
File size: 21.9 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/** \file MoleculeListClass.cpp
24 *
25 * Function implementations for the class MoleculeListClass.
26 *
27 */
28
29// include config.h
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#include "CodePatterns/MemDebug.hpp"
35
36#include <iostream>
37
38//#include <gsl/gsl_inline.h>
39#include <gsl/gsl_heapsort.h>
40
41#include "MoleculeListClass.hpp"
42
43#include "CodePatterns/Log.hpp"
44
45#include "Atom/atom.hpp"
46#include "Bond/bond.hpp"
47#include "Box.hpp"
48#include "config.hpp"
49#include "Element/element.hpp"
50#include "Element/periodentafel.hpp"
51#include "Fragmentation/Graph.hpp"
52#include "Fragmentation/KeySet.hpp"
53#include "Fragmentation/SortIndex.hpp"
54#include "Graph/BondGraph.hpp"
55#include "Helpers/helpers.hpp"
56#include "molecule.hpp"
57#include "LinearAlgebra/RealSpaceMatrix.hpp"
58#include "Parser/FormatParserStorage.hpp"
59#include "World.hpp"
60
61
62/** Constructor for MoleculeListClass.
63 */
64MoleculeListClass::MoleculeListClass(World *_world) :
65 Observable("MoleculeListClass"),
66 MaxIndex(1),
67 world(_world)
68{};
69
70/** Destructor for MoleculeListClass.
71 */
72MoleculeListClass::~MoleculeListClass()
73{
74 LOG(4, "Clearing ListOfMolecules.");
75 for(MoleculeList::iterator MolRunner = ListOfMolecules.begin(); MolRunner != ListOfMolecules.end(); ++MolRunner)
76 (*MolRunner)->signOff(this);
77 ListOfMolecules.clear(); // empty list
78};
79
80/** Insert a new molecule into the list and set its number.
81 * \param *mol molecule to add to list.
82 */
83void MoleculeListClass::insert(molecule *mol)
84{
85 OBSERVE;
86 mol->IndexNr = MaxIndex++;
87 ListOfMolecules.push_back(mol);
88 mol->signOn(this);
89};
90
91/** Erases a molecule from the list.
92 * \param *mol molecule to add to list.
93 */
94void MoleculeListClass::erase(molecule *mol)
95{
96 OBSERVE;
97 mol->signOff(this);
98 ListOfMolecules.remove(mol);
99};
100
101/** Comparison function for two values.
102 * \param *a
103 * \param *b
104 * \return <0, \a *a less than \a *b, ==0 if equal, >0 \a *a greater than \a *b
105 */
106int CompareDoubles (const void * a, const void * b)
107{
108 if (*(double *)a > *(double *)b)
109 return -1;
110 else if (*(double *)a < *(double *)b)
111 return 1;
112 else
113 return 0;
114};
115
116
117/** Compare whether two molecules are equal.
118 * \param *a molecule one
119 * \param *n molecule two
120 * \return lexical value (-1, 0, +1)
121 */
122int MolCompare(const void *a, const void *b)
123{
124 int *aList = NULL, *bList = NULL;
125 int Count, Counter, aCounter, bCounter;
126 int flag;
127
128 // sort each atom list and put the numbers into a list, then go through
129 //LOG(0, "Comparing fragment no. " << *(molecule **)a << " to " << *(molecule **)b << ".");
130 // Yes those types are awkward... but check it for yourself it checks out this way
131 molecule *const *mol1_ptr= static_cast<molecule *const *>(a);
132 molecule *mol1 = *mol1_ptr;
133 molecule *const *mol2_ptr= static_cast<molecule *const *>(b);
134 molecule *mol2 = *mol2_ptr;
135 if (mol1->getAtomCount() < mol2->getAtomCount()) {
136 return -1;
137 } else {
138 if (mol1->getAtomCount() > mol2->getAtomCount())
139 return +1;
140 else {
141 Count = mol1->getAtomCount();
142 aList = new int[Count];
143 bList = new int[Count];
144
145 // fill the lists
146 Counter = 0;
147 aCounter = 0;
148 bCounter = 0;
149 molecule::const_iterator aiter = mol1->begin();
150 molecule::const_iterator biter = mol2->begin();
151 for (;(aiter != mol1->end()) && (biter != mol2->end());
152 ++aiter, ++biter) {
153 if ((*aiter)->GetTrueFather() == NULL)
154 aList[Counter] = Count + (aCounter++);
155 else
156 aList[Counter] = (*aiter)->GetTrueFather()->getNr();
157 if ((*biter)->GetTrueFather() == NULL)
158 bList[Counter] = Count + (bCounter++);
159 else
160 bList[Counter] = (*biter)->GetTrueFather()->getNr();
161 Counter++;
162 }
163 // check if AtomCount was for real
164 flag = 0;
165 if ((aiter == mol1->end()) && (biter != mol2->end())) {
166 flag = -1;
167 } else {
168 if ((aiter != mol1->end()) && (biter == mol2->end()))
169 flag = 1;
170 }
171 if (flag == 0) {
172 // sort the lists
173 gsl_heapsort(aList, Count, sizeof(int), CompareDoubles);
174 gsl_heapsort(bList, Count, sizeof(int), CompareDoubles);
175 // compare the lists
176
177 flag = 0;
178 for (int i = 0; i < Count; i++) {
179 if (aList[i] < bList[i]) {
180 flag = -1;
181 } else {
182 if (aList[i] > bList[i])
183 flag = 1;
184 }
185 if (flag != 0)
186 break;
187 }
188 }
189 delete[] (aList);
190 delete[] (bList);
191 return flag;
192 }
193 }
194 return -1;
195};
196
197/** Output of a list of all molecules.
198 * \param *out output stream
199 */
200void MoleculeListClass::Enumerate(std::ostream *out)
201{
202 periodentafel *periode = World::getInstance().getPeriode();
203 std::map<atomicNumber_t,unsigned int> counts;
204 double size=0;
205 Vector Origin;
206
207 // header
208 (*out) << "Index\tName\t\tAtoms\tFormula\tCenter\tSize" << endl;
209 (*out) << "-----------------------------------------------" << endl;
210 if (ListOfMolecules.size() == 0)
211 (*out) << "\tNone" << endl;
212 else {
213 Origin.Zero();
214 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
215 // count atoms per element and determine size of bounding sphere
216 size=0.;
217 for (molecule::const_iterator iter = (*ListRunner)->begin(); iter != (*ListRunner)->end(); ++iter) {
218 counts[(*iter)->getType()->getAtomicNumber()]++;
219 if ((*iter)->DistanceSquared(Origin) > size)
220 size = (*iter)->DistanceSquared(Origin);
221 }
222 // output Index, Name, number of atoms, chemical formula
223 (*out) << ((*ListRunner)->ActiveFlag ? "*" : " ") << (*ListRunner)->IndexNr << "\t" << (*ListRunner)->name << "\t\t" << (*ListRunner)->getAtomCount() << "\t";
224
225 std::map<atomicNumber_t,unsigned int>::reverse_iterator iter;
226 for(iter=counts.rbegin(); iter!=counts.rend();++iter){
227 atomicNumber_t Z =(*iter).first;
228 (*out) << periode->FindElement(Z)->getSymbol() << (*iter).second;
229 }
230 // Center and size
231 Vector *Center = (*ListRunner)->DetermineCenterOfAll();
232 (*out) << "\t" << *Center << "\t" << sqrt(size) << endl;
233 delete(Center);
234 }
235 }
236};
237
238/** Returns the molecule with the given index \a index.
239 * \param index index of the desired molecule
240 * \return pointer to molecule structure, NULL if not found
241 */
242molecule * MoleculeListClass::ReturnIndex(int index)
243{
244 for(MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
245 if ((*ListRunner)->IndexNr == index)
246 return (*ListRunner);
247 return NULL;
248};
249
250
251/** Simple output of the pointers in ListOfMolecules.
252 * \param *out output stream
253 */
254void MoleculeListClass::Output(std::ostream *out)
255{
256 if (DoLog(1)) {
257 std::stringstream output;
258 output << "MoleculeList: ";
259 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
260 output << *ListRunner << "\t";
261 LOG(1, output.str());
262 }
263};
264
265/** Returns a string with \a i prefixed with 0s to match order of total number of molecules in digits.
266 * \param FragmentNumber total number of fragments to determine necessary number of digits
267 * \param digits number to create with 0 prefixed
268 * \return allocated(!) char array with number in digits, ten base.
269 */
270inline char *FixedDigitNumber(const int FragmentNumber, const int digits)
271{
272 char *returnstring;
273 int number = FragmentNumber;
274 int order = 0;
275 while (number != 0) { // determine number of digits needed
276 number = (int)floor(((double)number / 10.));
277 order++;
278 //LOG(0, "Number is " << number << ", order is " << order << ".");
279 }
280 // allocate string
281 returnstring = new char[order + 2];
282 // terminate and fill string array from end backward
283 returnstring[order] = '\0';
284 number = digits;
285 for (int i=order;i--;) {
286 returnstring[i] = '0' + (char)(number % 10);
287 number = (int)floor(((double)number / 10.));
288 }
289 //LOG(0, returnstring);
290 return returnstring;
291};
292
293/** Calculates necessary hydrogen correction due to unwanted interaction between saturated ones.
294 * If for a pair of two hydrogen atoms a and b, at least is a saturated one, and a and b are not
295 * bonded to the same atom, then we add for this pair a correction term constructed from a Morse
296 * potential function fit to QM calculations with respecting to the interatomic hydrogen distance.
297 * \param &path path to file
298 */
299bool MoleculeListClass::AddHydrogenCorrection(std::string &path)
300{
301 bond::ptr Binder = NULL;
302 double ***FitConstant = NULL, **correction = NULL;
303 int a, b;
304 ofstream output;
305 ifstream input;
306 string line;
307 stringstream zeile;
308 double distance;
309 char ParsedLine[1023];
310 double tmp;
311 char *FragmentNumber = NULL;
312
313 LOG(1, "Saving hydrogen saturation correction ... ");
314 // 0. parse in fit constant files that should have the same dimension as the final energy files
315 // 0a. find dimension of matrices with constants
316 line = path;
317 line += "1";
318 line += FITCONSTANTSUFFIX;
319 input.open(line.c_str());
320 if (input.fail()) {
321 LOG(1, endl << "Unable to open " << line << ", is the directory correct?");
322 return false;
323 }
324 a = 0;
325 b = -1; // we overcount by one
326 while (!input.eof()) {
327 input.getline(ParsedLine, 1023);
328 zeile.str(ParsedLine);
329 int i = 0;
330 while (!zeile.eof()) {
331 zeile >> distance;
332 i++;
333 }
334 if (i > a)
335 a = i;
336 b++;
337 }
338 LOG(0, "I recognized " << a << " columns and " << b << " rows, ");
339 input.close();
340
341 // 0b. allocate memory for constants
342 FitConstant = new double**[3];
343 for (int k = 0; k < 3; k++) {
344 FitConstant[k] = new double*[a];
345 for (int i = a; i--;) {
346 FitConstant[k][i] = new double[b];
347 for (int j = b; j--;) {
348 FitConstant[k][i][j] = 0.;
349 }
350 }
351 }
352 // 0c. parse in constants
353 for (int i = 0; i < 3; i++) {
354 line = path;
355 line.append("/");
356 line += FRAGMENTPREFIX;
357 sprintf(ParsedLine, "%d", i + 1);
358 line += ParsedLine;
359 line += FITCONSTANTSUFFIX;
360 input.open(line.c_str());
361 if (input.fail()) {
362 ELOG(0, endl << "Unable to open " << line << ", is the directory correct?");
363 performCriticalExit();
364 return false;
365 }
366 int k = 0, l;
367 while ((!input.eof()) && (k < b)) {
368 input.getline(ParsedLine, 1023);
369 //LOG(1, "INFO: Current Line: " << ParsedLine);
370 zeile.str(ParsedLine);
371 zeile.clear();
372 l = 0;
373 //std::stringstream output;
374 while ((!zeile.eof()) && (l < a)) {
375 zeile >> FitConstant[i][l][k];
376 //output << FitConstant[i][l][k] << "\t";
377 l++;
378 }
379 //LOG(1, "INFO: fit constant are " << output.str());
380 k++;
381 }
382 input.close();
383 }
384 if (DoLog(1)) {
385 for (int k = 0; k < 3; k++) {
386 std::stringstream output;
387 output << "Constants " << k << ": ";
388 for (int j = 0; j < b; j++) {
389 for (int i = 0; i < a; i++) {
390 output << FitConstant[k][i][j] << "\t";
391 }
392 output << std::endl;
393 }
394 LOG(0, output.str());
395 }
396 }
397
398 // 0d. allocate final correction matrix
399 correction = new double*[a];
400 for (int i = a; i--;)
401 correction[i] = new double[b];
402
403 // 1a. go through every molecule in the list
404 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
405 // 1b. zero final correction matrix
406 for (int k = a; k--;)
407 for (int j = b; j--;)
408 correction[k][j] = 0.;
409 // 2. take every hydrogen that is a saturated one
410 for (molecule::const_iterator iter = (*ListRunner)->begin(); iter != (*ListRunner)->end(); ++iter) {
411 //LOG(1, "(*iter): " << *(*iter) << " with first bond " << *((*iter)->getListOfBonds().begin()) << ".");
412 if (((*iter)->getType()->getAtomicNumber() == 1) && (((*iter)->father == NULL)
413 || ((*iter)->father->getType()->getAtomicNumber() != 1))) { // if it's a hydrogen
414 for (molecule::const_iterator runner = (*ListRunner)->begin(); runner != (*ListRunner)->end(); ++runner) {
415 //LOG(2, "Runner: " << *(*runner) << " with first bond " << *((*iter)->getListOfBonds().begin()) << ".");
416 // 3. take every other hydrogen that is the not the first and not bound to same bonding partner
417 const BondList &bondlist = (*runner)->getListOfBonds();
418 Binder = *(bondlist.begin());
419 if (((*runner)->getType()->getAtomicNumber() == 1) && ((*runner)->getNr() > (*iter)->getNr()) && (Binder->GetOtherAtom((*runner)) != Binder->GetOtherAtom((*iter)))) { // (hydrogens have only one bonding partner!)
420 // 4. evaluate the morse potential for each matrix component and add up
421 distance = (*runner)->distance(*(*iter));
422 //std::stringstream output;
423 //output << "Fragment " << (*ListRunner)->name << ": " << *(*runner) << "<= " << distance << "=>" << *(*iter) << ":";
424 for (int k = 0; k < a; k++) {
425 for (int j = 0; j < b; j++) {
426 switch (k) {
427 case 1:
428 case 7:
429 case 11:
430 tmp = pow(FitConstant[0][k][j] * (1. - exp(-FitConstant[1][k][j] * (distance - FitConstant[2][k][j]))), 2);
431 break;
432 default:
433 tmp = FitConstant[0][k][j] * pow(distance, FitConstant[1][k][j]) + FitConstant[2][k][j];
434 break;
435 };
436 correction[k][j] -= tmp; // ground state is actually lower (disturbed by additional interaction)
437 //output << tmp << "\t";
438 }
439 //output << endl;
440 }
441 //LOG(0, output.str());
442 }
443 }
444 }
445 }
446 // 5. write final matrix to file
447 line = path;
448 line.append("/");
449 line += FRAGMENTPREFIX;
450 FragmentNumber = FixedDigitNumber(ListOfMolecules.size(), (*ListRunner)->IndexNr);
451 line += FragmentNumber;
452 delete[] (FragmentNumber);
453 line += HCORRECTIONSUFFIX;
454 output.open(line.c_str());
455 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;
456 for (int j = 0; j < b; j++) {
457 for (int i = 0; i < a; i++)
458 output << correction[i][j] << "\t";
459 output << endl;
460 }
461 output.close();
462 }
463 for (int i = a; i--;)
464 delete[](correction[i]);
465 delete[](correction);
466
467 line = path;
468 line.append("/");
469 line += HCORRECTIONSUFFIX;
470 output.open(line.c_str());
471 output << "Time\t\tTotal\t\tKinetic\t\tNonLocal\tCorrelation\tExchange\tPseudo\t\tHartree\t\t-Gauss\t\tEwald\t\tIonKin\t\tETotal" << endl;
472 for (int j = 0; j < b; j++) {
473 for (int i = 0; i < a; i++)
474 output << 0 << "\t";
475 output << endl;
476 }
477 output.close();
478 // 6. free memory of parsed matrices
479 for (int k = 0; k < 3; k++) {
480 for (int i = a; i--;) {
481 delete[](FitConstant[k][i]);
482 }
483 delete[](FitConstant[k]);
484 }
485 delete[](FitConstant);
486 LOG(0, "done.");
487 return true;
488};
489
490/** Store force indices, i.e. the connection between the nuclear index in the total molecule config and the respective atom in fragment config.
491 * \param &path path to file
492 * \param SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
493 * \return true - file written successfully, false - writing failed
494 */
495bool MoleculeListClass::StoreForcesFile(std::string &path, const SortIndex_t &SortIndex)
496{
497 bool status = true;
498 string filename(path);
499 filename += FORCESFILE;
500 ofstream ForcesFile(filename.c_str());
501 periodentafel *periode=World::getInstance().getPeriode();
502
503 // open file for the force factors
504 LOG(1, "Saving force factors ... ");
505 if (!ForcesFile.fail()) {
506 //output << prefix << "Forces" << endl;
507 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
508 periodentafel::const_iterator elemIter;
509 for(elemIter=periode->begin();elemIter!=periode->end();++elemIter){
510 if ((*ListRunner)->hasElement((*elemIter).first)) { // if this element got atoms
511 for(molecule::iterator atomIter = (*ListRunner)->begin(); atomIter !=(*ListRunner)->end();++atomIter){
512 if ((*atomIter)->getType()->getAtomicNumber() == (*elemIter).first) {
513 if (((*atomIter)->GetTrueFather() != NULL) && ((*atomIter)->GetTrueFather() != (*atomIter))) {// if there is a rea
514 const atomId_t fatherid = (*atomIter)->GetTrueFather()->getId();
515 ForcesFile << SortIndex.find(fatherid) << "\t";
516 } else
517 // otherwise a -1 to indicate an added saturation hydrogen
518 ForcesFile << "-1\t";
519 }
520 }
521 }
522 }
523 ForcesFile << endl;
524 }
525 ForcesFile.close();
526 LOG(1, "done.");
527 } else {
528 status = false;
529 LOG(1, "failed to open file " << filename << ".");
530 }
531 ForcesFile.close();
532
533 return status;
534};
535
536/** Writes a config file for each molecule in the given \a **FragmentList.
537 * \param *out output stream for debugging
538 * \param &prefix path and prefix to the fragment config files
539 * \param SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config
540 * \param type desired type to store
541 * \return true - success (each file was written), false - something went wrong.
542 */
543bool MoleculeListClass::OutputConfigForListOfFragments(std::string &prefix, ParserTypes type)
544{
545 ofstream outputFragment;
546 std::string FragmentName;
547 bool result = true;
548 bool intermediateResult = true;
549 Vector BoxDimension;
550 char *FragmentNumber = NULL;
551 int FragmentCounter = 0;
552 ofstream output;
553 RealSpaceMatrix cell_size = World::getInstance().getDomain().getM();
554 RealSpaceMatrix cell_size_backup = cell_size;
555 int count=0;
556
557 // store the fragments as config and as xyz
558 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++) {
559 // correct periodic
560 if ((*ListRunner)->ScanForPeriodicCorrection()) {
561 count++;
562 }
563
564 {
565 // list atoms in fragment for debugging
566 std::stringstream output;
567 output << "Contained atoms: ";
568 for (molecule::const_iterator iter = (*ListRunner)->begin(); iter != (*ListRunner)->end(); ++iter) {
569 output << (*iter)->getName() << " ";
570 }
571 LOG(2, output.str());
572 }
573
574 {
575// // center on edge
576// (*ListRunner)->CenterEdge(&BoxDimension);
577// for (int k = 0; k < NDIM; k++) // if one edge is to small, set at least to 1 angstroem
578// if (BoxDimension[k] < 1.)
579// BoxDimension[k] += 1.;
580// (*ListRunner)->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary
581// for (int k = 0; k < NDIM; k++) {
582// BoxDimension[k] = 2.5 * (World::getInstance().getConfig()->GetIsAngstroem() ? 1. : 1. / AtomicLengthToAngstroem);
583// cell_size.at(k,k) = BoxDimension[k] * 2.;
584// }
585// World::getInstance().setDomain(cell_size);
586// (*ListRunner)->Translate(&BoxDimension);
587
588 // output file
589 std::vector<atom *> atoms;
590 // TODO: Convert iterator to const_iterator when FormatParserStorage::save() has vector<const atom *>
591 // We need iterator here because FormatParserStorage::save() need vector<atom *> not const refs.
592 for (molecule::iterator iter = (*ListRunner)->begin(); iter != (*ListRunner)->end(); ++iter) {
593 atoms.push_back(*iter);
594 }
595 FragmentNumber = FixedDigitNumber(ListOfMolecules.size(), FragmentCounter++);
596 FragmentName = prefix + FragmentNumber + "." + FormatParserStorage::getInstance().getSuffixFromType(type);
597 outputFragment.open(FragmentName.c_str(), ios::out);
598 std::stringstream output;
599 output << "Saving bond fragment No. " << FragmentNumber << "/" << FragmentCounter - 1 << " as XYZ ... ";
600 if ((intermediateResult = FormatParserStorage::getInstance().save(
601 outputFragment,
602 FormatParserStorage::getInstance().getSuffixFromType(type),
603 atoms)))
604 output << " done.";
605 else
606 output << " failed.";
607 LOG(3, output.str());
608 delete[](FragmentNumber);
609
610 result = result && intermediateResult;
611 outputFragment.close();
612 outputFragment.clear();
613 }
614 }
615 LOG(0, "STATUS: done.");
616
617 // printing final number
618 LOG(2, "INFO: Final number of fragments: " << FragmentCounter << ".");
619
620 // printing final number
621 LOG(2, "INFO: For " << count << " fragments periodic correction would have been necessary.");
622
623 // restore cell_size
624 World::getInstance().setDomain(cell_size_backup);
625
626 return result;
627};
628
629/** Counts the number of molecules with the molecule::ActiveFlag set.
630 * \return number of molecules with ActiveFlag set to true.
631 */
632int MoleculeListClass::NumberOfActiveMolecules()
633{
634 int count = 0;
635 for (MoleculeList::iterator ListRunner = ListOfMolecules.begin(); ListRunner != ListOfMolecules.end(); ListRunner++)
636 count += ((*ListRunner)->ActiveFlag ? 1 : 0);
637 return count;
638};
639
640/** Count all atoms in each molecule.
641 * \return number of atoms in the MoleculeListClass.
642 * TODO: the inner loop should be done by some (double molecule::CountAtom()) function
643 */
644int MoleculeListClass::CountAllAtoms() const
645{
646 int AtomNo = 0;
647 for (MoleculeList::const_iterator MolWalker = ListOfMolecules.begin(); MolWalker != ListOfMolecules.end(); MolWalker++) {
648 AtomNo += (*MolWalker)->size();
649 }
650 return AtomNo;
651}
Note: See TracBrowser for help on using the repository browser.