ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/sequentialProps/ContactAngle2.cpp
(Generate patch)

Comparing trunk/src/applications/sequentialProps/ContactAngle2.cpp (file contents):
Revision 2035 by gezelter, Tue Nov 4 15:31:51 2014 UTC vs.
Revision 2081 by gezelter, Tue Mar 17 18:22:18 2015 UTC

# Line 48 | Line 48
48   #include "primitives/Molecule.hpp"
49   #include "utils/NumericConstant.hpp"
50   #include "utils/PhysicalConstants.hpp"
51 < #include "math/Polynomial.hpp"
51 > #include "math/Eigenvalue.hpp"
52  
53   namespace OpenMD {
54 <
54 >  
55    ContactAngle2::ContactAngle2(SimInfo* info, const std::string& filename,
56                                 const std::string& sele, RealType solidZ,
57 <                               RealType threshDens, int nrbins, int nzbins)
58 <    : SequentialAnalyzer(info, filename), selectionScript_(sele),
59 <      evaluator_(info), seleMan_(info), solidZ_(solidZ),
60 <      threshDens_(threshDens), nRBins_(nrbins), nZBins_(nzbins) {
57 >                               RealType centroidX, RealType centroidY,
58 >                               RealType threshDens, RealType bufferLength,
59 >                               int nrbins, int nzbins)
60 >    : SequentialAnalyzer(info, filename), solidZ_(solidZ),
61 >      centroidX_(centroidX), centroidY_(centroidY),
62 >      threshDens_(threshDens), bufferLength_(bufferLength), nRBins_(nrbins),
63 >      nZBins_(nzbins), selectionScript_(sele), seleMan_(info),
64 >      evaluator_(info) {
65      
66      setOutputName(getPrefix(filename) + ".ca2");
67      
# Line 77 | Line 81 | namespace OpenMD {
81      Mat3x3d hmat = info_->getSnapshotManager()->getCurrentSnapshot()->getHmat();
82      RealType len = std::min(hmat(0, 0), hmat(1, 1));
83      RealType zLen = hmat(2,2);
84 +
85      RealType dr = len / (RealType) nRBins_;
86      RealType dz = zLen / (RealType) nZBins_;
87  
88      std::vector<std::vector<RealType> > histo;
89      histo.resize(nRBins_);
85    for (int i = 0 ; i < nRBins_; ++i) {
86      histo[i].resize(nZBins_);
87    }
90      for (unsigned int i = 0; i < histo.size(); ++i){
91 +      histo[i].resize(nZBins_);
92        std::fill(histo[i].begin(), histo[i].end(), 0.0);
93      }      
94          
# Line 94 | Line 97 | namespace OpenMD {
97      }
98      
99  
100 <    RealType mtot = 0.0;
101 <    Vector3d com(V3Zero);
102 <    RealType mass;
100 >    // RealType mtot = 0.0;
101 >    // Vector3d com(V3Zero);
102 >    // RealType mass;
103      
104 <    for (sd = seleMan_.beginSelected(i); sd != NULL;
105 <         sd = seleMan_.nextSelected(i)) {      
106 <      mass = sd->getMass();
107 <      mtot += mass;
108 <      com += sd->getPos() * mass;
109 <    }
104 >    // for (sd = seleMan_.beginSelected(i); sd != NULL;
105 >    //      sd = seleMan_.nextSelected(i)) {      
106 >    //   mass = sd->getMass();
107 >    //   mtot += mass;
108 >    //   com += sd->getPos() * mass;
109 >    // }
110  
111 <    com /= mtot;
111 >    // com /= mtot;
112  
113 +    Vector3d com(centroidX_, centroidY_, solidZ_);
114 +
115      // now that we have the centroid, we can make cylindrical density maps
116      Vector3d pos;
117      RealType r;
# Line 115 | Line 120 | namespace OpenMD {
120      for (sd = seleMan_.beginSelected(i); sd != NULL;
121           sd = seleMan_.nextSelected(i)) {      
122        pos = sd->getPos() - com;
123 <      
123 >
124 >      // r goes from zero upwards
125        r = sqrt(pow(pos.x(), 2) + pow(pos.y(), 2));
126 <      z = pos.z() - solidZ_;
127 <      
126 >      // z is possibly symmetric around 0
127 >      z = pos.z();
128 >          
129        int whichRBin = int(r / dr);
130 <      int whichZBin = int(z/ dz);
130 >      int whichZBin = int( (zLen/2.0 + z) / dz);
131        
132 <      if ((r <= len) && (z <= zLen))
132 >      if ((whichRBin < int(nRBins_)) && (whichZBin >= 0) && (whichZBin < int(nZBins_))) {
133          histo[whichRBin][whichZBin] += sd->getMass();
134 +      }
135        
136      }
137      
# Line 133 | Line 141 | namespace OpenMD {
141        RealType rU = rL + dr;
142        RealType volSlice = NumericConstant::PI * dz * (( rU*rU ) - ( rL*rL ));
143  
144 <      for (unsigned int j = 0; j < histo[i].size(); ++j){
144 >      for (unsigned int j = 0; j < histo[i].size(); ++j) {
145          histo[i][j] *= PhysicalConstants::densityConvert / volSlice;
146        }
147      }
148  
149 <    for (unsigned int i = 0; i < histo.size(); ++i) {
150 <      RealType ther = dr * (i + 0.5);
151 <      for(unsigned int j = 0; j < histo[i].size(); ++j) {
152 <        if (histo[i][j] <= threshDens_) {
153 <          RealType thez = dz * (j + 0.5);
154 <          cerr << ther << "\t" << thez << "\n";
155 <          break;
149 >    std::vector<Vector<RealType, 2> > points;
150 >    points.clear();
151 >    
152 >    for (unsigned int j = 0; j < nZBins_;  ++j) {
153 >
154 >      // The z coordinates were measured relative to the selection
155 >      // center of mass.  However, we're interested in the elevation
156 >      // above the solid surface.  Also, the binning was done around
157 >      // zero with enough bins to cover the zLength of the box:
158 >      
159 >      RealType thez =  com.z() - solidZ_  - zLen/2.0 + dz * (j + 0.5);
160 >      bool aboveThresh = false;
161 >      bool foundThresh = false;
162 >      int rloc = 0;
163 >      
164 >      for (std::size_t i = 0; i < nRBins_;  ++i) {
165 >
166 >        if (histo[i][j] >= threshDens_) aboveThresh = true;
167 >
168 >        if (aboveThresh && (histo[i][j] <= threshDens_)) {
169 >          rloc = i;
170 >          foundThresh = true;
171 >          aboveThresh = false;
172          }
173 +
174        }
175 +      if (foundThresh) {
176 +        Vector<RealType,2> point;
177 +        point[0] = dr*(rloc+0.5);
178 +        point[1] = thez;
179 +
180 +        if (thez > bufferLength_) {
181 +          points.push_back( point );
182 +        }
183 +      }      
184      }
185  
186 <    // values_.push_back( acos(maxct)*(180.0/M_PI) );
186 >    int numPoints = points.size();
187 >
188 >    // Compute the average of the data points.
189 >    Vector<RealType, 2> average = points[0];
190 >    int i0;
191 >    for (i0 = 1; i0 < numPoints; ++i0) {
192 >      average += points[i0];
193 >    }
194 >    RealType invNumPoints = ((RealType)1)/(RealType)numPoints;
195 >    average *= invNumPoints;
196      
197 +    DynamicRectMatrix<RealType> mat(4, 4);
198 +    int row, col;
199 +    for (row = 0; row < 4; ++row) {
200 +      for (col = 0; col < 4; ++col){
201 +        mat(row,col) = 0.0;        
202 +      }
203 +    }
204 +    for (int i = 0; i < numPoints; ++i) {
205 +      RealType x = points[i][0];
206 +      RealType y = points[i][1];
207 +      RealType x2 = x*x;
208 +      RealType y2 = y*y;
209 +      RealType xy = x*y;
210 +      RealType r2 = x2+y2;
211 +      RealType xr2 = x*r2;
212 +      RealType yr2 = y*r2;
213 +      RealType r4 = r2*r2;
214 +
215 +      mat(0,1) += x;
216 +      mat(0,2) += y;
217 +      mat(0,3) += r2;
218 +      mat(1,1) += x2;
219 +      mat(1,2) += xy;
220 +      mat(1,3) += xr2;
221 +      mat(2,2) += y2;
222 +      mat(2,3) += yr2;
223 +      mat(3,3) += r4;
224 +    }
225 +    mat(0,0) = (RealType)numPoints;
226 +
227 +    for (row = 0; row < 4; ++row) {
228 +      for (col = 0; col < row; ++col) {
229 +        mat(row,col) = mat(col,row);
230 +      }
231 +    }
232 +
233 +    for (row = 0; row < 4; ++row) {
234 +      for (col = 0; col < 4; ++col) {
235 +        mat(row,col) *= invNumPoints;
236 +      }
237 +    }
238 +
239 +    JAMA::Eigenvalue<RealType> eigensystem(mat);
240 +    DynamicRectMatrix<RealType> evects(4, 4);
241 +    DynamicVector<RealType> evals(4);
242 +
243 +    eigensystem.getRealEigenvalues(evals);
244 +    eigensystem.getV(evects);
245 +
246 +    DynamicVector<RealType> evector = evects.getColumn(0);
247 +    RealType inv = ((RealType)1)/evector[3];  // beware zero divide
248 +    RealType coeff[3];
249 +    for (row = 0; row < 3; ++row) {
250 +      coeff[row] = inv*evector[row];
251 +    }
252 +
253 +    Vector<RealType, 2> center;
254 +    
255 +    center[0] = -((RealType)0.5)*coeff[1];
256 +    center[1] = -((RealType)0.5)*coeff[2];
257 +    RealType radius = sqrt(fabs(center[0]*center[0] + center[1]*center[1]
258 +                                - coeff[0]));
259 +
260 +    int i1;
261 +    for (i1 = 0; i1 < 100; ++i1) {
262 +      // Update the iterates.
263 +      Vector<RealType, 2> current = center;
264 +      
265 +      // Compute average L, dL/da, dL/db.
266 +      RealType lenAverage = (RealType)0;
267 +      Vector<RealType, 2> derLenAverage = Vector<RealType, 2>(0.0);
268 +      for (i0 = 0; i0 < numPoints; ++i0) {
269 +        Vector<RealType, 2> diff = points[i0] - center;
270 +        RealType length = diff.length();
271 +        if (length > 1e-6) {
272 +          lenAverage += length;
273 +          RealType invLength = ((RealType)1)/length;
274 +          derLenAverage -= invLength*diff;
275 +        }
276 +      }
277 +      lenAverage *= invNumPoints;
278 +      derLenAverage *= invNumPoints;
279 +
280 +      center = average + lenAverage*derLenAverage;
281 +      radius = lenAverage;
282 +
283 +      Vector<RealType, 2> diff = center - current;
284 +      if (fabs(diff[0]) <= 1e-6 &&  fabs(diff[1]) <= 1e-6) {
285 +        break;
286 +      }
287 +    }
288 +
289 +    RealType zCen = center[1];
290 +    RealType rDrop = radius;
291 +    RealType ca;
292 +
293 +    if (fabs(zCen) > rDrop) {
294 +      ca = 180.0;
295 +    } else {
296 +      ca = 90.0 + asin(zCen/rDrop)*(180.0/M_PI);
297 +    }
298 +
299 +    values_.push_back( ca );
300 +    
301    }  
302   }
303  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines