ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/nonbonded/SC.cpp
Revision: 1895
Committed: Mon Jul 1 21:09:37 2013 UTC (12 years ago) by gezelter
File size: 11330 byte(s)
Log Message:
Speed!

File Contents

# User Rev Content
1 gezelter 1489 /*
2     * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9     * 1. Redistributions of source code must retain the above copyright
10     * notice, this list of conditions and the following disclaimer.
11     *
12     * 2. Redistributions in binary form must reproduce the above copyright
13     * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the
15     * distribution.
16     *
17     * This software is provided "AS IS," without a warranty of any
18     * kind. All express or implied conditions, representations and
19     * warranties, including any implied warranty of merchantability,
20     * fitness for a particular purpose or non-infringement, are hereby
21     * excluded. The University of Notre Dame and its licensors shall not
22     * be liable for any damages suffered by licensee as a result of
23     * using, modifying or distributing the software or its
24     * derivatives. In no event will the University of Notre Dame or its
25     * licensors be liable for any lost revenue, profit or data, or for
26     * direct, indirect, special, consequential, incidental or punitive
27     * damages, however caused and regardless of the theory of liability,
28     * arising out of the use of or inability to use software, even if the
29     * University of Notre Dame has been advised of the possibility of
30     * such damages.
31     *
32     * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     * research, please cite the appropriate papers when you publish your
34     * work. Good starting points are:
35     *
36     * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37     * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38 gezelter 1879 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 gezelter 1665 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 gezelter 1489 */
42    
43     #include <stdio.h>
44     #include <string.h>
45    
46     #include <cmath>
47     #include "nonbonded/SC.hpp"
48     #include "utils/simError.h"
49     #include "types/NonBondedInteractionType.hpp"
50    
51     namespace OpenMD {
52    
53    
54 gezelter 1502 SC::SC() : name_("SC"), initialized_(false), forceField_(NULL),
55     scRcut_(0.0), np_(3000) {}
56 gezelter 1489
57 gezelter 1879 SC::~SC() {
58     initialized_ = false;
59    
60     MixingMap.clear();
61 gezelter 1895 SCtypes.clear();
62     SCdata.clear();
63     SCtids.clear();
64 gezelter 1879 }
65    
66 gezelter 1489 RealType SC::getM(AtomType* atomType1, AtomType* atomType2) {
67 gezelter 1710 SuttonChenAdapter sca1 = SuttonChenAdapter(atomType1);
68     SuttonChenAdapter sca2 = SuttonChenAdapter(atomType2);
69     RealType m1 = sca1.getM();
70     RealType m2 = sca2.getM();
71 gezelter 1489 return 0.5 * (m1 + m2);
72     }
73    
74     RealType SC::getN(AtomType* atomType1, AtomType* atomType2) {
75 gezelter 1710 SuttonChenAdapter sca1 = SuttonChenAdapter(atomType1);
76     SuttonChenAdapter sca2 = SuttonChenAdapter(atomType2);
77     RealType n1 = sca1.getN();
78     RealType n2 = sca2.getN();
79 gezelter 1489 return 0.5 * (n1 + n2);
80     }
81    
82     RealType SC::getAlpha(AtomType* atomType1, AtomType* atomType2) {
83 gezelter 1710 SuttonChenAdapter sca1 = SuttonChenAdapter(atomType1);
84     SuttonChenAdapter sca2 = SuttonChenAdapter(atomType2);
85     RealType alpha1 = sca1.getAlpha();
86     RealType alpha2 = sca2.getAlpha();
87 gezelter 1489
88     ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
89     std::string DistanceMix = fopts.getDistanceMixingRule();
90     toUpper(DistanceMix);
91    
92     if (DistanceMix == "GEOMETRIC")
93     return sqrt(alpha1 * alpha2);
94     else
95     return 0.5 * (alpha1 + alpha2);
96     }
97    
98 gezelter 1710 RealType SC::getEpsilon(AtomType* atomType1, AtomType* atomType2) {
99     SuttonChenAdapter sca1 = SuttonChenAdapter(atomType1);
100     SuttonChenAdapter sca2 = SuttonChenAdapter(atomType2);
101     RealType epsilon1 = sca1.getEpsilon();
102     RealType epsilon2 = sca2.getEpsilon();
103 gezelter 1489 return sqrt(epsilon1 * epsilon2);
104     }
105    
106 gezelter 1895 void SC::initialize() {
107 gezelter 1489 // find all of the SC atom Types:
108 gezelter 1895 SCtypes.clear();
109     SCtids.clear();
110     SCdata.clear();
111     MixingMap.clear();
112     nSC_ = 0;
113 gezelter 1489
114 gezelter 1895 SCtids.resize( forceField_->getNAtomType(), -1);
115    
116     set<AtomType*>::iterator at;
117     for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
118     if ((*at)->isSC()) nSC_++;
119     }
120     SCdata.resize(nSC_);
121     MixingMap.resize(nSC_);
122     for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
123     if ((*at)->isSC()) addType((*at));
124     }
125 gezelter 1489 initialized_ = true;
126     }
127    
128    
129    
130     void SC::addType(AtomType* atomType){
131    
132 gezelter 1710 SuttonChenAdapter sca = SuttonChenAdapter(atomType);
133 gezelter 1489 SCAtomData scAtomData;
134    
135 gezelter 1710 scAtomData.c = sca.getC();
136     scAtomData.m = sca.getM();
137     scAtomData.n = sca.getN();
138     scAtomData.alpha = sca.getAlpha();
139     scAtomData.epsilon = sca.getEpsilon();
140 gezelter 1489 scAtomData.rCut = 2.0 * scAtomData.alpha;
141 gezelter 1895
142 gezelter 1489 // add it to the map:
143 gezelter 1895 int atid = atomType->getIdent();
144     int sctid = SCtypes.size();
145 gezelter 1489
146 gezelter 1895 pair<set<int>::iterator,bool> ret;
147     ret = SCtypes.insert( atid );
148 gezelter 1489 if (ret.second == false) {
149     sprintf( painCave.errMsg,
150     "SC already had a previous entry with ident %d\n",
151 gezelter 1895 atid );
152 gezelter 1489 painCave.severity = OPENMD_INFO;
153     painCave.isFatal = 0;
154     simError();
155     }
156    
157 gezelter 1895 SCtids[atid] = sctid;
158     SCdata[sctid] = scAtomData;
159     MixingMap[sctid].resize(nSC_);
160    
161 gezelter 1489 // Now, iterate over all known types and add to the mixing map:
162    
163 gezelter 1895 std::set<int>::iterator it;
164     for( it = SCtypes.begin(); it != SCtypes.end(); ++it) {
165 gezelter 1489
166 gezelter 1895 int sctid2 = SCtids[ (*it) ];
167     AtomType* atype2 = forceField_->getAtomType( (*it) );
168 gezelter 1489
169     SCInteractionData mixer;
170    
171     mixer.alpha = getAlpha(atomType, atype2);
172     mixer.rCut = 2.0 * mixer.alpha;
173     mixer.epsilon = getEpsilon(atomType, atype2);
174     mixer.m = getM(atomType, atype2);
175     mixer.n = getN(atomType, atype2);
176    
177     RealType dr = mixer.rCut / (np_ - 1);
178     vector<RealType> rvals;
179     vector<RealType> vvals;
180     vector<RealType> phivals;
181    
182     rvals.push_back(0.0);
183     vvals.push_back(0.0);
184     phivals.push_back(0.0);
185    
186     for (int k = 1; k < np_; k++) {
187     RealType r = dr * k;
188     rvals.push_back(r);
189     vvals.push_back( mixer.epsilon * pow(mixer.alpha/r, mixer.n) );
190     phivals.push_back( pow(mixer.alpha/r, mixer.m) );
191     }
192    
193     mixer.vCut = mixer.epsilon * pow(mixer.alpha/mixer.rCut, mixer.n);
194    
195     CubicSpline* V = new CubicSpline();
196     V->addPoints(rvals, vvals);
197    
198     CubicSpline* phi = new CubicSpline();
199     phi->addPoints(rvals, phivals);
200    
201     mixer.V = V;
202     mixer.phi = phi;
203    
204     mixer.explicitlySet = false;
205    
206 gezelter 1895 MixingMap[sctid2].resize( nSC_ );
207 gezelter 1489
208 gezelter 1895 MixingMap[sctid][sctid2] = mixer;
209     if (sctid2 != sctid) {
210     MixingMap[sctid2][sctid] = mixer;
211 gezelter 1489 }
212     }
213     return;
214     }
215    
216     void SC::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
217     RealType epsilon, RealType m, RealType n,
218     RealType alpha) {
219    
220     // in case these weren't already in the map
221     addType(atype1);
222     addType(atype2);
223    
224     SCInteractionData mixer;
225    
226     mixer.epsilon = epsilon;
227     mixer.m = m;
228     mixer.n = n;
229     mixer.alpha = alpha;
230     mixer.rCut = 2.0 * mixer.alpha;
231    
232     RealType dr = mixer.rCut / (np_ - 1);
233     vector<RealType> rvals;
234     vector<RealType> vvals;
235     vector<RealType> phivals;
236    
237     rvals.push_back(0.0);
238     vvals.push_back(0.0);
239     phivals.push_back(0.0);
240    
241     for (int k = 1; k < np_; k++) {
242     RealType r = dr * k;
243     rvals.push_back(r);
244     vvals.push_back( mixer.epsilon * pow(mixer.alpha/r, mixer.n) );
245     phivals.push_back( pow(mixer.alpha/r, mixer.m) );
246     }
247    
248     mixer.vCut = mixer.epsilon * pow(mixer.alpha/mixer.rCut, mixer.n);
249    
250     CubicSpline* V = new CubicSpline();
251     V->addPoints(rvals, vvals);
252    
253     CubicSpline* phi = new CubicSpline();
254     phi->addPoints(rvals, phivals);
255    
256     mixer.V = V;
257     mixer.phi = phi;
258    
259     mixer.explicitlySet = true;
260    
261 gezelter 1895 int sctid1 = SCtids[ atype1->getIdent() ];
262     int sctid2 = SCtids[ atype2->getIdent() ];
263    
264     MixingMap[sctid1][sctid2] = mixer;
265     if (sctid2 != sctid1) {
266     MixingMap[sctid2][sctid1] = mixer;
267 gezelter 1489 }
268     return;
269     }
270    
271 gezelter 1545 void SC::calcDensity(InteractionData &idat) {
272 gezelter 1489
273     if (!initialized_) initialize();
274 gezelter 1895 int sctid1 = SCtids[idat.atid1];
275     int sctid2 = SCtids[idat.atid2];
276 gezelter 1489
277 gezelter 1895 SCInteractionData &mixer = MixingMap[sctid1][sctid2];
278 gezelter 1489
279 gezelter 1502 RealType rcij = mixer.rCut;
280 gezelter 1489
281 gezelter 1554 if ( *(idat.rij) < rcij) {
282 gezelter 1575 RealType rho = mixer.phi->getValueAt( *(idat.rij) );
283     *(idat.rho1) += rho;
284     *(idat.rho2) += rho;
285     }
286 gezelter 1554
287 gezelter 1489 return;
288     }
289    
290 gezelter 1545 void SC::calcFunctional(SelfData &sdat) {
291 gezelter 1489
292     if (!initialized_) initialize();
293    
294 gezelter 1895 SCAtomData &data1 = SCdata[SCtids[sdat.atid]];
295 gezelter 1575
296     RealType u = - data1.c * data1.epsilon * sqrt( *(sdat.rho) );
297     *(sdat.frho) = u;
298 gezelter 1554 *(sdat.dfrhodrho) = 0.5 * *(sdat.frho) / *(sdat.rho);
299 gezelter 1575
300 gezelter 1583 (*(sdat.pot))[METALLIC_FAMILY] += u;
301 gezelter 1711 if (sdat.doParticlePot) {
302     *(sdat.particlePot) += u;
303     }
304    
305 gezelter 1489 return;
306     }
307 gezelter 1502
308 gezelter 1489
309 gezelter 1536 void SC::calcForce(InteractionData &idat) {
310 gezelter 1489
311     if (!initialized_) initialize();
312    
313 gezelter 1895 int &sctid1 = SCtids[idat.atid1];
314     int &sctid2 = SCtids[idat.atid2];
315 gezelter 1489
316 gezelter 1895 SCAtomData &data1 = SCdata[sctid1];
317     SCAtomData &data2 = SCdata[sctid2];
318 gezelter 1489
319 gezelter 1895 SCInteractionData &mixer = MixingMap[sctid1][sctid2];
320    
321 gezelter 1489 RealType rcij = mixer.rCut;
322    
323 gezelter 1554 if ( *(idat.rij) < rcij) {
324 gezelter 1895 RealType vcij = mixer.vCut;
325     RealType rhtmp, drhodr, vptmp, dvpdr;
326 gezelter 1502
327 gezelter 1895 mixer.phi->getValueAndDerivativeAt( *(idat.rij), rhtmp, drhodr );
328     mixer.V->getValueAndDerivativeAt( *(idat.rij), vptmp, dvpdr);
329 gezelter 1502
330     RealType pot_temp = vptmp - vcij;
331 gezelter 1554 *(idat.vpair) += pot_temp;
332 gezelter 1502
333 gezelter 1554 RealType dudr = drhodr * ( *(idat.dfrho1) + *(idat.dfrho2) ) + dvpdr;
334 gezelter 1502
335 gezelter 1554 *(idat.f1) += *(idat.d) * dudr / *(idat.rij) ;
336 gezelter 1489
337 gezelter 1711 if (idat.doParticlePot) {
338     // particlePot is the difference between the full potential and
339     // the full potential without the presence of a particular
340     // particle (atom1).
341     //
342     // This reduces the density at other particle locations, so we
343     // need to recompute the density at atom2 assuming atom1 didn't
344     // contribute. This then requires recomputing the density
345     // functional for atom2 as well.
346    
347     *(idat.particlePot1) -= data2.c * data2.epsilon *
348     sqrt( *(idat.rho2) - rhtmp) + *(idat.frho2);
349 gezelter 1575
350 gezelter 1711 *(idat.particlePot2) -= data1.c * data1.epsilon *
351     sqrt( *(idat.rho1) - rhtmp) + *(idat.frho1);
352     }
353 gezelter 1489
354 gezelter 1582 (*(idat.pot))[METALLIC_FAMILY] += pot_temp;
355 gezelter 1502 }
356    
357 gezelter 1489 return;
358     }
359 gezelter 1505
360 gezelter 1545 RealType SC::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
361 gezelter 1505 if (!initialized_) initialize();
362 gezelter 1545
363 gezelter 1895 int atid1 = atypes.first->getIdent();
364     int atid2 = atypes.second->getIdent();
365     int &sctid1 = SCtids[atid1];
366     int &sctid2 = SCtids[atid2];
367    
368     if (sctid1 == -1 || sctid2 == -1) {
369 gezelter 1505 return 0.0;
370 gezelter 1895 } else {
371     return MixingMap[sctid1][sctid2].rCut;
372 gezelter 1505 }
373     }
374 gezelter 1489 }

Properties

Name Value
svn:eol-style native