ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1764
Committed: Tue Jul 3 18:32:27 2012 UTC (12 years, 9 months ago) by gezelter
File size: 34271 byte(s)
Log Message:
Refactored Snapshot and Stats to use the Accumulator classes.  Collected
a number of methods into Thermo that belonged there.

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

Properties

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