source: src/molecule_graph.cpp@ 36bb2d

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 36bb2d was 94d5ac6, checked in by Frederik Heber <heber@…>, 12 years ago

FIX: As we use GSL internally, we are as of now required to use GPL v2 license.

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