ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/ForceManager.cpp
Revision: 2057
Committed: Tue Mar 3 15:22:26 2015 UTC (10 years, 2 months ago) by gezelter
File size: 37086 byte(s)
Log Message:
Performance improvements, Removed CutoffPolicy

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

Properties

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