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 |
|
|
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 |
|
|
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)) |
128 |
> |
if ((whichRBin < int(nRBins_)) && (whichZBin >= 0) && (whichZBin < int(nZBins_))) { |
129 |
|
histo[whichRBin][whichZBin] += sd->getMass(); |
130 |
+ |
} |
131 |
|
|
132 |
|
} |
133 |
|
|
137 |
|
RealType rU = rL + dr; |
138 |
|
RealType volSlice = NumericConstant::PI * dz * (( rU*rU ) - ( rL*rL )); |
139 |
|
|
140 |
< |
for (unsigned int j = 0; j < histo[i].size(); ++j){ |
140 |
> |
for (unsigned int j = 0; j < histo[i].size(); ++j) { |
141 |
|
histo[i][j] *= PhysicalConstants::densityConvert / volSlice; |
142 |
|
} |
143 |
|
} |
144 |
|
|
145 |
+ |
std::vector<Vector<RealType, 2> > points; |
146 |
+ |
points.clear(); |
147 |
+ |
|
148 |
|
for (unsigned int j = 0; j < nZBins_; ++j) { |
149 |
< |
RealType thez = dz * (j + 0.5); |
149 |
> |
|
150 |
> |
// The z coordinates were measured relative to the selection |
151 |
> |
// center of mass. However, we're interested in the elevation |
152 |
> |
// above the solid surface. Also, the binning was done around |
153 |
> |
// zero with enough bins to cover the zLength of the box: |
154 |
> |
|
155 |
> |
RealType thez = com.z() - solidZ_ - zLen/2.0 + dz * (j + 0.5); |
156 |
|
bool aboveThresh = false; |
157 |
< |
for (unsigned int i = 0; i < nRBins_; ++i) { |
158 |
< |
RealType ther = dr * (i + 0.5); |
157 |
> |
bool foundThresh = false; |
158 |
> |
int rloc = 0; |
159 |
> |
|
160 |
> |
for (std::size_t i = 0; i < nRBins_; ++i) { |
161 |
> |
|
162 |
|
if (histo[i][j] >= threshDens_) aboveThresh = true; |
163 |
|
|
164 |
|
if (aboveThresh && (histo[i][j] <= threshDens_)) { |
165 |
< |
cerr << thez << "\t" << ther << "\n"; |
166 |
< |
break; |
165 |
> |
rloc = i; |
166 |
> |
foundThresh = true; |
167 |
> |
aboveThresh = false; |
168 |
|
} |
169 |
+ |
|
170 |
|
} |
171 |
+ |
if (foundThresh) { |
172 |
+ |
Vector<RealType,2> point; |
173 |
+ |
point[0] = dr*(rloc+0.5); |
174 |
+ |
point[1] = thez; |
175 |
+ |
|
176 |
+ |
if (thez > bufferLength_) { |
177 |
+ |
points.push_back( point ); |
178 |
+ |
} |
179 |
+ |
} |
180 |
|
} |
181 |
+ |
|
182 |
+ |
int numPoints = points.size(); |
183 |
+ |
|
184 |
+ |
// Compute the average of the data points. |
185 |
+ |
Vector<RealType, 2> average = points[0]; |
186 |
+ |
int i0; |
187 |
+ |
for (i0 = 1; i0 < numPoints; ++i0) { |
188 |
+ |
average += points[i0]; |
189 |
+ |
} |
190 |
+ |
RealType invNumPoints = ((RealType)1)/(RealType)numPoints; |
191 |
+ |
average *= invNumPoints; |
192 |
|
|
193 |
< |
// values_.push_back( acos(maxct)*(180.0/M_PI) ); |
193 |
> |
DynamicRectMatrix<RealType> mat(4, 4); |
194 |
> |
int row, col; |
195 |
> |
for (row = 0; row < 4; ++row) { |
196 |
> |
for (col = 0; col < 4; ++col){ |
197 |
> |
mat(row,col) = 0.0; |
198 |
> |
} |
199 |
> |
} |
200 |
> |
for (int i = 0; i < numPoints; ++i) { |
201 |
> |
RealType x = points[i][0]; |
202 |
> |
RealType y = points[i][1]; |
203 |
> |
RealType x2 = x*x; |
204 |
> |
RealType y2 = y*y; |
205 |
> |
RealType xy = x*y; |
206 |
> |
RealType r2 = x2+y2; |
207 |
> |
RealType xr2 = x*r2; |
208 |
> |
RealType yr2 = y*r2; |
209 |
> |
RealType r4 = r2*r2; |
210 |
> |
|
211 |
> |
mat(0,1) += x; |
212 |
> |
mat(0,2) += y; |
213 |
> |
mat(0,3) += r2; |
214 |
> |
mat(1,1) += x2; |
215 |
> |
mat(1,2) += xy; |
216 |
> |
mat(1,3) += xr2; |
217 |
> |
mat(2,2) += y2; |
218 |
> |
mat(2,3) += yr2; |
219 |
> |
mat(3,3) += r4; |
220 |
> |
} |
221 |
> |
mat(0,0) = (RealType)numPoints; |
222 |
> |
|
223 |
> |
for (row = 0; row < 4; ++row) { |
224 |
> |
for (col = 0; col < row; ++col) { |
225 |
> |
mat(row,col) = mat(col,row); |
226 |
> |
} |
227 |
> |
} |
228 |
> |
|
229 |
> |
for (row = 0; row < 4; ++row) { |
230 |
> |
for (col = 0; col < 4; ++col) { |
231 |
> |
mat(row,col) *= invNumPoints; |
232 |
> |
} |
233 |
> |
} |
234 |
> |
|
235 |
> |
JAMA::Eigenvalue<RealType> eigensystem(mat); |
236 |
> |
DynamicRectMatrix<RealType> evects(4, 4); |
237 |
> |
DynamicVector<RealType> evals(4); |
238 |
> |
|
239 |
> |
eigensystem.getRealEigenvalues(evals); |
240 |
> |
eigensystem.getV(evects); |
241 |
> |
|
242 |
> |
DynamicVector<RealType> evector = evects.getColumn(0); |
243 |
> |
RealType inv = ((RealType)1)/evector[3]; // beware zero divide |
244 |
> |
RealType coeff[3]; |
245 |
> |
for (row = 0; row < 3; ++row) { |
246 |
> |
coeff[row] = inv*evector[row]; |
247 |
> |
} |
248 |
> |
|
249 |
> |
Vector<RealType, 2> center; |
250 |
|
|
251 |
+ |
center[0] = -((RealType)0.5)*coeff[1]; |
252 |
+ |
center[1] = -((RealType)0.5)*coeff[2]; |
253 |
+ |
RealType radius = sqrt(fabs(center[0]*center[0] + center[1]*center[1] |
254 |
+ |
- coeff[0])); |
255 |
+ |
|
256 |
+ |
int i1; |
257 |
+ |
for (i1 = 0; i1 < 100; ++i1) { |
258 |
+ |
// Update the iterates. |
259 |
+ |
Vector<RealType, 2> current = center; |
260 |
+ |
|
261 |
+ |
// Compute average L, dL/da, dL/db. |
262 |
+ |
RealType lenAverage = (RealType)0; |
263 |
+ |
Vector<RealType, 2> derLenAverage = Vector<RealType, 2>(0.0); |
264 |
+ |
for (i0 = 0; i0 < numPoints; ++i0) { |
265 |
+ |
Vector<RealType, 2> diff = points[i0] - center; |
266 |
+ |
RealType length = diff.length(); |
267 |
+ |
if (length > 1e-6) { |
268 |
+ |
lenAverage += length; |
269 |
+ |
RealType invLength = ((RealType)1)/length; |
270 |
+ |
derLenAverage -= invLength*diff; |
271 |
+ |
} |
272 |
+ |
} |
273 |
+ |
lenAverage *= invNumPoints; |
274 |
+ |
derLenAverage *= invNumPoints; |
275 |
+ |
|
276 |
+ |
center = average + lenAverage*derLenAverage; |
277 |
+ |
radius = lenAverage; |
278 |
+ |
|
279 |
+ |
Vector<RealType, 2> diff = center - current; |
280 |
+ |
if (fabs(diff[0]) <= 1e-6 && fabs(diff[1]) <= 1e-6) { |
281 |
+ |
break; |
282 |
+ |
} |
283 |
+ |
} |
284 |
+ |
|
285 |
+ |
RealType zCen = center[1]; |
286 |
+ |
RealType rDrop = radius; |
287 |
+ |
RealType ca; |
288 |
+ |
|
289 |
+ |
if (fabs(zCen) > rDrop) { |
290 |
+ |
ca = 180.0; |
291 |
+ |
} else { |
292 |
+ |
ca = 90.0 + asin(zCen/rDrop)*(180.0/M_PI); |
293 |
+ |
} |
294 |
+ |
|
295 |
+ |
values_.push_back( ca ); |
296 |
+ |
|
297 |
|
} |
298 |
|
} |
299 |
|
|