ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1712
Committed: Sat May 19 13:30:21 2012 UTC (12 years, 11 months ago) by gezelter
File size: 31771 byte(s)
Log Message:
Bugfixes (mostly related to particlePot and storageLayout).

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

Properties

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