source: src/analysis_bonds.cpp@ 435065

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 435065 was 735b1c, checked in by Frederik Heber <heber@…>, 14 years ago

ParticleInfo::ParticleInfo_nr is protected and accessed via getter/setter.

  • many changes (~400) in molecule- and tesselation-related functions.
  • Property mode set to 100644
File size: 12.3 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * analysis_bonds.cpp
10 *
11 * Created on: Nov 7, 2009
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "CodePatterns/MemDebug.hpp"
21
22#include "analysis_bonds.hpp"
23#include "atom.hpp"
24#include "bond.hpp"
25#include "element.hpp"
26#include "CodePatterns/Info.hpp"
27#include "CodePatterns/Verbose.hpp"
28#include "CodePatterns/Log.hpp"
29#include "molecule.hpp"
30
31/** Calculates the min, mean and maximum bond counts for the given molecule.
32 * \param *mol molecule with atoms and atom::ListOfBonds
33 * \param &Min minimum count on return
34 * \param &Mean mean count on return
35 * \param &Max maximum count on return
36 */
37void GetMaxMinMeanBondCount(const molecule * const mol, double &Min, double &Mean, double &Max)
38{
39 Min = 2e+6;
40 Max = -2e+5;
41 Mean = 0.;
42
43 int AtomCount = 0;
44 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
45 const BondList& ListOfBonds = (*iter)->getListOfBonds();
46 const int count = ListOfBonds.size();
47 if (Max < count)
48 Max = count;
49 if (Min > count)
50 Min = count;
51 Mean += count;
52 AtomCount++;
53 }
54 if (((int)Mean % 2) != 0)
55 DoeLog(1) && (eLog()<< Verbose(1) << "Something is wrong with the bond structure, the number of bonds is not even!" << endl);
56 Mean /= (double)AtomCount;
57};
58
59/** Calculates the min and max bond distance of all atoms of two given elements.
60 * \param *mol molecule with atoms
61 * \param *type1 one element
62 * \param *type2 other element
63 * \param &Min minimum distance on return, 0 if no bond between the two elements
64 * \param &Mean mean distance (i.e. sum of distance for matching element pairs, divided by number) on return, 0 if no bond between the two elements
65 * \param &Max maximum distance on return, 0 if no bond between the two elements
66 */
67void MinMeanMaxBondDistanceBetweenElements(const molecule *mol, const element *type1, const element *type2, double &Min, double &Mean, double &Max)
68{
69 Min = 2e+6;
70 Mean = 0.;
71 Max = -2e+6;
72
73 int AtomNo = 0;
74 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
75 if ((*iter)->getType() == type1) {
76 const BondList& ListOfBonds = (*iter)->getListOfBonds();
77 for (BondList::const_iterator BondRunner = ListOfBonds.begin();
78 BondRunner != ListOfBonds.end();
79 BondRunner++)
80 if ((*BondRunner)->GetOtherAtom((*iter))->getType() == type2) {
81 const double distance = (*BondRunner)->GetDistanceSquared();
82 if (Min > distance)
83 Min = distance;
84 if (Max < distance)
85 Max = distance;
86 Mean += sqrt(distance);
87 AtomNo++;
88 }
89 }
90 }
91 if (Max < 0) {
92 Max = Min = 0.;
93 } else {
94 Max = sqrt(Max);
95 Min = sqrt(Min);
96 Mean = Mean/(double)AtomNo;
97 }
98};
99
100/** Calculate the angle between \a *first and \a *origin and \a *second and \a *origin.
101 * \param *first first Vector
102 * \param *origin origin of angle taking
103 * \param *second second Vector
104 * \return angle between \a *first and \a *second, both relative to origin at \a *origin.
105 */
106double CalculateAngle(const Vector &first, const Vector &central, const Vector &second)
107{
108 Vector OHBond;
109 Vector OOBond;
110
111 OHBond = first - central;
112 OOBond = second - central;
113 const double angle = OHBond.Angle(OOBond);
114 return angle;
115};
116
117/** Checks whether the angle between \a *Oxygen and \a *Hydrogen and \a *Oxygen and \a *OtherOxygen is less than 30 degrees.
118 * Note that distance criterion is not checked.
119 * \param *Oxygen first oxygen atom, bonded to \a *Hydrogen
120 * \param *Hydrogen hydrogen bonded to \a *Oxygen
121 * \param *OtherOxygen other oxygen atom
122 * \return true - angle criteria fulfilled, false - criteria not fulfilled, angle greater than 30 degrees.
123 */
124bool CheckHydrogenBridgeBondAngle(atom *Oxygen, atom *Hydrogen, atom *OtherOxygen)
125{
126 Info FunctionInfo(__func__);
127
128 // check angle
129 if (CalculateAngle(Hydrogen->getPosition(), Oxygen->getPosition(), OtherOxygen->getPosition()) < M_PI*(30./180.)) {
130 return true;
131 } else {
132 return false;
133 }
134};
135
136/** Counts the number of hydrogen bridge bonds.
137 * With \a *InterfaceElement an extra element can be specified that identifies some boundary.
138 * Then, counting is for the h-bridges that connect to interface only.
139 * \param *molecules molecules to count bonds
140 * \param *InterfaceElement or NULL
141 * \param *Interface2Element or NULL
142 */
143int CountHydrogenBridgeBonds(MoleculeListClass *molecules, const element * InterfaceElement = NULL, const element * Interface2Element = NULL)
144{
145 int count = 0;
146 int OtherHydrogens = 0;
147 double Otherangle = 0.;
148 bool InterfaceFlag = false;
149 bool Interface2Flag = false;
150 bool OtherHydrogenFlag = true;
151 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin();MolWalker != molecules->ListOfMolecules.end(); ++MolWalker) {
152 molecule::iterator Walker = (*MolWalker)->begin();
153 for(;Walker!=(*MolWalker)->end();++Walker){
154 for (MoleculeList::const_iterator MolRunner = molecules->ListOfMolecules.begin();MolRunner != molecules->ListOfMolecules.end(); ++MolRunner) {
155 molecule::iterator Runner = (*MolRunner)->begin();
156 for(;Runner!=(*MolRunner)->end();++Runner){
157 if (((*Walker)->getType()->getAtomicNumber() == 8) && ((*Runner)->getType()->getAtomicNumber() == 8)) {
158 // check distance
159 const double distance = (*Runner)->DistanceSquared(*(*Walker));
160 if ((distance > MYEPSILON) && (distance < HBRIDGEDISTANCE*HBRIDGEDISTANCE)) { // distance >0 means different atoms
161 // on other atom(Runner) we check for bond to interface element and
162 // check that O-O line is not in between the shanks of the two connected hydrogens (Otherangle > 104.5)
163 OtherHydrogenFlag = true;
164 Otherangle = 0.;
165 OtherHydrogens = 0;
166 InterfaceFlag = (InterfaceElement == NULL);
167 Interface2Flag = (Interface2Element == NULL);
168 const BondList& ListOfBonds = (*Runner)->getListOfBonds();
169 for (BondList::const_iterator BondRunner = ListOfBonds.begin();
170 BondRunner != ListOfBonds.end();
171 BondRunner++) {
172 atom * const OtherAtom = (*BondRunner)->GetOtherAtom(*Runner);
173 // if hydrogen, check angle to be greater(!) than 30 degrees
174 if (OtherAtom->getType()->getAtomicNumber() == 1) {
175 const double angle = CalculateAngle(OtherAtom->getPosition(), (*Runner)->getPosition(), (*Walker)->getPosition());
176 OtherHydrogenFlag = OtherHydrogenFlag && (angle > M_PI*(30./180.) + MYEPSILON);
177 Otherangle += angle;
178 OtherHydrogens++;
179 }
180 InterfaceFlag = InterfaceFlag || (OtherAtom->getType() == InterfaceElement);
181 Interface2Flag = Interface2Flag || (OtherAtom->getType() == Interface2Element);
182 }
183 DoLog(1) && (Log() << Verbose(1) << "Otherangle is " << Otherangle << " for " << OtherHydrogens << " hydrogens." << endl);
184 switch (OtherHydrogens) {
185 case 0:
186 case 1:
187 break;
188 case 2:
189 OtherHydrogenFlag = OtherHydrogenFlag && (Otherangle > M_PI*(104.5/180.) + MYEPSILON);
190 break;
191 default: // 3 or more hydrogens ...
192 OtherHydrogenFlag = false;
193 break;
194 }
195 if (InterfaceFlag && Interface2Flag && OtherHydrogenFlag) {
196 // on this element (Walker) we check for bond to hydrogen, i.e. part of water molecule
197 const BondList& ListOfBonds = (*Walker)->getListOfBonds();
198 for (BondList::const_iterator BondRunner = ListOfBonds.begin();
199 BondRunner != ListOfBonds.end();
200 BondRunner++) {
201 atom * const OtherAtom = (*BondRunner)->GetOtherAtom(*Walker);
202 if (OtherAtom->getType()->getAtomicNumber() == 1) {
203 // check angle
204 if (CheckHydrogenBridgeBondAngle(*Walker, OtherAtom, *Runner)) {
205 DoLog(1) && (Log() << Verbose(1) << (*Walker)->getName() << ", " << OtherAtom->getName() << " and " << (*Runner)->getName() << " has a hydrogen bridge bond with distance " << sqrt(distance) << " and angle " << CalculateAngle(OtherAtom->getPosition(), (*Walker)->getPosition(), (*Runner)->getPosition())*(180./M_PI) << "." << endl);
206 count++;
207 break;
208 }
209 }
210 }
211 }
212 }
213 }
214 }
215 }
216 }
217 }
218 return count;
219}
220
221/** Counts the number of bonds between two given elements.
222 * \param *molecules list of molecules with all atoms
223 * \param *first pointer to first element
224 * \param *second pointer to second element
225 * \return number of found bonds (\a *first-\a *second)
226 */
227int CountBondsOfTwo(MoleculeListClass * const molecules, const element * const first, const element * const second)
228{
229 int count = 0;
230
231 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin();MolWalker != molecules->ListOfMolecules.end(); MolWalker++) {
232 molecule::iterator Walker = (*MolWalker)->begin();
233 for(;Walker!=(*MolWalker)->end();++Walker){
234 atom * theAtom = *Walker;
235 if ((theAtom->getType() == first) || (theAtom->getType() == second)) { // first element matches
236 const BondList& ListOfBonds = theAtom->getListOfBonds();
237 for (BondList::const_iterator BondRunner = ListOfBonds.begin();
238 BondRunner != ListOfBonds.end();
239 BondRunner++) {
240 atom * const OtherAtom = (*BondRunner)->GetOtherAtom(theAtom);
241 if (((OtherAtom->getType() == first) || (OtherAtom->getType() == second)) && (theAtom->getNr() < OtherAtom->getNr())) {
242 count++;
243 DoLog(1) && (Log() << Verbose(1) << *first << "-" << *second << " bond found between " << *Walker << " and " << *OtherAtom << "." << endl);
244 }
245 }
246 }
247 }
248 }
249 return count;
250};
251
252/** Counts the number of bonds between three given elements.
253 * Note that we do not look for arbitrary sequence of given bonds, but \a *second will be the central atom and we check
254 * whether it has bonds to both \a *first and \a *third.
255 * \param *molecules list of molecules with all atoms
256 * \param *first pointer to first element
257 * \param *second pointer to second element
258 * \param *third pointer to third element
259 * \return number of found bonds (\a *first-\a *second-\a *third, \a *third-\a *second-\a *first, respectively)
260 */
261int CountBondsOfThree(MoleculeListClass * const molecules, const element * const first, const element * const second, const element * const third)
262{
263 int count = 0;
264 bool MatchFlag[2];
265 bool result = false;
266 const element * ElementArray[2];
267 ElementArray[0] = first;
268 ElementArray[1] = third;
269
270 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin();MolWalker != molecules->ListOfMolecules.end(); MolWalker++) {
271 molecule::iterator Walker = (*MolWalker)->begin();
272 for(;Walker!=(*MolWalker)->end();++Walker){
273 atom *theAtom = *Walker;
274 if (theAtom->getType() == second) { // first element matches
275 for (int i=0;i<2;i++)
276 MatchFlag[i] = false;
277 const BondList& ListOfBonds = theAtom->getListOfBonds();
278 for (BondList::const_iterator BondRunner = ListOfBonds.begin();
279 BondRunner != ListOfBonds.end();
280 BondRunner++) {
281 atom * const OtherAtom = (*BondRunner)->GetOtherAtom(theAtom);
282 for (int i=0;i<2;i++)
283 if ((!MatchFlag[i]) && (OtherAtom->getType() == ElementArray[i])) {
284 MatchFlag[i] = true;
285 break; // each bonding atom can match at most one element we are looking for
286 }
287 }
288 result = true;
289 for (int i=0;i<2;i++) // gather results
290 result = result && MatchFlag[i];
291 if (result) { // check results
292 count++;
293 DoLog(1) && (Log() << Verbose(1) << *first << "-" << *second << "-" << *third << " bond found at " << *Walker << "." << endl);
294 }
295 }
296 }
297 }
298 return count;
299};
Note: See TracBrowser for help on using the repository browser.