ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/ForceManager.cpp
Revision: 1987
Committed: Thu Apr 17 19:07:31 2014 UTC (11 years ago) by gezelter
File size: 37324 byte(s)
Log Message:
Removing vestiges of deprecated MPI:: namespace C++ MPI bindings

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

Properties

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