source: src/molecule_graph.cpp@ 88c8ec

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

REFACTOR: Replaced all "bond *" appearances by bond::ptr.

  • this is preparatory for making bond::ptr a boost::shared_ptr of bond.
  • NOTE: We had to remove a const prefix at four or five places and forward declarations had to be replaced by the true inclusion of bond.hpp at tne or so files. Apart from that, the replacement has been very smooth.
  • Property mode set to 100644
File size: 13.2 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 * molecule_graph.cpp
25 *
26 * Created on: Oct 5, 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 <stack>
38
39#include "Atom/atom.hpp"
40#include "Bond/bond.hpp"
41#include "Box.hpp"
42#include "CodePatterns/Assert.hpp"
43#include "CodePatterns/Info.hpp"
44#include "CodePatterns/Log.hpp"
45#include "CodePatterns/Verbose.hpp"
46#include "config.hpp"
47#include "Graph/DepthFirstSearchAnalysis.hpp"
48#include "Element/element.hpp"
49#include "Graph/BondGraph.hpp"
50#include "Graph/ListOfLocalAtoms.hpp"
51#include "Helpers/defs.hpp"
52#include "Helpers/helpers.hpp"
53#include "LinearAlgebra/RealSpaceMatrix.hpp"
54#include "LinkedCell/linkedcell.hpp"
55#include "LinkedCell/PointCloudAdaptor.hpp"
56#include "molecule.hpp"
57#include "World.hpp"
58#include "WorldTime.hpp"
59
60
61/** Fills the bond structure of this chain list subgraphs that are derived from a complete \a *reference molecule.
62 * Calls this routine in each MoleculeLeafClass::next subgraph if it's not NULL.
63 * \param *reference reference molecule with the bond structure to be copied
64 * \param ListOfLocalAtoms Lookup table for this subgraph and index of each atom in \a *reference, may be NULL on start, then it is filled
65 * \param FreeList true - ListOfLocalAtoms is free'd before return, false - it is not
66 * \return true - success, false - failure
67 */
68bool molecule::FillBondStructureFromReference(const molecule * const reference, ListOfLocalAtoms_t &ListOfLocalAtoms, bool FreeList)
69{
70 bool status = true;
71
72 LOG(1, "Begin of FillBondStructureFromReference.");
73 // fill ListOfLocalAtoms if NULL was given
74 if (!FillListOfLocalAtoms(ListOfLocalAtoms, reference->getAtomCount())) {
75 LOG(1, "Filling of ListOfLocalAtoms failed.");
76 return false;
77 }
78
79 if (status) {
80 LOG(1, "Creating adjacency list for molecule " << getName() << ".");
81 // remove every bond from the list
82 for_each(begin(), end(),
83 boost::bind(&BondedParticle::ClearBondsAtStep,_1,WorldTime::getTime()));
84
85
86 for(molecule::iterator iter = begin(); iter != end(); ++iter) {
87 const atom * const Father = (*iter)->GetTrueFather();
88 //const int AtomNo = Father->getNr(); // global id of the current walker
89 const BondList& ListOfBonds = Father->getListOfBonds();
90 for (BondList::const_iterator Runner = ListOfBonds.begin();
91 Runner != ListOfBonds.end();
92 ++Runner) {
93 atom * const OtherAtom = (*Runner)->GetOtherAtom((*iter)->GetTrueFather());
94 const ListOfLocalAtoms_t::const_iterator localiter = ListOfLocalAtoms.find(OtherAtom->getNr());
95 ASSERT( localiter != ListOfLocalAtoms.end(),
96 "molecule::FillBondStructureFromReference() - could not find id"
97 +toString(OtherAtom->getNr())+" in ListOfLocalAtoms.");
98 atom * const OtherWalker = localiter->second; // local copy of current bond partner of walker
99 if (OtherWalker != NULL) {
100 if (OtherWalker->getNr() > (*iter)->getNr())
101 AddBond((*iter), OtherWalker, (*Runner)->BondDegree);
102 } else {
103 LOG(1, "OtherWalker = ListOfLocalAtoms[" << OtherAtom->getNr() << "] is NULL!");
104 status = false;
105 }
106 }
107 }
108 }
109
110 if ((FreeList) && (!ListOfLocalAtoms.empty())) {
111 // free the index lookup list
112 ListOfLocalAtoms.clear();
113 }
114 LOG(1, "End of FillBondStructureFromReference.");
115 return status;
116};
117
118/** Checks for presence of bonds within atom list.
119 * TODO: more sophisticated check for bond structure (e.g. connected subgraph, ...)
120 * \return true - bonds present, false - no bonds
121 */
122bool molecule::hasBondStructure() const
123{
124 for(molecule::const_iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner) {
125 //LOG(0, "molecule::hasBondStructure() - checking bond list of atom " << (*AtomRunner)->getId() << ".");
126 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();
127 if (!ListOfBonds.empty())
128 return true;
129 }
130 return false;
131}
132
133/** Prints a list of all bonds to \a *out.
134 */
135void molecule::OutputBondsList() const
136{
137 if (DoLog(1)) {
138 std::stringstream output;
139 output << std::endl << "From contents of bond chain list:";
140 for(molecule::const_iterator AtomRunner = molecule::begin(); AtomRunner != molecule::end(); ++AtomRunner) {
141 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();
142 for(BondList::const_iterator BondRunner = ListOfBonds.begin();
143 BondRunner != ListOfBonds.end();
144 ++BondRunner)
145 if ((*BondRunner)->leftatom == *AtomRunner) {
146 output << *(*BondRunner) << "\t";
147 }
148 }
149 LOG(1, output.str());
150 }
151}
152
153
154/** Storing the bond structure of a molecule to file.
155 * Simply stores Atom::Nr and then the Atom::Nr of all bond partners, one per line.
156 * \param &filename name of file
157 * \param path path to file, defaults to empty
158 * \return true - file written successfully, false - writing failed
159 */
160bool molecule::StoreBondsToFile(std::string filename, std::string path)
161{
162 ofstream BondFile;
163 string line;
164 bool status = true;
165
166 if (path != "")
167 line = path + "/" + filename;
168 else
169 line = filename;
170 BondFile.open(line.c_str(), ios::out);
171 LOG(1, "Saving adjacency list ... ");
172 if (BondFile.good()) {
173 BondFile << "m\tn" << endl;
174 for_each(begin(),end(),bind2nd(mem_fun(&atom::OutputBonds),&BondFile));
175 BondFile.close();
176 LOG(1, "\t... done.");
177 } else {
178 LOG(1, "\t... failed to open file " << line << ".");
179 status = false;
180 }
181
182 return status;
183}
184;
185
186/** Adds a bond as a copy to a given one
187 * \param *left leftatom of new bond
188 * \param *right rightatom of new bond
189 * \param *CopyBond rest of fields in bond are copied from this
190 * \return pointer to new bond
191 */
192bond::ptr molecule::CopyBond(atom *left, atom *right, bond::ptr CopyBond)
193{
194 bond::ptr Binder = AddBond(left, right, CopyBond->BondDegree);
195 Binder->Cyclic = CopyBond->Cyclic;
196 Binder->Type = CopyBond->Type;
197 return Binder;
198}
199;
200
201/** Fills a lookup list of father's Atom::nr -> atom for each subgraph.
202 * \param ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
203 * \param GlobalAtomCount number of atoms in the complete molecule
204 * \return true - success, false - failure (ListOfLocalAtoms != NULL)
205 */
206bool molecule::FillListOfLocalAtoms(ListOfLocalAtoms_t &ListOfLocalAtoms, const int GlobalAtomCount)
207{
208 bool status = true;
209
210 if (ListOfLocalAtoms.empty()) { // allocate and fill list of this fragment/subgraph
211 status = status && CreateFatherLookupTable(ListOfLocalAtoms, GlobalAtomCount);
212 } else
213 return false;
214
215 return status;
216}
217
218
219/** Creates a lookup table for true father's Atom::Nr -> atom ptr.
220 * \param *start begin of list (STL iterator, i.e. first item)
221 * \paran *end end of list (STL iterator, i.e. one past last item)
222 * \param **Lookuptable pointer to return allocated lookup table (should be NULL on start)
223 * \param count optional predetermined size for table (otherwise we set the count to highest true father id)
224 * \return true - success, false - failure
225 */
226bool molecule::CreateFatherLookupTable(ListOfLocalAtoms_t &LookupTable, int count)
227{
228 bool status = true;
229 int AtomNo;
230
231 if (!LookupTable.empty()) {
232 ELOG(1, "Pointer for Lookup table is not empty! Aborting ...");
233 return false;
234 }
235
236 // count them
237 if (count == 0) {
238 for (molecule::iterator iter = begin(); iter != end(); ++iter) { // create a lookup table (Atom::Nr -> atom) used as a marker table lateron
239 count = (count < (*iter)->GetTrueFather()->getNr()) ? (*iter)->GetTrueFather()->getNr() : count;
240 }
241 }
242 if (count <= 0) {
243 ELOG(1, "Count of lookup list is 0 or less.");
244 return false;
245 }
246
247 // allocate and fill
248 for (int i=0;i<=count;i++)
249 LookupTable[i] = NULL;
250 for (molecule::iterator iter = begin(); iter != end(); ++iter) {
251 AtomNo = (*iter)->GetTrueFather()->getNr();
252 if ((AtomNo >= 0) && (AtomNo <= count)) {
253 LOG(3, "DEBUG: Setting LookupTable[" << AtomNo << "] to " << *(*iter));
254 LookupTable[AtomNo] = (*iter);
255 } else {
256 ELOG(1, "Walker " << *(*iter) << " exceeded range of nuclear ids [0, " << count << "].");
257 status = false;
258 break;
259 }
260 }
261
262 return status;
263};
264
265
266
267/** Corrects the nuclei position if the fragment was created over the cell borders.
268 * Scans all bonds, checks the distance, if greater than typical, we have a candidate for the correction.
269 * We remove the bond whereafter the graph probably separates. Then, we translate the one component periodically
270 * and re-add the bond. Looping on the distance check.
271 * \param *out ofstream for debugging messages
272 */
273bool molecule::ScanForPeriodicCorrection()
274{
275 bond::ptr Binder = NULL;
276 //bond::ptr OtherBinder = NULL;
277 atom *Walker = NULL;
278 atom *OtherWalker = NULL;
279 RealSpaceMatrix matrix = World::getInstance().getDomain().getM();
280 enum GraphEdge::Shading *ColorList = NULL;
281 double tmp;
282 //bool LastBond = true; // only needed to due list construct
283 Vector Translationvector;
284 //std::deque<atom *> *CompStack = NULL;
285 std::deque<atom *> *AtomStack = new std::deque<atom *>; // (getAtomCount());
286 bool flag = true;
287 BondGraph *BG = World::getInstance().getBondGraph();
288
289 LOG(2, "Begin of ScanForPeriodicCorrection.");
290
291 ColorList = new enum GraphEdge::Shading[getAtomCount()];
292 for (int i=0;i<getAtomCount();i++)
293 ColorList[i] = (enum GraphEdge::Shading)0;
294 if (flag) {
295 // remove bonds that are beyond bonddistance
296 Translationvector.Zero();
297 // scan all bonds
298 flag = false;
299 for(molecule::iterator AtomRunner = begin(); (!flag) && (AtomRunner != end()); ++AtomRunner) {
300 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();
301 for(BondList::const_iterator BondRunner = ListOfBonds.begin();
302 (!flag) && (BondRunner != ListOfBonds.end());
303 ++BondRunner) {
304 Binder = (*BondRunner);
305 for (int i=NDIM;i--;) {
306 tmp = fabs(Binder->leftatom->at(i) - Binder->rightatom->at(i));
307 //LOG(3, "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << ".");
308 const range<double> MinMaxDistance(
309 BG->getMinMaxDistance(Binder->leftatom, Binder->rightatom));
310 if (!MinMaxDistance.isInRange(tmp)) {
311 LOG(2, "Correcting at bond " << *Binder << ".");
312 flag = true;
313 break;
314 }
315 }
316 }
317 }
318 //if (flag) {
319 if (0) {
320 // create translation vector from their periodically modified distance
321 for (int i=NDIM;i--;) {
322 tmp = Binder->leftatom->at(i) - Binder->rightatom->at(i);
323 const range<double> MinMaxDistance(
324 BG->getMinMaxDistance(Binder->leftatom, Binder->rightatom));
325 if (fabs(tmp) > MinMaxDistance.last) // check against Min is not useful for components
326 Translationvector[i] = (tmp < 0) ? +1. : -1.;
327 }
328 Translationvector *= matrix;
329 LOG(3, "INFO: Translation vector is " << Translationvector << ".");
330 // apply to all atoms of first component via BFS
331 for (int i=getAtomCount();i--;)
332 ColorList[i] = GraphEdge::white;
333 AtomStack->push_front(Binder->leftatom);
334 while (!AtomStack->empty()) {
335 Walker = AtomStack->front();
336 AtomStack->pop_front();
337 //LOG(3, "INFO: Current Walker is: " << *Walker << ".");
338 ColorList[Walker->getNr()] = GraphEdge::black; // mark as explored
339 *Walker += Translationvector; // translate
340 const BondList& ListOfBonds = Walker->getListOfBonds();
341 for (BondList::const_iterator Runner = ListOfBonds.begin();
342 Runner != ListOfBonds.end();
343 ++Runner) {
344 if ((*Runner) != Binder) {
345 OtherWalker = (*Runner)->GetOtherAtom(Walker);
346 if (ColorList[OtherWalker->getNr()] == GraphEdge::white) {
347 AtomStack->push_front(OtherWalker); // push if yet unexplored
348 }
349 }
350 }
351 }
352// // re-add bond
353// if (OtherBinder == NULL) { // is the only bond?
354// //Do nothing
355// } else {
356// if (!LastBond) {
357// link(Binder, OtherBinder); // no more implemented bond::previous ...
358// } else {
359// link(OtherBinder, Binder); // no more implemented bond::previous ...
360// }
361// }
362 } else {
363 LOG(3, "No corrections for this fragment.");
364 }
365 //delete(CompStack);
366 }
367 // free allocated space from ReturnFullMatrixforSymmetric()
368 delete(AtomStack);
369 delete[](ColorList);
370 LOG(2, "End of ScanForPeriodicCorrection.");
371
372 return flag;
373};
Note: See TracBrowser for help on using the repository browser.