ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/SC.cpp
Revision: 1489
Committed: Tue Aug 10 18:34:59 2010 UTC (14 years, 8 months ago) by gezelter
File size: 15768 byte(s)
Log Message:
Migrating Sutton-Chen from Fortran over to C++

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     * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).
39     * [4] Vardeman & Gezelter, in progress (2009).
40     */
41    
42     #include <stdio.h>
43     #include <string.h>
44    
45     #include <cmath>
46     #include "nonbonded/SC.hpp"
47     #include "utils/simError.h"
48     #include "types/NonBondedInteractionType.hpp"
49    
50     namespace OpenMD {
51    
52     bool SC::initialized_ = false;
53     RealType SC::scRcut_ = 0.0;
54     int SC::np_ = 3000;
55     ForceField* SC::forceField_ = NULL;
56     map<int, AtomType*> SC::SClist;
57     map<AtomType*, SCAtomData> SC::SCMap;
58     map<pair<AtomType*, AtomType*>, SCInteractionData> SC::MixingMap;
59    
60     SC* SC::_instance = NULL;
61    
62     SC* SC::Instance() {
63     if (!_instance) {
64     _instance = new SC();
65     }
66     return _instance;
67     }
68    
69     SCParam SC::getSCParam(AtomType* atomType) {
70    
71     // Do sanity checking on the AtomType we were passed before
72     // building any data structures:
73     if (!atomType->isSC()) {
74     sprintf( painCave.errMsg,
75     "SC::getSCParam was passed an atomType (%s) that does not\n"
76     "\tappear to be a Sutton-Chen (SC) atom.\n",
77     atomType->getName().c_str());
78     painCave.severity = OPENMD_ERROR;
79     painCave.isFatal = 1;
80     simError();
81     }
82    
83     GenericData* data = atomType->getPropertyByName("SC");
84     if (data == NULL) {
85     sprintf( painCave.errMsg, "SC::getSCParam could not find SC\n"
86     "\tparameters for atomType %s.\n",
87     atomType->getName().c_str());
88     painCave.severity = OPENMD_ERROR;
89     painCave.isFatal = 1;
90     simError();
91     }
92    
93     SCParamGenericData* scData = dynamic_cast<SCParamGenericData*>(data);
94     if (scData == NULL) {
95     sprintf( painCave.errMsg,
96     "SC::getSCParam could not convert GenericData to SCParamGenericData\n"
97     "\tfor atom type %s\n", atomType->getName().c_str());
98     painCave.severity = OPENMD_ERROR;
99     painCave.isFatal = 1;
100     simError();
101     }
102    
103     return scData->getData();
104     }
105    
106     RealType SC::getC(AtomType* atomType) {
107     SCParam scParam = getSCParam(atomType);
108     return scParam.c;
109     }
110    
111     RealType SC::getM(AtomType* atomType) {
112     SCParam scParam = getSCParam(atomType);
113     return scParam.m;
114     }
115    
116     RealType SC::getM(AtomType* atomType1, AtomType* atomType2) {
117     RealType m1 = getM(atomType1);
118     RealType m2 = getM(atomType2);
119     return 0.5 * (m1 + m2);
120     }
121    
122     RealType SC::getN(AtomType* atomType) {
123     SCParam scParam = getSCParam(atomType);
124     return scParam.n;
125     }
126    
127     RealType SC::getN(AtomType* atomType1, AtomType* atomType2) {
128     RealType n1 = getN(atomType1);
129     RealType n2 = getN(atomType2);
130     return 0.5 * (n1 + n2);
131     }
132    
133     RealType SC::getAlpha(AtomType* atomType) {
134     SCParam scParam = getSCParam(atomType);
135     return scParam.alpha;
136     }
137    
138     RealType SC::getAlpha(AtomType* atomType1, AtomType* atomType2) {
139     RealType alpha1 = getAlpha(atomType1);
140     RealType alpha2 = getAlpha(atomType2);
141    
142     ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
143     std::string DistanceMix = fopts.getDistanceMixingRule();
144     toUpper(DistanceMix);
145    
146     if (DistanceMix == "GEOMETRIC")
147     return sqrt(alpha1 * alpha2);
148     else
149     return 0.5 * (alpha1 + alpha2);
150     }
151    
152     RealType SC::getEpsilon(AtomType* atomType) {
153     SCParam scParam = getSCParam(atomType);
154     return scParam.epsilon;
155     }
156    
157     RealType SC::getEpsilon(AtomType* atomType1, AtomType* atomType2) {
158     RealType epsilon1 = getEpsilon(atomType1);
159     RealType epsilon2 = getEpsilon(atomType2);
160     return sqrt(epsilon1 * epsilon2);
161     }
162    
163     void SC::initialize() {
164     // find all of the SC atom Types:
165     ForceField::AtomTypeContainer* atomTypes = forceField_->getAtomTypes();
166     ForceField::AtomTypeContainer::MapTypeIterator i;
167     AtomType* at;
168    
169     for (at = atomTypes->beginType(i); at != NULL;
170     at = atomTypes->nextType(i)) {
171     if (at->isSC())
172     addType(at);
173     }
174     initialized_ = true;
175     }
176    
177    
178    
179     void SC::addType(AtomType* atomType){
180    
181     SCAtomData scAtomData;
182    
183     scAtomData.c = getC(atomType);
184     scAtomData.m = getM(atomType);
185     scAtomData.n = getN(atomType);
186     scAtomData.alpha = getAlpha(atomType);
187     scAtomData.epsilon = getEpsilon(atomType);
188     scAtomData.rCut = 2.0 * scAtomData.alpha;
189    
190     // add it to the map:
191     AtomTypeProperties atp = atomType->getATP();
192    
193     pair<map<int,AtomType*>::iterator,bool> ret;
194     ret = SClist.insert( pair<int, AtomType*>(atp.ident, atomType) );
195     if (ret.second == false) {
196     sprintf( painCave.errMsg,
197     "SC already had a previous entry with ident %d\n",
198     atp.ident);
199     painCave.severity = OPENMD_INFO;
200     painCave.isFatal = 0;
201     simError();
202     }
203    
204     SCMap[atomType] = scAtomData;
205    
206     // Now, iterate over all known types and add to the mixing map:
207    
208     map<AtomType*, SCAtomData>::iterator it;
209     for( it = SCMap.begin(); it != SCMap.end(); ++it) {
210    
211     AtomType* atype2 = (*it).first;
212    
213     SCInteractionData mixer;
214    
215     mixer.alpha = getAlpha(atomType, atype2);
216     mixer.rCut = 2.0 * mixer.alpha;
217     mixer.epsilon = getEpsilon(atomType, atype2);
218     mixer.m = getM(atomType, atype2);
219     mixer.n = getN(atomType, atype2);
220    
221     RealType dr = mixer.rCut / (np_ - 1);
222     vector<RealType> rvals;
223     vector<RealType> vvals;
224     vector<RealType> phivals;
225    
226     rvals.push_back(0.0);
227     vvals.push_back(0.0);
228     phivals.push_back(0.0);
229    
230     for (int k = 1; k < np_; k++) {
231     RealType r = dr * k;
232     rvals.push_back(r);
233     vvals.push_back( mixer.epsilon * pow(mixer.alpha/r, mixer.n) );
234     phivals.push_back( pow(mixer.alpha/r, mixer.m) );
235     }
236    
237     mixer.vCut = mixer.epsilon * pow(mixer.alpha/mixer.rCut, mixer.n);
238    
239     CubicSpline* V = new CubicSpline();
240     V->addPoints(rvals, vvals);
241    
242     CubicSpline* phi = new CubicSpline();
243     phi->addPoints(rvals, phivals);
244    
245     mixer.V = V;
246     mixer.phi = phi;
247    
248     mixer.explicitlySet = false;
249    
250     pair<AtomType*, AtomType*> key1, key2;
251     key1 = make_pair(atomType, atype2);
252     key2 = make_pair(atype2, atomType);
253    
254     MixingMap[key1] = mixer;
255     if (key2 != key1) {
256     MixingMap[key2] = mixer;
257     }
258     }
259     return;
260     }
261    
262     void SC::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
263     RealType epsilon, RealType m, RealType n,
264     RealType alpha) {
265    
266     // in case these weren't already in the map
267     addType(atype1);
268     addType(atype2);
269    
270     SCInteractionData mixer;
271    
272     mixer.epsilon = epsilon;
273     mixer.m = m;
274     mixer.n = n;
275     mixer.alpha = alpha;
276     mixer.rCut = 2.0 * mixer.alpha;
277    
278     RealType dr = mixer.rCut / (np_ - 1);
279     vector<RealType> rvals;
280     vector<RealType> vvals;
281     vector<RealType> phivals;
282    
283     rvals.push_back(0.0);
284     vvals.push_back(0.0);
285     phivals.push_back(0.0);
286    
287     for (int k = 1; k < np_; k++) {
288     RealType r = dr * k;
289     rvals.push_back(r);
290     vvals.push_back( mixer.epsilon * pow(mixer.alpha/r, mixer.n) );
291     phivals.push_back( pow(mixer.alpha/r, mixer.m) );
292     }
293    
294     mixer.vCut = mixer.epsilon * pow(mixer.alpha/mixer.rCut, mixer.n);
295    
296     CubicSpline* V = new CubicSpline();
297     V->addPoints(rvals, vvals);
298    
299     CubicSpline* phi = new CubicSpline();
300     phi->addPoints(rvals, phivals);
301    
302     mixer.V = V;
303     mixer.phi = phi;
304    
305     mixer.explicitlySet = true;
306    
307     pair<AtomType*, AtomType*> key1, key2;
308     key1 = make_pair(atype1, atype2);
309     key2 = make_pair(atype2, atype1);
310    
311     MixingMap[key1] = mixer;
312     if (key2 != key1) {
313     MixingMap[key2] = mixer;
314     }
315     return;
316     }
317    
318     void SC::calcDensity(AtomType* at1, AtomType* at2, const RealType rij,
319     RealType &rho_i_at_j, RealType &rho_j_at_i) {
320    
321     if (!initialized_) initialize();
322    
323     SCInteractionData mixer = MixingMap[make_pair(at1, at2)];
324    
325     rho_i_at_j = mixer.phi->getValueAt(rij);
326     rho_j_at_i = rho_i_at_j;
327    
328     return;
329     }
330    
331     void SC::calcFunctional(AtomType* at1, RealType rho, RealType &frho,
332     RealType &dfrhodrho) {
333    
334     if (!initialized_) initialize();
335    
336     SCAtomData data1 = SCMap[at1];
337    
338     frho = - data1.c * data1.epsilon * sqrt(rho);
339     dfrhodrho = 0.5 * frho / rho;
340    
341     return;
342     }
343    
344    
345     void SC::calcForce(AtomType* at1, AtomType* at2, Vector3d d,
346     RealType rij, RealType r2, RealType sw,
347     RealType &vpair, RealType &pot, Vector3d &f1,
348     RealType rho_i, RealType rho_j,
349     RealType dfrhodrho_i, RealType dfrhodrho_j,
350     RealType &fshift_i, RealType &fshift_j) {
351    
352     if (!initialized_) initialize();
353    
354     SCAtomData data1 = SCMap[at1];
355     SCAtomData data2 = SCMap[at1];
356    
357     SCInteractionData mixer = MixingMap[make_pair(at1, at2)];
358    
359     RealType rcij = mixer.rCut;
360     RealType vcij = mixer.vCut;
361    
362     pair<RealType, RealType> res;
363    
364     res = mixer.phi->getValueAndDerivativeAt(rij);
365     RealType rhtmp = res.first;
366     RealType drhodr = res.second;
367    
368     res = mixer.V->getValueAndDerivativeAt(rij);
369     RealType vptmp = res.first;
370     RealType dvpdr = res.second;
371    
372     RealType pot_temp = vptmp - vcij;
373     vpair += pot_temp;
374    
375     RealType dudr = drhodr * (dfrhodrho_i + dfrhodrho_j) + dvpdr;
376    
377     f1 += d * dudr / rij;
378    
379     // particle_pot is the difference between the full potential
380     // and the full potential without the presence of a particular
381     // particle (atom1).
382     //
383     // This reduces the density at other particle locations, so
384     // we need to recompute the density at atom2 assuming atom1
385     // didn't contribute. This then requires recomputing the
386     // density functional for atom2 as well.
387     //
388     // Most of the particle_pot heavy lifting comes from the
389     // pair interaction, and will be handled by vpair.
390    
391     fshift_i = - data1.c * data1.epsilon * sqrt(rho_i - rhtmp);
392     fshift_j = - data2.c * data2.epsilon * sqrt(rho_j - rhtmp);
393    
394     pot += pot_temp;
395    
396     return;
397     }
398    
399    
400     void SC::calc_sc_prepair_rho(int *atid1, int *atid2, RealType *rij,
401     RealType* rho_i_at_j, RealType* rho_j_at_i){
402    
403     if (!initialized_) initialize();
404    
405     AtomType* atype1 = SClist[*atid1];
406     AtomType* atype2 = SClist[*atid2];
407    
408     calcDensity(atype1, atype2, *rij, *rho_i_at_j, *rho_j_at_i);
409    
410     return;
411     }
412    
413     void SC::calc_sc_preforce_Frho(int *atid1, RealType *rho, RealType *frho,
414     RealType *dfrhodrho) {
415    
416     if (!initialized_) initialize();
417    
418     AtomType* atype1 = SClist[*atid1];
419    
420     calcFunctional(atype1, *rho, *frho, *dfrhodrho);
421    
422     return;
423     }
424    
425     RealType SC::getSCcut(int *atid1) {
426    
427     if (!initialized_) initialize();
428    
429     AtomType* atype1 = SClist[*atid1];
430    
431     return 2.0 * getAlpha(atype1);
432     }
433    
434     void SC::do_sc_pair(int *atid1, int *atid2, RealType *d, RealType *rij,
435     RealType *r2, RealType *sw, RealType *vpair,
436     RealType *pot, RealType *f1, RealType *rho1,
437     RealType *rho2, RealType *dfrho1, RealType *dfrho2,
438     RealType *fshift1, RealType *fshift2) {
439    
440     if (!initialized_) initialize();
441    
442     AtomType* atype1 = SClist[*atid1];
443     AtomType* atype2 = SClist[*atid2];
444    
445     Vector3d disp(d[0], d[1], d[2]);
446     Vector3d frc(f1[0], f1[1], f1[2]);
447    
448     calcForce(atype1, atype2, disp, *rij, *r2, *sw, *vpair, *pot, frc,
449     *rho1, *rho2, *dfrho1, *dfrho2, *fshift1, *fshift2);
450    
451     f1[0] = frc.x();
452     f1[1] = frc.y();
453     f1[2] = frc.z();
454    
455     return;
456     }
457    
458     void SC::setCutoffSC(RealType *thisRcut) {
459     scRcut_ = *thisRcut;
460     }
461     }
462    
463     extern "C" {
464    
465     #define fortranCalcDensity FC_FUNC(calc_sc_prepair_rho, CALC_SC_PREPAIR_RHO)
466     #define fortranCalcFunctional FC_FUNC(calc_sc_preforce_frho, CALC_SC_PREFORCE_FRHO)
467     #define fortranCalcForce FC_FUNC(do_sc_pair, DO_SC_PAIR)
468     #define fortranSetCutoffSC FC_FUNC(setcutoffsc, SETCUTOFFSC)
469     #define fortranGetSCcut FC_FUNC(getsccut, GETSCCUT)
470    
471    
472     void fortranCalcDensity(int *atid1, int *atid2, RealType *rij,
473     RealType *rho_i_at_j, RealType *rho_j_at_i) {
474    
475     return OpenMD::SC::Instance()->calc_sc_prepair_rho(atid1, atid2, rij,
476     rho_i_at_j,
477     rho_j_at_i);
478     }
479     void fortranCalcFunctional(int *atid1, RealType *rho, RealType *frho,
480     RealType *dfrhodrho) {
481    
482     return OpenMD::SC::Instance()->calc_sc_preforce_Frho(atid1, rho, frho,
483     dfrhodrho);
484    
485     }
486     void fortranSetCutoffSC(RealType *rcut) {
487     return OpenMD::SC::Instance()->setCutoffSC(rcut);
488     }
489     void fortranCalcForce(int *atid1, int *atid2, RealType *d, RealType *rij,
490     RealType *r2, RealType *sw, RealType *vpair,
491     RealType *pot, RealType *f1, RealType *rho1,
492     RealType *rho2, RealType *dfrho1, RealType *dfrho2,
493     RealType *fshift1, RealType *fshift2){
494    
495     return OpenMD::SC::Instance()->do_sc_pair(atid1, atid2, d, rij,
496     r2, sw, vpair,
497     pot, f1, rho1,
498     rho2, dfrho1, dfrho2,
499     fshift1, fshift2);
500     }
501     RealType fortranGetSCcut(int* atid) {
502     return OpenMD::SC::Instance()->getSCcut(atid);
503     }
504    
505     }

Properties

Name Value
svn:eol-style native