source: src/Atom/atom_bondedparticle.cpp@ 2d5137

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 2d5137 was 1f693d, checked in by Frederik Heber <heber@…>, 12 years ago

Wrapped Bond::BondDegree in getter.

  • Property mode set to 100644
File size: 14.3 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * atom_bondedparticle.cpp
25 *
26 * Created on: Oct 19, 2009
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "CodePatterns/MemDebug.hpp"
36
37#include <algorithm>
38#include <boost/bind.hpp>
39
40#include "atom.hpp"
41#include "atom_bondedparticle.hpp"
42#include "Bond/bond.hpp"
43#include "CodePatterns/Assert.hpp"
44#include "CodePatterns/Log.hpp"
45#include "CodePatterns/Verbose.hpp"
46#include "Element/element.hpp"
47#include "WorldTime.hpp"
48
49/** Constructor of class BondedParticle.
50 */
51BondedParticle::BondedParticle()
52{
53 ListOfBonds.push_back(BondList());
54};
55
56/** Destructor of class BondedParticle.
57 */
58BondedParticle::~BondedParticle()
59{
60 removeAllBonds();
61};
62
63/** Outputs the current atom::AdaptiveOrder and atom::MaxOrder to \a *file.
64 * \param *file output stream
65 */
66void BondedParticle::OutputOrder(ofstream *file) const
67{
68 *file << getNr() << "\t" << (int)AdaptiveOrder << "\t" << (int)MaxOrder << endl;
69 //LOG(2, "Storing: " << getNr() << "\t" << (int)AdaptiveOrder << "\t" << MaxOrder << ".");
70};
71
72/** Prints all bonds of this atom with total degree.
73 */
74void BondedParticle::OutputBondOfAtom(std::ostream &ost) const
75{
76 const BondList& ListOfBonds = getListOfBonds();
77 ost << "Atom " << getName() << "/" << getNr() << " with " << ListOfBonds.size() << " bonds: ";
78 int TotalDegree = 0;
79 for (BondList::const_iterator Runner = ListOfBonds.begin(); Runner != ListOfBonds.end(); ++Runner) {
80 ost << **Runner << "\t";
81 TotalDegree += (*Runner)->getDegree();
82 }
83 ost << " -- TotalDegree: " << TotalDegree;
84};
85
86/** Output of atom::Nr along each bond partner per line.
87 * Only bonds are printed where atom::Nr is smaller than the one of the bond partner.
88 * \param *AdjacencyFile output stream
89 */
90void BondedParticle::OutputBonds(ofstream * const BondFile) const
91{
92 const BondList& ListOfBonds = getListOfBonds();
93 for (BondList::const_iterator Runner = ListOfBonds.begin(); Runner != ListOfBonds.end(); (++Runner))
94 if (getNr() < (*Runner)->GetOtherAtom(this)->getNr())
95 *BondFile << getNr() << "\t" << (*Runner)->GetOtherAtom(this)->getNr() << "\n";
96};
97
98/**
99 * Adds a bond between this bonded particle and another. Returns present instance if this
100 * bond already exists.
101 *
102 * @param _step time step to access
103 * @param bonding partner
104 * @return pointer to created bond or to already present bonds
105 */
106bond::ptr BondedParticle::addBond(const unsigned int _step, BondedParticle* Partner)
107{
108 const BondList &bondlist = getListOfBondsAtStep(_step);
109 for (BondList::const_iterator runner = bondlist.begin();
110 runner != bondlist.end();
111 runner++) {
112 if ((*runner)->Contains(Partner))
113 return *runner;
114 }
115
116 bond::ptr newBond(new bond((atom*) this, (atom*) Partner, 1));
117 RegisterBond(_step, newBond);
118 Partner->RegisterBond(_step, newBond);
119
120 return newBond;
121}
122
123/**
124 * Adds a bond between this bonded particle and another. Returns present instance if this
125 * bond already exists.
126 *
127 * @param bonding partner
128 * @return pointer to created bond or to already present bonds
129 */
130bond::ptr BondedParticle::addBond(BondedParticle* Partner)
131{
132 return addBond(WorldTime::getTime(), Partner);
133}
134
135/** Helper function to find the time step to a given bond in \a Binder.
136 *
137 * \param Binder bond to look for
138 * \return ListOfBonds::size() - not found, else - step containing \a Binder
139 */
140unsigned int BondedParticle::findBondsStep(bond::ptr const Binder) const
141{
142
143 size_t _step = 0;
144 for (;_step < ListOfBonds.size();++_step) {
145 const BondList& ListOfBonds = getListOfBondsAtStep(_step);
146 if (std::find(ListOfBonds.begin(), ListOfBonds.end(), Binder) != ListOfBonds.end())
147 break;
148 }
149 return _step;
150}
151
152/** Helper function to find the iterator to a bond at a given time \a step to
153 * a given bond partner in \a Partner.
154 *
155 * \param _step time step to look at
156 * \param Partner bond partner to look for
157 * \return ListOfBonds::end() - not found, else - iterator pointing \a Binder
158 */
159BondList::const_iterator BondedParticle::findBondPartnerAtStep(
160 const unsigned int _step,
161 BondedParticle * const Partner) const
162{
163 const BondList& ListOfBonds = getListOfBondsAtStep(_step);
164 BondList::const_iterator iter = std::find_if(ListOfBonds.begin(), ListOfBonds.end(),
165 boost::bind(
166 static_cast<bool (bond::*)(const ParticleInfo * const) const>(&bond::Contains),
167 _1,
168 boost::cref(Partner)));
169 return iter;
170}
171
172/** Removes a bond of this atom to a given \a Partner.
173 *
174 * @param _step time step
175 * @param Partner bond partner
176 */
177void BondedParticle::removeBond(const unsigned int _step, BondedParticle * const Partner)
178{
179 BondList::const_iterator iter = findBondPartnerAtStep(_step, Partner);
180 if (iter != getListOfBondsAtStep(_step).end()) {
181 // iter becomes invalid upon first unregister,
182 // hence store the bond someplace else first
183 bond::ptr const Binder = *iter;
184 UnregisterBond(_step, Binder);
185 Partner->UnregisterBond(_step, Binder);
186 } else
187 ELOG(1, "BondedParticle::removeBond() - I cannot find the bond in between "
188 +toString(getName())+" and "+toString(Partner->getName())+".");
189}
190
191/** Removes a bond of this atom to a given \a Partner.
192 *
193 * @param Partner bond partner
194 */
195void BondedParticle::removeBond(BondedParticle * const Partner)
196{
197 removeBond(WorldTime::getTime(), Partner);
198}
199
200/** Removes a bond for this atom.
201 *
202 * @param Binder bond to remove
203 */
204void BondedParticle::removeBond(bond::ptr &binder)
205{
206 if (binder != NULL) {
207 atom * const Other = binder->GetOtherAtom(this);
208 ASSERT( Other != NULL,
209 "BondedParticle::removeBonds() - cannot find bond partner for "
210 +toString(*binder)+".");
211 // find bond at step
212 unsigned int step = findBondsStep(binder);
213 if (step != ListOfBonds.size()) {
214 UnregisterBond(step, binder);
215 Other->UnregisterBond(step, binder);
216 binder.reset();
217 }
218 }
219}
220
221/** Removes all bonds in all timesteps and their instances, too.
222 *
223 */
224void BondedParticle::removeAllBonds()
225{
226 for (size_t index = 0; index < ListOfBonds.size(); ++index)
227 removeAllBonds(index);
228}
229
230/** Removes all bonds for a given \a _step and their instances, too.
231 *
232 * @param _step time step to access
233 */
234void BondedParticle::removeAllBonds(const unsigned int _step)
235{
236 //LOG(3,"INFO: Clearing all bonds of " << *this << ": " << ListOfBonds[_step]);
237 for (BondList::iterator iter = (ListOfBonds[_step]).begin();
238 !(ListOfBonds[_step]).empty();
239 iter = (ListOfBonds[_step]).begin()) {
240 //LOG(3,"INFO: Clearing bond (" << *iter << ") " << *(*iter) << " of list " << &ListOfBonds);
241 atom * const Other = (*iter)->GetOtherAtom(this);
242 ASSERT( Other != NULL,
243 "BondedParticle::removeAllBonds() - cannot find bond partner for "
244 +toString(**iter)+".");
245 Other->UnregisterBond(_step, *iter);
246 UnregisterBond(_step, *iter);
247 }
248}
249
250/** Puts a given bond into atom::ListOfBonds.
251 * @param _step time step to access
252 * \param *Binder bond to insert
253 */
254bool BondedParticle::RegisterBond(const unsigned int _step, bond::ptr const Binder)
255{
256 bool status = false;
257 if (Binder != NULL) {
258 OBSERVE;
259 if (Binder->Contains(this)) {
260 //LOG(3,"INFO: Registering bond "<< *Binder << " with atom " << *this << " at step " << _step);
261 if (ListOfBonds.size() <= _step)
262 ListOfBonds.resize(_step+1);
263 ListOfBonds[_step].push_back(Binder);
264 if (WorldTime::getTime() == _step)
265 NOTIFY(AtomObservable::BondsAdded);
266 status = true;
267 } else {
268 ELOG(1, *Binder << " does not contain " << *this << ".");
269 }
270 } else {
271 ELOG(1, "Binder is " << Binder << ".");
272 }
273 return status;
274};
275
276/** Removes a given bond from atom::ListOfBonds.
277 *
278 * \warning This only removes this atom not its bond partner, i.e.
279 * both atoms need to call this function to fully empty a bond.
280 *
281 * @param _step time step to access
282 * \param *Binder bond to remove
283 */
284bool BondedParticle::UnregisterBond(const unsigned int _step, bond::ptr const Binder)
285{
286 bool status = false;
287 if (Binder != NULL) {
288 if (Binder->Contains(this)) {
289 OBSERVE;
290 //LOG(0,"INFO: Unregistering bond "<< *Binder << " from list " << &ListOfBonds << " of atom " << *this << " at step " << step);
291#ifndef NDEBUG
292 BondList::const_iterator iter =
293 std::find(ListOfBonds[_step].begin(), ListOfBonds[_step].end(), Binder);
294 ASSERT( iter != ListOfBonds[_step].end(),
295 "BondedParticle::UnregisterBond() - "+toString(*Binder)+" not contained at "
296 +toString(_step));
297#endif
298 Binder->removeAtom(this);
299 ListOfBonds[_step].remove(Binder);
300 if (WorldTime::getTime() == _step)
301 NOTIFY(AtomObservable::BondsRemoved);
302 status = true;
303 } else {
304 ELOG(1, *Binder << " does not contain " << *this << ".");
305 }
306 } else {
307 ELOG(1, "Binder is " << Binder << ".");
308 }
309 return status;
310};
311
312/** Removes all bonds of given \a _step with freeing memory.
313 *
314 * @param _step time step whose bonds to free
315 */
316void BondedParticle::ClearBondsAtStep(const unsigned int _step)
317{
318 removeAllBonds(_step);
319}
320
321/** Searches for the time step where the given bond \a *Binder is a bond of this particle.
322 *
323 * @param Binder bond to check
324 * @return >=0 - first time step where bond appears, -1 - bond not present in lists
325 */
326int BondedParticle::ContainsBondAtStep(bond::ptr Binder) const
327{
328 int step = -1;
329 int tempstep = 0;
330 for(std::vector<BondList>::const_iterator iter = ListOfBonds.begin();
331 iter != ListOfBonds.end();
332 ++iter,++tempstep) {
333 for (BondList::const_iterator bonditer = iter->begin();
334 bonditer != iter->end();
335 ++bonditer) {
336 if ((*bonditer) == Binder) {
337 step = tempstep;
338 break;
339 }
340 }
341 if (step != -1)
342 break;
343 }
344
345 return step;
346}
347
348/** Corrects the bond degree by one at most if necessary.
349 * \return number of corrections done
350 */
351int BondedParticle::CorrectBondDegree()
352{
353 OBSERVE;
354 NOTIFY(AtomObservable::BondDegreeChanged);
355 int NoBonds = 0;
356 int OtherNoBonds = 0;
357 int FalseBondDegree = 0;
358 int CandidateDeltaNoBonds = -1;
359 atom *OtherWalker = NULL;
360 bond::ptr CandidateBond;
361
362 NoBonds = CountBonds();
363 LOG(3, "Walker " << *this << ": " << (int)this->getType()->getNoValenceOrbitals() << " > " << NoBonds << "?");
364 const int DeltaNoBonds = (int)(getType()->getNoValenceOrbitals()) - NoBonds;
365 if (DeltaNoBonds > 0) { // we have a mismatch, check all bonding partners for mismatch
366 const BondList& ListOfBonds = getListOfBonds();
367 for (BondList::const_iterator Runner = ListOfBonds.begin(); Runner != ListOfBonds.end(); (++Runner)) {
368 OtherWalker = (*Runner)->GetOtherAtom(this);
369 OtherNoBonds = OtherWalker->CountBonds();
370 const int OtherDeltaNoBonds = (int)(OtherWalker->getType()->getNoValenceOrbitals()) - OtherNoBonds;
371 LOG(3, "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->getType()->getNoValenceOrbitals() << " > " << OtherNoBonds << "?");
372 if (OtherDeltaNoBonds > 0) { // check if possible candidate
373 const BondList& OtherListOfBonds = OtherWalker->getListOfBonds();
374 if ((CandidateBond == NULL)
375 || (ListOfBonds.size() > OtherListOfBonds.size()) // pick the one with fewer number of bonds first
376 || ((CandidateDeltaNoBonds < 0) || (CandidateDeltaNoBonds > OtherDeltaNoBonds)) ) // pick the one closer to fulfilling its valence first
377 {
378 CandidateDeltaNoBonds = OtherDeltaNoBonds;
379 CandidateBond = (*Runner);
380 LOG(3, "New candidate is " << *CandidateBond << ".");
381 }
382 }
383 }
384 if ((CandidateBond != NULL)) {
385 CandidateBond->setDegree(CandidateBond->getDegree()+1);
386 LOG(2, "Increased bond degree for bond " << *CandidateBond << ".");
387 } else {
388 ELOG(2, "Could not find correct degree for atom " << *this << ".");
389 FalseBondDegree++;
390 }
391 }
392 return FalseBondDegree;
393};
394
395/** Sets the weight of all connected bonds to one.
396 */
397void BondedParticle::resetBondDegree()
398{
399 OBSERVE;
400 NOTIFY(BondedParticle::BondDegreeChanged);
401 for (std::vector<BondList>::iterator Runner = ListOfBonds.begin();
402 Runner != ListOfBonds.end();
403 ++Runner)
404 for (BondList::iterator BondRunner = (*Runner).begin();
405 BondRunner != (*Runner).end();
406 ++BondRunner)
407 (*BondRunner)->setDegree(1);
408};
409
410/** Counts the number of bonds weighted by bond::BondDegree.
411 * @param _step time step to access
412 * \param bonds times bond::BondDegree
413 */
414int BondedParticle::CountBonds() const
415{
416 int NoBonds = 0;
417 const BondList& ListOfBonds = getListOfBonds();
418 for (BondList::const_iterator Runner = ListOfBonds.begin();
419 Runner != ListOfBonds.end();
420 (++Runner))
421 NoBonds += (*Runner)->getDegree();
422 return NoBonds;
423};
424
425/** Checks whether there is a bond between \a this atom and the given \a *BondPartner.
426 * @param _step time step to access
427 * \param *BondPartner atom to check for
428 * \return true - bond exists, false - bond does not exist
429 */
430bool BondedParticle::IsBondedTo(const unsigned int _step, BondedParticle * const BondPartner) const
431{
432 bool status = false;
433
434 const BondList& ListOfBonds = getListOfBondsAtStep(_step);
435 for (BondList::const_iterator runner = ListOfBonds.begin();
436 runner != ListOfBonds.end();
437 runner++) {
438 status = status || ((*runner)->Contains(BondPartner));
439 }
440 return status;
441};
442
443std::ostream & BondedParticle::operator << (std::ostream &ost) const
444{
445 ParticleInfo::operator<<(ost);
446 ost << "," << getPosition();
447 return ost;
448}
449
450std::ostream & operator << (std::ostream &ost, const BondedParticle &a)
451{
452 a.ParticleInfo::operator<<(ost);
453 ost << "," << a.getPosition();
454 return ost;
455}
456
Note: See TracBrowser for help on using the repository browser.