ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1764
Committed: Tue Jul 3 18:32:27 2012 UTC (12 years, 9 months ago) by gezelter
File size: 34271 byte(s)
Log Message:
Refactored Snapshot and Stats to use the Accumulator classes.  Collected
a number of methods into Thermo that belonged there.

File Contents

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

Properties

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