source: molecuilder/src/analysis_correlation.cpp@ dd3a80

Last change on this file since dd3a80 was dd3a80, checked in by Frederik Heber <heber@…>, 16 years ago

BUGFIX: rounding imprecision let values appear twice in BinMap.

  • we fix this by always converting bin to integer and then back to double when putting into map in BinData()
  • GetBin returns integer

Signed-off-by: Frederik Heber <heber@…>

  • Property mode set to 100644
File size: 18.4 KB
RevLine 
[57cfb7]1/*
2 * analysis.cpp
3 *
4 * Created on: Oct 13, 2009
5 * Author: heber
6 */
7
8#include <iostream>
9
10#include "analysis_correlation.hpp"
11#include "element.hpp"
[f78203]12#include "info.hpp"
[543ce4]13#include "log.hpp"
[57cfb7]14#include "molecule.hpp"
15#include "tesselation.hpp"
16#include "tesselationhelpers.hpp"
17#include "vector.hpp"
[e1900f]18#include "verbose.hpp"
[57cfb7]19
20
21/** Calculates the pair correlation between given elements.
22 * Note given element order is unimportant (i.e. g(Si, O) === g(O, Si))
23 * \param *out output stream for debugging
[e1900f]24 * \param *molecules list of molecules structure
[57cfb7]25 * \param *type1 first element or NULL (if any element)
26 * \param *type2 second element or NULL (if any element)
27 * \return Map of doubles with values the pair of the two atoms.
28 */
[543ce4]29PairCorrelationMap *PairCorrelation(MoleculeListClass * const &molecules, const element * const type1, const element * const type2 )
[57cfb7]30{
[f78203]31 Info FunctionInfo(__func__);
[57cfb7]32 PairCorrelationMap *outmap = NULL;
33 double distance = 0.;
34
[e1900f]35 if (molecules->ListOfMolecules.empty()) {
[543ce4]36 eLog() << Verbose(1) <<"No molecule given." << endl;
[57cfb7]37 return outmap;
38 }
39 outmap = new PairCorrelationMap;
[e1900f]40 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin(); MolWalker != molecules->ListOfMolecules.end(); MolWalker++)
41 if ((*MolWalker)->ActiveFlag) {
[543ce4]42 eLog() << Verbose(2) << "Current molecule is " << *MolWalker << "." << endl;
[e1900f]43 atom *Walker = (*MolWalker)->start;
44 while (Walker->next != (*MolWalker)->end) {
45 Walker = Walker->next;
[543ce4]46 Log() << Verbose(3) << "Current atom is " << *Walker << "." << endl;
[e1900f]47 if ((type1 == NULL) || (Walker->type == type1)) {
48 for (MoleculeList::const_iterator MolOtherWalker = MolWalker; MolOtherWalker != molecules->ListOfMolecules.end(); MolOtherWalker++)
49 if ((*MolOtherWalker)->ActiveFlag) {
[543ce4]50 Log() << Verbose(2) << "Current other molecule is " << *MolOtherWalker << "." << endl;
[e1900f]51 atom *OtherWalker = (*MolOtherWalker)->start;
52 while (OtherWalker->next != (*MolOtherWalker)->end) { // only go up to Walker
53 OtherWalker = OtherWalker->next;
[543ce4]54 Log() << Verbose(3) << "Current otheratom is " << *OtherWalker << "." << endl;
[e1900f]55 if (Walker->nr < OtherWalker->nr)
56 if ((type2 == NULL) || (OtherWalker->type == type2)) {
[20895b]57 distance = Walker->node->PeriodicDistance(OtherWalker->node, (*MolWalker)->cell_size);
[543ce4]58 //Log() << Verbose(1) <<"Inserting " << *Walker << " and " << *OtherWalker << endl;
[e1900f]59 outmap->insert ( pair<double, pair <atom *, atom*> > (distance, pair<atom *, atom*> (Walker, OtherWalker) ) );
60 }
61 }
[57cfb7]62 }
[e1900f]63 }
[57cfb7]64 }
65 }
66
67 return outmap;
68};
69
[5f1d021]70/** Calculates the pair correlation between given elements.
71 * Note given element order is unimportant (i.e. g(Si, O) === g(O, Si))
72 * \param *out output stream for debugging
73 * \param *molecules list of molecules structure
74 * \param *type1 first element or NULL (if any element)
75 * \param *type2 second element or NULL (if any element)
76 * \param ranges[NDIM] interval boundaries for the periodic images to scan also
77 * \return Map of doubles with values the pair of the two atoms.
78 */
[543ce4]79PairCorrelationMap *PeriodicPairCorrelation(MoleculeListClass * const &molecules, const element * const type1, const element * const type2, const int ranges[NDIM] )
[5f1d021]80{
[f78203]81 Info FunctionInfo(__func__);
[5f1d021]82 PairCorrelationMap *outmap = NULL;
83 double distance = 0.;
84 int n[NDIM];
85 Vector checkX;
86 Vector periodicX;
87 int Othern[NDIM];
88 Vector checkOtherX;
89 Vector periodicOtherX;
90
91 if (molecules->ListOfMolecules.empty()) {
[543ce4]92 eLog() << Verbose(1) <<"No molecule given." << endl;
[5f1d021]93 return outmap;
94 }
95 outmap = new PairCorrelationMap;
96 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin(); MolWalker != molecules->ListOfMolecules.end(); MolWalker++)
97 if ((*MolWalker)->ActiveFlag) {
[4ef101]98 double * FullMatrix = ReturnFullMatrixforSymmetric((*MolWalker)->cell_size);
99 double * FullInverseMatrix = InverseMatrix(FullMatrix);
[543ce4]100 eLog() << Verbose(2) << "Current molecule is " << *MolWalker << "." << endl;
[5f1d021]101 atom *Walker = (*MolWalker)->start;
102 while (Walker->next != (*MolWalker)->end) {
103 Walker = Walker->next;
[543ce4]104 Log() << Verbose(3) << "Current atom is " << *Walker << "." << endl;
[5f1d021]105 if ((type1 == NULL) || (Walker->type == type1)) {
106 periodicX.CopyVector(Walker->node);
107 periodicX.MatrixMultiplication(FullInverseMatrix); // x now in [0,1)^3
108 // go through every range in xyz and get distance
109 for (n[0]=-ranges[0]; n[0] <= ranges[0]; n[0]++)
110 for (n[1]=-ranges[1]; n[1] <= ranges[1]; n[1]++)
111 for (n[2]=-ranges[2]; n[2] <= ranges[2]; n[2]++) {
112 checkX.Init(n[0], n[1], n[2]);
113 checkX.AddVector(&periodicX);
114 checkX.MatrixMultiplication(FullMatrix);
115 for (MoleculeList::const_iterator MolOtherWalker = MolWalker; MolOtherWalker != molecules->ListOfMolecules.end(); MolOtherWalker++)
116 if ((*MolOtherWalker)->ActiveFlag) {
[543ce4]117 Log() << Verbose(2) << "Current other molecule is " << *MolOtherWalker << "." << endl;
[5f1d021]118 atom *OtherWalker = (*MolOtherWalker)->start;
119 while (OtherWalker->next != (*MolOtherWalker)->end) { // only go up to Walker
120 OtherWalker = OtherWalker->next;
[543ce4]121 Log() << Verbose(3) << "Current otheratom is " << *OtherWalker << "." << endl;
[5f1d021]122 if (Walker->nr < OtherWalker->nr)
123 if ((type2 == NULL) || (OtherWalker->type == type2)) {
124 periodicOtherX.CopyVector(OtherWalker->node);
125 periodicOtherX.MatrixMultiplication(FullInverseMatrix); // x now in [0,1)^3
126 // go through every range in xyz and get distance
127 for (Othern[0]=-ranges[0]; Othern[0] <= ranges[0]; Othern[0]++)
128 for (Othern[1]=-ranges[1]; Othern[1] <= ranges[1]; Othern[1]++)
129 for (Othern[2]=-ranges[2]; Othern[2] <= ranges[2]; Othern[2]++) {
130 checkOtherX.Init(Othern[0], Othern[1], Othern[2]);
131 checkOtherX.AddVector(&periodicOtherX);
132 checkOtherX.MatrixMultiplication(FullMatrix);
133 distance = checkX.Distance(&checkOtherX);
[543ce4]134 //Log() << Verbose(1) <<"Inserting " << *Walker << " and " << *OtherWalker << endl;
[5f1d021]135 outmap->insert ( pair<double, pair <atom *, atom*> > (distance, pair<atom *, atom*> (Walker, OtherWalker) ) );
136 }
137 }
138 }
139 }
140 }
141 }
142 }
[4ef101]143 Free(&FullMatrix);
144 Free(&FullInverseMatrix);
[5f1d021]145 }
146
147 return outmap;
148};
149
[57cfb7]150/** Calculates the distance (pair) correlation between a given element and a point.
151 * \param *out output stream for debugging
[e1900f]152 * \param *molecules list of molecules structure
[57cfb7]153 * \param *type element or NULL (if any element)
154 * \param *point vector to the correlation point
155 * \return Map of dobules with values as pairs of atom and the vector
156 */
[543ce4]157CorrelationToPointMap *CorrelationToPoint(MoleculeListClass * const &molecules, const element * const type, const Vector *point )
[57cfb7]158{
[f78203]159 Info FunctionInfo(__func__);
[57cfb7]160 CorrelationToPointMap *outmap = NULL;
161 double distance = 0.;
162
[e1900f]163 if (molecules->ListOfMolecules.empty()) {
[543ce4]164 Log() << Verbose(1) <<"No molecule given." << endl;
[57cfb7]165 return outmap;
166 }
167 outmap = new CorrelationToPointMap;
[e1900f]168 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin(); MolWalker != molecules->ListOfMolecules.end(); MolWalker++)
169 if ((*MolWalker)->ActiveFlag) {
[543ce4]170 Log() << Verbose(2) << "Current molecule is " << *MolWalker << "." << endl;
[e1900f]171 atom *Walker = (*MolWalker)->start;
172 while (Walker->next != (*MolWalker)->end) {
173 Walker = Walker->next;
[543ce4]174 Log() << Verbose(3) << "Current atom is " << *Walker << "." << endl;
[e1900f]175 if ((type == NULL) || (Walker->type == type)) {
[20895b]176 distance = Walker->node->PeriodicDistance(point, (*MolWalker)->cell_size);
[543ce4]177 Log() << Verbose(4) << "Current distance is " << distance << "." << endl;
[e1900f]178 outmap->insert ( pair<double, pair<atom *, const Vector*> >(distance, pair<atom *, const Vector*> (Walker, point) ) );
179 }
180 }
[57cfb7]181 }
182
183 return outmap;
184};
185
[5f1d021]186/** Calculates the distance (pair) correlation between a given element, all its periodic images and a point.
187 * \param *out output stream for debugging
188 * \param *molecules list of molecules structure
189 * \param *type element or NULL (if any element)
190 * \param *point vector to the correlation point
191 * \param ranges[NDIM] interval boundaries for the periodic images to scan also
192 * \return Map of dobules with values as pairs of atom and the vector
193 */
[543ce4]194CorrelationToPointMap *PeriodicCorrelationToPoint(MoleculeListClass * const &molecules, const element * const type, const Vector *point, const int ranges[NDIM] )
[5f1d021]195{
[f78203]196 Info FunctionInfo(__func__);
[5f1d021]197 CorrelationToPointMap *outmap = NULL;
198 double distance = 0.;
199 int n[NDIM];
200 Vector periodicX;
201 Vector checkX;
202
203 if (molecules->ListOfMolecules.empty()) {
[543ce4]204 Log() << Verbose(1) <<"No molecule given." << endl;
[5f1d021]205 return outmap;
206 }
207 outmap = new CorrelationToPointMap;
208 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin(); MolWalker != molecules->ListOfMolecules.end(); MolWalker++)
209 if ((*MolWalker)->ActiveFlag) {
[4ef101]210 double * FullMatrix = ReturnFullMatrixforSymmetric((*MolWalker)->cell_size);
211 double * FullInverseMatrix = InverseMatrix(FullMatrix);
[543ce4]212 Log() << Verbose(2) << "Current molecule is " << *MolWalker << "." << endl;
[5f1d021]213 atom *Walker = (*MolWalker)->start;
214 while (Walker->next != (*MolWalker)->end) {
215 Walker = Walker->next;
[543ce4]216 Log() << Verbose(3) << "Current atom is " << *Walker << "." << endl;
[5f1d021]217 if ((type == NULL) || (Walker->type == type)) {
218 periodicX.CopyVector(Walker->node);
219 periodicX.MatrixMultiplication(FullInverseMatrix); // x now in [0,1)^3
220 // go through every range in xyz and get distance
221 for (n[0]=-ranges[0]; n[0] <= ranges[0]; n[0]++)
222 for (n[1]=-ranges[1]; n[1] <= ranges[1]; n[1]++)
223 for (n[2]=-ranges[2]; n[2] <= ranges[2]; n[2]++) {
224 checkX.Init(n[0], n[1], n[2]);
225 checkX.AddVector(&periodicX);
226 checkX.MatrixMultiplication(FullMatrix);
227 distance = checkX.Distance(point);
[543ce4]228 Log() << Verbose(4) << "Current distance is " << distance << "." << endl;
[5f1d021]229 outmap->insert ( pair<double, pair<atom *, const Vector*> >(distance, pair<atom *, const Vector*> (Walker, point) ) );
230 }
231 }
232 }
[4ef101]233 Free(&FullMatrix);
234 Free(&FullInverseMatrix);
[5f1d021]235 }
236
237 return outmap;
238};
239
[57cfb7]240/** Calculates the distance (pair) correlation between a given element and a surface.
241 * \param *out output stream for debugging
[e1900f]242 * \param *molecules list of molecules structure
[57cfb7]243 * \param *type element or NULL (if any element)
244 * \param *Surface pointer to Tesselation class surface
245 * \param *LC LinkedCell structure to quickly find neighbouring atoms
246 * \return Map of doubles with values as pairs of atom and the BoundaryTriangleSet that's closest
247 */
[543ce4]248CorrelationToSurfaceMap *CorrelationToSurface(MoleculeListClass * const &molecules, const element * const type, const Tesselation * const Surface, const LinkedCell *LC )
[57cfb7]249{
[f78203]250 Info FunctionInfo(__func__);
[57cfb7]251 CorrelationToSurfaceMap *outmap = NULL;
[20895b]252 double distance = 0;
[57cfb7]253 class BoundaryTriangleSet *triangle = NULL;
254 Vector centroid;
[5f1d021]255
256 if ((Surface == NULL) || (LC == NULL) || (molecules->ListOfMolecules.empty())) {
[543ce4]257 Log() << Verbose(1) <<"No Tesselation, no LinkedCell or no molecule given." << endl;
[5f1d021]258 return outmap;
259 }
260 outmap = new CorrelationToSurfaceMap;
261 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin(); MolWalker != molecules->ListOfMolecules.end(); MolWalker++)
262 if ((*MolWalker)->ActiveFlag) {
[543ce4]263 Log() << Verbose(2) << "Current molecule is " << *MolWalker << "." << endl;
[5f1d021]264 atom *Walker = (*MolWalker)->start;
265 while (Walker->next != (*MolWalker)->end) {
266 Walker = Walker->next;
[543ce4]267 Log() << Verbose(3) << "Current atom is " << *Walker << "." << endl;
[5f1d021]268 if ((type == NULL) || (Walker->type == type)) {
[543ce4]269 triangle = Surface->FindClosestTriangleToPoint(Walker->node, LC );
[5f1d021]270 if (triangle != NULL) {
[543ce4]271 distance = DistanceToTrianglePlane(Walker->node, triangle);
[5f1d021]272 outmap->insert ( pair<double, pair<atom *, BoundaryTriangleSet*> >(distance, pair<atom *, BoundaryTriangleSet*> (Walker, triangle) ) );
273 }
274 }
275 }
276 }
277
278 return outmap;
279};
280
281/** Calculates the distance (pair) correlation between a given element, all its periodic images and and a surface.
282 * Note that we also put all periodic images found in the cells given by [ -ranges[i], ranges[i] ] and i=0,...,NDIM-1.
283 * 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
284 * axis an integer from [ -ranges[i], ranges[i] ] onto it and multiply with the domain matrix to bring it back into
285 * the real space. Then, we Tesselation::FindClosestTriangleToPoint() and DistanceToTrianglePlane().
286 * \param *out output stream for debugging
287 * \param *molecules list of molecules structure
288 * \param *type element or NULL (if any element)
289 * \param *Surface pointer to Tesselation class surface
290 * \param *LC LinkedCell structure to quickly find neighbouring atoms
291 * \param ranges[NDIM] interval boundaries for the periodic images to scan also
292 * \return Map of doubles with values as pairs of atom and the BoundaryTriangleSet that's closest
293 */
[543ce4]294CorrelationToSurfaceMap *PeriodicCorrelationToSurface(MoleculeListClass * const &molecules, const element * const type, const Tesselation * const Surface, const LinkedCell *LC, const int ranges[NDIM] )
[5f1d021]295{
[f78203]296 Info FunctionInfo(__func__);
[5f1d021]297 CorrelationToSurfaceMap *outmap = NULL;
298 double distance = 0;
299 class BoundaryTriangleSet *triangle = NULL;
300 Vector centroid;
[20895b]301 int n[NDIM];
302 Vector periodicX;
303 Vector checkX;
[57cfb7]304
[e1900f]305 if ((Surface == NULL) || (LC == NULL) || (molecules->ListOfMolecules.empty())) {
[543ce4]306 Log() << Verbose(1) <<"No Tesselation, no LinkedCell or no molecule given." << endl;
[57cfb7]307 return outmap;
308 }
309 outmap = new CorrelationToSurfaceMap;
[e1900f]310 for (MoleculeList::const_iterator MolWalker = molecules->ListOfMolecules.begin(); MolWalker != molecules->ListOfMolecules.end(); MolWalker++)
311 if ((*MolWalker)->ActiveFlag) {
[4ef101]312 double * FullMatrix = ReturnFullMatrixforSymmetric((*MolWalker)->cell_size);
313 double * FullInverseMatrix = InverseMatrix(FullMatrix);
[543ce4]314 Log() << Verbose(2) << "Current molecule is " << *MolWalker << "." << endl;
[e1900f]315 atom *Walker = (*MolWalker)->start;
316 while (Walker->next != (*MolWalker)->end) {
317 Walker = Walker->next;
[543ce4]318 Log() << Verbose(3) << "Current atom is " << *Walker << "." << endl;
[e1900f]319 if ((type == NULL) || (Walker->type == type)) {
[20895b]320 periodicX.CopyVector(Walker->node);
321 periodicX.MatrixMultiplication(FullInverseMatrix); // x now in [0,1)^3
322 // go through every range in xyz and get distance
323 for (n[0]=-ranges[0]; n[0] <= ranges[0]; n[0]++)
324 for (n[1]=-ranges[1]; n[1] <= ranges[1]; n[1]++)
325 for (n[2]=-ranges[2]; n[2] <= ranges[2]; n[2]++) {
326 checkX.Init(n[0], n[1], n[2]);
327 checkX.AddVector(&periodicX);
328 checkX.MatrixMultiplication(FullMatrix);
[543ce4]329 triangle = Surface->FindClosestTriangleToPoint(&checkX, LC );
[20895b]330 if (triangle != NULL) {
[543ce4]331 distance = DistanceToTrianglePlane(&checkX, triangle);
[20895b]332 outmap->insert ( pair<double, pair<atom *, BoundaryTriangleSet*> >(distance, pair<atom *, BoundaryTriangleSet*> (Walker, triangle) ) );
333 }
[e1900f]334 }
335 }
[57cfb7]336 }
[4ef101]337 Free(&FullMatrix);
338 Free(&FullInverseMatrix);
[57cfb7]339 }
340
341 return outmap;
342};
343
[dd3a80]344/** Returns the index of the bin for a given value.
[57cfb7]345 * \param value value whose bin to look for
346 * \param BinWidth width of bin
347 * \param BinStart first bin
348 */
[dd3a80]349int GetBin ( const double value, const double BinWidth, const double BinStart )
[57cfb7]350{
[f78203]351 Info FunctionInfo(__func__);
[dd3a80]352 int bin =(int) (floor((value - BinStart)/BinWidth));
353 return (bin);
[57cfb7]354};
355
356
357/** Prints correlation (double, int) pairs to file.
358 * \param *file file to write to
359 * \param *map map to write
360 */
[e1900f]361void OutputCorrelation( ofstream * const file, const BinPairMap * const map )
[57cfb7]362{
[f78203]363 Info FunctionInfo(__func__);
[57cfb7]364 *file << "# BinStart\tCount" << endl;
[a9b2a0a]365 for (BinPairMap::const_iterator runner = map->begin(); runner != map->end(); ++runner) {
[57cfb7]366 *file << runner->first << "\t" << runner->second << endl;
367 }
368};
[e72287]369
370/** Prints correlation (double, (atom*,atom*) ) pairs to file.
371 * \param *file file to write to
372 * \param *map map to write
373 */
[e1900f]374void OutputPairCorrelation( ofstream * const file, const PairCorrelationMap * const map )
[e72287]375{
[f78203]376 Info FunctionInfo(__func__);
[e72287]377 *file << "# BinStart\tAtom1\tAtom2" << endl;
[a9b2a0a]378 for (PairCorrelationMap::const_iterator runner = map->begin(); runner != map->end(); ++runner) {
[e72287]379 *file << runner->first << "\t" << *(runner->second.first) << "\t" << *(runner->second.second) << endl;
380 }
381};
382
383/** Prints correlation (double, int) pairs to file.
384 * \param *file file to write to
385 * \param *map map to write
386 */
[e1900f]387void OutputCorrelationToPoint( ofstream * const file, const CorrelationToPointMap * const map )
[e72287]388{
[f78203]389 Info FunctionInfo(__func__);
[e72287]390 *file << "# BinStart\tAtom::x[i]-point.x[i]" << endl;
[a9b2a0a]391 for (CorrelationToPointMap::const_iterator runner = map->begin(); runner != map->end(); ++runner) {
[e72287]392 *file << runner->first;
393 for (int i=0;i<NDIM;i++)
394 *file << "\t" << (runner->second.first->node->x[i] - runner->second.second->x[i]);
395 *file << endl;
396 }
397};
398
399/** Prints correlation (double, int) pairs to file.
400 * \param *file file to write to
401 * \param *map map to write
402 */
[e1900f]403void OutputCorrelationToSurface( ofstream * const file, const CorrelationToSurfaceMap * const map )
[e72287]404{
[f78203]405 Info FunctionInfo(__func__);
[e72287]406 *file << "# BinStart\tTriangle" << endl;
[a9b2a0a]407 for (CorrelationToSurfaceMap::const_iterator runner = map->begin(); runner != map->end(); ++runner) {
[e72287]408 *file << runner->first << "\t" << *(runner->second.second) << endl;
409 }
410};
411
Note: See TracBrowser for help on using the repository browser.