source: src/analysis_bonds.cpp@ ff58f1

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

Added ifdef HAVE_CONFIG and config.h include to each and every cpp file.

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