ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1849
Committed: Wed Feb 20 13:52:51 2013 UTC (12 years, 2 months ago) by gezelter
File size: 36167 byte(s)
Log Message:
Performance increases for cubic spline.
Bug fix for electric field in parallel.
Cleaned up globals.
Started adding infrastructure for long range corrections.

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

Properties

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