ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/ForceManager.cpp
Revision: 1969
Committed: Wed Feb 26 14:14:50 2014 UTC (11 years, 2 months ago) by gezelter
File size: 37971 byte(s)
Log Message:
Fixes to deal with deprecation of MPI C++ bindings.  We've reverted back to the
C calls.

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     // MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bondPotential, 1, MPI::REALTYPE,
650     // MPI::SUM);
651     // MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bendPotential, 1, MPI::REALTYPE,
652     // MPI::SUM);
653     // MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &torsionPotential, 1,
654     // MPI::REALTYPE, MPI::SUM);
655     // MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &inversionPotential, 1,
656     // MPI::REALTYPE, MPI::SUM);
657 gezelter 1782 #endif
658    
659 gezelter 246 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
660 gezelter 1782
661     curSnapshot->setBondPotential(bondPotential);
662     curSnapshot->setBendPotential(bendPotential);
663     curSnapshot->setTorsionPotential(torsionPotential);
664     curSnapshot->setInversionPotential(inversionPotential);
665 tim 665
666 gezelter 1782 // RealType shortRangePotential = bondPotential + bendPotential +
667     // torsionPotential + inversionPotential;
668    
669     // curSnapshot->setShortRangePotential(shortRangePotential);
670 gezelter 507 }
671 gezelter 1126
672 gezelter 1782 void ForceManager::longRangeInteractions() {
673 gezelter 246
674 gezelter 1782 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
675     DataStorage* config = &(curSnapshot->atomData);
676     DataStorage* cgConfig = &(curSnapshot->cgData);
677    
678 gezelter 1924
679 gezelter 246 //calculate the center of mass of cutoff group
680 gezelter 1782
681 gezelter 246 SimInfo::MoleculeIterator mi;
682     Molecule* mol;
683     Molecule::CutoffGroupIterator ci;
684     CutoffGroup* cg;
685 gezelter 1782
686     if(info_->getNCutoffGroups() > 0){
687 gezelter 1126 for (mol = info_->beginMolecule(mi); mol != NULL;
688     mol = info_->nextMolecule(mi)) {
689     for(cg = mol->beginCutoffGroup(ci); cg != NULL;
690     cg = mol->nextCutoffGroup(ci)) {
691 gezelter 1782 cg->updateCOM();
692 gezelter 246 }
693 gezelter 1782 }
694 gezelter 246 } else {
695 gezelter 1126 // center of mass of the group is the same as position of the atom
696     // if cutoff group does not exist
697 gezelter 1782 cgConfig->position = config->position;
698     cgConfig->velocity = config->velocity;
699 gezelter 246 }
700 gezelter 1782
701     fDecomp_->zeroWorkArrays();
702     fDecomp_->distributeData();
703 gezelter 1126
704 gezelter 1782 int cg1, cg2, atom1, atom2, topoDist;
705     Vector3d d_grp, dag, d, gvel2, vel2;
706     RealType rgrpsq, rgrp, r2, r;
707     RealType electroMult, vdwMult;
708     RealType vij;
709     Vector3d fij, fg, f1;
710     tuple3<RealType, RealType, RealType> cuts;
711 gezelter 1896 RealType rCut, rCutSq, rListSq;
712 gezelter 1782 bool in_switching_region;
713     RealType sw, dswdr, swderiv;
714 gezelter 1879 vector<int> atomListColumn, atomListRow;
715 gezelter 1782 InteractionData idat;
716     SelfData sdat;
717     RealType mf;
718     RealType vpair;
719     RealType dVdFQ1(0.0);
720     RealType dVdFQ2(0.0);
721     potVec longRangePotential(0.0);
722 gezelter 1925 RealType reciprocalPotential(0.0);
723 gezelter 1782 potVec workPot(0.0);
724     potVec exPot(0.0);
725 gezelter 1880 Vector3d eField1(0.0);
726     Vector3d eField2(0.0);
727 gezelter 1782 vector<int>::iterator ia, jb;
728 gezelter 246
729 gezelter 1782 int loopStart, loopEnd;
730 gezelter 1895
731 gezelter 1896 idat.rcut = &rCut;
732 gezelter 1782 idat.vdwMult = &vdwMult;
733     idat.electroMult = &electroMult;
734     idat.pot = &workPot;
735     idat.excludedPot = &exPot;
736     sdat.pot = fDecomp_->getEmbeddingPotential();
737     sdat.excludedPot = fDecomp_->getExcludedSelfPotential();
738     idat.vpair = &vpair;
739     idat.dVdFQ1 = &dVdFQ1;
740     idat.dVdFQ2 = &dVdFQ2;
741 gezelter 1788 idat.eField1 = &eField1;
742 gezelter 1879 idat.eField2 = &eField2;
743 gezelter 1782 idat.f1 = &f1;
744     idat.sw = &sw;
745     idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
746 gezelter 1879 idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE || cutoffMethod_ == TAYLOR_SHIFTED) ? true : false;
747 gezelter 1782 idat.doParticlePot = doParticlePot_;
748 gezelter 1879 idat.doElectricField = doElectricField_;
749 gezelter 1782 sdat.doParticlePot = doParticlePot_;
750    
751     loopEnd = PAIR_LOOP;
752     if (info_->requiresPrepair() ) {
753     loopStart = PREPAIR_LOOP;
754     } else {
755     loopStart = PAIR_LOOP;
756 chuckv 664 }
757 gezelter 1782 for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
758 gezelter 1126
759 gezelter 1782 if (iLoop == loopStart) {
760     bool update_nlist = fDecomp_->checkNeighborList();
761 gezelter 1879 if (update_nlist) {
762     if (!usePeriodicBoundaryConditions_)
763     Mat3x3d bbox = thermo->getBoundingBox();
764 gezelter 1895 fDecomp_->buildNeighborList(neighborList_);
765 gezelter 1879 }
766     }
767 gezelter 1782
768 gezelter 1895 for (vector<pair<int, int> >::iterator it = neighborList_.begin();
769     it != neighborList_.end(); ++it) {
770 gezelter 1782
771     cg1 = (*it).first;
772     cg2 = (*it).second;
773    
774 gezelter 1896 fDecomp_->getGroupCutoffs(cg1, cg2, rCut, rCutSq, rListSq);
775 gezelter 1782
776     d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
777    
778 gezelter 1893 // already wrapped in the getIntergroupVector call:
779     // curSnapshot->wrapVector(d_grp);
780 gezelter 1782 rgrpsq = d_grp.lengthSquare();
781    
782     if (rgrpsq < rCutSq) {
783     if (iLoop == PAIR_LOOP) {
784     vij = 0.0;
785 gezelter 1879 fij.zero();
786     eField1.zero();
787     eField2.zero();
788 gezelter 1782 }
789    
790     in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr,
791     rgrp);
792    
793     atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
794     atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
795    
796     if (doHeatFlux_)
797     gvel2 = fDecomp_->getGroupVelocityColumn(cg2);
798    
799     for (ia = atomListRow.begin();
800     ia != atomListRow.end(); ++ia) {
801     atom1 = (*ia);
802    
803     for (jb = atomListColumn.begin();
804     jb != atomListColumn.end(); ++jb) {
805     atom2 = (*jb);
806    
807     if (!fDecomp_->skipAtomPair(atom1, atom2, cg1, cg2)) {
808    
809     vpair = 0.0;
810     workPot = 0.0;
811     exPot = 0.0;
812 gezelter 1879 f1.zero();
813 gezelter 1782 dVdFQ1 = 0.0;
814     dVdFQ2 = 0.0;
815    
816     fDecomp_->fillInteractionData(idat, atom1, atom2);
817    
818     topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
819     vdwMult = vdwScale_[topoDist];
820     electroMult = electrostaticScale_[topoDist];
821    
822     if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
823     idat.d = &d_grp;
824     idat.r2 = &rgrpsq;
825     if (doHeatFlux_)
826     vel2 = gvel2;
827     } else {
828     d = fDecomp_->getInteratomicVector(atom1, atom2);
829     curSnapshot->wrapVector( d );
830     r2 = d.lengthSquare();
831     idat.d = &d;
832     idat.r2 = &r2;
833     if (doHeatFlux_)
834     vel2 = fDecomp_->getAtomVelocityColumn(atom2);
835     }
836    
837     r = sqrt( *(idat.r2) );
838     idat.rij = &r;
839 gezelter 1924
840 gezelter 1782 if (iLoop == PREPAIR_LOOP) {
841     interactionMan_->doPrePair(idat);
842     } else {
843     interactionMan_->doPair(idat);
844     fDecomp_->unpackInteractionData(idat, atom1, atom2);
845     vij += vpair;
846     fij += f1;
847     stressTensor -= outProduct( *(idat.d), f1);
848     if (doHeatFlux_)
849     fDecomp_->addToHeatFlux(*(idat.d) * dot(f1, vel2));
850     }
851     }
852     }
853     }
854    
855     if (iLoop == PAIR_LOOP) {
856     if (in_switching_region) {
857     swderiv = vij * dswdr / rgrp;
858     fg = swderiv * d_grp;
859     fij += fg;
860    
861     if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
862 gezelter 1809 if (!fDecomp_->skipAtomPair(atomListRow[0],
863     atomListColumn[0],
864     cg1, cg2)) {
865     stressTensor -= outProduct( *(idat.d), fg);
866     if (doHeatFlux_)
867     fDecomp_->addToHeatFlux(*(idat.d) * dot(fg, vel2));
868     }
869 gezelter 1782 }
870    
871     for (ia = atomListRow.begin();
872     ia != atomListRow.end(); ++ia) {
873     atom1 = (*ia);
874     mf = fDecomp_->getMassFactorRow(atom1);
875     // fg is the force on atom ia due to cutoff group's
876     // presence in switching region
877     fg = swderiv * d_grp * mf;
878     fDecomp_->addForceToAtomRow(atom1, fg);
879     if (atomListRow.size() > 1) {
880     if (info_->usesAtomicVirial()) {
881     // find the distance between the atom
882     // and the center of the cutoff group:
883     dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
884     stressTensor -= outProduct(dag, fg);
885     if (doHeatFlux_)
886     fDecomp_->addToHeatFlux( dag * dot(fg, vel2));
887     }
888     }
889     }
890     for (jb = atomListColumn.begin();
891     jb != atomListColumn.end(); ++jb) {
892     atom2 = (*jb);
893     mf = fDecomp_->getMassFactorColumn(atom2);
894     // fg is the force on atom jb due to cutoff group's
895     // presence in switching region
896     fg = -swderiv * d_grp * mf;
897     fDecomp_->addForceToAtomColumn(atom2, fg);
898    
899     if (atomListColumn.size() > 1) {
900     if (info_->usesAtomicVirial()) {
901     // find the distance between the atom
902     // and the center of the cutoff group:
903     dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
904     stressTensor -= outProduct(dag, fg);
905     if (doHeatFlux_)
906     fDecomp_->addToHeatFlux( dag * dot(fg, vel2));
907     }
908     }
909     }
910     }
911     //if (!info_->usesAtomicVirial()) {
912     // stressTensor -= outProduct(d_grp, fij);
913     // if (doHeatFlux_)
914     // fDecomp_->addToHeatFlux( d_grp * dot(fij, vel2));
915     //}
916     }
917     }
918     }
919    
920     if (iLoop == PREPAIR_LOOP) {
921     if (info_->requiresPrepair()) {
922    
923     fDecomp_->collectIntermediateData();
924    
925     for (unsigned int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
926     fDecomp_->fillSelfData(sdat, atom1);
927     interactionMan_->doPreForce(sdat);
928     }
929    
930     fDecomp_->distributeIntermediateData();
931    
932     }
933     }
934 gezelter 246 }
935 gezelter 1880
936 gezelter 1782 // collects pairwise information
937     fDecomp_->collectData();
938 gezelter 1915 if (cutoffMethod_ == EWALD_FULL) {
939 gezelter 1923 interactionMan_->doReciprocalSpaceSum(reciprocalPotential);
940 gezelter 1925
941     curSnapshot->setReciprocalPotential(reciprocalPotential);
942 gezelter 1915 }
943 gezelter 1782
944     if (info_->requiresSelfCorrection()) {
945     for (unsigned int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
946     fDecomp_->fillSelfData(sdat, atom1);
947     interactionMan_->doSelfCorrection(sdat);
948     }
949 chrisfen 998 }
950 gezelter 1782
951     // collects single-atom information
952     fDecomp_->collectSelfData();
953    
954     longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
955 gezelter 1925 *(fDecomp_->getPairwisePotential());
956 gezelter 1782
957     curSnapshot->setLongRangePotential(longRangePotential);
958 gezelter 1126
959 gezelter 1782 curSnapshot->setExcludedPotentials(*(fDecomp_->getExcludedSelfPotential()) +
960     *(fDecomp_->getExcludedPotential()));
961    
962 gezelter 507 }
963 gezelter 246
964 gezelter 1464 void ForceManager::postCalculation() {
965 gezelter 1782
966     vector<Perturbation*>::iterator pi;
967     for (pi = perturbations_.begin(); pi != perturbations_.end(); ++pi) {
968     (*pi)->applyPerturbation();
969     }
970    
971 gezelter 246 SimInfo::MoleculeIterator mi;
972     Molecule* mol;
973     Molecule::RigidBodyIterator rbIter;
974     RigidBody* rb;
975 gezelter 1126 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
976 gezelter 1782
977 gezelter 246 // collect the atomic forces onto rigid bodies
978 gezelter 1126
979     for (mol = info_->beginMolecule(mi); mol != NULL;
980     mol = info_->nextMolecule(mi)) {
981     for (rb = mol->beginRigidBody(rbIter); rb != NULL;
982     rb = mol->nextRigidBody(rbIter)) {
983 gezelter 1464 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
984 gezelter 1782 stressTensor += rbTau;
985 gezelter 507 }
986 gezelter 1126 }
987 gezelter 1464
988 gezelter 1126 #ifdef IS_MPI
989 gezelter 1969 MPI_Allreduce(MPI_IN_PLACE, stressTensor.getArrayPointer(), 9,
990     MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
991     // MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, stressTensor.getArrayPointer(), 9,
992     // MPI::REALTYPE, MPI::SUM);
993 gezelter 1126 #endif
994 gezelter 1782 curSnapshot->setStressTensor(stressTensor);
995    
996 gezelter 1879 if (info_->getSimParams()->getUseLongRangeCorrections()) {
997     /*
998     RealType vol = curSnapshot->getVolume();
999     RealType Elrc(0.0);
1000     RealType Wlrc(0.0);
1001    
1002     set<AtomType*>::iterator i;
1003     set<AtomType*>::iterator j;
1004    
1005     RealType n_i, n_j;
1006     RealType rho_i, rho_j;
1007     pair<RealType, RealType> LRI;
1008    
1009     for (i = atomTypes_.begin(); i != atomTypes_.end(); ++i) {
1010     n_i = RealType(info_->getGlobalCountOfType(*i));
1011     rho_i = n_i / vol;
1012     for (j = atomTypes_.begin(); j != atomTypes_.end(); ++j) {
1013     n_j = RealType(info_->getGlobalCountOfType(*j));
1014     rho_j = n_j / vol;
1015    
1016     LRI = interactionMan_->getLongRangeIntegrals( (*i), (*j) );
1017    
1018     Elrc += n_i * rho_j * LRI.first;
1019     Wlrc -= rho_i * rho_j * LRI.second;
1020     }
1021     }
1022     Elrc *= 2.0 * NumericConstant::PI;
1023     Wlrc *= 2.0 * NumericConstant::PI;
1024    
1025     RealType lrp = curSnapshot->getLongRangePotential();
1026     curSnapshot->setLongRangePotential(lrp + Elrc);
1027     stressTensor += Wlrc * SquareMatrix3<RealType>::identity();
1028     curSnapshot->setStressTensor(stressTensor);
1029     */
1030    
1031     }
1032 gezelter 507 }
1033 gezelter 1879 }

Properties

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