ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1754
Committed: Wed Jun 13 14:45:59 2012 UTC (12 years, 10 months ago) by jmichalk
File size: 32988 byte(s)
Log Message:
Removed a line in Integrator.cpp where the forceMan_ was being initialized too early. Additionally, added a dummy value for rCut_ in ForceManager.cpp::setupCutoffs. JRM

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 are zeroed here, before any are accumulated.
453
454 for (mol = info_->beginMolecule(mi); mol != NULL;
455 mol = info_->nextMolecule(mi)) {
456 for(atom = mol->beginAtom(ai); atom != NULL;
457 atom = mol->nextAtom(ai)) {
458 atom->zeroForcesAndTorques();
459 }
460
461 //change the positions of atoms which belong to the rigidbodies
462 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
463 rb = mol->nextRigidBody(rbIter)) {
464 rb->zeroForcesAndTorques();
465 }
466
467 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
468 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
469 cg = mol->nextCutoffGroup(ci)) {
470 //calculate the center of mass of cutoff group
471 cg->updateCOM();
472 }
473 }
474 }
475
476 // Zero out the stress tensor
477 stressTensor *= 0.0;
478 // Zero out the heatFlux
479 fDecomp_->setHeatFlux( Vector3d(0.0) );
480 }
481
482 void ForceManager::shortRangeInteractions() {
483 Molecule* mol;
484 RigidBody* rb;
485 Bond* bond;
486 Bend* bend;
487 Torsion* torsion;
488 Inversion* inversion;
489 SimInfo::MoleculeIterator mi;
490 Molecule::RigidBodyIterator rbIter;
491 Molecule::BondIterator bondIter;;
492 Molecule::BendIterator bendIter;
493 Molecule::TorsionIterator torsionIter;
494 Molecule::InversionIterator inversionIter;
495 RealType bondPotential = 0.0;
496 RealType bendPotential = 0.0;
497 RealType torsionPotential = 0.0;
498 RealType inversionPotential = 0.0;
499
500 //calculate short range interactions
501 for (mol = info_->beginMolecule(mi); mol != NULL;
502 mol = info_->nextMolecule(mi)) {
503
504 //change the positions of atoms which belong to the rigidbodies
505 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
506 rb = mol->nextRigidBody(rbIter)) {
507 rb->updateAtoms();
508 }
509
510 for (bond = mol->beginBond(bondIter); bond != NULL;
511 bond = mol->nextBond(bondIter)) {
512 bond->calcForce(doParticlePot_);
513 bondPotential += bond->getPotential();
514 }
515
516 for (bend = mol->beginBend(bendIter); bend != NULL;
517 bend = mol->nextBend(bendIter)) {
518
519 RealType angle;
520 bend->calcForce(angle, doParticlePot_);
521 RealType currBendPot = bend->getPotential();
522
523 bendPotential += bend->getPotential();
524 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
525 if (i == bendDataSets.end()) {
526 BendDataSet dataSet;
527 dataSet.prev.angle = dataSet.curr.angle = angle;
528 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
529 dataSet.deltaV = 0.0;
530 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend,
531 dataSet));
532 }else {
533 i->second.prev.angle = i->second.curr.angle;
534 i->second.prev.potential = i->second.curr.potential;
535 i->second.curr.angle = angle;
536 i->second.curr.potential = currBendPot;
537 i->second.deltaV = fabs(i->second.curr.potential -
538 i->second.prev.potential);
539 }
540 }
541
542 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
543 torsion = mol->nextTorsion(torsionIter)) {
544 RealType angle;
545 torsion->calcForce(angle, doParticlePot_);
546 RealType currTorsionPot = torsion->getPotential();
547 torsionPotential += torsion->getPotential();
548 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
549 if (i == torsionDataSets.end()) {
550 TorsionDataSet dataSet;
551 dataSet.prev.angle = dataSet.curr.angle = angle;
552 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
553 dataSet.deltaV = 0.0;
554 torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
555 }else {
556 i->second.prev.angle = i->second.curr.angle;
557 i->second.prev.potential = i->second.curr.potential;
558 i->second.curr.angle = angle;
559 i->second.curr.potential = currTorsionPot;
560 i->second.deltaV = fabs(i->second.curr.potential -
561 i->second.prev.potential);
562 }
563 }
564
565 for (inversion = mol->beginInversion(inversionIter);
566 inversion != NULL;
567 inversion = mol->nextInversion(inversionIter)) {
568 RealType angle;
569 inversion->calcForce(angle, doParticlePot_);
570 RealType currInversionPot = inversion->getPotential();
571 inversionPotential += inversion->getPotential();
572 map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
573 if (i == inversionDataSets.end()) {
574 InversionDataSet dataSet;
575 dataSet.prev.angle = dataSet.curr.angle = angle;
576 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
577 dataSet.deltaV = 0.0;
578 inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
579 }else {
580 i->second.prev.angle = i->second.curr.angle;
581 i->second.prev.potential = i->second.curr.potential;
582 i->second.curr.angle = angle;
583 i->second.curr.potential = currInversionPot;
584 i->second.deltaV = fabs(i->second.curr.potential -
585 i->second.prev.potential);
586 }
587 }
588 }
589
590 RealType shortRangePotential = bondPotential + bendPotential +
591 torsionPotential + inversionPotential;
592 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
593 curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential;
594 curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential;
595 curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential;
596 curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential;
597 curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential;
598 }
599
600 void ForceManager::longRangeInteractions() {
601
602
603 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
604 DataStorage* config = &(curSnapshot->atomData);
605 DataStorage* cgConfig = &(curSnapshot->cgData);
606
607 //calculate the center of mass of cutoff group
608
609 SimInfo::MoleculeIterator mi;
610 Molecule* mol;
611 Molecule::CutoffGroupIterator ci;
612 CutoffGroup* cg;
613
614 if(info_->getNCutoffGroups() > 0){
615 for (mol = info_->beginMolecule(mi); mol != NULL;
616 mol = info_->nextMolecule(mi)) {
617 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
618 cg = mol->nextCutoffGroup(ci)) {
619 cg->updateCOM();
620 }
621 }
622 } else {
623 // center of mass of the group is the same as position of the atom
624 // if cutoff group does not exist
625 cgConfig->position = config->position;
626 cgConfig->velocity = config->velocity;
627 }
628
629 fDecomp_->zeroWorkArrays();
630 fDecomp_->distributeData();
631
632 int cg1, cg2, atom1, atom2, topoDist;
633 Vector3d d_grp, dag, d, gvel2, vel2;
634 RealType rgrpsq, rgrp, r2, r;
635 RealType electroMult, vdwMult;
636 RealType vij;
637 Vector3d fij, fg, f1;
638 tuple3<RealType, RealType, RealType> cuts;
639 RealType rCutSq;
640 bool in_switching_region;
641 RealType sw, dswdr, swderiv;
642 vector<int> atomListColumn, atomListRow, atomListLocal;
643 InteractionData idat;
644 SelfData sdat;
645 RealType mf;
646 RealType lrPot;
647 RealType vpair;
648 RealType dVdFQ1(0.0);
649 RealType dVdFQ2(0.0);
650 potVec longRangePotential(0.0);
651 potVec workPot(0.0);
652 vector<int>::iterator ia, jb;
653
654 int loopStart, loopEnd;
655
656 idat.vdwMult = &vdwMult;
657 idat.electroMult = &electroMult;
658 idat.pot = &workPot;
659 sdat.pot = fDecomp_->getEmbeddingPotential();
660 idat.vpair = &vpair;
661 idat.dVdFQ1 = &dVdFQ1;
662 idat.dVdFQ2 = &dVdFQ2;
663 idat.f1 = &f1;
664 idat.sw = &sw;
665 idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
666 idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
667 idat.doParticlePot = doParticlePot_;
668 sdat.doParticlePot = doParticlePot_;
669
670 loopEnd = PAIR_LOOP;
671 if (info_->requiresPrepair() ) {
672 loopStart = PREPAIR_LOOP;
673 } else {
674 loopStart = PAIR_LOOP;
675 }
676 for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
677
678 if (iLoop == loopStart) {
679 bool update_nlist = fDecomp_->checkNeighborList();
680 if (update_nlist)
681 neighborList = fDecomp_->buildNeighborList();
682 }
683
684 for (vector<pair<int, int> >::iterator it = neighborList.begin();
685 it != neighborList.end(); ++it) {
686
687 cg1 = (*it).first;
688 cg2 = (*it).second;
689
690 cuts = fDecomp_->getGroupCutoffs(cg1, cg2);
691
692 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
693
694 curSnapshot->wrapVector(d_grp);
695 rgrpsq = d_grp.lengthSquare();
696 rCutSq = cuts.second;
697
698 if (rgrpsq < rCutSq) {
699 idat.rcut = &cuts.first;
700 if (iLoop == PAIR_LOOP) {
701 vij = 0.0;
702 fij = V3Zero;
703 }
704
705 in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr,
706 rgrp);
707 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
708 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
709
710 if (doHeatFlux_)
711 gvel2 = fDecomp_->getGroupVelocityColumn(cg2);
712
713 for (ia = atomListRow.begin();
714 ia != atomListRow.end(); ++ia) {
715 atom1 = (*ia);
716
717 for (jb = atomListColumn.begin();
718 jb != atomListColumn.end(); ++jb) {
719 atom2 = (*jb);
720
721 if (!fDecomp_->skipAtomPair(atom1, atom2)) {
722 vpair = 0.0;
723 workPot = 0.0;
724 f1 = V3Zero;
725 dVdFQ1 = 0.0;
726 dVdFQ2 = 0.0;
727
728 fDecomp_->fillInteractionData(idat, atom1, atom2);
729
730 topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
731 vdwMult = vdwScale_[topoDist];
732 electroMult = electrostaticScale_[topoDist];
733
734 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
735 idat.d = &d_grp;
736 idat.r2 = &rgrpsq;
737 if (doHeatFlux_)
738 vel2 = gvel2;
739 } else {
740 d = fDecomp_->getInteratomicVector(atom1, atom2);
741 curSnapshot->wrapVector( d );
742 r2 = d.lengthSquare();
743 idat.d = &d;
744 idat.r2 = &r2;
745 if (doHeatFlux_)
746 vel2 = fDecomp_->getAtomVelocityColumn(atom2);
747 }
748
749 r = sqrt( *(idat.r2) );
750 idat.rij = &r;
751
752 if (iLoop == PREPAIR_LOOP) {
753 interactionMan_->doPrePair(idat);
754 } else {
755 interactionMan_->doPair(idat);
756 fDecomp_->unpackInteractionData(idat, atom1, atom2);
757 vij += vpair;
758 fij += f1;
759 stressTensor -= outProduct( *(idat.d), f1);
760 if (doHeatFlux_)
761 fDecomp_->addToHeatFlux(*(idat.d) * dot(f1, vel2));
762 }
763 }
764 }
765 }
766
767 if (iLoop == PAIR_LOOP) {
768 if (in_switching_region) {
769 swderiv = vij * dswdr / rgrp;
770 fg = swderiv * d_grp;
771 fij += fg;
772
773 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
774 stressTensor -= outProduct( *(idat.d), fg);
775 if (doHeatFlux_)
776 fDecomp_->addToHeatFlux(*(idat.d) * dot(fg, vel2));
777
778 }
779
780 for (ia = atomListRow.begin();
781 ia != atomListRow.end(); ++ia) {
782 atom1 = (*ia);
783 mf = fDecomp_->getMassFactorRow(atom1);
784 // fg is the force on atom ia due to cutoff group's
785 // presence in switching region
786 fg = swderiv * d_grp * mf;
787 fDecomp_->addForceToAtomRow(atom1, fg);
788 if (atomListRow.size() > 1) {
789 if (info_->usesAtomicVirial()) {
790 // find the distance between the atom
791 // and the center of the cutoff group:
792 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
793 stressTensor -= outProduct(dag, fg);
794 if (doHeatFlux_)
795 fDecomp_->addToHeatFlux( dag * dot(fg, vel2));
796 }
797 }
798 }
799 for (jb = atomListColumn.begin();
800 jb != atomListColumn.end(); ++jb) {
801 atom2 = (*jb);
802 mf = fDecomp_->getMassFactorColumn(atom2);
803 // fg is the force on atom jb due to cutoff group's
804 // presence in switching region
805 fg = -swderiv * d_grp * mf;
806 fDecomp_->addForceToAtomColumn(atom2, fg);
807
808 if (atomListColumn.size() > 1) {
809 if (info_->usesAtomicVirial()) {
810 // find the distance between the atom
811 // and the center of the cutoff group:
812 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
813 stressTensor -= outProduct(dag, fg);
814 if (doHeatFlux_)
815 fDecomp_->addToHeatFlux( dag * dot(fg, vel2));
816 }
817 }
818 }
819 }
820 //if (!info_->usesAtomicVirial()) {
821 // stressTensor -= outProduct(d_grp, fij);
822 // if (doHeatFlux_)
823 // fDecomp_->addToHeatFlux( d_grp * dot(fij, vel2));
824 //}
825 }
826 }
827 }
828
829 if (iLoop == PREPAIR_LOOP) {
830 if (info_->requiresPrepair()) {
831
832 fDecomp_->collectIntermediateData();
833
834 for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
835 fDecomp_->fillSelfData(sdat, atom1);
836 interactionMan_->doPreForce(sdat);
837 }
838
839 fDecomp_->distributeIntermediateData();
840
841 }
842 }
843 }
844
845 fDecomp_->collectData();
846
847 if (info_->requiresSelfCorrection()) {
848
849 for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
850 fDecomp_->fillSelfData(sdat, atom1);
851 interactionMan_->doSelfCorrection(sdat);
852 }
853
854 }
855
856 longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
857 *(fDecomp_->getPairwisePotential());
858
859 lrPot = longRangePotential.sum();
860
861 //store the stressTensor and long range potential
862 curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
863 curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
864 curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
865 }
866
867
868 void ForceManager::postCalculation() {
869 SimInfo::MoleculeIterator mi;
870 Molecule* mol;
871 Molecule::RigidBodyIterator rbIter;
872 RigidBody* rb;
873 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
874
875 // collect the atomic forces onto rigid bodies
876
877 for (mol = info_->beginMolecule(mi); mol != NULL;
878 mol = info_->nextMolecule(mi)) {
879 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
880 rb = mol->nextRigidBody(rbIter)) {
881 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
882 stressTensor += rbTau;
883 }
884 }
885
886 #ifdef IS_MPI
887
888 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, stressTensor.getArrayPointer(), 9,
889 MPI::REALTYPE, MPI::SUM);
890 #endif
891 curSnapshot->setStressTensor(stressTensor);
892
893 }
894
895 } //end namespace OpenMD

Properties

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