ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1715
Committed: Tue May 22 21:55:31 2012 UTC (12 years, 11 months ago) by gezelter
File size: 31717 byte(s)
Log Message:
Adding more support structure for Fluctuating Charges.

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 vector<int>::iterator ia, jb;
645
646 int loopStart, loopEnd;
647
648 idat.vdwMult = &vdwMult;
649 idat.electroMult = &electroMult;
650 idat.pot = &workPot;
651 sdat.pot = fDecomp_->getEmbeddingPotential();
652 idat.vpair = &vpair;
653 idat.f1 = &f1;
654 idat.sw = &sw;
655 idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
656 idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
657 idat.doParticlePot = doParticlePot_;
658 sdat.doParticlePot = doParticlePot_;
659
660 loopEnd = PAIR_LOOP;
661 if (info_->requiresPrepair() ) {
662 loopStart = PREPAIR_LOOP;
663 } else {
664 loopStart = PAIR_LOOP;
665 }
666
667 for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
668
669 if (iLoop == loopStart) {
670 bool update_nlist = fDecomp_->checkNeighborList();
671 if (update_nlist)
672 neighborList = fDecomp_->buildNeighborList();
673 }
674
675 for (vector<pair<int, int> >::iterator it = neighborList.begin();
676 it != neighborList.end(); ++it) {
677
678 cg1 = (*it).first;
679 cg2 = (*it).second;
680
681 cuts = fDecomp_->getGroupCutoffs(cg1, cg2);
682
683 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
684
685 curSnapshot->wrapVector(d_grp);
686 rgrpsq = d_grp.lengthSquare();
687 rCutSq = cuts.second;
688
689 if (rgrpsq < rCutSq) {
690 idat.rcut = &cuts.first;
691 if (iLoop == PAIR_LOOP) {
692 vij = 0.0;
693 fij = V3Zero;
694 }
695
696 in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr,
697 rgrp);
698
699 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
700 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
701
702 for (ia = atomListRow.begin();
703 ia != atomListRow.end(); ++ia) {
704 atom1 = (*ia);
705
706 for (jb = atomListColumn.begin();
707 jb != atomListColumn.end(); ++jb) {
708 atom2 = (*jb);
709
710 if (!fDecomp_->skipAtomPair(atom1, atom2)) {
711 vpair = 0.0;
712 workPot = 0.0;
713 f1 = V3Zero;
714
715 fDecomp_->fillInteractionData(idat, atom1, atom2);
716
717 topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
718 vdwMult = vdwScale_[topoDist];
719 electroMult = electrostaticScale_[topoDist];
720
721 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
722 idat.d = &d_grp;
723 idat.r2 = &rgrpsq;
724 } else {
725 d = fDecomp_->getInteratomicVector(atom1, atom2);
726 curSnapshot->wrapVector( d );
727 r2 = d.lengthSquare();
728 idat.d = &d;
729 idat.r2 = &r2;
730 }
731
732 r = sqrt( *(idat.r2) );
733 idat.rij = &r;
734
735 if (iLoop == PREPAIR_LOOP) {
736 interactionMan_->doPrePair(idat);
737 } else {
738 interactionMan_->doPair(idat);
739 fDecomp_->unpackInteractionData(idat, atom1, atom2);
740 vij += vpair;
741 fij += f1;
742 tau -= outProduct( *(idat.d), f1);
743 }
744 }
745 }
746 }
747
748 if (iLoop == PAIR_LOOP) {
749 if (in_switching_region) {
750 swderiv = vij * dswdr / rgrp;
751 fg = swderiv * d_grp;
752 fij += fg;
753
754 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
755 tau -= outProduct( *(idat.d), fg);
756 }
757
758 for (ia = atomListRow.begin();
759 ia != atomListRow.end(); ++ia) {
760 atom1 = (*ia);
761 mf = fDecomp_->getMassFactorRow(atom1);
762 // fg is the force on atom ia due to cutoff group's
763 // presence in switching region
764 fg = swderiv * d_grp * mf;
765 fDecomp_->addForceToAtomRow(atom1, fg);
766 if (atomListRow.size() > 1) {
767 if (info_->usesAtomicVirial()) {
768 // find the distance between the atom
769 // and the center of the cutoff group:
770 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
771 tau -= outProduct(dag, fg);
772 }
773 }
774 }
775 for (jb = atomListColumn.begin();
776 jb != atomListColumn.end(); ++jb) {
777 atom2 = (*jb);
778 mf = fDecomp_->getMassFactorColumn(atom2);
779 // fg is the force on atom jb due to cutoff group's
780 // presence in switching region
781 fg = -swderiv * d_grp * mf;
782 fDecomp_->addForceToAtomColumn(atom2, fg);
783
784 if (atomListColumn.size() > 1) {
785 if (info_->usesAtomicVirial()) {
786 // find the distance between the atom
787 // and the center of the cutoff group:
788 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
789 tau -= outProduct(dag, fg);
790 }
791 }
792 }
793 }
794 //if (!info_->usesAtomicVirial()) {
795 // tau -= outProduct(d_grp, fij);
796 //}
797 }
798 }
799 }
800
801 if (iLoop == PREPAIR_LOOP) {
802 if (info_->requiresPrepair()) {
803
804 fDecomp_->collectIntermediateData();
805
806 for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
807 fDecomp_->fillSelfData(sdat, atom1);
808 interactionMan_->doPreForce(sdat);
809 }
810
811 fDecomp_->distributeIntermediateData();
812
813 }
814 }
815 }
816
817 fDecomp_->collectData();
818
819 if (info_->requiresSelfCorrection()) {
820
821 for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
822 fDecomp_->fillSelfData(sdat, atom1);
823 interactionMan_->doSelfCorrection(sdat);
824 }
825
826 }
827
828 longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
829 *(fDecomp_->getPairwisePotential());
830
831 lrPot = longRangePotential.sum();
832
833 //store the tau and long range potential
834 curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
835 curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
836 curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
837 }
838
839
840 void ForceManager::postCalculation() {
841 SimInfo::MoleculeIterator mi;
842 Molecule* mol;
843 Molecule::RigidBodyIterator rbIter;
844 RigidBody* rb;
845 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
846
847 // collect the atomic forces onto rigid bodies
848
849 for (mol = info_->beginMolecule(mi); mol != NULL;
850 mol = info_->nextMolecule(mi)) {
851 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
852 rb = mol->nextRigidBody(rbIter)) {
853 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
854 tau += rbTau;
855 }
856 }
857
858 #ifdef IS_MPI
859 Mat3x3d tmpTau(tau);
860 MPI_Allreduce(tmpTau.getArrayPointer(), tau.getArrayPointer(),
861 9, MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
862 #endif
863 curSnapshot->setTau(tau);
864 }
865
866 } //end namespace OpenMD

Properties

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