source: src/Graph/BondGraph.hpp@ 105b72

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 105b72 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 100644
File size: 19.6 KB
Line 
1/*
2 * bondgraph.hpp
3 *
4 * Created on: Oct 29, 2009
5 * Author: heber
6 */
7
8#ifndef BONDGRAPH_HPP_
9#define BONDGRAPH_HPP_
10
11using namespace std;
12
13/*********************************************** includes ***********************************/
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include <iosfwd>
21#include <set>
22
23#include <boost/serialization/array.hpp>
24
25#include "Atom/AtomSet.hpp"
26#include "Bond/bond.hpp"
27#include "Box.hpp"
28#include "CodePatterns/Assert.hpp"
29#include "CodePatterns/Log.hpp"
30#include "CodePatterns/Range.hpp"
31#include "Element/element.hpp"
32#include "Fragmentation/MatrixContainer.hpp"
33#include "Helpers/defs.hpp"
34#include "LinkedCell/LinkedCell_View.hpp"
35#include "LinkedCell/IPointCloud.hpp"
36#include "LinkedCell/PointCloudAdaptor.hpp"
37#include "WorldTime.hpp"
38
39/****************************************** forward declarations *****************************/
40
41class molecule;
42class BondedParticle;
43class MatrixContainer;
44
45/********************************************** definitions *********************************/
46
47/********************************************** declarations *******************************/
48
49
50class BondGraph {
51 //!> analysis bonds unit test should be friend to access private parts.
52 friend class AnalysisBondsTest;
53 //!> own bond graph unit test should be friend to access private parts.
54 friend class BondGraphTest;
55public:
56 /** Constructor of class BondGraph.
57 * This classes contains typical bond lengths and thus may be used to construct a bond graph for a given molecule.
58 */
59 BondGraph(bool IsA);
60
61 /** Destructor of class BondGraph.
62 */
63 ~BondGraph();
64
65 /** Parses the bond lengths in a given file and puts them int a matrix form.
66 * Allocates \a MatrixContainer for BondGraph::BondLengthMatrix, using MatrixContainer::ParseMatrix(),
67 * but only if parsing is successful. Otherwise variable is left as NULL.
68 * \param &input input stream to parse table from
69 * \return true - success in parsing file, false - failed to parse the file
70 */
71 bool LoadBondLengthTable(std::istream &input);
72
73 /** Removes allocated bond length table.
74 *
75 */
76 void CleanupBondLengthTable();
77
78 /** Internal helper to convert a set of atomicNumber_t to element refs.
79 *
80 * @param Set set of atomicNumber_t
81 * @return set of element refs
82 */
83 std::set< const element *> getElementSetFromNumbers(const std::set<atomicNumber_t> &Set) const;
84
85 /** Determines the maximum of all element::CovalentRadius for elements present in \a &Set.
86 *
87 * I.e. the function returns a sensible cutoff criteria for bond recognition,
88 * e.g. to be used for LinkedCell_deprecated or others.
89 *
90 * \param &PresentElements set of elements whose maximal pair to find
91 */
92 double getMaxPossibleBondDistance(
93 const std::set< const element *> &PresentElements) const
94 {
95 double max_distance = 0.;
96
97 // create all element combinations
98 for (std::set< const element *>::const_iterator iter = PresentElements.begin();
99 iter != PresentElements.end();
100 ++iter) {
101 for (std::set< const element *>::const_iterator otheriter = iter;
102 otheriter != PresentElements.end();
103 ++otheriter) {
104 const range<double> MinMaxDistance(getMinMaxDistance((*iter),(*otheriter)));
105 if (MinMaxDistance.last > max_distance)
106 max_distance = MinMaxDistance.last;
107 }
108 }
109 return max_distance;
110 }
111
112 /** Determines the maximum of all element::CovalentRadius for elements present in \a &Set.
113 *
114 * I.e. the function returns a sensible cutoff criteria for bond recognition,
115 * e.g. to be used for LinkedCell_deprecated or others.
116 *
117 * \param Walker element first element in the pair
118 * \param &PresentElements set of elements whose maximal pair to find
119 */
120 double getMaxPossibleBondDistance(
121 const element * const Walker,
122 const std::set< const element *> &PresentElements) const
123 {
124 double max_distance = 0.;
125
126 // create all element combinations
127 for (std::set< const element *>::const_iterator iter = PresentElements.begin();
128 iter != PresentElements.end();
129 ++iter) {
130 const range<double> MinMaxDistance(getMinMaxDistance((*iter),Walker));
131 if (MinMaxDistance.last > max_distance)
132 max_distance = MinMaxDistance.last;
133 }
134 return max_distance;
135 }
136
137 /** Returns bond criterion for given pair based on a bond length matrix.
138 * This calls element-version of getMinMaxDistance().
139 * \param *Walker first BondedParticle
140 * \param *OtherWalker second BondedParticle
141 * \return Range with bond interval
142 */
143 range<double> getMinMaxDistance(
144 const BondedParticle * const Walker,
145 const BondedParticle * const OtherWalker) const;
146
147 /** Returns SQUARED bond criterion for given pair based on a bond length matrix.
148 * This calls element-version of getMinMaxDistance() and squares the values
149 * of either interval end.
150 * \param *Walker first BondedParticle
151 * \param *OtherWalker second BondedParticle
152 * \return Range with bond interval
153 */
154 range<double> getMinMaxDistanceSquared(
155 const BondedParticle * const Walker,
156 const BondedParticle * const OtherWalker) const;
157
158 /** Creates an adjacency list of the molecule.
159 * Generally, we use the CSD approach to bond recognition, that is the the distance
160 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with
161 * a threshold t = 0.4 Angstroem.
162 * To make it O(N log N) the function uses the linked-cell technique as follows:
163 * The procedure is step-wise:
164 * -# Remove every bond in list
165 * -# go through every atom in given \a set, check the atoms therein against all possible bond partners, add bond if true
166 * -# correct the bond degree iteratively (single->double->triple bond)
167 * -# finally print the bond list to \a *out if desired
168 * \param &set Container with all atoms to create adjacency for
169 */
170 template <class container_type,
171 class iterator_type,
172 class const_iterator_type>
173 void CreateAdjacency(
174 AtomSetMixin<container_type,iterator_type,const_iterator_type> &Set) const
175 {
176 LOG(1, "STATUS: Removing all present bonds.");
177 cleanAdjacencyList(Set);
178
179 // gather set of all present elements
180 std::set<atomicNumber_t> elements;
181 for(typename AtomSetMixin<container_type,iterator_type,const_iterator_type>::iterator iter = Set.begin();
182 iter != Set.end(); ++iter) {
183 const atom * const Walker = dynamic_cast<const atom *>(*iter);
184 ASSERT(Walker != NULL,
185 "BondGraph::CreateAdjacency() - TesselPoint "
186 +(*iter)->getName()+" that was not an atom retrieved from given set");
187 elements.insert( Walker->getElementNo() );
188 }
189 // get all elements
190 std::set< const element *> PresentElements = getElementSetFromNumbers(elements);
191
192 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)
193 const unsigned int counter = Set.size();
194 if (counter > 1) {
195 LOG(1, "STATUS: Setting max bond distance.");
196 LinkedCell::LinkedCell_View LC = getLinkedCell(getMaxPossibleBondDistance(PresentElements));
197
198 LOG(1, "STATUS: Creating LinkedCell structure for given " << counter << " atoms.");
199
200 Box &domain = getDomain();
201 unsigned int CurrentTime = getTime();
202
203 unsigned int BondCount = 0;
204 // go through every atom in the set (observed cause we change its bonds)
205 for(typename AtomSetMixin<container_type,iterator_type,const_iterator_type>::iterator iter = Set.begin();
206 iter != Set.end(); ++iter) {
207 const atom * const Walker = dynamic_cast<const atom *>(*iter);
208 ASSERT(Walker != NULL,
209 "BondGraph::CreateAdjacency() - TesselPoint "
210 +(*iter)->getName()+" that was not an atom retrieved from given set");
211 LOG(2, "INFO: Current Atom is " << *Walker << ".");
212
213 // obtain all possible neighbors
214 LinkedCell::LinkedList ListOfNeighbors = LC.getAllNeighbors(
215 getMaxPossibleBondDistance(Walker->getType(), PresentElements),
216 Walker->getPosition());
217 if (!ListOfNeighbors.empty()) {
218 // we have some possible candidates, go through each
219 for (LinkedCell::LinkedList::const_iterator neighboriter = ListOfNeighbors.begin();
220 neighboriter != ListOfNeighbors.end();
221 ++neighboriter) {
222 if ((*neighboriter) > Walker) { // just to not add bonds from both sides
223 const atom * const OtherWalker = dynamic_cast<const atom *>(*neighboriter);
224 ASSERT(OtherWalker != NULL,
225 "BondGraph::CreateAdjacency() - TesselPoint "
226 +(*neighboriter)->getName()+" that was not an atom retrieved from LinkedList");
227 LOG(3, "INFO: Current other atom is " << *OtherWalker << ".");
228
229 const range<double> MinMaxDistanceSquared(
230 getMinMaxDistanceSquared(Walker, OtherWalker));
231 const double distance = domain.periodicDistanceSquared(OtherWalker->getPosition(),Walker->getPosition());
232 LOG(3, "INFO: Checking squared distance " << distance << " against typical bond length of " << MinMaxDistanceSquared << ".");
233 const bool status = MinMaxDistanceSquared.isInRange(distance);
234 if (status) { // create bond if distance is smaller
235 LOG(1, "ACCEPT: Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << ".");
236 // directly use iter to avoid const_cast'ing Walker, too
237 //const bond::ptr Binder =
238 const_cast<atom *>(Walker)->addBond(CurrentTime, const_cast<atom *>(OtherWalker));
239 ++BondCount;
240 } else {
241 LOG(2, "REJECT: Squared distance "
242 << distance << " is out of squared covalent bounds "
243 << MinMaxDistanceSquared << ".");
244 }
245
246 } else {
247 LOG(5, "REJECT: Not Adding: Wrong order.");
248 }
249 }
250 }
251 }
252 LOG(1, "I detected " << BondCount << " bonds in the molecule.");
253
254 // correct bond degree by comparing valence and bond degree
255 LOG(1, "STATUS: Correcting bond degree.");
256 CorrectBondDegree(Set);
257
258 // output bonds for debugging (if bond chain list was correctly installed)
259 LOG(2, "STATUS: Printing list of created bonds.");
260 std::stringstream output;
261 for(const_iterator_type AtomRunner = Set.begin(); AtomRunner != Set.end(); ++AtomRunner) {
262 (*AtomRunner)->OutputBondOfAtom(output);
263 output << std::endl << "\t\t";
264 }
265 LOG(2, output.str());
266 } else {
267 LOG(1, "REJECT: AtomCount is " << counter << ", thus no bonds, no connections.");
268 }
269 }
270
271 /** Creates an adjacency list of the given \a Set of atoms.
272 *
273 * Note that the input stream is required to refer to the same number of
274 * atoms also contained in \a Set.
275 *
276 * \param &Set container with atoms
277 * \param *input input stream to parse
278 * \param skiplines how many header lines to skip
279 * \param id_offset is base id compared to World startin at 0
280 */
281 template <class container_type,
282 class iterator_type,
283 class const_iterator_type>
284 void CreateAdjacencyListFromDbondFile(
285 AtomSetMixin<container_type,iterator_type,const_iterator_type> &Set,
286 ifstream *input,
287 unsigned int skiplines,
288 int id_offset) const
289 {
290 char line[MAXSTRINGSIZE];
291
292 // check input stream
293 if (input->fail()) {
294 ELOG(0, "Opening of bond file failed \n");
295 return;
296 };
297 // skip headers
298 for (unsigned int i=0;i<skiplines;i++)
299 input->getline(line,MAXSTRINGSIZE);
300
301 // create lookup map
302 LOG(1, "STATUS: Creating lookup map.");
303 std::map< unsigned int, atom *> AtomLookup;
304 unsigned int counter = id_offset; // if ids do not start at 0
305 for (iterator_type iter = Set.begin(); iter != Set.end(); ++iter) {
306 AtomLookup.insert( make_pair( counter++, *iter) );
307 }
308 LOG(2, "INFO: There are " << counter << " atoms in the given set.");
309
310 LOG(1, "STATUS: Scanning file.");
311 unsigned int atom1, atom2;
312 unsigned int bondcounter = 0;
313 while (!input->eof()) // Check whether we read everything already
314 {
315 input->getline(line,MAXSTRINGSIZE);
316 stringstream zeile(line);
317 if (zeile.str().empty())
318 continue;
319 zeile >> atom1;
320 zeile >> atom2;
321
322 LOG(4, "INFO: Looking for atoms " << atom1 << " and " << atom2 << ".");
323 if (atom2 < atom1) //Sort indices of atoms in order
324 std::swap(atom1, atom2);
325 ASSERT(atom2 < counter,
326 "BondGraph::CreateAdjacencyListFromDbondFile() - ID "
327 +toString(atom2)+" exceeds number of present atoms "+toString(counter)+".");
328 ASSERT(AtomLookup.count(atom1),
329 "BondGraph::CreateAdjacencyListFromDbondFile() - Could not find an atom with the ID given in dbond file");
330 ASSERT(AtomLookup.count(atom2),
331 "BondGraph::CreateAdjacencyListFromDbondFile() - Could not find an atom with the ID given in dbond file");
332 atom * const Walker = AtomLookup[atom1];
333 atom * const OtherWalker = AtomLookup[atom2];
334
335 LOG(3, "INFO: Creating bond between atoms " << atom1 << " and " << atom2 << ".");
336 //const bond::ptr Binder =
337 Walker->addBond(WorldTime::getTime(), OtherWalker);
338 bondcounter++;
339 }
340 LOG(1, "STATUS: "<< bondcounter << " bonds have been parsed.");
341 }
342
343 /** Removes all bonds within the given set of iterable atoms.
344 *
345 * @param Set Range with atoms
346 */
347 template <class container_type,
348 class iterator_type,
349 class const_iterator_type>
350 void cleanAdjacencyList(
351 AtomSetMixin<container_type,iterator_type,const_iterator_type> &Set) const
352 {
353 // remove every bond from the list
354 for(iterator_type AtomRunner = Set.begin(); AtomRunner != Set.end(); ++AtomRunner) {
355 (*AtomRunner)->removeAllBonds();
356// BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();
357// for(BondList::iterator BondRunner = ListOfBonds.begin();
358// !ListOfBonds.empty();
359// BondRunner = ListOfBonds.begin()) {
360// ASSERT((*BondRunner)->Contains(*AtomRunner),
361// "BondGraph::cleanAdjacencyList() - "+
362// toString(*BondRunner)+" does not contain "+
363// toString(*AtomRunner)+".");
364// delete((*BondRunner));
365// }
366 }
367 }
368
369 /** correct bond degree by comparing valence and bond degree.
370 * correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
371 * iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
372 * preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
373 * double bonds as was expected.
374 * @param Set Range with atoms
375 * \return number of bonds that could not be corrected
376 */
377 template <class container_type,
378 class iterator_type,
379 class const_iterator_type>
380 int CorrectBondDegree(
381 AtomSetMixin<container_type,iterator_type,const_iterator_type> &Set) const
382 {
383 // reset
384 resetBondDegree(Set);
385 // re-calculate
386 return calculateBondDegree(Set);
387 }
388
389 /** Equality comparator for class BondGraph.
390 *
391 * @param other other instance to compare to
392 * @return true - if equal in every member variable, except static
393 * \a BondGraph::BondThreshold.
394 */
395 bool operator==(const BondGraph &other) const;
396
397 /** Unequality comparator for class BondGraph.
398 *
399 * @param other other instance to compare to
400 * @return false - if equal in every member variable, except static
401 * \a BondGraph::BondThreshold.
402 */
403 bool operator!=(const BondGraph &other) const {
404 return !(*this == other);
405 }
406
407private:
408 /** Convenience function to place access to World::getLinkedCell() into source module.
409 *
410 * @return ref to LinkedCell_View
411 */
412 LinkedCell::LinkedCell_View getLinkedCell(const double max_distance) const;
413
414 /** Convenience function to place access to World::getDomain() into source module.
415 *
416 * @return ref to Box
417 */
418 Box &getDomain() const;
419
420 /** Convenience function to place access to WorldTime::getTime() into source module.
421 *
422 * @return current time step
423 */
424 unsigned int getTime() const;
425
426 /** Returns the BondLengthMatrix entry for a given index pair.
427 * \param firstelement index/atom number of first element (row index)
428 * \param secondelement index/atom number of second element (column index)
429 * \note matrix is of course symmetric.
430 */
431 double GetBondLength(
432 int firstelement,
433 int secondelement) const;
434
435 /** Returns bond criterion for given pair based on a bond length matrix.
436 * This calls either the covalent or the bond matrix criterion.
437 * \param *Walker first BondedParticle
438 * \param *OtherWalker second BondedParticle
439 * \return Range with bond interval
440 */
441 range<double> getMinMaxDistance(
442 const element * const Walker,
443 const element * const OtherWalker) const;
444
445 /** Returns bond criterion for given pair of elements based on a bond length matrix.
446 * The matrix should be contained in \a this BondGraph and contain an element-
447 * to-element length.
448 * \param *Walker first element
449 * \param *OtherWalker second element
450 * \return Range with bond interval
451 */
452 range<double> BondLengthMatrixMinMaxDistance(
453 const element * const Walker,
454 const element * const OtherWalker) const;
455
456 /** Returns bond criterion for given pair of elements based on covalent radius.
457 * \param *Walker first element
458 * \param *OtherWalker second element
459 * \return Range with bond interval
460 */
461 range<double> CovalentMinMaxDistance(
462 const element * const Walker,
463 const element * const OtherWalker) const;
464
465
466 /** Resets the bond::BondDegree of all atoms in the set to 1.
467 *
468 * @param Set Range with atoms
469 */
470 template <class container_type,
471 class iterator_type,
472 class const_iterator_type>
473 void resetBondDegree(
474 AtomSetMixin<container_type,iterator_type,const_iterator_type> &Set) const
475 {
476 // reset bond degrees
477 for(iterator_type AtomRunner = Set.begin(); AtomRunner != Set.end(); ++AtomRunner) {
478 (*AtomRunner)->resetBondDegree();
479 }
480 }
481
482 /** Calculates the bond degree for each atom on the set.
483 *
484 * @param Set Range with atoms
485 * @return number of non-matching bonds
486 */
487 template <class container_type,
488 class iterator_type,
489 class const_iterator_type>
490 int calculateBondDegree(
491 AtomSetMixin<container_type,iterator_type,const_iterator_type> &Set) const
492 {
493 //LOG(1, "Correcting Bond degree of each bond ... ");
494 int No = 0, OldNo = -1;
495 do {
496 OldNo = No;
497 No=0;
498 for(iterator_type AtomRunner = Set.begin(); AtomRunner != Set.end(); ++AtomRunner) {
499 No+=(*AtomRunner)->CorrectBondDegree();
500 }
501 } while (OldNo != No);
502 //LOG(0, " done.");
503 return No;
504 }
505
506 bool operator==(const periodentafel &other) const;
507
508 bool operator!=(const periodentafel &other) const {
509 return !(*this == other);
510 }
511
512private:
513 // default constructor for serialization
514 BondGraph();
515
516 friend class boost::serialization::access;
517 // serialization
518 template<class Archive>
519 void serialize(Archive & ar, const unsigned int version)
520 {
521 //ar & const_cast<double &>(BondThreshold);
522 ar & BondLengthMatrix;
523 ar & IsAngstroem;
524 }
525
526 //!> half width of the interval for allowed bond distances
527 static const double BondThreshold;
528 //!> Matrix with bond lenth per two elements
529 MatrixContainer *BondLengthMatrix;
530 //!> distance units are angstroem (true), bohr radii (false)
531 bool IsAngstroem;
532};
533
534#endif /* BONDGRAPH_HPP_ */
Note: See TracBrowser for help on using the repository browser.