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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines