ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1866
Committed: Thu Apr 25 14:32:56 2013 UTC (12 years ago) by gezelter
File size: 36412 byte(s)
Log Message:
Fixes for Qhull static build strangeness

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

Properties

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