ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/nonbonded/Morse.cpp
Revision: 2017
Committed: Tue Sep 2 18:31:44 2014 UTC (10 years, 8 months ago) by gezelter
File size: 8125 byte(s)
Log Message:
Latest

File Contents

# User Rev Content
1 gezelter 1501 /*
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 1501 */
42    
43     #include <stdio.h>
44     #include <string.h>
45    
46     #include <cmath>
47     #include "nonbonded/Morse.hpp"
48     #include "utils/simError.h"
49 gezelter 1664 #include "types/MorseInteractionType.hpp"
50 gezelter 1501
51     using namespace std;
52    
53     namespace OpenMD {
54    
55 gezelter 1583 Morse::Morse() : name_("Morse"), initialized_(false), forceField_(NULL) {}
56 gezelter 1501
57     void Morse::initialize() {
58    
59 gezelter 1895 Mtypes.clear();
60     Mtids.clear();
61     MixingMap.clear();
62     Mtids.resize( forceField_->getNAtomType(), -1);
63    
64 gezelter 1501 ForceField::NonBondedInteractionTypeContainer* nbiTypes = forceField_->getNonBondedInteractionTypes();
65     ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
66 gezelter 1895 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
67 gezelter 1501 NonBondedInteractionType* nbt;
68 gezelter 1895 int mtid1, mtid2;
69 gezelter 1501
70     for (nbt = nbiTypes->beginType(j); nbt != NULL;
71     nbt = nbiTypes->nextType(j)) {
72    
73     if (nbt->isMorse()) {
74 gezelter 1664 keys = nbiTypes->getKeys(j);
75     AtomType* at1 = forceField_->getAtomType(keys[0]);
76     AtomType* at2 = forceField_->getAtomType(keys[1]);
77 gezelter 1501
78 gezelter 1895 int atid1 = at1->getIdent();
79     if (Mtids[atid1] == -1) {
80     mtid1 = Mtypes.size();
81     Mtypes.insert(atid1);
82     Mtids[atid1] = mtid1;
83     }
84     int atid2 = at2->getIdent();
85     if (Mtids[atid2] == -1) {
86     mtid2 = Mtypes.size();
87     Mtypes.insert(atid2);
88     Mtids[atid2] = mtid2;
89     }
90    
91 gezelter 1664 MorseInteractionType* mit = dynamic_cast<MorseInteractionType*>(nbt);
92 gezelter 1501
93 gezelter 1664 if (mit == NULL) {
94 gezelter 1501 sprintf( painCave.errMsg,
95 gezelter 1664 "Morse::initialize could not convert NonBondedInteractionType\n"
96     "\tto MorseInteractionType for %s - %s interaction.\n",
97     at1->getName().c_str(),
98     at2->getName().c_str());
99 gezelter 1501 painCave.severity = OPENMD_ERROR;
100     painCave.isFatal = 1;
101     simError();
102     }
103 gezelter 1664
104     RealType De = mit->getD();
105     RealType Re = mit->getR();
106     RealType beta = mit->getBeta();
107    
108     MorseType variant = mit->getInteractionType();
109     addExplicitInteraction(at1, at2, De, Re, beta, variant );
110 gezelter 1501 }
111     }
112     initialized_ = true;
113     }
114    
115     void Morse::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
116     RealType De, RealType Re, RealType beta,
117 gezelter 1664 MorseType mt) {
118 gezelter 1501
119     MorseInteractionData mixer;
120     mixer.De = De;
121     mixer.Re = Re;
122     mixer.beta = beta;
123 gezelter 1664 mixer.variant = mt;
124 gezelter 1501
125 gezelter 1895 int mtid1 = Mtids[atype1->getIdent()];
126     int mtid2 = Mtids[atype2->getIdent()];
127     int nM = Mtypes.size();
128    
129     MixingMap.resize(nM);
130     MixingMap[mtid1].resize(nM);
131 gezelter 1501
132 gezelter 1895 MixingMap[mtid1][mtid2] = mixer;
133     if (mtid2 != mtid1) {
134     MixingMap[mtid2].resize(nM);
135     MixingMap[mtid2][mtid1] = mixer;
136 gezelter 1501 }
137     }
138    
139 gezelter 1536 void Morse::calcForce(InteractionData &idat) {
140 gezelter 1501
141     if (!initialized_) initialize();
142    
143 gezelter 1895 MorseInteractionData &mixer = MixingMap[Mtids[idat.atid1]][Mtids[idat.atid2]];
144    
145     RealType myPot = 0.0;
146     RealType myPotC = 0.0;
147     RealType myDeriv = 0.0;
148     RealType myDerivC = 0.0;
149    
150     RealType De = mixer.De;
151     RealType Re = mixer.Re;
152     RealType beta = mixer.beta;
153     MorseType variant = mixer.variant;
154    
155     // V(r) = D_e exp(-a(r-re)(exp(-a(r-re))-2)
156    
157     RealType expt = -beta*( *(idat.rij) - Re);
158     RealType expfnc = exp(expt);
159     RealType expfnc2 = expfnc*expfnc;
160    
161     RealType exptC = 0.0;
162     RealType expfncC = 0.0;
163     RealType expfnc2C = 0.0;
164    
165     if (idat.shiftedPot || idat.shiftedForce) {
166     exptC = -beta*( *(idat.rcut) - Re);
167     expfncC = exp(exptC);
168     expfnc2C = expfncC*expfncC;
169     }
170    
171    
172     switch(variant) {
173     case mtShifted : {
174 gezelter 1505
175 gezelter 1895 myPot = De * (expfnc2 - 2.0 * expfnc);
176     myDeriv = 2.0 * De * beta * (expfnc - expfnc2);
177 gezelter 1505
178 gezelter 1895 if (idat.shiftedPot) {
179     myPotC = De * (expfnc2C - 2.0 * expfncC);
180     myDerivC = 0.0;
181     } else if (idat.shiftedForce) {
182     myPotC = De * (expfnc2C - 2.0 * expfncC);
183     myDerivC = 2.0 * De * beta * (expfncC - expfnc2C);
184     myPotC += myDerivC * ( *(idat.rij) - *(idat.rcut) );
185     } else {
186     myPotC = 0.0;
187     myDerivC = 0.0;
188 gezelter 1501 }
189 gezelter 1505
190 gezelter 1895 break;
191     }
192     case mtRepulsive : {
193    
194     myPot = De * expfnc2;
195     myDeriv = -2.0 * De * beta * expfnc2;
196 gezelter 1505
197 gezelter 1895 if (idat.shiftedPot) {
198     myPotC = De * expfnc2C;
199     myDerivC = 0.0;
200     } else if (idat.shiftedForce) {
201     myPotC = De * expfnc2C;
202     myDerivC = -2.0 * De * beta * expfnc2C;
203     myPotC += myDerivC * ( *(idat.rij) - *(idat.rcut));
204     } else {
205     myPotC = 0.0;
206     myDerivC = 0.0;
207 gezelter 1501 }
208 gezelter 1505
209 gezelter 1895 break;
210 gezelter 1501 }
211 gezelter 1895 case mtUnknown: {
212     // don't know what to do so don't do anything
213     break;
214     }
215     }
216 gezelter 1501
217 gezelter 2017
218 gezelter 1895 RealType pot_temp = *(idat.vdwMult) * (myPot - myPotC);
219     *(idat.vpair) += pot_temp;
220    
221     RealType dudr = *(idat.sw) * *(idat.vdwMult) * (myDeriv - myDerivC);
222 gezelter 2017
223 gezelter 1895
224     (*(idat.pot))[VANDERWAALS_FAMILY] += *(idat.sw) * pot_temp;
225     *(idat.f1) = *(idat.d) * dudr / *(idat.rij);
226    
227     return;
228 gezelter 1505 }
229 gezelter 1895
230 gezelter 1545 RealType Morse::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
231 gezelter 1505 if (!initialized_) initialize();
232 gezelter 1895
233     int atid1 = atypes.first->getIdent();
234     int atid2 = atypes.second->getIdent();
235     int mtid1 = Mtids[atid1];
236     int mtid2 = Mtids[atid2];
237    
238     if ( mtid1 == -1 || mtid2 == -1) return 0.0;
239     else {
240     MorseInteractionData mixer = MixingMap[mtid1][mtid2];
241 gezelter 1505 RealType Re = mixer.Re;
242     RealType beta = mixer.beta;
243     // This value of the r corresponds to an energy about 1.48% of
244     // the energy at the bottom of the Morse well. For comparison, the
245     // Lennard-Jones function is about 1.63% of it's minimum value at
246     // a distance of 2.5 sigma.
247     return (4.9 + beta * Re) / beta;
248     }
249 gezelter 1501 }
250     }
251    

Properties

Name Value
svn:eol-style native