ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/ForceManager.cpp
Revision: 1924
Committed: Mon Aug 5 21:46:11 2013 UTC (11 years, 8 months ago) by gezelter
File size: 37333 byte(s)
Log Message:
Ewald fixes

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

Properties

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