ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1665
Committed: Tue Nov 22 20:38:56 2011 UTC (13 years, 5 months ago) by gezelter
File size: 31565 byte(s)
Log Message:
updated copyright notices

File Contents

# User Rev Content
1 gezelter 507 /*
2 gezelter 246 * 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 gezelter 1390 * 1. Redistributions of source code must retain the above copyright
10 gezelter 246 * notice, this list of conditions and the following disclaimer.
11     *
12 gezelter 1390 * 2. Redistributions in binary form must reproduce the above copyright
13 gezelter 246 * 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 gezelter 1390 *
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 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 246 */
42    
43 gezelter 507 /**
44     * @file ForceManager.cpp
45     * @author tlin
46     * @date 11/09/2004
47     * @time 10:39am
48     * @version 1.0
49     */
50 gezelter 246
51 gezelter 1576
52 gezelter 246 #include "brains/ForceManager.hpp"
53     #include "primitives/Molecule.hpp"
54 gezelter 1390 #define __OPENMD_C
55 gezelter 246 #include "utils/simError.h"
56 xsun 1215 #include "primitives/Bond.hpp"
57 tim 749 #include "primitives/Bend.hpp"
58 cli2 1275 #include "primitives/Torsion.hpp"
59     #include "primitives/Inversion.hpp"
60 gezelter 1551 #include "nonbonded/NonBondedInteraction.hpp"
61 gezelter 1549 #include "parallel/ForceMatrixDecomposition.hpp"
62 gezelter 1467
63 gezelter 1583 #include <cstdio>
64     #include <iostream>
65     #include <iomanip>
66    
67 gezelter 1545 using namespace std;
68 gezelter 1390 namespace OpenMD {
69 gezelter 1469
70 gezelter 1545 ForceManager::ForceManager(SimInfo * info) : info_(info) {
71 gezelter 1576 forceField_ = info_->getForceField();
72 gezelter 1577 interactionMan_ = new InteractionManager();
73 gezelter 1579 fDecomp_ = new ForceMatrixDecomposition(info_, interactionMan_);
74 gezelter 1469 }
75 gezelter 1576
76     /**
77     * setupCutoffs
78     *
79 gezelter 1587 * Sets the values of cutoffRadius, switchingRadius, cutoffMethod,
80     * and cutoffPolicy
81 gezelter 1576 *
82     * cutoffRadius : realType
83     * If the cutoffRadius was explicitly set, use that value.
84     * If the cutoffRadius was not explicitly set:
85     * Are there electrostatic atoms? Use 12.0 Angstroms.
86     * No electrostatic atoms? Poll the atom types present in the
87     * simulation for suggested cutoff values (e.g. 2.5 * sigma).
88     * Use the maximum suggested value that was found.
89     *
90 gezelter 1590 * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE,
91     * or SHIFTED_POTENTIAL)
92 gezelter 1576 * If cutoffMethod was explicitly set, use that choice.
93     * If cutoffMethod was not explicitly set, use SHIFTED_FORCE
94     *
95     * cutoffPolicy : (one of MIX, MAX, TRADITIONAL)
96     * If cutoffPolicy was explicitly set, use that choice.
97     * If cutoffPolicy was not explicitly set, use TRADITIONAL
98 gezelter 1587 *
99     * switchingRadius : realType
100     * If the cutoffMethod was set to SWITCHED:
101     * If the switchingRadius was explicitly set, use that value
102     * (but do a sanity check first).
103     * If the switchingRadius was not explicitly set: use 0.85 *
104     * cutoffRadius_
105     * If the cutoffMethod was not set to SWITCHED:
106     * Set switchingRadius equal to cutoffRadius for safety.
107 gezelter 1576 */
108     void ForceManager::setupCutoffs() {
109    
110     Globals* simParams_ = info_->getSimParams();
111     ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions();
112 gezelter 1613 int mdFileVersion;
113 gezelter 1576
114 gezelter 1613 if (simParams_->haveMDfileVersion())
115     mdFileVersion = simParams_->getMDfileVersion();
116     else
117     mdFileVersion = 0;
118    
119 gezelter 1576 if (simParams_->haveCutoffRadius()) {
120     rCut_ = simParams_->getCutoffRadius();
121     } else {
122     if (info_->usesElectrostaticAtoms()) {
123     sprintf(painCave.errMsg,
124     "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
125     "\tOpenMD will use a default value of 12.0 angstroms"
126     "\tfor the cutoffRadius.\n");
127     painCave.isFatal = 0;
128     painCave.severity = OPENMD_INFO;
129     simError();
130     rCut_ = 12.0;
131     } else {
132     RealType thisCut;
133     set<AtomType*>::iterator i;
134     set<AtomType*> atomTypes;
135     atomTypes = info_->getSimulatedAtomTypes();
136     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
137     thisCut = interactionMan_->getSuggestedCutoffRadius((*i));
138     rCut_ = max(thisCut, rCut_);
139     }
140     sprintf(painCave.errMsg,
141     "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
142     "\tOpenMD will use %lf angstroms.\n",
143     rCut_);
144     painCave.isFatal = 0;
145     painCave.severity = OPENMD_INFO;
146     simError();
147 gezelter 1579 }
148 gezelter 1576 }
149    
150 gezelter 1583 fDecomp_->setUserCutoff(rCut_);
151 gezelter 1584 interactionMan_->setCutoffRadius(rCut_);
152 gezelter 1583
153 gezelter 1576 map<string, CutoffMethod> stringToCutoffMethod;
154     stringToCutoffMethod["HARD"] = HARD;
155     stringToCutoffMethod["SWITCHED"] = SWITCHED;
156     stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;
157     stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE;
158 gezelter 1545
159 gezelter 1576 if (simParams_->haveCutoffMethod()) {
160     string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
161     map<string, CutoffMethod>::iterator i;
162     i = stringToCutoffMethod.find(cutMeth);
163     if (i == stringToCutoffMethod.end()) {
164     sprintf(painCave.errMsg,
165     "ForceManager::setupCutoffs: Could not find chosen cutoffMethod %s\n"
166     "\tShould be one of: "
167     "HARD, SWITCHED, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n",
168     cutMeth.c_str());
169     painCave.isFatal = 1;
170     painCave.severity = OPENMD_ERROR;
171     simError();
172     } else {
173     cutoffMethod_ = i->second;
174     }
175     } else {
176 gezelter 1616 if (mdFileVersion > 1) {
177     sprintf(painCave.errMsg,
178     "ForceManager::setupCutoffs: No value was set for the cutoffMethod.\n"
179     "\tOpenMD will use SHIFTED_FORCE.\n");
180     painCave.isFatal = 0;
181     painCave.severity = OPENMD_INFO;
182     simError();
183     cutoffMethod_ = SHIFTED_FORCE;
184     } else {
185     // handle the case where the old file version was in play
186     // (there should be no cutoffMethod, so we have to deduce it
187     // from other data).
188    
189     sprintf(painCave.errMsg,
190     "ForceManager::setupCutoffs : DEPRECATED FILE FORMAT!\n"
191     "\tOpenMD found a file which does not set a cutoffMethod.\n"
192     "\tOpenMD will attempt to deduce a cutoffMethod using the\n"
193     "\tbehavior of the older (version 1) code. To remove this\n"
194     "\twarning, add an explicit cutoffMethod and change the top\n"
195     "\tof the file so that it begins with <OpenMD version=2>\n");
196     painCave.isFatal = 0;
197     painCave.severity = OPENMD_WARNING;
198     simError();
199    
200     // The old file version tethered the shifting behavior to the
201     // electrostaticSummationMethod keyword.
202    
203     if (simParams_->haveElectrostaticSummationMethod()) {
204     std::string myMethod = simParams_->getElectrostaticSummationMethod();
205     toUpper(myMethod);
206    
207     if (myMethod == "SHIFTED_POTENTIAL") {
208     cutoffMethod_ = SHIFTED_POTENTIAL;
209     } else if (myMethod == "SHIFTED_FORCE") {
210     cutoffMethod_ = SHIFTED_FORCE;
211     }
212    
213     if (simParams_->haveSwitchingRadius())
214     rSwitch_ = simParams_->getSwitchingRadius();
215    
216     if (myMethod == "SHIFTED_POTENTIAL" || myMethod == "SHIFTED_FORCE") {
217     if (simParams_->haveSwitchingRadius()){
218     sprintf(painCave.errMsg,
219     "ForceManager::setupCutoffs : DEPRECATED ERROR MESSAGE\n"
220     "\tA value was set for the switchingRadius\n"
221     "\teven though the electrostaticSummationMethod was\n"
222     "\tset to %s\n", myMethod.c_str());
223     painCave.severity = OPENMD_WARNING;
224     painCave.isFatal = 1;
225     simError();
226     }
227     }
228     if (abs(rCut_ - rSwitch_) < 0.0001) {
229     if (cutoffMethod_ == SHIFTED_FORCE) {
230     sprintf(painCave.errMsg,
231     "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
232     "\tcutoffRadius and switchingRadius are set to the\n"
233     "\tsame value. OpenMD will use shifted force\n"
234     "\tpotentials instead of switching functions.\n");
235     painCave.isFatal = 0;
236     painCave.severity = OPENMD_WARNING;
237     simError();
238     } else {
239     cutoffMethod_ = SHIFTED_POTENTIAL;
240     sprintf(painCave.errMsg,
241     "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
242     "\tcutoffRadius and switchingRadius are set to the\n"
243     "\tsame value. OpenMD will use shifted potentials\n"
244     "\tinstead of switching functions.\n");
245     painCave.isFatal = 0;
246     painCave.severity = OPENMD_WARNING;
247     simError();
248     }
249     }
250     }
251     }
252 gezelter 1576 }
253    
254     map<string, CutoffPolicy> stringToCutoffPolicy;
255     stringToCutoffPolicy["MIX"] = MIX;
256     stringToCutoffPolicy["MAX"] = MAX;
257     stringToCutoffPolicy["TRADITIONAL"] = TRADITIONAL;
258    
259     std::string cutPolicy;
260     if (forceFieldOptions_.haveCutoffPolicy()){
261     cutPolicy = forceFieldOptions_.getCutoffPolicy();
262     }else if (simParams_->haveCutoffPolicy()) {
263     cutPolicy = simParams_->getCutoffPolicy();
264     }
265    
266     if (!cutPolicy.empty()){
267     toUpper(cutPolicy);
268     map<string, CutoffPolicy>::iterator i;
269     i = stringToCutoffPolicy.find(cutPolicy);
270    
271     if (i == stringToCutoffPolicy.end()) {
272     sprintf(painCave.errMsg,
273     "ForceManager::setupCutoffs: Could not find chosen cutoffPolicy %s\n"
274     "\tShould be one of: "
275     "MIX, MAX, or TRADITIONAL\n",
276     cutPolicy.c_str());
277     painCave.isFatal = 1;
278     painCave.severity = OPENMD_ERROR;
279     simError();
280     } else {
281     cutoffPolicy_ = i->second;
282     }
283     } else {
284     sprintf(painCave.errMsg,
285     "ForceManager::setupCutoffs: No value was set for the cutoffPolicy.\n"
286     "\tOpenMD will use TRADITIONAL.\n");
287     painCave.isFatal = 0;
288     painCave.severity = OPENMD_INFO;
289     simError();
290     cutoffPolicy_ = TRADITIONAL;
291     }
292 gezelter 1587
293 gezelter 1579 fDecomp_->setCutoffPolicy(cutoffPolicy_);
294 gezelter 1587
295     // create the switching function object:
296 gezelter 1576
297 gezelter 1577 switcher_ = new SwitchingFunction();
298 gezelter 1587
299     if (cutoffMethod_ == SWITCHED) {
300     if (simParams_->haveSwitchingRadius()) {
301     rSwitch_ = simParams_->getSwitchingRadius();
302     if (rSwitch_ > rCut_) {
303     sprintf(painCave.errMsg,
304     "ForceManager::setupCutoffs: switchingRadius (%f) is larger "
305     "than the cutoffRadius(%f)\n", rSwitch_, rCut_);
306     painCave.isFatal = 1;
307     painCave.severity = OPENMD_ERROR;
308     simError();
309     }
310     } else {
311     rSwitch_ = 0.85 * rCut_;
312 gezelter 1576 sprintf(painCave.errMsg,
313 gezelter 1587 "ForceManager::setupCutoffs: No value was set for the switchingRadius.\n"
314     "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n"
315     "\tswitchingRadius = %f. for this simulation\n", rSwitch_);
316     painCave.isFatal = 0;
317     painCave.severity = OPENMD_WARNING;
318 gezelter 1576 simError();
319     }
320 gezelter 1587 } else {
321 gezelter 1618 if (mdFileVersion > 1) {
322     // throw an error if we define a switching radius and don't need one.
323     // older file versions should not do this.
324     if (simParams_->haveSwitchingRadius()) {
325     map<string, CutoffMethod>::const_iterator it;
326     string theMeth;
327     for (it = stringToCutoffMethod.begin();
328     it != stringToCutoffMethod.end(); ++it) {
329     if (it->second == cutoffMethod_) {
330     theMeth = it->first;
331     break;
332     }
333 gezelter 1587 }
334 gezelter 1618 sprintf(painCave.errMsg,
335     "ForceManager::setupCutoffs: the cutoffMethod (%s)\n"
336     "\tis not set to SWITCHED, so switchingRadius value\n"
337     "\twill be ignored for this simulation\n", theMeth.c_str());
338     painCave.isFatal = 0;
339     painCave.severity = OPENMD_WARNING;
340     simError();
341 gezelter 1587 }
342     }
343     rSwitch_ = rCut_;
344     }
345 gezelter 1576
346 gezelter 1577 // Default to cubic switching function.
347     sft_ = cubic;
348 gezelter 1576 if (simParams_->haveSwitchingFunctionType()) {
349     string funcType = simParams_->getSwitchingFunctionType();
350     toUpper(funcType);
351     if (funcType == "CUBIC") {
352     sft_ = cubic;
353     } else {
354     if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
355     sft_ = fifth_order_poly;
356     } else {
357     // throw error
358     sprintf( painCave.errMsg,
359     "ForceManager::setupSwitching : Unknown switchingFunctionType. (Input file specified %s .)\n"
360     "\tswitchingFunctionType must be one of: "
361     "\"cubic\" or \"fifth_order_polynomial\".",
362     funcType.c_str() );
363     painCave.isFatal = 1;
364     painCave.severity = OPENMD_ERROR;
365     simError();
366     }
367     }
368     }
369     switcher_->setSwitchType(sft_);
370     switcher_->setSwitch(rSwitch_, rCut_);
371 gezelter 1584 interactionMan_->setSwitchingRadius(rSwitch_);
372 gezelter 1576 }
373 gezelter 1616
374    
375    
376 gezelter 1576
377     void ForceManager::initialize() {
378    
379 gezelter 1569 if (!info_->isTopologyDone()) {
380 gezelter 1590
381 gezelter 507 info_->update();
382 gezelter 1546 interactionMan_->setSimInfo(info_);
383     interactionMan_->initialize();
384 gezelter 1576
385     // We want to delay the cutoffs until after the interaction
386     // manager has set up the atom-atom interactions so that we can
387     // query them for suggested cutoff values
388     setupCutoffs();
389    
390     info_->prepareTopology();
391 gezelter 246 }
392 gezelter 1576
393     ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
394 gezelter 1126
395 gezelter 1590 // Force fields can set options on how to scale van der Waals and
396     // electrostatic interactions for atoms connected via bonds, bends
397     // and torsions in this case the topological distance between
398     // atoms is:
399 gezelter 1576 // 0 = topologically unconnected
400     // 1 = bonded together
401     // 2 = connected via a bend
402     // 3 = connected via a torsion
403    
404     vdwScale_.reserve(4);
405     fill(vdwScale_.begin(), vdwScale_.end(), 0.0);
406    
407     electrostaticScale_.reserve(4);
408     fill(electrostaticScale_.begin(), electrostaticScale_.end(), 0.0);
409    
410     vdwScale_[0] = 1.0;
411     vdwScale_[1] = fopts.getvdw12scale();
412     vdwScale_[2] = fopts.getvdw13scale();
413     vdwScale_[3] = fopts.getvdw14scale();
414    
415     electrostaticScale_[0] = 1.0;
416     electrostaticScale_[1] = fopts.getelectrostatic12scale();
417     electrostaticScale_[2] = fopts.getelectrostatic13scale();
418     electrostaticScale_[3] = fopts.getelectrostatic14scale();
419    
420     fDecomp_->distributeInitialData();
421    
422     initialized_ = true;
423    
424     }
425    
426     void ForceManager::calcForces() {
427    
428     if (!initialized_) initialize();
429    
430 gezelter 1544 preCalculation();
431 gezelter 1546 shortRangeInteractions();
432     longRangeInteractions();
433 gezelter 1576 postCalculation();
434 gezelter 507 }
435 gezelter 1126
436 gezelter 507 void ForceManager::preCalculation() {
437 gezelter 246 SimInfo::MoleculeIterator mi;
438     Molecule* mol;
439     Molecule::AtomIterator ai;
440     Atom* atom;
441     Molecule::RigidBodyIterator rbIter;
442     RigidBody* rb;
443 gezelter 1540 Molecule::CutoffGroupIterator ci;
444     CutoffGroup* cg;
445 gezelter 246
446     // forces are zeroed here, before any are accumulated.
447 chuckv 1245
448 gezelter 1126 for (mol = info_->beginMolecule(mi); mol != NULL;
449     mol = info_->nextMolecule(mi)) {
450 gezelter 1590 for(atom = mol->beginAtom(ai); atom != NULL;
451     atom = mol->nextAtom(ai)) {
452 gezelter 507 atom->zeroForcesAndTorques();
453     }
454 gezelter 1590
455 gezelter 507 //change the positions of atoms which belong to the rigidbodies
456 gezelter 1126 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
457     rb = mol->nextRigidBody(rbIter)) {
458 gezelter 507 rb->zeroForcesAndTorques();
459     }
460 gezelter 1590
461 gezelter 1540 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
462     for(cg = mol->beginCutoffGroup(ci); cg != NULL;
463     cg = mol->nextCutoffGroup(ci)) {
464     //calculate the center of mass of cutoff group
465     cg->updateCOM();
466     }
467     }
468 gezelter 246 }
469 gezelter 1590
470 gezelter 1126 // Zero out the stress tensor
471 gezelter 1591 tau *= 0.0;
472 gezelter 1126
473 gezelter 507 }
474 gezelter 1126
475 gezelter 1546 void ForceManager::shortRangeInteractions() {
476 gezelter 246 Molecule* mol;
477     RigidBody* rb;
478     Bond* bond;
479     Bend* bend;
480     Torsion* torsion;
481 cli2 1275 Inversion* inversion;
482 gezelter 246 SimInfo::MoleculeIterator mi;
483     Molecule::RigidBodyIterator rbIter;
484     Molecule::BondIterator bondIter;;
485     Molecule::BendIterator bendIter;
486     Molecule::TorsionIterator torsionIter;
487 cli2 1275 Molecule::InversionIterator inversionIter;
488 tim 963 RealType bondPotential = 0.0;
489     RealType bendPotential = 0.0;
490     RealType torsionPotential = 0.0;
491 cli2 1275 RealType inversionPotential = 0.0;
492 gezelter 246
493     //calculate short range interactions
494 gezelter 1126 for (mol = info_->beginMolecule(mi); mol != NULL;
495     mol = info_->nextMolecule(mi)) {
496 gezelter 246
497 gezelter 507 //change the positions of atoms which belong to the rigidbodies
498 gezelter 1126 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
499     rb = mol->nextRigidBody(rbIter)) {
500     rb->updateAtoms();
501 gezelter 507 }
502 gezelter 246
503 gezelter 1126 for (bond = mol->beginBond(bondIter); bond != NULL;
504     bond = mol->nextBond(bondIter)) {
505 tim 749 bond->calcForce();
506     bondPotential += bond->getPotential();
507 gezelter 507 }
508 gezelter 246
509 gezelter 1126 for (bend = mol->beginBend(bendIter); bend != NULL;
510     bend = mol->nextBend(bendIter)) {
511    
512     RealType angle;
513     bend->calcForce(angle);
514     RealType currBendPot = bend->getPotential();
515 gezelter 1448
516 gezelter 1126 bendPotential += bend->getPotential();
517 gezelter 1545 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
518 gezelter 1126 if (i == bendDataSets.end()) {
519     BendDataSet dataSet;
520     dataSet.prev.angle = dataSet.curr.angle = angle;
521     dataSet.prev.potential = dataSet.curr.potential = currBendPot;
522     dataSet.deltaV = 0.0;
523 gezelter 1590 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend,
524     dataSet));
525 gezelter 1126 }else {
526     i->second.prev.angle = i->second.curr.angle;
527     i->second.prev.potential = i->second.curr.potential;
528     i->second.curr.angle = angle;
529     i->second.curr.potential = currBendPot;
530     i->second.deltaV = fabs(i->second.curr.potential -
531     i->second.prev.potential);
532     }
533 gezelter 507 }
534 gezelter 1126
535     for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
536     torsion = mol->nextTorsion(torsionIter)) {
537 tim 963 RealType angle;
538 gezelter 1126 torsion->calcForce(angle);
539 tim 963 RealType currTorsionPot = torsion->getPotential();
540 gezelter 1126 torsionPotential += torsion->getPotential();
541 gezelter 1545 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
542 gezelter 1126 if (i == torsionDataSets.end()) {
543     TorsionDataSet dataSet;
544     dataSet.prev.angle = dataSet.curr.angle = angle;
545     dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
546     dataSet.deltaV = 0.0;
547 gezelter 1545 torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
548 gezelter 1126 }else {
549     i->second.prev.angle = i->second.curr.angle;
550     i->second.prev.potential = i->second.curr.potential;
551     i->second.curr.angle = angle;
552     i->second.curr.potential = currTorsionPot;
553     i->second.deltaV = fabs(i->second.curr.potential -
554     i->second.prev.potential);
555     }
556     }
557 gezelter 1545
558 cli2 1275 for (inversion = mol->beginInversion(inversionIter);
559     inversion != NULL;
560     inversion = mol->nextInversion(inversionIter)) {
561     RealType angle;
562     inversion->calcForce(angle);
563     RealType currInversionPot = inversion->getPotential();
564     inversionPotential += inversion->getPotential();
565 gezelter 1545 map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
566 cli2 1275 if (i == inversionDataSets.end()) {
567     InversionDataSet dataSet;
568     dataSet.prev.angle = dataSet.curr.angle = angle;
569     dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
570     dataSet.deltaV = 0.0;
571 gezelter 1545 inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
572 cli2 1275 }else {
573     i->second.prev.angle = i->second.curr.angle;
574     i->second.prev.potential = i->second.curr.potential;
575     i->second.curr.angle = angle;
576     i->second.curr.potential = currInversionPot;
577     i->second.deltaV = fabs(i->second.curr.potential -
578     i->second.prev.potential);
579     }
580     }
581 gezelter 246 }
582    
583 gezelter 1126 RealType shortRangePotential = bondPotential + bendPotential +
584 cli2 1275 torsionPotential + inversionPotential;
585 gezelter 246 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
586     curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential;
587 tim 665 curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential;
588     curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential;
589     curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential;
590 gezelter 1545 curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential;
591 gezelter 507 }
592 gezelter 1126
593 gezelter 1546 void ForceManager::longRangeInteractions() {
594 gezelter 1581
595 gezelter 1545 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
596     DataStorage* config = &(curSnapshot->atomData);
597     DataStorage* cgConfig = &(curSnapshot->cgData);
598    
599 gezelter 1581 //calculate the center of mass of cutoff group
600    
601     SimInfo::MoleculeIterator mi;
602     Molecule* mol;
603     Molecule::CutoffGroupIterator ci;
604     CutoffGroup* cg;
605    
606     if(info_->getNCutoffGroups() > 0){
607     for (mol = info_->beginMolecule(mi); mol != NULL;
608     mol = info_->nextMolecule(mi)) {
609     for(cg = mol->beginCutoffGroup(ci); cg != NULL;
610     cg = mol->nextCutoffGroup(ci)) {
611     cg->updateCOM();
612     }
613     }
614     } else {
615     // center of mass of the group is the same as position of the atom
616     // if cutoff group does not exist
617     cgConfig->position = config->position;
618     }
619    
620 gezelter 1575 fDecomp_->zeroWorkArrays();
621 gezelter 1549 fDecomp_->distributeData();
622 gezelter 1579
623     int cg1, cg2, atom1, atom2, topoDist;
624     Vector3d d_grp, dag, d;
625     RealType rgrpsq, rgrp, r2, r;
626     RealType electroMult, vdwMult;
627 gezelter 1549 RealType vij;
628 gezelter 1581 Vector3d fij, fg, f1;
629 gezelter 1576 tuple3<RealType, RealType, RealType> cuts;
630 gezelter 1545 RealType rCutSq;
631     bool in_switching_region;
632     RealType sw, dswdr, swderiv;
633 gezelter 1549 vector<int> atomListColumn, atomListRow, atomListLocal;
634 gezelter 1545 InteractionData idat;
635 gezelter 1546 SelfData sdat;
636     RealType mf;
637 gezelter 1575 RealType lrPot;
638 gezelter 1579 RealType vpair;
639 gezelter 1583 potVec longRangePotential(0.0);
640     potVec workPot(0.0);
641 gezelter 1544
642 gezelter 1545 int loopStart, loopEnd;
643 gezelter 1544
644 gezelter 1581 idat.vdwMult = &vdwMult;
645     idat.electroMult = &electroMult;
646 gezelter 1583 idat.pot = &workPot;
647     sdat.pot = fDecomp_->getEmbeddingPotential();
648 gezelter 1581 idat.vpair = &vpair;
649     idat.f1 = &f1;
650     idat.sw = &sw;
651 gezelter 1583 idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
652     idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
653    
654 gezelter 1545 loopEnd = PAIR_LOOP;
655 gezelter 1546 if (info_->requiresPrepair() ) {
656 gezelter 1545 loopStart = PREPAIR_LOOP;
657     } else {
658     loopStart = PAIR_LOOP;
659     }
660 gezelter 1583
661 gezelter 1579 for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
662    
663 gezelter 1545 if (iLoop == loopStart) {
664 gezelter 1549 bool update_nlist = fDecomp_->checkNeighborList();
665 gezelter 1545 if (update_nlist)
666 gezelter 1549 neighborList = fDecomp_->buildNeighborList();
667 gezelter 1612 }
668    
669 gezelter 1545 for (vector<pair<int, int> >::iterator it = neighborList.begin();
670     it != neighborList.end(); ++it) {
671 gezelter 1579
672 gezelter 1545 cg1 = (*it).first;
673     cg2 = (*it).second;
674 gezelter 1576
675     cuts = fDecomp_->getGroupCutoffs(cg1, cg2);
676 gezelter 1545
677 gezelter 1549 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
678 gezelter 1613
679 gezelter 1545 curSnapshot->wrapVector(d_grp);
680     rgrpsq = d_grp.lengthSquare();
681 gezelter 1576 rCutSq = cuts.second;
682    
683 gezelter 1545 if (rgrpsq < rCutSq) {
684 gezelter 1579 idat.rcut = &cuts.first;
685 gezelter 1545 if (iLoop == PAIR_LOOP) {
686 gezelter 1587 vij = 0.0;
687 gezelter 1545 fij = V3Zero;
688     }
689    
690 gezelter 1579 in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr,
691 gezelter 1576 rgrp);
692 gezelter 1616
693 gezelter 1549 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
694     atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
695 gezelter 1545
696 gezelter 1549 for (vector<int>::iterator ia = atomListRow.begin();
697     ia != atomListRow.end(); ++ia) {
698 gezelter 1545 atom1 = (*ia);
699    
700 gezelter 1549 for (vector<int>::iterator jb = atomListColumn.begin();
701     jb != atomListColumn.end(); ++jb) {
702 gezelter 1545 atom2 = (*jb);
703 gezelter 1593
704 gezelter 1549 if (!fDecomp_->skipAtomPair(atom1, atom2)) {
705 gezelter 1579 vpair = 0.0;
706 gezelter 1583 workPot = 0.0;
707 gezelter 1581 f1 = V3Zero;
708 gezelter 1575
709 gezelter 1581 fDecomp_->fillInteractionData(idat, atom1, atom2);
710 gezelter 1579
711     topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
712     vdwMult = vdwScale_[topoDist];
713     electroMult = electrostaticScale_[topoDist];
714 gezelter 1546
715 gezelter 1549 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
716 gezelter 1579 idat.d = &d_grp;
717     idat.r2 = &rgrpsq;
718 gezelter 1545 } else {
719 gezelter 1579 d = fDecomp_->getInteratomicVector(atom1, atom2);
720     curSnapshot->wrapVector( d );
721     r2 = d.lengthSquare();
722     idat.d = &d;
723     idat.r2 = &r2;
724 gezelter 1545 }
725 gezelter 1601
726 gezelter 1581 r = sqrt( *(idat.r2) );
727 gezelter 1579 idat.rij = &r;
728 gezelter 1546
729 gezelter 1545 if (iLoop == PREPAIR_LOOP) {
730     interactionMan_->doPrePair(idat);
731     } else {
732     interactionMan_->doPair(idat);
733 gezelter 1575 fDecomp_->unpackInteractionData(idat, atom1, atom2);
734 gezelter 1581 vij += vpair;
735     fij += f1;
736     tau -= outProduct( *(idat.d), f1);
737 gezelter 1545 }
738     }
739     }
740     }
741    
742     if (iLoop == PAIR_LOOP) {
743     if (in_switching_region) {
744     swderiv = vij * dswdr / rgrp;
745     fg = swderiv * d_grp;
746     fij += fg;
747    
748 gezelter 1549 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
749 gezelter 1554 tau -= outProduct( *(idat.d), fg);
750 gezelter 1545 }
751    
752 gezelter 1549 for (vector<int>::iterator ia = atomListRow.begin();
753     ia != atomListRow.end(); ++ia) {
754 gezelter 1545 atom1 = (*ia);
755 gezelter 1569 mf = fDecomp_->getMassFactorRow(atom1);
756 gezelter 1545 // fg is the force on atom ia due to cutoff group's
757     // presence in switching region
758     fg = swderiv * d_grp * mf;
759 gezelter 1549 fDecomp_->addForceToAtomRow(atom1, fg);
760     if (atomListRow.size() > 1) {
761 gezelter 1546 if (info_->usesAtomicVirial()) {
762 gezelter 1545 // find the distance between the atom
763     // and the center of the cutoff group:
764 gezelter 1549 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
765 gezelter 1545 tau -= outProduct(dag, fg);
766     }
767     }
768     }
769 gezelter 1549 for (vector<int>::iterator jb = atomListColumn.begin();
770     jb != atomListColumn.end(); ++jb) {
771 gezelter 1545 atom2 = (*jb);
772 gezelter 1569 mf = fDecomp_->getMassFactorColumn(atom2);
773 gezelter 1545 // fg is the force on atom jb due to cutoff group's
774     // presence in switching region
775     fg = -swderiv * d_grp * mf;
776 gezelter 1549 fDecomp_->addForceToAtomColumn(atom2, fg);
777 gezelter 1545
778 gezelter 1549 if (atomListColumn.size() > 1) {
779 gezelter 1546 if (info_->usesAtomicVirial()) {
780 gezelter 1545 // find the distance between the atom
781     // and the center of the cutoff group:
782 gezelter 1549 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
783 gezelter 1545 tau -= outProduct(dag, fg);
784     }
785     }
786     }
787     }
788 gezelter 1613 //if (!info_->usesAtomicVirial()) {
789 gezelter 1545 // tau -= outProduct(d_grp, fij);
790     //}
791     }
792     }
793     }
794    
795     if (iLoop == PREPAIR_LOOP) {
796 gezelter 1590 if (info_->requiresPrepair()) {
797    
798 gezelter 1549 fDecomp_->collectIntermediateData();
799 gezelter 1570
800     for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
801 gezelter 1581 fDecomp_->fillSelfData(sdat, atom1);
802 gezelter 1545 interactionMan_->doPreForce(sdat);
803     }
804 gezelter 1590
805     fDecomp_->distributeIntermediateData();
806    
807 gezelter 1545 }
808     }
809 gezelter 1544 }
810 gezelter 1545
811 gezelter 1549 fDecomp_->collectData();
812 gezelter 1570
813     if (info_->requiresSelfCorrection()) {
814 gezelter 1545
815 gezelter 1570 for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
816 gezelter 1581 fDecomp_->fillSelfData(sdat, atom1);
817 gezelter 1570 interactionMan_->doSelfCorrection(sdat);
818     }
819    
820     }
821    
822 gezelter 1583 longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
823     *(fDecomp_->getPairwisePotential());
824    
825 gezelter 1575 lrPot = longRangePotential.sum();
826    
827 gezelter 246 //store the tau and long range potential
828 chuckv 664 curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
829 gezelter 1550 curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
830     curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
831 gezelter 507 }
832 gezelter 246
833 gezelter 1126
834 gezelter 1464 void ForceManager::postCalculation() {
835 gezelter 246 SimInfo::MoleculeIterator mi;
836     Molecule* mol;
837     Molecule::RigidBodyIterator rbIter;
838     RigidBody* rb;
839 gezelter 1126 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
840 gezelter 246
841     // collect the atomic forces onto rigid bodies
842 gezelter 1126
843     for (mol = info_->beginMolecule(mi); mol != NULL;
844     mol = info_->nextMolecule(mi)) {
845     for (rb = mol->beginRigidBody(rbIter); rb != NULL;
846     rb = mol->nextRigidBody(rbIter)) {
847 gezelter 1464 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
848     tau += rbTau;
849 gezelter 507 }
850 gezelter 1126 }
851 gezelter 1464
852 gezelter 1126 #ifdef IS_MPI
853 gezelter 1464 Mat3x3d tmpTau(tau);
854     MPI_Allreduce(tmpTau.getArrayPointer(), tau.getArrayPointer(),
855     9, MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
856 gezelter 1126 #endif
857 gezelter 1464 curSnapshot->statData.setTau(tau);
858 gezelter 507 }
859 gezelter 246
860 gezelter 1390 } //end namespace OpenMD

Properties

Name Value
svn:executable *
svn:keywords Author Id Revision Date