ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1618
Committed: Mon Sep 12 17:09:26 2011 UTC (13 years, 7 months ago) by gezelter
File size: 31499 byte(s)
Log Message:
Build fixes for qhull 2011, fixes for compilation with PGI.


File Contents

# User Rev Content
1 gezelter 507 /*
2 gezelter 246 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9 gezelter 1390 * 1. Redistributions of source code must retain the above copyright
10 gezelter 246 * notice, this list of conditions and the following disclaimer.
11     *
12 gezelter 1390 * 2. Redistributions in binary form must reproduce the above copyright
13 gezelter 246 * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the
15     * distribution.
16     *
17     * This software is provided "AS IS," without a warranty of any
18     * kind. All express or implied conditions, representations and
19     * warranties, including any implied warranty of merchantability,
20     * fitness for a particular purpose or non-infringement, are hereby
21     * excluded. The University of Notre Dame and its licensors shall not
22     * be liable for any damages suffered by licensee as a result of
23     * using, modifying or distributing the software or its
24     * derivatives. In no event will the University of Notre Dame or its
25     * licensors be liable for any lost revenue, profit or data, or for
26     * direct, indirect, special, consequential, incidental or punitive
27     * damages, however caused and regardless of the theory of liability,
28     * arising out of the use of or inability to use software, even if the
29     * University of Notre Dame has been advised of the possibility of
30     * such damages.
31 gezelter 1390 *
32     * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     * research, please cite the appropriate papers when you publish your
34     * work. Good starting points are:
35     *
36     * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37     * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38     * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).
39     * [4] Vardeman & Gezelter, in progress (2009).
40 gezelter 246 */
41    
42 gezelter 507 /**
43     * @file ForceManager.cpp
44     * @author tlin
45     * @date 11/09/2004
46     * @time 10:39am
47     * @version 1.0
48     */
49 gezelter 246
50 gezelter 1576
51 gezelter 246 #include "brains/ForceManager.hpp"
52     #include "primitives/Molecule.hpp"
53 gezelter 1390 #define __OPENMD_C
54 gezelter 246 #include "utils/simError.h"
55 xsun 1215 #include "primitives/Bond.hpp"
56 tim 749 #include "primitives/Bend.hpp"
57 cli2 1275 #include "primitives/Torsion.hpp"
58     #include "primitives/Inversion.hpp"
59 gezelter 1551 #include "nonbonded/NonBondedInteraction.hpp"
60 gezelter 1549 #include "parallel/ForceMatrixDecomposition.hpp"
61 gezelter 1467
62 gezelter 1583 #include <cstdio>
63     #include <iostream>
64     #include <iomanip>
65    
66 gezelter 1545 using namespace std;
67 gezelter 1390 namespace OpenMD {
68 gezelter 1469
69 gezelter 1545 ForceManager::ForceManager(SimInfo * info) : info_(info) {
70 gezelter 1576 forceField_ = info_->getForceField();
71 gezelter 1577 interactionMan_ = new InteractionManager();
72 gezelter 1579 fDecomp_ = new ForceMatrixDecomposition(info_, interactionMan_);
73 gezelter 1469 }
74 gezelter 1576
75     /**
76     * setupCutoffs
77     *
78 gezelter 1587 * Sets the values of cutoffRadius, switchingRadius, cutoffMethod,
79     * and cutoffPolicy
80 gezelter 1576 *
81     * cutoffRadius : realType
82     * If the cutoffRadius was explicitly set, use that value.
83     * If the cutoffRadius was not explicitly set:
84     * Are there electrostatic atoms? Use 12.0 Angstroms.
85     * No electrostatic atoms? Poll the atom types present in the
86     * simulation for suggested cutoff values (e.g. 2.5 * sigma).
87     * Use the maximum suggested value that was found.
88     *
89 gezelter 1590 * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE,
90     * or SHIFTED_POTENTIAL)
91 gezelter 1576 * If cutoffMethod was explicitly set, use that choice.
92     * If cutoffMethod was not explicitly set, use SHIFTED_FORCE
93     *
94     * cutoffPolicy : (one of MIX, MAX, TRADITIONAL)
95     * If cutoffPolicy was explicitly set, use that choice.
96     * If cutoffPolicy was not explicitly set, use TRADITIONAL
97 gezelter 1587 *
98     * switchingRadius : realType
99     * If the cutoffMethod was set to SWITCHED:
100     * If the switchingRadius was explicitly set, use that value
101     * (but do a sanity check first).
102     * If the switchingRadius was not explicitly set: use 0.85 *
103     * cutoffRadius_
104     * If the cutoffMethod was not set to SWITCHED:
105     * Set switchingRadius equal to cutoffRadius for safety.
106 gezelter 1576 */
107     void ForceManager::setupCutoffs() {
108    
109     Globals* simParams_ = info_->getSimParams();
110     ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions();
111 gezelter 1613 int mdFileVersion;
112 gezelter 1576
113 gezelter 1613 if (simParams_->haveMDfileVersion())
114     mdFileVersion = simParams_->getMDfileVersion();
115     else
116     mdFileVersion = 0;
117    
118 gezelter 1576 if (simParams_->haveCutoffRadius()) {
119     rCut_ = simParams_->getCutoffRadius();
120     } else {
121     if (info_->usesElectrostaticAtoms()) {
122     sprintf(painCave.errMsg,
123     "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
124     "\tOpenMD will use a default value of 12.0 angstroms"
125     "\tfor the cutoffRadius.\n");
126     painCave.isFatal = 0;
127     painCave.severity = OPENMD_INFO;
128     simError();
129     rCut_ = 12.0;
130     } else {
131     RealType thisCut;
132     set<AtomType*>::iterator i;
133     set<AtomType*> atomTypes;
134     atomTypes = info_->getSimulatedAtomTypes();
135     for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
136     thisCut = interactionMan_->getSuggestedCutoffRadius((*i));
137     rCut_ = max(thisCut, rCut_);
138     }
139     sprintf(painCave.errMsg,
140     "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
141     "\tOpenMD will use %lf angstroms.\n",
142     rCut_);
143     painCave.isFatal = 0;
144     painCave.severity = OPENMD_INFO;
145     simError();
146 gezelter 1579 }
147 gezelter 1576 }
148    
149 gezelter 1583 fDecomp_->setUserCutoff(rCut_);
150 gezelter 1584 interactionMan_->setCutoffRadius(rCut_);
151 gezelter 1583
152 gezelter 1576 map<string, CutoffMethod> stringToCutoffMethod;
153     stringToCutoffMethod["HARD"] = HARD;
154     stringToCutoffMethod["SWITCHED"] = SWITCHED;
155     stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;
156     stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE;
157 gezelter 1545
158 gezelter 1576 if (simParams_->haveCutoffMethod()) {
159     string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
160     map<string, CutoffMethod>::iterator i;
161     i = stringToCutoffMethod.find(cutMeth);
162     if (i == stringToCutoffMethod.end()) {
163     sprintf(painCave.errMsg,
164     "ForceManager::setupCutoffs: Could not find chosen cutoffMethod %s\n"
165     "\tShould be one of: "
166     "HARD, SWITCHED, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n",
167     cutMeth.c_str());
168     painCave.isFatal = 1;
169     painCave.severity = OPENMD_ERROR;
170     simError();
171     } else {
172     cutoffMethod_ = i->second;
173     }
174     } else {
175 gezelter 1616 if (mdFileVersion > 1) {
176     sprintf(painCave.errMsg,
177     "ForceManager::setupCutoffs: No value was set for the cutoffMethod.\n"
178     "\tOpenMD will use SHIFTED_FORCE.\n");
179     painCave.isFatal = 0;
180     painCave.severity = OPENMD_INFO;
181     simError();
182     cutoffMethod_ = SHIFTED_FORCE;
183     } else {
184     // handle the case where the old file version was in play
185     // (there should be no cutoffMethod, so we have to deduce it
186     // from other data).
187    
188     sprintf(painCave.errMsg,
189     "ForceManager::setupCutoffs : DEPRECATED FILE FORMAT!\n"
190     "\tOpenMD found a file which does not set a cutoffMethod.\n"
191     "\tOpenMD will attempt to deduce a cutoffMethod using the\n"
192     "\tbehavior of the older (version 1) code. To remove this\n"
193     "\twarning, add an explicit cutoffMethod and change the top\n"
194     "\tof the file so that it begins with <OpenMD version=2>\n");
195     painCave.isFatal = 0;
196     painCave.severity = OPENMD_WARNING;
197     simError();
198    
199     // The old file version tethered the shifting behavior to the
200     // electrostaticSummationMethod keyword.
201    
202     if (simParams_->haveElectrostaticSummationMethod()) {
203     std::string myMethod = simParams_->getElectrostaticSummationMethod();
204     toUpper(myMethod);
205    
206     if (myMethod == "SHIFTED_POTENTIAL") {
207     cutoffMethod_ = SHIFTED_POTENTIAL;
208     } else if (myMethod == "SHIFTED_FORCE") {
209     cutoffMethod_ = SHIFTED_FORCE;
210     }
211    
212     if (simParams_->haveSwitchingRadius())
213     rSwitch_ = simParams_->getSwitchingRadius();
214    
215     if (myMethod == "SHIFTED_POTENTIAL" || myMethod == "SHIFTED_FORCE") {
216     if (simParams_->haveSwitchingRadius()){
217     sprintf(painCave.errMsg,
218     "ForceManager::setupCutoffs : DEPRECATED ERROR MESSAGE\n"
219     "\tA value was set for the switchingRadius\n"
220     "\teven though the electrostaticSummationMethod was\n"
221     "\tset to %s\n", myMethod.c_str());
222     painCave.severity = OPENMD_WARNING;
223     painCave.isFatal = 1;
224     simError();
225     }
226     }
227     if (abs(rCut_ - rSwitch_) < 0.0001) {
228     if (cutoffMethod_ == SHIFTED_FORCE) {
229     sprintf(painCave.errMsg,
230     "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
231     "\tcutoffRadius and switchingRadius are set to the\n"
232     "\tsame value. OpenMD will use shifted force\n"
233     "\tpotentials instead of switching functions.\n");
234     painCave.isFatal = 0;
235     painCave.severity = OPENMD_WARNING;
236     simError();
237     } else {
238     cutoffMethod_ = SHIFTED_POTENTIAL;
239     sprintf(painCave.errMsg,
240     "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
241     "\tcutoffRadius and switchingRadius are set to the\n"
242     "\tsame value. OpenMD will use shifted potentials\n"
243     "\tinstead of switching functions.\n");
244     painCave.isFatal = 0;
245     painCave.severity = OPENMD_WARNING;
246     simError();
247     }
248     }
249     }
250     }
251 gezelter 1576 }
252    
253     map<string, CutoffPolicy> stringToCutoffPolicy;
254     stringToCutoffPolicy["MIX"] = MIX;
255     stringToCutoffPolicy["MAX"] = MAX;
256     stringToCutoffPolicy["TRADITIONAL"] = TRADITIONAL;
257    
258     std::string cutPolicy;
259     if (forceFieldOptions_.haveCutoffPolicy()){
260     cutPolicy = forceFieldOptions_.getCutoffPolicy();
261     }else if (simParams_->haveCutoffPolicy()) {
262     cutPolicy = simParams_->getCutoffPolicy();
263     }
264    
265     if (!cutPolicy.empty()){
266     toUpper(cutPolicy);
267     map<string, CutoffPolicy>::iterator i;
268     i = stringToCutoffPolicy.find(cutPolicy);
269    
270     if (i == stringToCutoffPolicy.end()) {
271     sprintf(painCave.errMsg,
272     "ForceManager::setupCutoffs: Could not find chosen cutoffPolicy %s\n"
273     "\tShould be one of: "
274     "MIX, MAX, or TRADITIONAL\n",
275     cutPolicy.c_str());
276     painCave.isFatal = 1;
277     painCave.severity = OPENMD_ERROR;
278     simError();
279     } else {
280     cutoffPolicy_ = i->second;
281     }
282     } else {
283     sprintf(painCave.errMsg,
284     "ForceManager::setupCutoffs: No value was set for the cutoffPolicy.\n"
285     "\tOpenMD will use TRADITIONAL.\n");
286     painCave.isFatal = 0;
287     painCave.severity = OPENMD_INFO;
288     simError();
289     cutoffPolicy_ = TRADITIONAL;
290     }
291 gezelter 1587
292 gezelter 1579 fDecomp_->setCutoffPolicy(cutoffPolicy_);
293 gezelter 1587
294     // create the switching function object:
295 gezelter 1576
296 gezelter 1577 switcher_ = new SwitchingFunction();
297 gezelter 1587
298     if (cutoffMethod_ == SWITCHED) {
299     if (simParams_->haveSwitchingRadius()) {
300     rSwitch_ = simParams_->getSwitchingRadius();
301     if (rSwitch_ > rCut_) {
302     sprintf(painCave.errMsg,
303     "ForceManager::setupCutoffs: switchingRadius (%f) is larger "
304     "than the cutoffRadius(%f)\n", rSwitch_, rCut_);
305     painCave.isFatal = 1;
306     painCave.severity = OPENMD_ERROR;
307     simError();
308     }
309     } else {
310     rSwitch_ = 0.85 * rCut_;
311 gezelter 1576 sprintf(painCave.errMsg,
312 gezelter 1587 "ForceManager::setupCutoffs: No value was set for the switchingRadius.\n"
313     "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n"
314     "\tswitchingRadius = %f. for this simulation\n", rSwitch_);
315     painCave.isFatal = 0;
316     painCave.severity = OPENMD_WARNING;
317 gezelter 1576 simError();
318     }
319 gezelter 1587 } else {
320 gezelter 1618 if (mdFileVersion > 1) {
321     // throw an error if we define a switching radius and don't need one.
322     // older file versions should not do this.
323     if (simParams_->haveSwitchingRadius()) {
324     map<string, CutoffMethod>::const_iterator it;
325     string theMeth;
326     for (it = stringToCutoffMethod.begin();
327     it != stringToCutoffMethod.end(); ++it) {
328     if (it->second == cutoffMethod_) {
329     theMeth = it->first;
330     break;
331     }
332 gezelter 1587 }
333 gezelter 1618 sprintf(painCave.errMsg,
334     "ForceManager::setupCutoffs: the cutoffMethod (%s)\n"
335     "\tis not set to SWITCHED, so switchingRadius value\n"
336     "\twill be ignored for this simulation\n", theMeth.c_str());
337     painCave.isFatal = 0;
338     painCave.severity = OPENMD_WARNING;
339     simError();
340 gezelter 1587 }
341     }
342     rSwitch_ = rCut_;
343     }
344 gezelter 1576
345 gezelter 1577 // Default to cubic switching function.
346     sft_ = cubic;
347 gezelter 1576 if (simParams_->haveSwitchingFunctionType()) {
348     string funcType = simParams_->getSwitchingFunctionType();
349     toUpper(funcType);
350     if (funcType == "CUBIC") {
351     sft_ = cubic;
352     } else {
353     if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
354     sft_ = fifth_order_poly;
355     } else {
356     // throw error
357     sprintf( painCave.errMsg,
358     "ForceManager::setupSwitching : Unknown switchingFunctionType. (Input file specified %s .)\n"
359     "\tswitchingFunctionType must be one of: "
360     "\"cubic\" or \"fifth_order_polynomial\".",
361     funcType.c_str() );
362     painCave.isFatal = 1;
363     painCave.severity = OPENMD_ERROR;
364     simError();
365     }
366     }
367     }
368     switcher_->setSwitchType(sft_);
369     switcher_->setSwitch(rSwitch_, rCut_);
370 gezelter 1584 interactionMan_->setSwitchingRadius(rSwitch_);
371 gezelter 1576 }
372 gezelter 1616
373    
374    
375 gezelter 1576
376     void ForceManager::initialize() {
377    
378 gezelter 1569 if (!info_->isTopologyDone()) {
379 gezelter 1590
380 gezelter 507 info_->update();
381 gezelter 1546 interactionMan_->setSimInfo(info_);
382     interactionMan_->initialize();
383 gezelter 1576
384     // We want to delay the cutoffs until after the interaction
385     // manager has set up the atom-atom interactions so that we can
386     // query them for suggested cutoff values
387     setupCutoffs();
388    
389     info_->prepareTopology();
390 gezelter 246 }
391 gezelter 1576
392     ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
393 gezelter 1126
394 gezelter 1590 // Force fields can set options on how to scale van der Waals and
395     // electrostatic interactions for atoms connected via bonds, bends
396     // and torsions in this case the topological distance between
397     // atoms is:
398 gezelter 1576 // 0 = topologically unconnected
399     // 1 = bonded together
400     // 2 = connected via a bend
401     // 3 = connected via a torsion
402    
403     vdwScale_.reserve(4);
404     fill(vdwScale_.begin(), vdwScale_.end(), 0.0);
405    
406     electrostaticScale_.reserve(4);
407     fill(electrostaticScale_.begin(), electrostaticScale_.end(), 0.0);
408    
409     vdwScale_[0] = 1.0;
410     vdwScale_[1] = fopts.getvdw12scale();
411     vdwScale_[2] = fopts.getvdw13scale();
412     vdwScale_[3] = fopts.getvdw14scale();
413    
414     electrostaticScale_[0] = 1.0;
415     electrostaticScale_[1] = fopts.getelectrostatic12scale();
416     electrostaticScale_[2] = fopts.getelectrostatic13scale();
417     electrostaticScale_[3] = fopts.getelectrostatic14scale();
418    
419     fDecomp_->distributeInitialData();
420    
421     initialized_ = true;
422    
423     }
424    
425     void ForceManager::calcForces() {
426    
427     if (!initialized_) initialize();
428    
429 gezelter 1544 preCalculation();
430 gezelter 1546 shortRangeInteractions();
431     longRangeInteractions();
432 gezelter 1576 postCalculation();
433 gezelter 507 }
434 gezelter 1126
435 gezelter 507 void ForceManager::preCalculation() {
436 gezelter 246 SimInfo::MoleculeIterator mi;
437     Molecule* mol;
438     Molecule::AtomIterator ai;
439     Atom* atom;
440     Molecule::RigidBodyIterator rbIter;
441     RigidBody* rb;
442 gezelter 1540 Molecule::CutoffGroupIterator ci;
443     CutoffGroup* cg;
444 gezelter 246
445     // forces are zeroed here, before any are accumulated.
446 chuckv 1245
447 gezelter 1126 for (mol = info_->beginMolecule(mi); mol != NULL;
448     mol = info_->nextMolecule(mi)) {
449 gezelter 1590 for(atom = mol->beginAtom(ai); atom != NULL;
450     atom = mol->nextAtom(ai)) {
451 gezelter 507 atom->zeroForcesAndTorques();
452     }
453 gezelter 1590
454 gezelter 507 //change the positions of atoms which belong to the rigidbodies
455 gezelter 1126 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
456     rb = mol->nextRigidBody(rbIter)) {
457 gezelter 507 rb->zeroForcesAndTorques();
458     }
459 gezelter 1590
460 gezelter 1540 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
461     for(cg = mol->beginCutoffGroup(ci); cg != NULL;
462     cg = mol->nextCutoffGroup(ci)) {
463     //calculate the center of mass of cutoff group
464     cg->updateCOM();
465     }
466     }
467 gezelter 246 }
468 gezelter 1590
469 gezelter 1126 // Zero out the stress tensor
470 gezelter 1591 tau *= 0.0;
471 gezelter 1126
472 gezelter 507 }
473 gezelter 1126
474 gezelter 1546 void ForceManager::shortRangeInteractions() {
475 gezelter 246 Molecule* mol;
476     RigidBody* rb;
477     Bond* bond;
478     Bend* bend;
479     Torsion* torsion;
480 cli2 1275 Inversion* inversion;
481 gezelter 246 SimInfo::MoleculeIterator mi;
482     Molecule::RigidBodyIterator rbIter;
483     Molecule::BondIterator bondIter;;
484     Molecule::BendIterator bendIter;
485     Molecule::TorsionIterator torsionIter;
486 cli2 1275 Molecule::InversionIterator inversionIter;
487 tim 963 RealType bondPotential = 0.0;
488     RealType bendPotential = 0.0;
489     RealType torsionPotential = 0.0;
490 cli2 1275 RealType inversionPotential = 0.0;
491 gezelter 246
492     //calculate short range interactions
493 gezelter 1126 for (mol = info_->beginMolecule(mi); mol != NULL;
494     mol = info_->nextMolecule(mi)) {
495 gezelter 246
496 gezelter 507 //change the positions of atoms which belong to the rigidbodies
497 gezelter 1126 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
498     rb = mol->nextRigidBody(rbIter)) {
499     rb->updateAtoms();
500 gezelter 507 }
501 gezelter 246
502 gezelter 1126 for (bond = mol->beginBond(bondIter); bond != NULL;
503     bond = mol->nextBond(bondIter)) {
504 tim 749 bond->calcForce();
505     bondPotential += bond->getPotential();
506 gezelter 507 }
507 gezelter 246
508 gezelter 1126 for (bend = mol->beginBend(bendIter); bend != NULL;
509     bend = mol->nextBend(bendIter)) {
510    
511     RealType angle;
512     bend->calcForce(angle);
513     RealType currBendPot = bend->getPotential();
514 gezelter 1448
515 gezelter 1126 bendPotential += bend->getPotential();
516 gezelter 1545 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
517 gezelter 1126 if (i == bendDataSets.end()) {
518     BendDataSet dataSet;
519     dataSet.prev.angle = dataSet.curr.angle = angle;
520     dataSet.prev.potential = dataSet.curr.potential = currBendPot;
521     dataSet.deltaV = 0.0;
522 gezelter 1590 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend,
523     dataSet));
524 gezelter 1126 }else {
525     i->second.prev.angle = i->second.curr.angle;
526     i->second.prev.potential = i->second.curr.potential;
527     i->second.curr.angle = angle;
528     i->second.curr.potential = currBendPot;
529     i->second.deltaV = fabs(i->second.curr.potential -
530     i->second.prev.potential);
531     }
532 gezelter 507 }
533 gezelter 1126
534     for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
535     torsion = mol->nextTorsion(torsionIter)) {
536 tim 963 RealType angle;
537 gezelter 1126 torsion->calcForce(angle);
538 tim 963 RealType currTorsionPot = torsion->getPotential();
539 gezelter 1126 torsionPotential += torsion->getPotential();
540 gezelter 1545 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
541 gezelter 1126 if (i == torsionDataSets.end()) {
542     TorsionDataSet dataSet;
543     dataSet.prev.angle = dataSet.curr.angle = angle;
544     dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
545     dataSet.deltaV = 0.0;
546 gezelter 1545 torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
547 gezelter 1126 }else {
548     i->second.prev.angle = i->second.curr.angle;
549     i->second.prev.potential = i->second.curr.potential;
550     i->second.curr.angle = angle;
551     i->second.curr.potential = currTorsionPot;
552     i->second.deltaV = fabs(i->second.curr.potential -
553     i->second.prev.potential);
554     }
555     }
556 gezelter 1545
557 cli2 1275 for (inversion = mol->beginInversion(inversionIter);
558     inversion != NULL;
559     inversion = mol->nextInversion(inversionIter)) {
560     RealType angle;
561     inversion->calcForce(angle);
562     RealType currInversionPot = inversion->getPotential();
563     inversionPotential += inversion->getPotential();
564 gezelter 1545 map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
565 cli2 1275 if (i == inversionDataSets.end()) {
566     InversionDataSet dataSet;
567     dataSet.prev.angle = dataSet.curr.angle = angle;
568     dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
569     dataSet.deltaV = 0.0;
570 gezelter 1545 inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
571 cli2 1275 }else {
572     i->second.prev.angle = i->second.curr.angle;
573     i->second.prev.potential = i->second.curr.potential;
574     i->second.curr.angle = angle;
575     i->second.curr.potential = currInversionPot;
576     i->second.deltaV = fabs(i->second.curr.potential -
577     i->second.prev.potential);
578     }
579     }
580 gezelter 246 }
581    
582 gezelter 1126 RealType shortRangePotential = bondPotential + bendPotential +
583 cli2 1275 torsionPotential + inversionPotential;
584 gezelter 246 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
585     curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential;
586 tim 665 curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential;
587     curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential;
588     curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential;
589 gezelter 1545 curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential;
590 gezelter 507 }
591 gezelter 1126
592 gezelter 1546 void ForceManager::longRangeInteractions() {
593 gezelter 1581
594 gezelter 1545 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
595     DataStorage* config = &(curSnapshot->atomData);
596     DataStorage* cgConfig = &(curSnapshot->cgData);
597    
598 gezelter 1581 //calculate the center of mass of cutoff group
599    
600     SimInfo::MoleculeIterator mi;
601     Molecule* mol;
602     Molecule::CutoffGroupIterator ci;
603     CutoffGroup* cg;
604    
605     if(info_->getNCutoffGroups() > 0){
606     for (mol = info_->beginMolecule(mi); mol != NULL;
607     mol = info_->nextMolecule(mi)) {
608     for(cg = mol->beginCutoffGroup(ci); cg != NULL;
609     cg = mol->nextCutoffGroup(ci)) {
610     cg->updateCOM();
611     }
612     }
613     } else {
614     // center of mass of the group is the same as position of the atom
615     // if cutoff group does not exist
616     cgConfig->position = config->position;
617     }
618    
619 gezelter 1575 fDecomp_->zeroWorkArrays();
620 gezelter 1549 fDecomp_->distributeData();
621 gezelter 1579
622     int cg1, cg2, atom1, atom2, topoDist;
623     Vector3d d_grp, dag, d;
624     RealType rgrpsq, rgrp, r2, r;
625     RealType electroMult, vdwMult;
626 gezelter 1549 RealType vij;
627 gezelter 1581 Vector3d fij, fg, f1;
628 gezelter 1576 tuple3<RealType, RealType, RealType> cuts;
629 gezelter 1545 RealType rCutSq;
630     bool in_switching_region;
631     RealType sw, dswdr, swderiv;
632 gezelter 1549 vector<int> atomListColumn, atomListRow, atomListLocal;
633 gezelter 1545 InteractionData idat;
634 gezelter 1546 SelfData sdat;
635     RealType mf;
636 gezelter 1575 RealType lrPot;
637 gezelter 1579 RealType vpair;
638 gezelter 1583 potVec longRangePotential(0.0);
639     potVec workPot(0.0);
640 gezelter 1544
641 gezelter 1545 int loopStart, loopEnd;
642 gezelter 1544
643 gezelter 1581 idat.vdwMult = &vdwMult;
644     idat.electroMult = &electroMult;
645 gezelter 1583 idat.pot = &workPot;
646     sdat.pot = fDecomp_->getEmbeddingPotential();
647 gezelter 1581 idat.vpair = &vpair;
648     idat.f1 = &f1;
649     idat.sw = &sw;
650 gezelter 1583 idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
651     idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
652    
653 gezelter 1545 loopEnd = PAIR_LOOP;
654 gezelter 1546 if (info_->requiresPrepair() ) {
655 gezelter 1545 loopStart = PREPAIR_LOOP;
656     } else {
657     loopStart = PAIR_LOOP;
658     }
659 gezelter 1583
660 gezelter 1579 for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
661    
662 gezelter 1545 if (iLoop == loopStart) {
663 gezelter 1549 bool update_nlist = fDecomp_->checkNeighborList();
664 gezelter 1545 if (update_nlist)
665 gezelter 1549 neighborList = fDecomp_->buildNeighborList();
666 gezelter 1612 }
667    
668 gezelter 1545 for (vector<pair<int, int> >::iterator it = neighborList.begin();
669     it != neighborList.end(); ++it) {
670 gezelter 1579
671 gezelter 1545 cg1 = (*it).first;
672     cg2 = (*it).second;
673 gezelter 1576
674     cuts = fDecomp_->getGroupCutoffs(cg1, cg2);
675 gezelter 1545
676 gezelter 1549 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
677 gezelter 1613
678 gezelter 1545 curSnapshot->wrapVector(d_grp);
679     rgrpsq = d_grp.lengthSquare();
680 gezelter 1576 rCutSq = cuts.second;
681    
682 gezelter 1545 if (rgrpsq < rCutSq) {
683 gezelter 1579 idat.rcut = &cuts.first;
684 gezelter 1545 if (iLoop == PAIR_LOOP) {
685 gezelter 1587 vij = 0.0;
686 gezelter 1545 fij = V3Zero;
687     }
688    
689 gezelter 1579 in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr,
690 gezelter 1576 rgrp);
691 gezelter 1616
692 gezelter 1549 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
693     atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
694 gezelter 1545
695 gezelter 1549 for (vector<int>::iterator ia = atomListRow.begin();
696     ia != atomListRow.end(); ++ia) {
697 gezelter 1545 atom1 = (*ia);
698    
699 gezelter 1549 for (vector<int>::iterator jb = atomListColumn.begin();
700     jb != atomListColumn.end(); ++jb) {
701 gezelter 1545 atom2 = (*jb);
702 gezelter 1593
703 gezelter 1549 if (!fDecomp_->skipAtomPair(atom1, atom2)) {
704 gezelter 1579 vpair = 0.0;
705 gezelter 1583 workPot = 0.0;
706 gezelter 1581 f1 = V3Zero;
707 gezelter 1575
708 gezelter 1581 fDecomp_->fillInteractionData(idat, atom1, atom2);
709 gezelter 1579
710     topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
711     vdwMult = vdwScale_[topoDist];
712     electroMult = electrostaticScale_[topoDist];
713 gezelter 1546
714 gezelter 1549 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
715 gezelter 1579 idat.d = &d_grp;
716     idat.r2 = &rgrpsq;
717 gezelter 1545 } else {
718 gezelter 1579 d = fDecomp_->getInteratomicVector(atom1, atom2);
719     curSnapshot->wrapVector( d );
720     r2 = d.lengthSquare();
721     idat.d = &d;
722     idat.r2 = &r2;
723 gezelter 1545 }
724 gezelter 1601
725 gezelter 1581 r = sqrt( *(idat.r2) );
726 gezelter 1579 idat.rij = &r;
727 gezelter 1546
728 gezelter 1545 if (iLoop == PREPAIR_LOOP) {
729     interactionMan_->doPrePair(idat);
730     } else {
731     interactionMan_->doPair(idat);
732 gezelter 1575 fDecomp_->unpackInteractionData(idat, atom1, atom2);
733 gezelter 1581 vij += vpair;
734     fij += f1;
735     tau -= outProduct( *(idat.d), f1);
736 gezelter 1545 }
737     }
738     }
739     }
740    
741     if (iLoop == PAIR_LOOP) {
742     if (in_switching_region) {
743     swderiv = vij * dswdr / rgrp;
744     fg = swderiv * d_grp;
745     fij += fg;
746    
747 gezelter 1549 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
748 gezelter 1554 tau -= outProduct( *(idat.d), fg);
749 gezelter 1545 }
750    
751 gezelter 1549 for (vector<int>::iterator ia = atomListRow.begin();
752     ia != atomListRow.end(); ++ia) {
753 gezelter 1545 atom1 = (*ia);
754 gezelter 1569 mf = fDecomp_->getMassFactorRow(atom1);
755 gezelter 1545 // fg is the force on atom ia due to cutoff group's
756     // presence in switching region
757     fg = swderiv * d_grp * mf;
758 gezelter 1549 fDecomp_->addForceToAtomRow(atom1, fg);
759     if (atomListRow.size() > 1) {
760 gezelter 1546 if (info_->usesAtomicVirial()) {
761 gezelter 1545 // find the distance between the atom
762     // and the center of the cutoff group:
763 gezelter 1549 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
764 gezelter 1545 tau -= outProduct(dag, fg);
765     }
766     }
767     }
768 gezelter 1549 for (vector<int>::iterator jb = atomListColumn.begin();
769     jb != atomListColumn.end(); ++jb) {
770 gezelter 1545 atom2 = (*jb);
771 gezelter 1569 mf = fDecomp_->getMassFactorColumn(atom2);
772 gezelter 1545 // fg is the force on atom jb due to cutoff group's
773     // presence in switching region
774     fg = -swderiv * d_grp * mf;
775 gezelter 1549 fDecomp_->addForceToAtomColumn(atom2, fg);
776 gezelter 1545
777 gezelter 1549 if (atomListColumn.size() > 1) {
778 gezelter 1546 if (info_->usesAtomicVirial()) {
779 gezelter 1545 // find the distance between the atom
780     // and the center of the cutoff group:
781 gezelter 1549 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
782 gezelter 1545 tau -= outProduct(dag, fg);
783     }
784     }
785     }
786     }
787 gezelter 1613 //if (!info_->usesAtomicVirial()) {
788 gezelter 1545 // tau -= outProduct(d_grp, fij);
789     //}
790     }
791     }
792     }
793    
794     if (iLoop == PREPAIR_LOOP) {
795 gezelter 1590 if (info_->requiresPrepair()) {
796    
797 gezelter 1549 fDecomp_->collectIntermediateData();
798 gezelter 1570
799     for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
800 gezelter 1581 fDecomp_->fillSelfData(sdat, atom1);
801 gezelter 1545 interactionMan_->doPreForce(sdat);
802     }
803 gezelter 1590
804     fDecomp_->distributeIntermediateData();
805    
806 gezelter 1545 }
807     }
808 gezelter 1544 }
809 gezelter 1545
810 gezelter 1549 fDecomp_->collectData();
811 gezelter 1570
812     if (info_->requiresSelfCorrection()) {
813 gezelter 1545
814 gezelter 1570 for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
815 gezelter 1581 fDecomp_->fillSelfData(sdat, atom1);
816 gezelter 1570 interactionMan_->doSelfCorrection(sdat);
817     }
818    
819     }
820    
821 gezelter 1583 longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
822     *(fDecomp_->getPairwisePotential());
823    
824 gezelter 1575 lrPot = longRangePotential.sum();
825    
826 gezelter 246 //store the tau and long range potential
827 chuckv 664 curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
828 gezelter 1550 curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
829     curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
830 gezelter 507 }
831 gezelter 246
832 gezelter 1126
833 gezelter 1464 void ForceManager::postCalculation() {
834 gezelter 246 SimInfo::MoleculeIterator mi;
835     Molecule* mol;
836     Molecule::RigidBodyIterator rbIter;
837     RigidBody* rb;
838 gezelter 1126 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
839 gezelter 246
840     // collect the atomic forces onto rigid bodies
841 gezelter 1126
842     for (mol = info_->beginMolecule(mi); mol != NULL;
843     mol = info_->nextMolecule(mi)) {
844     for (rb = mol->beginRigidBody(rbIter); rb != NULL;
845     rb = mol->nextRigidBody(rbIter)) {
846 gezelter 1464 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
847     tau += rbTau;
848 gezelter 507 }
849 gezelter 1126 }
850 gezelter 1464
851 gezelter 1126 #ifdef IS_MPI
852 gezelter 1464 Mat3x3d tmpTau(tau);
853     MPI_Allreduce(tmpTau.getArrayPointer(), tau.getArrayPointer(),
854     9, MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
855 gezelter 1126 #endif
856 gezelter 1464 curSnapshot->statData.setTau(tau);
857 gezelter 507 }
858 gezelter 246
859 gezelter 1390 } //end namespace OpenMD

Properties

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