source: src/Graph/BondGraph.hpp@ cdaae6

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 cdaae6 was 6bd7e0, checked in by Frederik Heber <heber@…>, 13 years ago

Renamed old LinkedCell class to LinkedCell_deprecated.

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