ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1794
Committed: Thu Sep 6 19:44:06 2012 UTC (12 years, 7 months ago) by gezelter
File size: 34917 byte(s)
Log Message:
Merging some of the trunk changes back to the development branch,
cleaning up a datastorage bug

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

Properties

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