source: src/Analysis/analysis_correlation.cpp@ f96874

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 f96874 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: 28.8 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 * analysis.cpp
25 *
26 * Created on: Oct 13, 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 <iostream>
39#include <iomanip>
40#include <limits>
41
42#include "Atom/atom.hpp"
43#include "Bond/bond.hpp"
44#include "Tesselation/BoundaryTriangleSet.hpp"
45#include "Box.hpp"
46#include "Element/element.hpp"
47#include "CodePatterns/Info.hpp"
48#include "CodePatterns/Log.hpp"
49#include "CodePatterns/Verbose.hpp"
50#include "Descriptors/AtomOfMoleculeSelectionDescriptor.hpp"
51#include "Descriptors/MoleculeFormulaDescriptor.hpp"
52#include "Descriptors/MoleculeOfAtomSelectionDescriptor.hpp"
53#include "Formula.hpp"
54#include "LinearAlgebra/Vector.hpp"
55#include "LinearAlgebra/RealSpaceMatrix.hpp"
56#include "LinkedCell/LinkedCell_View.hpp"
57#include "molecule.hpp"
58#include "Tesselation/tesselation.hpp"
59#include "Tesselation/tesselationhelpers.hpp"
60#include "Tesselation/triangleintersectionlist.hpp"
61#include "World.hpp"
62#include "WorldTime.hpp"
63
64#include "analysis_correlation.hpp"
65
66/** Calculates the dipole vector of a given atomSet.
67 *
68 * Note that we use the following procedure as rule of thumb:
69 * -# go through every bond of the atom
70 * -# calculate the difference of electronegativities \f$\Delta\mathrm{EN}\f$
71 * -# if \f$\Delta\mathrm{EN} > 0.5\f$, we align the bond vector in direction of the more negative element
72 * -# sum up all vectors
73 * -# finally, divide by the number of summed vectors
74 *
75 * @param atomsbegin begin iterator of atomSet
76 * @param atomsend end iterator of atomset
77 * @return dipole vector
78 */
79Vector getDipole(molecule::const_iterator atomsbegin, molecule::const_iterator atomsend)
80{
81 Vector DipoleVector;
82 size_t SumOfVectors = 0;
83 Box &domain = World::getInstance().getDomain();
84
85 // go through all atoms
86 for (molecule::const_iterator atomiter = atomsbegin;
87 atomiter != atomsend;
88 ++atomiter) {
89 // go through all bonds
90 const BondList& ListOfBonds = (*atomiter)->getListOfBonds();
91 ASSERT(ListOfBonds.begin() != ListOfBonds.end(),
92 "getDipole() - no bonds in molecule!");
93 for (BondList::const_iterator bonditer = ListOfBonds.begin();
94 bonditer != ListOfBonds.end();
95 ++bonditer) {
96 const atom * Otheratom = (*bonditer)->GetOtherAtom(*atomiter);
97 if (Otheratom->getId() > (*atomiter)->getId()) {
98 const double DeltaEN = (*atomiter)->getType()->getElectronegativity()
99 -Otheratom->getType()->getElectronegativity();
100 // get distance and correct for boundary conditions
101 Vector BondDipoleVector = domain.periodicDistanceVector(
102 (*atomiter)->getPosition(),
103 Otheratom->getPosition());
104 // DeltaEN is always positive, gives correct orientation of vector
105 BondDipoleVector.Normalize();
106 BondDipoleVector *= DeltaEN;
107 LOG(3,"INFO: Dipole vector from bond " << **bonditer << " is " << BondDipoleVector);
108 DipoleVector += BondDipoleVector;
109 SumOfVectors++;
110 }
111 }
112 }
113 LOG(3,"INFO: Sum over all bond dipole vectors is "
114 << DipoleVector << " with " << SumOfVectors << " in total.");
115 if (SumOfVectors != 0)
116 DipoleVector *= 1./(double)SumOfVectors;
117 LOG(2, "INFO: Resulting dipole vector is " << DipoleVector);
118
119 return DipoleVector;
120};
121
122/** Calculate minimum and maximum amount of trajectory steps by going through given atomic trajectories.
123 * \param vector of atoms whose trajectories to check for [min,max]
124 * \return range with [min, max]
125 */
126range<size_t> getMaximumTrajectoryBounds(const std::vector<atom *> &atoms)
127{
128 // get highest trajectory size
129 LOG(0,"STATUS: Retrieving maximum amount of time steps ...");
130 if (atoms.size() == 0)
131 return range<size_t>(0,0);
132 size_t max_timesteps = std::numeric_limits<size_t>::min();
133 size_t min_timesteps = std::numeric_limits<size_t>::max();
134 BOOST_FOREACH(atom *_atom, atoms) {
135 if (_atom->getTrajectorySize() > max_timesteps)
136 max_timesteps = _atom->getTrajectorySize();
137 if (_atom->getTrajectorySize() < min_timesteps)
138 min_timesteps = _atom->getTrajectorySize();
139 }
140 LOG(1,"INFO: Minimum number of time steps found is " << min_timesteps);
141 LOG(1,"INFO: Maximum number of time steps found is " << max_timesteps);
142
143 return range<size_t>(min_timesteps, max_timesteps);
144}
145
146/** Calculates the angular dipole zero orientation from current time step.
147 * \param molecules vector of molecules to calculate dipoles of
148 * \return map with orientation vector for each atomic id given in \a atoms.
149 */
150std::map<atomId_t, Vector> CalculateZeroAngularDipole(const std::vector<molecule *> &molecules)
151{
152 // get zero orientation for each molecule.
153 LOG(0,"STATUS: Calculating dipoles for current time step ...");
154 std::map<atomId_t, Vector> ZeroVector;
155 BOOST_FOREACH(molecule *_mol, molecules) {
156 const Vector Dipole = getDipole(_mol->begin(), _mol->end());
157 for(molecule::const_iterator iter = _mol->begin(); iter != _mol->end(); ++iter)
158 ZeroVector[(*iter)->getId()] = Dipole;
159 LOG(2,"INFO: Zero alignment for molecule " << _mol->getId() << " is " << Dipole);
160 }
161 LOG(1,"INFO: We calculated zero orientation for a total of " << molecules.size() << " molecule(s).");
162
163 return ZeroVector;
164}
165
166/** Calculates the dipole angular correlation for given molecule type.
167 * Calculate the change of the dipole orientation angle over time.
168 * Note given element order is unimportant (i.e. g(Si, O) === g(O, Si))
169 * Angles are given in degrees.
170 * \param &atoms list of atoms of the molecules taking part (Note: molecules may
171 * change over time as bond structure is recalculated, hence we need the atoms)
172 * \param timestep time step to calculate angular correlation for (relative to
173 * \a ZeroVector)
174 * \param ZeroVector map with Zero orientation vector for each atom in \a atoms.
175 * \param DontResetTime don't reset time to old value (triggers re-creation of bond system)
176 * \return Map of doubles with values the pair of the two atoms.
177 */
178DipoleAngularCorrelationMap *DipoleAngularCorrelation(
179 const Formula &DipoleFormula,
180 const size_t timestep,
181 const std::map<atomId_t, Vector> &ZeroVector,
182 const enum ResetWorldTime DoTimeReset
183 )
184{
185 Info FunctionInfo(__func__);
186 DipoleAngularCorrelationMap *outmap = new DipoleAngularCorrelationMap;
187
188 unsigned int oldtime = 0;
189 if (DoTimeReset == DoResetTime) {
190 // store original time step
191 oldtime = WorldTime::getTime();
192 }
193
194 // set time step
195 LOG(0,"STATUS: Stepping onto to time step " << timestep << ".");
196 World::getInstance().setTime(timestep);
197
198 // get all molecules for this time step
199 World::getInstance().clearMoleculeSelection();
200 World::getInstance().selectAllMolecules(MoleculeByFormula(DipoleFormula));
201 std::vector<molecule *> molecules = World::getInstance().getSelectedMolecules();
202 LOG(1,"INFO: There are " << molecules.size() << " molecules for time step " << timestep << ".");
203
204 // calculate dipoles for each
205 LOG(0,"STATUS: Calculating dipoles for time step " << timestep << " ...");
206 size_t i=0;
207 size_t Counter_rejections = 0;
208 BOOST_FOREACH(molecule *_mol, molecules) {
209 const Vector Dipole = getDipole(_mol->begin(), _mol->end());
210 LOG(3,"INFO: Dipole vector at time step " << timestep << " for for molecule "
211 << _mol->getId() << " is " << Dipole);
212 // check that all atoms are valid (zeroVector known)
213 molecule::const_iterator iter = _mol->begin();
214 for(; iter != _mol->end(); ++iter) {
215 if (!ZeroVector.count((*iter)->getId()))
216 break;
217 }
218 if (iter != _mol->end()) {
219 ELOG(2, "Skipping molecule " << _mol->getName() << " as not all atoms have a valid zeroVector.");
220 ++Counter_rejections;
221 continue;
222 } else
223 iter = _mol->begin();
224 std::map<atomId_t, Vector>::const_iterator zeroValue = ZeroVector.find((*iter)->getId()); //due to iter is const
225 double angle = 0.;
226 LOG(2, "INFO: ZeroVector of first atom " << **iter << " is "
227 << zeroValue->second << ".");
228 LOG(4, "INFO: Squared norm of difference vector is "
229 << (zeroValue->second - Dipole).NormSquared() << ".");
230 if ((zeroValue->second - Dipole).NormSquared() > MYEPSILON)
231 angle = Dipole.Angle(zeroValue->second) * (180./M_PI);
232 else
233 LOG(2, "INFO: Both vectors (almost) coincide, numerically unstable, angle set to zero.");
234 LOG(1,"INFO: Resulting relative angle for molecule " << _mol->getName()
235 << " is " << angle << ".");
236 outmap->insert ( std::make_pair (angle, *iter ) );
237 ++i;
238 }
239 ASSERT(Counter_rejections <= molecules.size(),
240 "DipoleAngularCorrelation() - more rejections ("+toString(Counter_rejections)
241 +") than there are molecules ("+toString(molecules.size())+").");
242 LOG(1,"INFO: " << Counter_rejections << " molecules have been rejected in time step " << timestep << ".");
243
244 LOG(0,"STATUS: Done with calculating dipoles.");
245
246 if (DoTimeReset == DoResetTime) {
247 // re-set to original time step again
248 World::getInstance().setTime(oldtime);
249 }
250
251 // and return results
252 return outmap;
253};
254
255/** Calculates the dipole correlation for given molecule type.
256 * I.e. we calculate how the angle between any two given dipoles in the
257 * systems behaves. Sort of pair correlation but distance is replaced by
258 * the orientation distance, i.e. an angle.
259 * Note given element order is unimportant (i.e. g(Si, O) === g(O, Si))
260 * Angles are given in degrees.
261 * \param *molecules vector of molecules
262 * \return Map of doubles with values the pair of the two atoms.
263 */
264DipoleCorrelationMap *DipoleCorrelation(std::vector<molecule *> &molecules)
265{
266 Info FunctionInfo(__func__);
267 DipoleCorrelationMap *outmap = new DipoleCorrelationMap;
268// double distance = 0.;
269// Box &domain = World::getInstance().getDomain();
270//
271 if (molecules.empty()) {
272 ELOG(1, "No molecule given.");
273 return outmap;
274 }
275
276 for (std::vector<molecule *>::const_iterator MolWalker = molecules.begin();
277 MolWalker != molecules.end(); ++MolWalker) {
278 LOG(2, "INFO: Current molecule is " << (*MolWalker)->getId() << ".");
279 const Vector Dipole = getDipole((*MolWalker)->begin(), (*MolWalker)->end());
280 std::vector<molecule *>::const_iterator MolOtherWalker = MolWalker;
281 for (++MolOtherWalker;
282 MolOtherWalker != molecules.end();
283 ++MolOtherWalker) {
284 LOG(2, "INFO: Current other molecule is " << (*MolOtherWalker)->getId() << ".");
285 const Vector OtherDipole = getDipole((*MolOtherWalker)->begin(), (*MolOtherWalker)->end());
286 const double angle = Dipole.Angle(OtherDipole) * (180./M_PI);
287 LOG(1, "Angle is " << angle << ".");
288 outmap->insert ( make_pair (angle, make_pair ((*MolWalker), (*MolOtherWalker)) ) );
289 }
290 }
291 return outmap;
292};
293
294/** Calculates the pair correlation between given atom sets.
295 *
296 * Note we correlate each of the \a &atomsfirst with each of the second set
297 * \a &atoms_second. However, we are aware of double counting. If an atom is
298 * in either set, the pair is counted only once.
299 *
300 * \param &atoms_first vector of atoms
301 * \param &atoms_second vector of atoms
302 * \param max_distance maximum distance for the correlation
303 * \return Map of doubles with values the pair of the two atoms.
304 */
305PairCorrelationMap *PairCorrelation(
306 const World::AtomComposite &atoms_first,
307 const World::AtomComposite &atoms_second,
308 const double max_distance)
309{
310 Info FunctionInfo(__func__);
311 PairCorrelationMap *outmap = new PairCorrelationMap;
312 //double distance = 0.;
313 Box &domain = World::getInstance().getDomain();
314
315 if (atoms_first.empty() || atoms_second.empty()) {
316 ELOG(1, "No atoms given.");
317 return outmap;
318 }
319
320 //!> typedef for an unsorted container, (output) compatible with STL algorithms
321 typedef std::vector<const TesselPoint *> LinkedVector;
322
323 // create intersection (to know when to check for double-counting)
324 LinkedVector intersected_atoms(atoms_second.size(), NULL);
325 LinkedVector::iterator intersected_atoms_end =
326 std::set_intersection(
327 atoms_first.begin(),atoms_first.end(),
328 atoms_second.begin(), atoms_second.end(),
329 intersected_atoms.begin());
330 const LinkedCell::LinkedList intersected_atoms_set(intersected_atoms.begin(), intersected_atoms.end());
331
332 // create map
333 outmap = new PairCorrelationMap;
334
335 // get linked cell view
336 LinkedCell::LinkedCell_View LC = World::getInstance().getLinkedCell(max_distance);
337
338 // convert second to _sorted_ set
339 LinkedCell::LinkedList atoms_second_set(atoms_second.begin(), atoms_second.end());
340 LOG(2, "INFO: first set has " << atoms_first.size()
341 << " and second set has " << atoms_second_set.size() << " atoms.");
342
343 // fill map
344 for (World::AtomComposite::const_iterator iter = atoms_first.begin();
345 iter != atoms_first.end();
346 ++iter) {
347 const TesselPoint * const Walker = *iter;
348 LOG(3, "INFO: Current point is " << Walker->getName() << ".");
349 // obtain all possible neighbors (that is a sorted set)
350 LinkedCell::LinkedList ListOfNeighbors = LC.getPointsInsideSphere(
351 max_distance,
352 Walker->getPosition());
353 LOG(2, "INFO: There are " << ListOfNeighbors.size() << " neighbors.");
354
355 // create intersection with second set
356 // NOTE: STL algorithms do mostly not work on sorted container because reassignment
357 // of a value may also require changing its position.
358 LinkedVector intersected_set(atoms_second.size(), NULL);
359 LinkedVector::iterator intersected_end =
360 std::set_intersection(
361 ListOfNeighbors.begin(),ListOfNeighbors.end(),
362 atoms_second_set.begin(), atoms_second_set.end(),
363 intersected_set.begin());
364 // count remaining elements
365 LOG(2, "INFO: Intersection with second set has " << int(intersected_end - intersected_set.begin()) << " elements.");
366 // we have some possible candidates, go through each
367 for (LinkedVector::const_iterator neighboriter = intersected_set.begin();
368 neighboriter != intersected_end;
369 ++neighboriter) {
370 const TesselPoint * const OtherWalker = (*neighboriter);
371 LinkedCell::LinkedList::const_iterator equaliter = intersected_atoms_set.find(OtherWalker);
372 if ((equaliter != intersected_atoms_set.end()) && (OtherWalker <= Walker)) {
373 // present in both sets, assure that we are larger
374 continue;
375 }
376 LOG(3, "INFO: Current other point is " << *OtherWalker << ".");
377 const double distance = domain.periodicDistance(OtherWalker->getPosition(),Walker->getPosition());
378 LOG(3, "INFO: Resulting distance is " << distance << ".");
379 outmap->insert (
380 std::pair<double, std::pair <const TesselPoint *, const TesselPoint*> > (
381 distance,
382 std::make_pair (Walker, OtherWalker)
383 )
384 );
385 }
386 }
387 // and return
388 return outmap;
389};
390
391/** Calculates the distance (pair) correlation between a given element and a point.
392 * \param *molecules list of molecules structure
393 * \param &elements vector of elements to correlate with point
394 * \param *point vector to the correlation point
395 * \return Map of dobules with values as pairs of atom and the vector
396 */
397CorrelationToPointMap *CorrelationToPoint(std::vector<molecule *> &molecules, const std::vector<const element *> &elements, const Vector *point )
398{
399 Info FunctionInfo(__func__);
400 CorrelationToPointMap *outmap = new CorrelationToPointMap;
401 double distance = 0.;
402 Box &domain = World::getInstance().getDomain();
403
404 if (molecules.empty()) {
405 LOG(1, "No molecule given.");
406 return outmap;
407 }
408
409 outmap = new CorrelationToPointMap;
410 for (std::vector<molecule *>::const_iterator MolWalker = molecules.begin(); MolWalker != molecules.end(); MolWalker++) {
411 LOG(2, "Current molecule is " << *MolWalker << ".");
412 for (molecule::const_iterator iter = (*MolWalker)->begin(); iter != (*MolWalker)->end(); ++iter) {
413 LOG(3, "Current atom is " << **iter << ".");
414 for (vector<const element *>::const_iterator type = elements.begin(); type != elements.end(); ++type)
415 if ((*type == NULL) || ((*iter)->getType() == *type)) {
416 distance = domain.periodicDistance((*iter)->getPosition(),*point);
417 LOG(4, "Current distance is " << distance << ".");
418 outmap->insert (
419 std::pair<double, std::pair<const atom *, const Vector*> >(
420 distance,
421 std::pair<const atom *, const Vector*> (
422 (*iter),
423 point)
424 )
425 );
426 }
427 }
428 }
429
430 return outmap;
431};
432
433/** Calculates the distance (pair) correlation between a given element, all its periodic images and a point.
434 * \param *molecules list of molecules structure
435 * \param &elements vector of elements to correlate to point
436 * \param *point vector to the correlation point
437 * \param ranges[NDIM] interval boundaries for the periodic images to scan also
438 * \return Map of dobules with values as pairs of atom and the vector
439 */
440CorrelationToPointMap *PeriodicCorrelationToPoint(std::vector<molecule *> &molecules, const std::vector<const element *> &elements, const Vector *point, const int ranges[NDIM] )
441{
442 Info FunctionInfo(__func__);
443 CorrelationToPointMap *outmap = new CorrelationToPointMap;
444 double distance = 0.;
445 int n[NDIM];
446 Vector periodicX;
447 Vector checkX;
448
449 if (molecules.empty()) {
450 LOG(1, "No molecule given.");
451 return outmap;
452 }
453
454 outmap = new CorrelationToPointMap;
455 for (std::vector<molecule *>::const_iterator MolWalker = molecules.begin(); MolWalker != molecules.end(); MolWalker++) {
456 RealSpaceMatrix FullMatrix = World::getInstance().getDomain().getM();
457 RealSpaceMatrix FullInverseMatrix = World::getInstance().getDomain().getMinv();
458 LOG(2, "Current molecule is " << *MolWalker << ".");
459 for (molecule::const_iterator iter = (*MolWalker)->begin(); iter != (*MolWalker)->end(); ++iter) {
460 LOG(3, "Current atom is " << **iter << ".");
461 for (vector<const element *>::const_iterator type = elements.begin(); type != elements.end(); ++type)
462 if ((*type == NULL) || ((*iter)->getType() == *type)) {
463 periodicX = FullInverseMatrix * ((*iter)->getPosition()); // x now in [0,1)^3
464 // go through every range in xyz and get distance
465 for (n[0]=-ranges[0]; n[0] <= ranges[0]; n[0]++)
466 for (n[1]=-ranges[1]; n[1] <= ranges[1]; n[1]++)
467 for (n[2]=-ranges[2]; n[2] <= ranges[2]; n[2]++) {
468 checkX = FullMatrix * (Vector(n[0], n[1], n[2]) + periodicX);
469 distance = checkX.distance(*point);
470 LOG(4, "Current distance is " << distance << ".");
471 outmap->insert (
472 std::pair<double,
473 std::pair<const atom *, const Vector*> >(
474 distance,
475 std::pair<const atom *, const Vector*> (
476 *iter,
477 point)
478 )
479 );
480 }
481 }
482 }
483 }
484
485 return outmap;
486};
487
488/** Calculates the distance (pair) correlation between a given element and a surface.
489 * \param *molecules list of molecules structure
490 * \param &elements vector of elements to correlate to surface
491 * \param *Surface pointer to Tesselation class surface
492 * \param *LC LinkedCell_deprecated structure to quickly find neighbouring atoms
493 * \return Map of doubles with values as pairs of atom and the BoundaryTriangleSet that's closest
494 */
495CorrelationToSurfaceMap *CorrelationToSurface(std::vector<molecule *> &molecules, const std::vector<const element *> &elements, const Tesselation * const Surface, const LinkedCell_deprecated *LC )
496{
497 Info FunctionInfo(__func__);
498 CorrelationToSurfaceMap *outmap = new CorrelationToSurfaceMap;
499 double distance = 0;
500 class BoundaryTriangleSet *triangle = NULL;
501 Vector centroid;
502
503 if ((Surface == NULL) || (LC == NULL) || (molecules.empty())) {
504 ELOG(1, "No Tesselation, no LinkedCell or no molecule given.");
505 return outmap;
506 }
507
508 outmap = new CorrelationToSurfaceMap;
509 for (std::vector<molecule *>::const_iterator MolWalker = molecules.begin(); MolWalker != molecules.end(); MolWalker++) {
510 LOG(2, "Current molecule is " << (*MolWalker)->name << ".");
511 if ((*MolWalker)->empty())
512 LOG(2, "\t is empty.");
513 for (molecule::const_iterator iter = (*MolWalker)->begin(); iter != (*MolWalker)->end(); ++iter) {
514 LOG(3, "\tCurrent atom is " << *(*iter) << ".");
515 for (vector<const element *>::const_iterator type = elements.begin(); type != elements.end(); ++type)
516 if ((*type == NULL) || ((*iter)->getType() == *type)) {
517 TriangleIntersectionList Intersections((*iter)->getPosition(),Surface,LC);
518 distance = Intersections.GetSmallestDistance();
519 triangle = Intersections.GetClosestTriangle();
520 outmap->insert (
521 std::pair<double,
522 std::pair<const atom *, BoundaryTriangleSet*> >(
523 distance,
524 std::pair<const atom *, BoundaryTriangleSet*> (
525 (*iter),
526 triangle)
527 )
528 );
529 }
530 }
531 }
532
533 return outmap;
534};
535
536/** Calculates the distance (pair) correlation between a given element, all its periodic images and and a surface.
537 * Note that we also put all periodic images found in the cells given by [ -ranges[i], ranges[i] ] and i=0,...,NDIM-1.
538 * I.e. We multiply the atom::node with the inverse of the domain matrix, i.e. transform it to \f$[0,0^3\f$, then add per
539 * axis an integer from [ -ranges[i], ranges[i] ] onto it and multiply with the domain matrix to bring it back into
540 * the real space. Then, we Tesselation::FindClosestTriangleToPoint() and DistanceToTrianglePlane().
541 * \param *molecules list of molecules structure
542 * \param &elements vector of elements to correlate to surface
543 * \param *Surface pointer to Tesselation class surface
544 * \param *LC LinkedCell_deprecated structure to quickly find neighbouring atoms
545 * \param ranges[NDIM] interval boundaries for the periodic images to scan also
546 * \return Map of doubles with values as pairs of atom and the BoundaryTriangleSet that's closest
547 */
548CorrelationToSurfaceMap *PeriodicCorrelationToSurface(std::vector<molecule *> &molecules, const std::vector<const element *> &elements, const Tesselation * const Surface, const LinkedCell_deprecated *LC, const int ranges[NDIM] )
549{
550 Info FunctionInfo(__func__);
551 CorrelationToSurfaceMap *outmap = new CorrelationToSurfaceMap;
552 double distance = 0;
553 class BoundaryTriangleSet *triangle = NULL;
554 Vector centroid;
555 int n[NDIM];
556 Vector periodicX;
557 Vector checkX;
558
559 if ((Surface == NULL) || (LC == NULL) || (molecules.empty())) {
560 LOG(1, "No Tesselation, no LinkedCell or no molecule given.");
561 return outmap;
562 }
563
564 outmap = new CorrelationToSurfaceMap;
565 double ShortestDistance = 0.;
566 BoundaryTriangleSet *ShortestTriangle = NULL;
567 for (std::vector<molecule *>::const_iterator MolWalker = molecules.begin(); MolWalker != molecules.end(); MolWalker++) {
568 RealSpaceMatrix FullMatrix = World::getInstance().getDomain().getM();
569 RealSpaceMatrix FullInverseMatrix = World::getInstance().getDomain().getMinv();
570 LOG(2, "Current molecule is " << *MolWalker << ".");
571 for (molecule::const_iterator iter = (*MolWalker)->begin(); iter != (*MolWalker)->end(); ++iter) {
572 LOG(3, "Current atom is " << **iter << ".");
573 for (vector<const element *>::const_iterator type = elements.begin(); type != elements.end(); ++type)
574 if ((*type == NULL) || ((*iter)->getType() == *type)) {
575 periodicX = FullInverseMatrix * ((*iter)->getPosition()); // x now in [0,1)^3
576 // go through every range in xyz and get distance
577 ShortestDistance = -1.;
578 for (n[0]=-ranges[0]; n[0] <= ranges[0]; n[0]++)
579 for (n[1]=-ranges[1]; n[1] <= ranges[1]; n[1]++)
580 for (n[2]=-ranges[2]; n[2] <= ranges[2]; n[2]++) {
581 checkX = FullMatrix * (Vector(n[0], n[1], n[2]) + periodicX);
582 TriangleIntersectionList Intersections(checkX,Surface,LC);
583 distance = Intersections.GetSmallestDistance();
584 triangle = Intersections.GetClosestTriangle();
585 if ((ShortestDistance == -1.) || (distance < ShortestDistance)) {
586 ShortestDistance = distance;
587 ShortestTriangle = triangle;
588 }
589 }
590 // insert
591 outmap->insert (
592 std::pair<double,
593 std::pair<const atom *, BoundaryTriangleSet*> >(
594 ShortestDistance,
595 std::pair<const atom *, BoundaryTriangleSet*> (
596 *iter,
597 ShortestTriangle)
598 )
599 );
600 //LOG(1, "INFO: Inserting " << Walker << " with distance " << ShortestDistance << " to " << *ShortestTriangle << ".");
601 }
602 }
603 }
604
605 return outmap;
606};
607
608/** Returns the index of the bin for a given value.
609 * \param value value whose bin to look for
610 * \param BinWidth width of bin
611 * \param BinStart first bin
612 */
613int GetBin ( const double value, const double BinWidth, const double BinStart )
614{
615 //Info FunctionInfo(__func__);
616 int bin =(int) (floor((value - BinStart)/BinWidth));
617 return (bin);
618};
619
620
621/** Adds header part that is unique to BinPairMap.
622 *
623 * @param file stream to print to
624 */
625void OutputCorrelation_Header( ofstream * const file )
626{
627 *file << "\tCount";
628};
629
630/** Prints values stored in BinPairMap iterator.
631 *
632 * @param file stream to print to
633 * @param runner iterator pointing at values to print
634 */
635void OutputCorrelation_Value( ofstream * const file, BinPairMap::const_iterator &runner )
636{
637 *file << runner->second;
638};
639
640
641/** Adds header part that is unique to DipoleAngularCorrelationMap.
642 *
643 * @param file stream to print to
644 */
645void OutputDipoleAngularCorrelation_Header( ofstream * const file )
646{
647 *file << "\tFirstAtomOfMolecule";
648};
649
650/** Prints values stored in DipoleCorrelationMap iterator.
651 *
652 * @param file stream to print to
653 * @param runner iterator pointing at values to print
654 */
655void OutputDipoleAngularCorrelation_Value( ofstream * const file, DipoleAngularCorrelationMap::const_iterator &runner )
656{
657 *file << *(runner->second);
658};
659
660
661/** Adds header part that is unique to DipoleAngularCorrelationMap.
662 *
663 * @param file stream to print to
664 */
665void OutputDipoleCorrelation_Header( ofstream * const file )
666{
667 *file << "\tMolecule";
668};
669
670/** Prints values stored in DipoleCorrelationMap iterator.
671 *
672 * @param file stream to print to
673 * @param runner iterator pointing at values to print
674 */
675void OutputDipoleCorrelation_Value( ofstream * const file, DipoleCorrelationMap::const_iterator &runner )
676{
677 *file << runner->second.first->getId() << "\t" << runner->second.second->getId();
678};
679
680
681/** Adds header part that is unique to PairCorrelationMap.
682 *
683 * @param file stream to print to
684 */
685void OutputPairCorrelation_Header( ofstream * const file )
686{
687 *file << "\tAtom1\tAtom2";
688};
689
690/** Prints values stored in PairCorrelationMap iterator.
691 *
692 * @param file stream to print to
693 * @param runner iterator pointing at values to print
694 */
695void OutputPairCorrelation_Value( ofstream * const file, PairCorrelationMap::const_iterator &runner )
696{
697 *file << *(runner->second.first) << "\t" << *(runner->second.second);
698};
699
700
701/** Adds header part that is unique to CorrelationToPointMap.
702 *
703 * @param file stream to print to
704 */
705void OutputCorrelationToPoint_Header( ofstream * const file )
706{
707 *file << "\tAtom::x[i]-point.x[i]";
708};
709
710/** Prints values stored in CorrelationToPointMap iterator.
711 *
712 * @param file stream to print to
713 * @param runner iterator pointing at values to print
714 */
715void OutputCorrelationToPoint_Value( ofstream * const file, CorrelationToPointMap::const_iterator &runner )
716{
717 for (int i=0;i<NDIM;i++)
718 *file << "\t" << setprecision(8) << (runner->second.first->at(i) - runner->second.second->at(i));
719};
720
721
722/** Adds header part that is unique to CorrelationToSurfaceMap.
723 *
724 * @param file stream to print to
725 */
726void OutputCorrelationToSurface_Header( ofstream * const file )
727{
728 *file << "\tTriangle";
729};
730
731/** Prints values stored in CorrelationToSurfaceMap iterator.
732 *
733 * @param file stream to print to
734 * @param runner iterator pointing at values to print
735 */
736void OutputCorrelationToSurface_Value( ofstream * const file, CorrelationToSurfaceMap::const_iterator &runner )
737{
738 *file << *(runner->second.first) << "\t" << *(runner->second.second);
739};
Note: See TracBrowser for help on using the repository browser.