ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/ForceManager.cpp
Revision: 1788
Committed: Wed Aug 29 20:17:07 2012 UTC (12 years, 8 months ago) by gezelter
File size: 34600 byte(s)
Log Message:
Fixed a bug in ForceManager and a compilation issue for cygwin

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

Properties

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