ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/InteractionManager.cpp
Revision: 1550
Committed: Wed Apr 27 21:49:59 2011 UTC (14 years ago) by gezelter
File size: 22137 byte(s)
Log Message:
more fortran removal

File Contents

# Content
1 /*
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 "nonbonded/InteractionManager.hpp"
43
44 namespace OpenMD {
45
46 InteractionManager* InteractionManager::_instance = NULL;
47 SimInfo* InteractionManager::info_ = NULL;
48 bool InteractionManager::initialized_ = false;
49
50 RealType InteractionManager::rCut_ = 0.0;
51 RealType InteractionManager::rSwitch_ = 0.0;
52 RealType InteractionManager::skinThickness_ = 0.0;
53 RealType InteractionManager::listRadius_ = 0.0;
54 CutoffMethod InteractionManager::cutoffMethod_ = SHIFTED_FORCE;
55 SwitchingFunctionType InteractionManager::sft_ = cubic;
56 RealType InteractionManager::vdwScale_[4] = {1.0, 0.0, 0.0, 0.0};
57 RealType InteractionManager::electrostaticScale_[4] = {1.0, 0.0, 0.0, 0.0};
58
59 map<int, AtomType*> InteractionManager::typeMap_;
60 map<pair<AtomType*, AtomType*>, set<NonBondedInteraction*> > InteractionManager::interactions_;
61
62 LJ* InteractionManager::lj_ = new LJ();
63 GB* InteractionManager::gb_ = new GB();
64 Sticky* InteractionManager::sticky_ = new Sticky();
65 Morse* InteractionManager::morse_ = new Morse();
66 EAM* InteractionManager::eam_ = new EAM();
67 SC* InteractionManager::sc_ = new SC();
68 Electrostatic* InteractionManager::electrostatic_ = new Electrostatic();
69 MAW* InteractionManager::maw_ = new MAW();
70 SwitchingFunction* InteractionManager::switcher_ = new SwitchingFunction();
71
72 InteractionManager* InteractionManager::Instance() {
73 if (!_instance) {
74 _instance = new InteractionManager();
75 }
76 return _instance;
77 }
78
79 void InteractionManager::initialize() {
80
81 ForceField* forceField_ = info_->getForceField();
82
83 lj_->setForceField(forceField_);
84 gb_->setForceField(forceField_);
85 sticky_->setForceField(forceField_);
86 eam_->setForceField(forceField_);
87 sc_->setForceField(forceField_);
88 morse_->setForceField(forceField_);
89 electrostatic_->setForceField(forceField_);
90 maw_->setForceField(forceField_);
91
92 ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
93
94 // Force fields can set options on how to scale van der Waals and electrostatic
95 // interactions for atoms connected via bonds, bends and torsions
96 // in this case the topological distance between atoms is:
97 // 0 = topologically unconnected
98 // 1 = bonded together
99 // 2 = connected via a bend
100 // 3 = connected via a torsion
101
102 vdwScale_[0] = 1.0;
103 vdwScale_[1] = fopts.getvdw12scale();
104 vdwScale_[2] = fopts.getvdw13scale();
105 vdwScale_[3] = fopts.getvdw14scale();
106
107 electrostaticScale_[0] = 1.0;
108 electrostaticScale_[1] = fopts.getelectrostatic12scale();
109 electrostaticScale_[2] = fopts.getelectrostatic13scale();
110 electrostaticScale_[3] = fopts.getelectrostatic14scale();
111
112 ForceField::AtomTypeContainer* atomTypes = forceField_->getAtomTypes();
113 ForceField::AtomTypeContainer::MapTypeIterator i1, i2;
114 AtomType* atype1;
115 AtomType* atype2;
116 pair<AtomType*, AtomType*> key;
117 pair<set<NonBondedInteraction*>::iterator, bool> ret;
118
119 for (atype1 = atomTypes->beginType(i1); atype1 != NULL;
120 atype1 = atomTypes->nextType(i1)) {
121
122 // add it to the map:
123 AtomTypeProperties atp = atype1->getATP();
124
125 pair<map<int,AtomType*>::iterator,bool> ret;
126 ret = typeMap_.insert( pair<int, AtomType*>(atp.ident, atype1) );
127 if (ret.second == false) {
128 sprintf( painCave.errMsg,
129 "InteractionManager already had a previous entry with ident %d\n",
130 atp.ident);
131 painCave.severity = OPENMD_INFO;
132 painCave.isFatal = 0;
133 simError();
134 }
135 }
136
137 // Now, iterate over all known types and add to the interaction map:
138
139 map<int, AtomType*>::iterator it1, it2;
140 for (it1 = typeMap_.begin(); it1 != typeMap_.end(); ++it1) {
141 atype1 = (*it1).second;
142
143 for( it2 = typeMap_.begin(); it2 != typeMap_.end(); ++it2) {
144 atype2 = (*it2).second;
145
146 bool vdwExplicit = false;
147 bool metExplicit = false;
148 bool hbExplicit = false;
149
150 key = make_pair(atype1, atype2);
151
152 if (atype1->isLennardJones() && atype2->isLennardJones()) {
153 interactions_[key].insert(lj_);
154 }
155 if (atype1->isElectrostatic() && atype2->isElectrostatic() ) {
156 interactions_[key].insert(electrostatic_);
157 }
158 if (atype1->isSticky() && atype2->isSticky() ) {
159 interactions_[key].insert(sticky_);
160 }
161 if (atype1->isStickyPower() && atype2->isStickyPower() ) {
162 interactions_[key].insert(sticky_);
163 }
164 if (atype1->isEAM() && atype2->isEAM() ) {
165 interactions_[key].insert(eam_);
166 }
167 if (atype1->isSC() && atype2->isSC() ) {
168 interactions_[key].insert(sc_);
169 }
170 if (atype1->isGayBerne() && atype2->isGayBerne() ) {
171 interactions_[key].insert(gb_);
172 }
173 if ((atype1->isGayBerne() && atype2->isLennardJones())
174 || (atype1->isLennardJones() && atype2->isGayBerne())) {
175 interactions_[key].insert(gb_);
176 }
177
178 // look for an explicitly-set non-bonded interaction type using the
179 // two atom types.
180 NonBondedInteractionType* nbiType = forceField_->getNonBondedInteractionType(atype1->getName(), atype2->getName());
181
182 if (nbiType != NULL) {
183
184 if (nbiType->isLennardJones()) {
185 // We found an explicit Lennard-Jones interaction.
186 // override all other vdw entries for this pair of atom types:
187 set<NonBondedInteraction*>::iterator it;
188 for (it = interactions_[key].begin();
189 it != interactions_[key].end(); ++it) {
190 InteractionFamily ifam = (*it)->getFamily();
191 if (ifam == VANDERWAALS_FAMILY) interactions_[key].erase(*it);
192 }
193 interactions_[key].insert(lj_);
194 vdwExplicit = true;
195 }
196
197 if (nbiType->isMorse()) {
198 if (vdwExplicit) {
199 sprintf( painCave.errMsg,
200 "InteractionManager::initialize found more than one "
201 "explicit \n"
202 "\tvan der Waals interaction for atom types %s - %s\n",
203 atype1->getName().c_str(), atype2->getName().c_str());
204 painCave.severity = OPENMD_ERROR;
205 painCave.isFatal = 1;
206 simError();
207 }
208 // We found an explicit Morse interaction.
209 // override all other vdw entries for this pair of atom types:
210 set<NonBondedInteraction*>::iterator it;
211 for (it = interactions_[key].begin();
212 it != interactions_[key].end(); ++it) {
213 InteractionFamily ifam = (*it)->getFamily();
214 if (ifam == VANDERWAALS_FAMILY) interactions_[key].erase(*it);
215 }
216 interactions_[key].insert(morse_);
217 vdwExplicit = true;
218 }
219
220 if (nbiType->isEAM()) {
221 // We found an explicit EAM interaction.
222 // override all other metallic entries for this pair of atom types:
223 set<NonBondedInteraction*>::iterator it;
224 for (it = interactions_[key].begin();
225 it != interactions_[key].end(); ++it) {
226 InteractionFamily ifam = (*it)->getFamily();
227 if (ifam == METALLIC_FAMILY) interactions_[key].erase(*it);
228 }
229 interactions_[key].insert(eam_);
230 metExplicit = true;
231 }
232
233 if (nbiType->isSC()) {
234 if (metExplicit) {
235 sprintf( painCave.errMsg,
236 "InteractionManager::initialize found more than one "
237 "explicit\n"
238 "\tmetallic interaction for atom types %s - %s\n",
239 atype1->getName().c_str(), atype2->getName().c_str());
240 painCave.severity = OPENMD_ERROR;
241 painCave.isFatal = 1;
242 simError();
243 }
244 // We found an explicit Sutton-Chen interaction.
245 // override all other metallic entries for this pair of atom types:
246 set<NonBondedInteraction*>::iterator it;
247 for (it = interactions_[key].begin();
248 it != interactions_[key].end(); ++it) {
249 InteractionFamily ifam = (*it)->getFamily();
250 if (ifam == METALLIC_FAMILY) interactions_[key].erase(*it);
251 }
252 interactions_[key].insert(sc_);
253 metExplicit = true;
254 }
255
256 if (nbiType->isMAW()) {
257 if (vdwExplicit) {
258 sprintf( painCave.errMsg,
259 "InteractionManager::initialize found more than one "
260 "explicit\n"
261 "\tvan der Waals interaction for atom types %s - %s\n",
262 atype1->getName().c_str(), atype2->getName().c_str());
263 painCave.severity = OPENMD_ERROR;
264 painCave.isFatal = 1;
265 simError();
266 }
267 // We found an explicit MAW interaction.
268 // override all other vdw entries for this pair of atom types:
269 set<NonBondedInteraction*>::iterator it;
270 for (it = interactions_[key].begin();
271 it != interactions_[key].end(); ++it) {
272 InteractionFamily ifam = (*it)->getFamily();
273 if (ifam == VANDERWAALS_FAMILY) interactions_[key].erase(*it);
274 }
275 interactions_[key].insert(maw_);
276 vdwExplicit = true;
277 }
278 }
279 }
280 }
281
282
283 // make sure every pair of atom types in this simulation has a
284 // non-bonded interaction:
285
286 set<AtomType*> simTypes = info_->getSimulatedAtomTypes();
287 set<AtomType*>::iterator it, jt;
288 for (it = simTypes.begin(); it != simTypes.end(); ++it) {
289 atype1 = (*it);
290 for (jt = simTypes.begin(); jt != simTypes.end(); ++jt) {
291 atype2 = (*jt);
292 key = make_pair(atype1, atype2);
293
294 if (interactions_[key].size() == 0) {
295 sprintf( painCave.errMsg,
296 "InteractionManager unable to find an appropriate non-bonded\n"
297 "\tinteraction for atom types %s - %s\n",
298 atype1->getName().c_str(), atype2->getName().c_str());
299 painCave.severity = OPENMD_INFO;
300 painCave.isFatal = 1;
301 simError();
302 }
303 }
304 }
305
306 setupCutoffs();
307 setupSwitching();
308 setupNeighborlists();
309
310 //int ljsp = cutoffMethod_ == SHIFTED_POTENTIAL ? 1 : 0;
311 //int ljsf = cutoffMethod_ == SHIFTED_FORCE ? 1 : 0;
312 //notifyFortranCutoffs(&rCut_, &rSwitch_, &ljsp, &ljsf);
313 //notifyFortranSkinThickness(&skinThickness_);
314
315 initialized_ = true;
316 }
317
318 /**
319 * setupCutoffs
320 *
321 * Sets the values of cutoffRadius and cutoffMethod
322 *
323 * cutoffRadius : realType
324 * If the cutoffRadius was explicitly set, use that value.
325 * If the cutoffRadius was not explicitly set:
326 * Are there electrostatic atoms? Use 12.0 Angstroms.
327 * No electrostatic atoms? Poll the atom types present in the
328 * simulation for suggested cutoff values (e.g. 2.5 * sigma).
329 * Use the maximum suggested value that was found.
330 *
331 * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE, SHIFTED_POTENTIAL)
332 * If cutoffMethod was explicitly set, use that choice.
333 * If cutoffMethod was not explicitly set, use SHIFTED_FORCE
334 */
335 void InteractionManager::setupCutoffs() {
336
337 Globals* simParams_ = info_->getSimParams();
338
339 if (simParams_->haveCutoffRadius()) {
340 rCut_ = simParams_->getCutoffRadius();
341 } else {
342 if (info_->usesElectrostaticAtoms()) {
343 sprintf(painCave.errMsg,
344 "InteractionManager::setupCutoffs: No value was set for the cutoffRadius.\n"
345 "\tOpenMD will use a default value of 12.0 angstroms"
346 "\tfor the cutoffRadius.\n");
347 painCave.isFatal = 0;
348 painCave.severity = OPENMD_INFO;
349 simError();
350 rCut_ = 12.0;
351 } else {
352 RealType thisCut;
353 set<AtomType*>::iterator i;
354 set<AtomType*> atomTypes;
355 atomTypes = info_->getSimulatedAtomTypes();
356 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
357 thisCut = getSuggestedCutoffRadius((*i));
358 rCut_ = max(thisCut, rCut_);
359 }
360 sprintf(painCave.errMsg,
361 "InteractionManager::setupCutoffs: No value was set for the cutoffRadius.\n"
362 "\tOpenMD will use %lf angstroms.\n",
363 rCut_);
364 painCave.isFatal = 0;
365 painCave.severity = OPENMD_INFO;
366 simError();
367 }
368 }
369
370 map<string, CutoffMethod> stringToCutoffMethod;
371 stringToCutoffMethod["HARD"] = HARD;
372 stringToCutoffMethod["SWITCHED"] = SWITCHED;
373 stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;
374 stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE;
375
376 if (simParams_->haveCutoffMethod()) {
377 string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
378 map<string, CutoffMethod>::iterator i;
379 i = stringToCutoffMethod.find(cutMeth);
380 if (i == stringToCutoffMethod.end()) {
381 sprintf(painCave.errMsg,
382 "InteractionManager::setupCutoffs: Could not find chosen cutoffMethod %s\n"
383 "\tShould be one of: "
384 "HARD, SWITCHED, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n",
385 cutMeth.c_str());
386 painCave.isFatal = 1;
387 painCave.severity = OPENMD_ERROR;
388 simError();
389 } else {
390 cutoffMethod_ = i->second;
391 }
392 } else {
393 sprintf(painCave.errMsg,
394 "InteractionManager::setupCutoffs: No value was set for the cutoffMethod.\n"
395 "\tOpenMD will use SHIFTED_FORCE.\n");
396 painCave.isFatal = 0;
397 painCave.severity = OPENMD_INFO;
398 simError();
399 cutoffMethod_ = SHIFTED_FORCE;
400 }
401 }
402
403
404 /**
405 * setupSwitching
406 *
407 * Sets the values of switchingRadius and
408 * If the switchingRadius was explicitly set, use that value (but check it)
409 * If the switchingRadius was not explicitly set: use 0.85 * cutoffRadius_
410 */
411 void InteractionManager::setupSwitching() {
412 Globals* simParams_ = info_->getSimParams();
413
414 if (simParams_->haveSwitchingRadius()) {
415 rSwitch_ = simParams_->getSwitchingRadius();
416 if (rSwitch_ > rCut_) {
417 sprintf(painCave.errMsg,
418 "InteractionManager::setupSwitching: switchingRadius (%f) is larger than cutoffRadius(%f)\n",
419 rSwitch_, rCut_);
420 painCave.isFatal = 1;
421 painCave.severity = OPENMD_ERROR;
422 simError();
423 }
424 } else {
425 rSwitch_ = 0.85 * rCut_;
426 sprintf(painCave.errMsg,
427 "InteractionManager::setupSwitching: No value was set for the switchingRadius.\n"
428 "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n"
429 "\tswitchingRadius = %f. for this simulation\n", rSwitch_);
430 painCave.isFatal = 0;
431 painCave.severity = OPENMD_WARNING;
432 simError();
433 }
434
435 if (simParams_->haveSwitchingFunctionType()) {
436 string funcType = simParams_->getSwitchingFunctionType();
437 toUpper(funcType);
438 if (funcType == "CUBIC") {
439 sft_ = cubic;
440 } else {
441 if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
442 sft_ = fifth_order_poly;
443 } else {
444 // throw error
445 sprintf( painCave.errMsg,
446 "InteractionManager::setupSwitching : Unknown switchingFunctionType. (Input file specified %s .)\n"
447 "\tswitchingFunctionType must be one of: "
448 "\"cubic\" or \"fifth_order_polynomial\".",
449 funcType.c_str() );
450 painCave.isFatal = 1;
451 painCave.severity = OPENMD_ERROR;
452 simError();
453 }
454 }
455 }
456
457 switcher_->setSwitchType(sft_);
458 switcher_->setSwitch(rSwitch_, rCut_);
459 }
460
461 /**
462 * setupNeighborlists
463 *
464 * If the skinThickness was explicitly set, use that value (but check it)
465 * If the skinThickness was not explicitly set: use 1.0 angstroms
466 */
467 void InteractionManager::setupNeighborlists() {
468
469 Globals* simParams_ = info_->getSimParams();
470
471 if (simParams_->haveSkinThickness()) {
472 skinThickness_ = simParams_->getSkinThickness();
473 } else {
474 skinThickness_ = 1.0;
475 sprintf(painCave.errMsg,
476 "InteractionManager::setupNeighborlists: No value was set for the skinThickness.\n"
477 "\tOpenMD will use a default value of %f Angstroms\n"
478 "\tfor this simulation\n", skinThickness_);
479 painCave.severity = OPENMD_INFO;
480 painCave.isFatal = 0;
481 simError();
482 }
483
484 listRadius_ = rCut_ + skinThickness_;
485 }
486
487
488 void InteractionManager::doPrePair(InteractionData idat){
489
490 if (!initialized_) initialize();
491
492 set<NonBondedInteraction*>::iterator it;
493
494 for (it = interactions_[idat.atypes].begin();
495 it != interactions_[idat.atypes].end(); ++it){
496 if ((*it)->getFamily() == METALLIC_FAMILY) {
497 dynamic_cast<MetallicInteraction*>(*it)->calcDensity(idat);
498 }
499 }
500
501 return;
502 }
503
504 void InteractionManager::doPreForce(SelfData sdat){
505
506 if (!initialized_) initialize();
507
508 pair<AtomType*, AtomType*> key = make_pair(sdat.atype, sdat.atype);
509 set<NonBondedInteraction*>::iterator it;
510
511 for (it = interactions_[key].begin(); it != interactions_[key].end(); ++it){
512 if ((*it)->getFamily() == METALLIC_FAMILY) {
513 dynamic_cast<MetallicInteraction*>(*it)->calcFunctional(sdat);
514 }
515 }
516
517 return;
518 }
519
520 void InteractionManager::doPair(InteractionData idat){
521
522 if (!initialized_) initialize();
523
524 set<NonBondedInteraction*>::iterator it;
525
526 for (it = interactions_[idat.atypes].begin();
527 it != interactions_[idat.atypes].end(); ++it)
528 (*it)->calcForce(idat);
529
530 return;
531 }
532
533 void InteractionManager::doSkipCorrection(InteractionData idat){
534
535 if (!initialized_) initialize();
536
537 set<NonBondedInteraction*>::iterator it;
538
539 for (it = interactions_[idat.atypes].begin();
540 it != interactions_[idat.atypes].end(); ++it){
541 if ((*it)->getFamily() == ELECTROSTATIC_FAMILY) {
542 dynamic_cast<ElectrostaticInteraction*>(*it)->calcSkipCorrection(idat);
543 }
544 }
545
546 return;
547 }
548
549 void InteractionManager::doSelfCorrection(SelfData sdat){
550
551 if (!initialized_) initialize();
552
553 pair<AtomType*, AtomType*> key = make_pair(sdat.atype, sdat.atype);
554 set<NonBondedInteraction*>::iterator it;
555
556 for (it = interactions_[key].begin(); it != interactions_[key].end(); ++it){
557 if ((*it)->getFamily() == ELECTROSTATIC_FAMILY) {
558 dynamic_cast<ElectrostaticInteraction*>(*it)->calcSelfCorrection(sdat);
559 }
560 }
561
562 return;
563 }
564
565 RealType InteractionManager::getSuggestedCutoffRadius(int *atid) {
566 if (!initialized_) initialize();
567
568 AtomType* atype = typeMap_[*atid];
569
570 pair<AtomType*, AtomType*> key = make_pair(atype, atype);
571 set<NonBondedInteraction*>::iterator it;
572 RealType cutoff = 0.0;
573
574 for (it = interactions_[key].begin(); it != interactions_[key].end(); ++it)
575 cutoff = max(cutoff, (*it)->getSuggestedCutoffRadius(key));
576 return cutoff;
577 }
578
579 RealType InteractionManager::getSuggestedCutoffRadius(AtomType* atype) {
580 if (!initialized_) initialize();
581
582 pair<AtomType*, AtomType*> key = make_pair(atype, atype);
583 set<NonBondedInteraction*>::iterator it;
584 RealType cutoff = 0.0;
585
586 for (it = interactions_[key].begin(); it != interactions_[key].end(); ++it)
587 cutoff = max(cutoff, (*it)->getSuggestedCutoffRadius(key));
588 return cutoff;
589 }
590 } //end namespace OpenMD

Properties

Name Value
svn:eol-style native
svn:executable *