ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/Sticky.cpp
(Generate patch)

Comparing branches/development/src/nonbonded/Sticky.cpp (file contents):
Revision 1485 by gezelter, Wed Jul 28 19:52:00 2010 UTC vs.
Revision 1505 by gezelter, Sun Oct 3 22:18:59 2010 UTC

# Line 49 | Line 49 | namespace OpenMD {
49  
50   using namespace std;
51   namespace OpenMD {
52
53  bool Sticky::initialized_ = false;
54  ForceField* Sticky::forceField_ = NULL;
55  map<int, AtomType*> Sticky::StickyMap;
56  map<pair<AtomType*, AtomType*>, StickyInteractionData> Sticky::MixingMap;
52    
53 <  Sticky* Sticky::_instance = NULL;
53 >  Sticky::Sticky() : name_("Sticky"), initialized_(false), forceField_(NULL) {}
54    
60  Sticky* Sticky::Instance() {
61    if (!_instance) {
62      _instance = new Sticky();
63    }
64    return _instance;
65  }
66  
55    StickyParam Sticky::getStickyParam(AtomType* atomType) {
56      
57      // Do sanity checking on the AtomType we were passed before
# Line 189 | Line 177 | namespace OpenMD {
177      }
178    }
179  
180 <  RealType Sticky::getStickyCut(int atid) {
180 >  /**
181 >   * This function does the sticky portion of the SSD potential
182 >   * [Chandra and Ichiye, Journal of Chemical Physics 111, 2701
183 >   * (1999)].  The Lennard-Jones and dipolar interaction must be
184 >   * handled separately.  We assume that the rotation matrices have
185 >   * already been calculated and placed in the A1 & A2 entries in the
186 >   * idat structure.
187 >   */
188 >  
189 >  void Sticky::calcForce(InteractionData idat) {
190 >  
191      if (!initialized_) initialize();
194    std::map<int, AtomType*> :: const_iterator it;
195    it = StickyMap.find(atid);
196    if (it == StickyMap.end()) {
197      sprintf( painCave.errMsg,
198               "Sticky::getStickyCut could not find atid %d in StickyMap\n",
199               (atid));
200      painCave.severity = OPENMD_ERROR;
201      painCave.isFatal = 1;
202      simError();          
203    }
204
205    AtomType* atype = it->second;
206    return MixingMap[make_pair(atype, atype)].rbig;
207  }
208
209
210  void Sticky::calcForce(AtomType* at1, AtomType* at2, Vector3d d,
211                         RealType rij, RealType r2, RealType sw,
212                         RealType &vpair, RealType &pot,
213                         RotMat3x3d A1, RotMat3x3d A2, Vector3d &f1,
214                         Vector3d &t1, Vector3d &t2) {
215
216    // This routine does only the sticky portion of the SSD potential
217    // [Chandra and Ichiye, J. Chem. Phys. 111, 2701 (1999)].
218    // The Lennard-Jones and dipolar interaction must be handled separately.
192      
193 <    // We assume that the rotation matrices have already been calculated
194 <    // and placed in the A array.
195 <    
196 <    if (!initialized_) initialize();
224 <    
225 <    pair<AtomType*, AtomType*> key = make_pair(at1, at2);
226 <    StickyInteractionData mixer = MixingMap[key];
227 <
228 <    RealType w0  = mixer.w0;
229 <    RealType v0  = mixer.v0;
230 <    RealType v0p = mixer.v0p;
231 <    RealType rl  = mixer.rl;
232 <    RealType ru  = mixer.ru;
233 <    RealType rlp = mixer.rlp;
234 <    RealType rup = mixer.rup;
235 <    RealType rbig = mixer.rbig;
236 <    bool isPower = mixer.isPower;
237 <
238 <    if (rij <= rbig) {
239 <
240 <      RealType r3 = r2 * rij;
241 <      RealType r5 = r3 * r2;
242 <          
243 <      RotMat3x3d A1trans = A1.transpose();
244 <      RotMat3x3d A2trans = A2.transpose();
245 <
246 <      // rotate the inter-particle separation into the two different
247 <      // body-fixed coordinate systems:
248 <
249 <      Vector3d ri = A1 * d;
250 <
251 <      // negative sign because this is the vector from j to i:
252 <
253 <      Vector3d rj = -A2 * d;
254 <
255 <      RealType xi = ri.x();
256 <      RealType yi = ri.y();
257 <      RealType zi = ri.z();
258 <
259 <      RealType xj = rj.x();
260 <      RealType yj = rj.y();
261 <      RealType zj = rj.z();
262 <
263 <      RealType xi2 = xi * xi;
264 <      RealType yi2 = yi * yi;
265 <      RealType zi2 = zi * zi;
266 <
267 <      RealType xj2 = xj * xj;
268 <      RealType yj2 = yj * yj;
269 <      RealType zj2 = zj * zj;    
270 <
271 <      // calculate the switching info. from the splines
272 <
273 <      RealType s = 0.0;
274 <      RealType dsdr = 0.0;
275 <      RealType sp = 0.0;
276 <      RealType dspdr = 0.0;
277 <
278 <      if (rij < ru) {
279 <        if (rij < rl) {
280 <          s = 1.0;
281 <          dsdr = 0.0;
282 <        } else {          
283 <          // we are in the switching region
284 <
285 <          pair<RealType, RealType> res = mixer.s->getValueAndDerivativeAt(rij);
286 <          s = res.first;
287 <          dsdr = res.second;
288 <        }
289 <      }
193 >    pair<AtomType*, AtomType*> key = make_pair(idat.atype1, idat.atype2);
194 >    map<pair<AtomType*, AtomType*>, StickyInteractionData>::iterator it;
195 >    it = MixingMap.find(key);
196 >    if (it != MixingMap.end()) {
197  
198 <      if (rij < rup) {
292 <        if (rij < rlp) {
293 <          sp = 1.0;
294 <          dspdr = 0.0;
295 <        } else {
296 <          // we are in the switching region
297 <
298 <          pair<RealType, RealType> res =mixer.sp->getValueAndDerivativeAt(rij);
299 <          sp = res.first;
300 <          dspdr = res.second;
301 <        }
302 <      }
303 <
304 <      RealType wi = 2.0*(xi2-yi2)*zi / r3;
305 <      RealType wj = 2.0*(xj2-yj2)*zj / r3;
306 <      RealType w = wi+wj;
307 <
308 <
309 <      RealType zif = zi/rij - 0.6;
310 <      RealType zis = zi/rij + 0.8;
311 <
312 <      RealType zjf = zj/rij - 0.6;
313 <      RealType zjs = zj/rij + 0.8;
314 <
315 <      RealType wip = zif*zif*zis*zis - w0;
316 <      RealType wjp = zjf*zjf*zjs*zjs - w0;
317 <      RealType wp = wip + wjp;
318 <
319 <      Vector3d dwi(4.0*xi*zi/r3  - 6.0*xi*zi*(xi2-yi2)/r5,
320 <                   - 4.0*yi*zi/r3  - 6.0*yi*zi*(xi2-yi2)/r5,
321 <                   2.0*(xi2-yi2)/r3  - 6.0*zi2*(xi2-yi2)/r5);
198 >      StickyInteractionData mixer = (*it).second;
199        
200 <      Vector3d dwj(4.0*xj*zj/r3  - 6.0*xj*zj*(xj2-yj2)/r5,
201 <                   - 4.0*yj*zj/r3  - 6.0*yj*zj*(xj2-yj2)/r5,
202 <                   2.0*(xj2-yj2)/r3  - 6.0*zj2*(xj2-yj2)/r5);
203 <
204 <      RealType uglyi = zif*zif*zis + zif*zis*zis;
205 <      RealType uglyj = zjf*zjf*zjs + zjf*zjs*zjs;
206 <
207 <      Vector3d dwip(-2.0*xi*zi*uglyi/r3,
208 <                    -2.0*yi*zi*uglyi/r3,
332 <                    2.0*(1.0/rij - zi2/r3)*uglyi);
333 <
334 <      Vector3d dwjp(-2.0*xj*zj*uglyj/r3,
335 <                    -2.0*yj*zj*uglyj/r3,
336 <                    2.0*(1.0/rij - zj2/r3)*uglyj);
337 <
338 <      Vector3d dwidu(4.0*(yi*zi2 + 0.5*yi*(xi2-yi2))/r3,
339 <                     4.0*(xi*zi2 - 0.5*xi*(xi2-yi2))/r3,
340 <                     - 8.0*xi*yi*zi/r3);
341 <
342 <      Vector3d dwjdu(4.0*(yj*zj2 + 0.5*yj*(xj2-yj2))/r3,
343 <                     4.0*(xj*zj2 - 0.5*xj*(xj2-yj2))/r3,
344 <                     - 8.0*xj*yj*zj/r3);
345 <      
346 <      Vector3d dwipdu(2.0*yi*uglyi/rij,
347 <                      -2.0*xi*uglyi/rij,
348 <                      0.0);
349 <
350 <      Vector3d dwjpdu(2.0*yj*uglyj/rij,
351 <                      -2.0*xj*uglyj/rij,
352 <                      0.0);
353 <
354 <      if (isPower) {
355 <        RealType frac1 = 0.25;
356 <        RealType frac2 = 0.75;      
357 <        RealType wi2 = wi*wi;
358 <        RealType wj2 = wj*wj;
359 <        // sticky power has no w' function:
360 <        w = frac1 * wi * wi2 + frac2*wi + frac1*wj*wj2 + frac2*wj + v0p;
361 <        wp = 0.0;
362 <        dwi = frac1*3.0*wi2*dwi + frac2*dwi;
363 <        dwj = frac1*3.0*wj2*dwi + frac2*dwi;
364 <        dwip = V3Zero;
365 <        dwjp = V3Zero;
366 <        dwidu = frac1*3.0*wi2*dwidu + frac2*dwidu;
367 <        dwidu = frac1*3.0*wj2*dwjdu + frac2*dwjdu;
368 <        dwipdu = V3Zero;
369 <        dwjpdu = V3Zero;
370 <        sp = 0.0;
371 <        dspdr = 0.0;
372 <      }
373 <
374 <      vpair += 0.5*(v0*s*w + v0p*sp*wp);
375 <      pot += 0.5*(v0*s*w + v0p*sp*wp)*sw;
376 <
377 <      // do the torques first since they are easy:
378 <      // remember that these are still in the body-fixed axes
379 <
380 <      Vector3d ti = 0.5*sw*(v0*s*dwidu + v0p*sp*dwipdu);
381 <      Vector3d tj = 0.5*sw*(v0*s*dwjdu + v0p*sp*dwjpdu);
382 <
383 <      // go back to lab frame using transpose of rotation matrix:
384 <
385 <      t1 += A1trans * ti;
386 <      t2 += A2trans * tj;
387 <
388 <      // Now, on to the forces:
389 <
390 <      // first rotate the i terms back into the lab frame:
391 <
392 <      Vector3d radcomi = (v0 * s * dwi + v0p * sp * dwip) * sw;
393 <      Vector3d radcomj = (v0 * s * dwj + v0p * sp * dwjp) * sw;
394 <
395 <      Vector3d fii = A1trans * radcomi;
396 <      Vector3d fjj = A2trans * radcomj;
397 <      
398 <      // now assemble these with the radial-only terms:
200 >      RealType w0  = mixer.w0;
201 >      RealType v0  = mixer.v0;
202 >      RealType v0p = mixer.v0p;
203 >      RealType rl  = mixer.rl;
204 >      RealType ru  = mixer.ru;
205 >      RealType rlp = mixer.rlp;
206 >      RealType rup = mixer.rup;
207 >      RealType rbig = mixer.rbig;
208 >      bool isPower = mixer.isPower;
209        
210 <      f1 += 0.5 * ((v0*dsdr*w + v0p*dspdr*wp) * d / rij + fii - fjj);
210 >      if (idat.rij <= rbig) {
211 >        
212 >        RealType r3 = idat.r2 * idat.rij;
213 >        RealType r5 = r3 * idat.r2;
214 >        
215 >        RotMat3x3d A1trans = idat.A1.transpose();
216 >        RotMat3x3d A2trans = idat.A2.transpose();
217 >        
218 >        // rotate the inter-particle separation into the two different
219 >        // body-fixed coordinate systems:
220 >        
221 >        Vector3d ri = idat.A1 * idat.d;
222 >        
223 >        // negative sign because this is the vector from j to i:
224 >        
225 >        Vector3d rj = - idat.A2 * idat.d;
226 >        
227 >        RealType xi = ri.x();
228 >        RealType yi = ri.y();
229 >        RealType zi = ri.z();
230 >        
231 >        RealType xj = rj.x();
232 >        RealType yj = rj.y();
233 >        RealType zj = rj.z();
234 >        
235 >        RealType xi2 = xi * xi;
236 >        RealType yi2 = yi * yi;
237 >        RealType zi2 = zi * zi;
238 >        
239 >        RealType xj2 = xj * xj;
240 >        RealType yj2 = yj * yj;
241 >        RealType zj2 = zj * zj;    
242 >        
243 >        // calculate the switching info. from the splines
244 >        
245 >        RealType s = 0.0;
246 >        RealType dsdr = 0.0;
247 >        RealType sp = 0.0;
248 >        RealType dspdr = 0.0;
249 >        
250 >        if (idat.rij < ru) {
251 >          if (idat.rij < rl) {
252 >            s = 1.0;
253 >            dsdr = 0.0;
254 >          } else {          
255 >            // we are in the switching region
256 >            
257 >            pair<RealType, RealType> res = mixer.s->getValueAndDerivativeAt(idat.rij);
258 >            s = res.first;
259 >            dsdr = res.second;
260 >          }
261 >        }
262 >        
263 >        if (idat.rij < rup) {
264 >          if (idat.rij < rlp) {
265 >            sp = 1.0;
266 >            dspdr = 0.0;
267 >          } else {
268 >            // we are in the switching region
269 >            
270 >            pair<RealType, RealType> res =mixer.sp->getValueAndDerivativeAt(idat.rij);
271 >            sp = res.first;
272 >            dspdr = res.second;
273 >          }
274 >        }
275 >        
276 >        RealType wi = 2.0*(xi2-yi2)*zi / r3;
277 >        RealType wj = 2.0*(xj2-yj2)*zj / r3;
278 >        RealType w = wi+wj;
279 >        
280 >        
281 >        RealType zif = zi/idat.rij - 0.6;
282 >        RealType zis = zi/idat.rij + 0.8;
283 >        
284 >        RealType zjf = zj/idat.rij - 0.6;
285 >        RealType zjs = zj/idat.rij + 0.8;
286 >        
287 >        RealType wip = zif*zif*zis*zis - w0;
288 >        RealType wjp = zjf*zjf*zjs*zjs - w0;
289 >        RealType wp = wip + wjp;
290 >        
291 >        Vector3d dwi(4.0*xi*zi/r3  - 6.0*xi*zi*(xi2-yi2)/r5,
292 >                     - 4.0*yi*zi/r3  - 6.0*yi*zi*(xi2-yi2)/r5,
293 >                     2.0*(xi2-yi2)/r3  - 6.0*zi2*(xi2-yi2)/r5);
294 >        
295 >        Vector3d dwj(4.0*xj*zj/r3  - 6.0*xj*zj*(xj2-yj2)/r5,
296 >                     - 4.0*yj*zj/r3  - 6.0*yj*zj*(xj2-yj2)/r5,
297 >                     2.0*(xj2-yj2)/r3  - 6.0*zj2*(xj2-yj2)/r5);
298 >        
299 >        RealType uglyi = zif*zif*zis + zif*zis*zis;
300 >        RealType uglyj = zjf*zjf*zjs + zjf*zjs*zjs;
301  
302 +        Vector3d dwip(-2.0*xi*zi*uglyi/r3,
303 +                      -2.0*yi*zi*uglyi/r3,
304 +                      2.0*(1.0/idat.rij - zi2/r3)*uglyi);
305 +        
306 +        Vector3d dwjp(-2.0*xj*zj*uglyj/r3,
307 +                      -2.0*yj*zj*uglyj/r3,
308 +                      2.0*(1.0/idat.rij - zj2/r3)*uglyj);
309 +        
310 +        Vector3d dwidu(4.0*(yi*zi2 + 0.5*yi*(xi2-yi2))/r3,
311 +                       4.0*(xi*zi2 - 0.5*xi*(xi2-yi2))/r3,
312 +                       - 8.0*xi*yi*zi/r3);
313 +        
314 +        Vector3d dwjdu(4.0*(yj*zj2 + 0.5*yj*(xj2-yj2))/r3,
315 +                       4.0*(xj*zj2 - 0.5*xj*(xj2-yj2))/r3,
316 +                       - 8.0*xj*yj*zj/r3);
317 +        
318 +        Vector3d dwipdu(2.0*yi*uglyi/idat.rij,
319 +                        -2.0*xi*uglyi/idat.rij,
320 +                        0.0);
321 +        
322 +        Vector3d dwjpdu(2.0*yj*uglyj/idat.rij,
323 +                        -2.0*xj*uglyj/idat.rij,
324 +                        0.0);
325 +        
326 +        if (isPower) {
327 +          RealType frac1 = 0.25;
328 +          RealType frac2 = 0.75;      
329 +          RealType wi2 = wi*wi;
330 +          RealType wj2 = wj*wj;
331 +          // sticky power has no w' function:
332 +          w = frac1 * wi * wi2 + frac2*wi + frac1*wj*wj2 + frac2*wj + v0p;
333 +          wp = 0.0;
334 +          dwi = frac1*3.0*wi2*dwi + frac2*dwi;
335 +          dwj = frac1*3.0*wj2*dwi + frac2*dwi;
336 +          dwip = V3Zero;
337 +          dwjp = V3Zero;
338 +          dwidu = frac1*3.0*wi2*dwidu + frac2*dwidu;
339 +          dwidu = frac1*3.0*wj2*dwjdu + frac2*dwjdu;
340 +          dwipdu = V3Zero;
341 +          dwjpdu = V3Zero;
342 +          sp = 0.0;
343 +          dspdr = 0.0;
344 +        }
345 +        
346 +        idat.vpair += 0.5*(v0*s*w + v0p*sp*wp);
347 +        idat.pot += 0.5*(v0*s*w + v0p*sp*wp)*idat.sw;
348 +        
349 +        // do the torques first since they are easy:
350 +        // remember that these are still in the body-fixed axes
351 +        
352 +        Vector3d ti = 0.5*idat.sw*(v0*s*dwidu + v0p*sp*dwipdu);
353 +        Vector3d tj = 0.5*idat.sw*(v0*s*dwjdu + v0p*sp*dwjpdu);
354 +        
355 +        // go back to lab frame using transpose of rotation matrix:
356 +        
357 +        idat.t1 += A1trans * ti;
358 +        idat.t2 += A2trans * tj;
359 +        
360 +        // Now, on to the forces:
361 +        
362 +        // first rotate the i terms back into the lab frame:
363 +        
364 +        Vector3d radcomi = (v0 * s * dwi + v0p * sp * dwip) * idat.sw;
365 +        Vector3d radcomj = (v0 * s * dwj + v0p * sp * dwjp) * idat.sw;
366 +        
367 +        Vector3d fii = A1trans * radcomi;
368 +        Vector3d fjj = A2trans * radcomj;
369 +        
370 +        // now assemble these with the radial-only terms:
371 +        
372 +        idat.f1 += 0.5 * ((v0*dsdr*w + v0p*dspdr*wp) * idat.d /
373 +                          idat.rij + fii - fjj);
374 +        
375 +      }
376      }
403      
404    return;
377      
378 +    return;      
379    }
380  
381 <  void Sticky::do_sticky_pair(int *atid1, int *atid2, RealType *d,
382 <                              RealType *r, RealType *r2, RealType *sw,
383 <                              RealType *vpair, RealType *pot, RealType *A1,
384 <                              RealType *A2, RealType *f1,
385 <                              RealType *t1, RealType *t2) {
386 <    
387 <    if (!initialized_) initialize();
388 <    
389 <    AtomType* atype1 = StickyMap[*atid1];
390 <    AtomType* atype2 = StickyMap[*atid2];
391 <    
419 <    Vector3d disp(d);
420 <    Vector3d frc(f1);
421 <    Vector3d trq1(t1);
422 <    Vector3d trq2(t2);
423 <    RotMat3x3d Ai(A1);
424 <    RotMat3x3d Aj(A2);
425 <  
426 <    calcForce(atype1, atype2, disp, *r, *r2, *sw, *vpair, *pot,
427 <              Ai, Aj, frc, trq1, trq2);
428 <      
429 <    f1[0] = frc.x();
430 <    f1[1] = frc.y();
431 <    f1[2] = frc.z();
432 <
433 <    t1[0] = trq1.x();
434 <    t1[1] = trq1.y();
435 <    t1[2] = trq1.z();
436 <
437 <    t2[0] = trq2.x();
438 <    t2[1] = trq2.y();
439 <    t2[2] = trq2.z();
440 <
441 <    return;    
381 >  RealType Sticky::getSuggestedCutoffRadius(AtomType* at1, AtomType* at2) {
382 >    if (!initialized_) initialize();  
383 >    pair<AtomType*, AtomType*> key = make_pair(at1, at2);
384 >    map<pair<AtomType*, AtomType*>, StickyInteractionData>::iterator it;
385 >    it = MixingMap.find(key);
386 >    if (it == MixingMap.end())
387 >      return 0.0;
388 >    else  {
389 >      StickyInteractionData mixer = (*it).second;
390 >      return mixer.rbig;
391 >    }
392    }
393   }
444
445 extern "C" {
446  
447 #define fortranGetStickyCut FC_FUNC(getstickycut, GETSTICKYCUT)
448 #define fortranDoStickyPair FC_FUNC(do_sticky_pair, DO_STICKY_PAIR)
449  
450  RealType fortranGetStickyCut(int* atid) {
451    return OpenMD::Sticky::Instance()->getStickyCut(*atid);
452  }
453
454  void fortranDoStickyPair(int *atid1, int *atid2, RealType *d, RealType *r,
455                       RealType *r2, RealType *sw, RealType *vpair, RealType *pot,
456                       RealType *A1, RealType *A2, RealType *f1,
457                       RealType *t1, RealType *t2){
458    
459    return OpenMD::Sticky::Instance()->do_sticky_pair(atid1, atid2, d, r, r2,
460                                                      sw, vpair, pot, A1, A2,
461                                                      f1, t1, t2);
462  }
463 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines