ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1709
Committed: Tue May 15 13:04:08 2012 UTC (12 years, 11 months ago) by gezelter
File size: 31556 byte(s)
Log Message:
Moving silly stuff out of Stats and into Snapshot.  Most of it should go
into a not-yet-implemented FrameData class.

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

Properties

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