source: src/Analysis/analysis_correlation.cpp@ 7672284

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 7672284 was 7daf73, checked in by Frederik Heber <heber@…>, 9 years ago

LinkedCell's LinkedList is now a vector and no longer a set.

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