source: src/analysis_bonds.cpp@ bd6bfa

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

Merge commit 'jupiter/MoleculeStartEndSwitch' into CommandLineActionMapping

Conflicts:

molecuilder/src/Makefile.am
molecuilder/src/builder.cpp
molecuilder/src/config.cpp
molecuilder/src/helpers.hpp
molecuilder/src/molecule.cpp
molecuilder/src/molecule_dynamics.cpp
molecuilder/src/molecule_fragmentation.cpp
molecuilder/src/molecule_geometry.cpp
molecuilder/src/molecule_graph.cpp
molecuilder/src/moleculelist.cpp
molecuilder/src/unittests/AnalysisCorrelationToPointUnitTest.cpp
molecuilder/src/unittests/listofbondsunittest.cpp

Integration of MoleculeStartEndSwitch had the following consequences:

  • no more AtomCount -> getAtomCount()
  • no more start/end -> begin(), end() and iterator
  • no more decent ordering in atomic ids (hence, Simple_configuration/8 and Domain/5, Domain/6 now check by comparing sorted xyz, not confs)

There is still a huge problem with bonds. One test runs into an endless loop.

Signed-off-by: Frederik Heber <heber@…>

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