ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1794
Committed: Thu Sep 6 19:44:06 2012 UTC (12 years, 7 months ago) by gezelter
File size: 34917 byte(s)
Log Message:
Merging some of the trunk changes back to the development branch,
cleaning up a datastorage bug

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 }
374
375
376
377
378 void ForceManager::initialize() {
379
380 if (!info_->isTopologyDone()) {
381
382 info_->update();
383 interactionMan_->setSimInfo(info_);
384 interactionMan_->initialize();
385
386 // We want to delay the cutoffs until after the interaction
387 // manager has set up the atom-atom interactions so that we can
388 // query them for suggested cutoff values
389 setupCutoffs();
390
391 info_->prepareTopology();
392
393 doParticlePot_ = info_->getSimParams()->getOutputParticlePotential();
394 doHeatFlux_ = info_->getSimParams()->getPrintHeatFlux();
395 if (doHeatFlux_) doParticlePot_ = true;
396
397 doElectricField_ = info_->getSimParams()->getOutputElectricField();
398
399 }
400
401 ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
402
403 // Force fields can set options on how to scale van der Waals and
404 // electrostatic interactions for atoms connected via bonds, bends
405 // and torsions in this case the topological distance between
406 // atoms is:
407 // 0 = topologically unconnected
408 // 1 = bonded together
409 // 2 = connected via a bend
410 // 3 = connected via a torsion
411
412 vdwScale_.reserve(4);
413 fill(vdwScale_.begin(), vdwScale_.end(), 0.0);
414
415 electrostaticScale_.reserve(4);
416 fill(electrostaticScale_.begin(), electrostaticScale_.end(), 0.0);
417
418 vdwScale_[0] = 1.0;
419 vdwScale_[1] = fopts.getvdw12scale();
420 vdwScale_[2] = fopts.getvdw13scale();
421 vdwScale_[3] = fopts.getvdw14scale();
422
423 electrostaticScale_[0] = 1.0;
424 electrostaticScale_[1] = fopts.getelectrostatic12scale();
425 electrostaticScale_[2] = fopts.getelectrostatic13scale();
426 electrostaticScale_[3] = fopts.getelectrostatic14scale();
427
428 if (info_->getSimParams()->haveElectricField()) {
429 ElectricField* eField = new ElectricField(info_);
430 perturbations_.push_back(eField);
431 }
432
433 fDecomp_->distributeInitialData();
434
435 initialized_ = true;
436
437 }
438
439 void ForceManager::calcForces() {
440
441 if (!initialized_) initialize();
442
443 preCalculation();
444 shortRangeInteractions();
445 longRangeInteractions();
446 postCalculation();
447 }
448
449 void ForceManager::preCalculation() {
450 SimInfo::MoleculeIterator mi;
451 Molecule* mol;
452 Molecule::AtomIterator ai;
453 Atom* atom;
454 Molecule::RigidBodyIterator rbIter;
455 RigidBody* rb;
456 Molecule::CutoffGroupIterator ci;
457 CutoffGroup* cg;
458
459 // forces and potentials are zeroed here, before any are
460 // accumulated.
461
462 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
463
464 snap->setBondPotential(0.0);
465 snap->setBendPotential(0.0);
466 snap->setTorsionPotential(0.0);
467 snap->setInversionPotential(0.0);
468
469 potVec zeroPot(0.0);
470 snap->setLongRangePotential(zeroPot);
471 snap->setExcludedPotentials(zeroPot);
472
473 snap->setRestraintPotential(0.0);
474 snap->setRawPotential(0.0);
475
476 for (mol = info_->beginMolecule(mi); mol != NULL;
477 mol = info_->nextMolecule(mi)) {
478 for(atom = mol->beginAtom(ai); atom != NULL;
479 atom = mol->nextAtom(ai)) {
480 atom->zeroForcesAndTorques();
481 }
482
483 //change the positions of atoms which belong to the rigidbodies
484 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
485 rb = mol->nextRigidBody(rbIter)) {
486 rb->zeroForcesAndTorques();
487 }
488
489 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
490 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
491 cg = mol->nextCutoffGroup(ci)) {
492 //calculate the center of mass of cutoff group
493 cg->updateCOM();
494 }
495 }
496 }
497
498 // Zero out the stress tensor
499 stressTensor *= 0.0;
500 // Zero out the heatFlux
501 fDecomp_->setHeatFlux( Vector3d(0.0) );
502 }
503
504 void ForceManager::shortRangeInteractions() {
505 Molecule* mol;
506 RigidBody* rb;
507 Bond* bond;
508 Bend* bend;
509 Torsion* torsion;
510 Inversion* inversion;
511 SimInfo::MoleculeIterator mi;
512 Molecule::RigidBodyIterator rbIter;
513 Molecule::BondIterator bondIter;;
514 Molecule::BendIterator bendIter;
515 Molecule::TorsionIterator torsionIter;
516 Molecule::InversionIterator inversionIter;
517 RealType bondPotential = 0.0;
518 RealType bendPotential = 0.0;
519 RealType torsionPotential = 0.0;
520 RealType inversionPotential = 0.0;
521
522 //calculate short range interactions
523 for (mol = info_->beginMolecule(mi); mol != NULL;
524 mol = info_->nextMolecule(mi)) {
525
526 //change the positions of atoms which belong to the rigidbodies
527 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
528 rb = mol->nextRigidBody(rbIter)) {
529 rb->updateAtoms();
530 }
531
532 for (bond = mol->beginBond(bondIter); bond != NULL;
533 bond = mol->nextBond(bondIter)) {
534 bond->calcForce(doParticlePot_);
535 bondPotential += bond->getPotential();
536 }
537
538 for (bend = mol->beginBend(bendIter); bend != NULL;
539 bend = mol->nextBend(bendIter)) {
540
541 RealType angle;
542 bend->calcForce(angle, doParticlePot_);
543 RealType currBendPot = bend->getPotential();
544
545 bendPotential += bend->getPotential();
546 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
547 if (i == bendDataSets.end()) {
548 BendDataSet dataSet;
549 dataSet.prev.angle = dataSet.curr.angle = angle;
550 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
551 dataSet.deltaV = 0.0;
552 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend,
553 dataSet));
554 }else {
555 i->second.prev.angle = i->second.curr.angle;
556 i->second.prev.potential = i->second.curr.potential;
557 i->second.curr.angle = angle;
558 i->second.curr.potential = currBendPot;
559 i->second.deltaV = fabs(i->second.curr.potential -
560 i->second.prev.potential);
561 }
562 }
563
564 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
565 torsion = mol->nextTorsion(torsionIter)) {
566 RealType angle;
567 torsion->calcForce(angle, doParticlePot_);
568 RealType currTorsionPot = torsion->getPotential();
569 torsionPotential += torsion->getPotential();
570 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
571 if (i == torsionDataSets.end()) {
572 TorsionDataSet dataSet;
573 dataSet.prev.angle = dataSet.curr.angle = angle;
574 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
575 dataSet.deltaV = 0.0;
576 torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
577 }else {
578 i->second.prev.angle = i->second.curr.angle;
579 i->second.prev.potential = i->second.curr.potential;
580 i->second.curr.angle = angle;
581 i->second.curr.potential = currTorsionPot;
582 i->second.deltaV = fabs(i->second.curr.potential -
583 i->second.prev.potential);
584 }
585 }
586
587 for (inversion = mol->beginInversion(inversionIter);
588 inversion != NULL;
589 inversion = mol->nextInversion(inversionIter)) {
590 RealType angle;
591 inversion->calcForce(angle, doParticlePot_);
592 RealType currInversionPot = inversion->getPotential();
593 inversionPotential += inversion->getPotential();
594 map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
595 if (i == inversionDataSets.end()) {
596 InversionDataSet dataSet;
597 dataSet.prev.angle = dataSet.curr.angle = angle;
598 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
599 dataSet.deltaV = 0.0;
600 inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
601 }else {
602 i->second.prev.angle = i->second.curr.angle;
603 i->second.prev.potential = i->second.curr.potential;
604 i->second.curr.angle = angle;
605 i->second.curr.potential = currInversionPot;
606 i->second.deltaV = fabs(i->second.curr.potential -
607 i->second.prev.potential);
608 }
609 }
610 }
611
612 #ifdef IS_MPI
613 // Collect from all nodes. This should eventually be moved into a
614 // SystemDecomposition, but this is a better place than in
615 // Thermo to do the collection.
616 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bondPotential, 1, MPI::REALTYPE,
617 MPI::SUM);
618 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bendPotential, 1, MPI::REALTYPE,
619 MPI::SUM);
620 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &torsionPotential, 1,
621 MPI::REALTYPE, MPI::SUM);
622 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &inversionPotential, 1,
623 MPI::REALTYPE, MPI::SUM);
624 #endif
625
626 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
627
628 curSnapshot->setBondPotential(bondPotential);
629 curSnapshot->setBendPotential(bendPotential);
630 curSnapshot->setTorsionPotential(torsionPotential);
631 curSnapshot->setInversionPotential(inversionPotential);
632
633 // RealType shortRangePotential = bondPotential + bendPotential +
634 // torsionPotential + inversionPotential;
635
636 // curSnapshot->setShortRangePotential(shortRangePotential);
637 }
638
639 void ForceManager::longRangeInteractions() {
640
641
642 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
643 DataStorage* config = &(curSnapshot->atomData);
644 DataStorage* cgConfig = &(curSnapshot->cgData);
645
646 //calculate the center of mass of cutoff group
647
648 SimInfo::MoleculeIterator mi;
649 Molecule* mol;
650 Molecule::CutoffGroupIterator ci;
651 CutoffGroup* cg;
652
653 if(info_->getNCutoffGroups() > 0){
654 for (mol = info_->beginMolecule(mi); mol != NULL;
655 mol = info_->nextMolecule(mi)) {
656 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
657 cg = mol->nextCutoffGroup(ci)) {
658 cg->updateCOM();
659 }
660 }
661 } else {
662 // center of mass of the group is the same as position of the atom
663 // if cutoff group does not exist
664 cgConfig->position = config->position;
665 cgConfig->velocity = config->velocity;
666 }
667
668 fDecomp_->zeroWorkArrays();
669 fDecomp_->distributeData();
670
671 int cg1, cg2, atom1, atom2, topoDist;
672 Vector3d d_grp, dag, d, gvel2, vel2;
673 RealType rgrpsq, rgrp, r2, r;
674 RealType electroMult, vdwMult;
675 RealType vij;
676 Vector3d fij, fg, f1;
677 tuple3<RealType, RealType, RealType> cuts;
678 RealType rCutSq;
679 bool in_switching_region;
680 RealType sw, dswdr, swderiv;
681 vector<int> atomListColumn, atomListRow, atomListLocal;
682 InteractionData idat;
683 SelfData sdat;
684 RealType mf;
685 RealType vpair;
686 RealType dVdFQ1(0.0);
687 RealType dVdFQ2(0.0);
688 potVec longRangePotential(0.0);
689 potVec workPot(0.0);
690 potVec exPot(0.0);
691 Vector3d eField1(0.0);
692 Vector3d eField2(0.0);
693 vector<int>::iterator ia, jb;
694
695 int loopStart, loopEnd;
696
697 idat.vdwMult = &vdwMult;
698 idat.electroMult = &electroMult;
699 idat.pot = &workPot;
700 idat.excludedPot = &exPot;
701 sdat.pot = fDecomp_->getEmbeddingPotential();
702 sdat.excludedPot = fDecomp_->getExcludedSelfPotential();
703 idat.vpair = &vpair;
704 idat.dVdFQ1 = &dVdFQ1;
705 idat.dVdFQ2 = &dVdFQ2;
706 idat.eField1 = &eField1;
707 idat.eField2 = &eField2;
708 idat.f1 = &f1;
709 idat.sw = &sw;
710 idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
711 idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
712 idat.doParticlePot = doParticlePot_;
713 idat.doElectricField = doElectricField_;
714 sdat.doParticlePot = doParticlePot_;
715
716 loopEnd = PAIR_LOOP;
717 if (info_->requiresPrepair() ) {
718 loopStart = PREPAIR_LOOP;
719 } else {
720 loopStart = PAIR_LOOP;
721 }
722 for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
723
724 if (iLoop == loopStart) {
725 bool update_nlist = fDecomp_->checkNeighborList();
726 if (update_nlist)
727 neighborList = fDecomp_->buildNeighborList();
728 }
729
730 for (vector<pair<int, int> >::iterator it = neighborList.begin();
731 it != neighborList.end(); ++it) {
732
733 cg1 = (*it).first;
734 cg2 = (*it).second;
735
736 cuts = fDecomp_->getGroupCutoffs(cg1, cg2);
737
738 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
739
740 curSnapshot->wrapVector(d_grp);
741 rgrpsq = d_grp.lengthSquare();
742 rCutSq = cuts.second;
743
744 if (rgrpsq < rCutSq) {
745 idat.rcut = &cuts.first;
746 if (iLoop == PAIR_LOOP) {
747 vij = 0.0;
748 fij = V3Zero;
749 }
750
751 in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr,
752 rgrp);
753
754 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
755 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
756
757 if (doHeatFlux_)
758 gvel2 = fDecomp_->getGroupVelocityColumn(cg2);
759
760 for (ia = atomListRow.begin();
761 ia != atomListRow.end(); ++ia) {
762 atom1 = (*ia);
763
764 for (jb = atomListColumn.begin();
765 jb != atomListColumn.end(); ++jb) {
766 atom2 = (*jb);
767
768 if (!fDecomp_->skipAtomPair(atom1, atom2, cg1, cg2)) {
769
770 vpair = 0.0;
771 workPot = 0.0;
772 exPot = 0.0;
773 f1 = V3Zero;
774 dVdFQ1 = 0.0;
775 dVdFQ2 = 0.0;
776
777 fDecomp_->fillInteractionData(idat, atom1, atom2);
778
779 topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
780 vdwMult = vdwScale_[topoDist];
781 electroMult = electrostaticScale_[topoDist];
782
783 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
784 idat.d = &d_grp;
785 idat.r2 = &rgrpsq;
786 if (doHeatFlux_)
787 vel2 = gvel2;
788 } else {
789 d = fDecomp_->getInteratomicVector(atom1, atom2);
790 curSnapshot->wrapVector( d );
791 r2 = d.lengthSquare();
792 idat.d = &d;
793 idat.r2 = &r2;
794 if (doHeatFlux_)
795 vel2 = fDecomp_->getAtomVelocityColumn(atom2);
796 }
797
798 r = sqrt( *(idat.r2) );
799 idat.rij = &r;
800
801 if (iLoop == PREPAIR_LOOP) {
802 interactionMan_->doPrePair(idat);
803 } else {
804 interactionMan_->doPair(idat);
805 fDecomp_->unpackInteractionData(idat, atom1, atom2);
806 vij += vpair;
807 fij += f1;
808 stressTensor -= outProduct( *(idat.d), f1);
809 if (doHeatFlux_)
810 fDecomp_->addToHeatFlux(*(idat.d) * dot(f1, vel2));
811 }
812 }
813 }
814 }
815
816 if (iLoop == PAIR_LOOP) {
817 if (in_switching_region) {
818 swderiv = vij * dswdr / rgrp;
819 fg = swderiv * d_grp;
820 fij += fg;
821
822 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
823 stressTensor -= outProduct( *(idat.d), fg);
824 if (doHeatFlux_)
825 fDecomp_->addToHeatFlux(*(idat.d) * dot(fg, vel2));
826
827 }
828
829 for (ia = atomListRow.begin();
830 ia != atomListRow.end(); ++ia) {
831 atom1 = (*ia);
832 mf = fDecomp_->getMassFactorRow(atom1);
833 // fg is the force on atom ia due to cutoff group's
834 // presence in switching region
835 fg = swderiv * d_grp * mf;
836 fDecomp_->addForceToAtomRow(atom1, fg);
837 if (atomListRow.size() > 1) {
838 if (info_->usesAtomicVirial()) {
839 // find the distance between the atom
840 // and the center of the cutoff group:
841 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
842 stressTensor -= outProduct(dag, fg);
843 if (doHeatFlux_)
844 fDecomp_->addToHeatFlux( dag * dot(fg, vel2));
845 }
846 }
847 }
848 for (jb = atomListColumn.begin();
849 jb != atomListColumn.end(); ++jb) {
850 atom2 = (*jb);
851 mf = fDecomp_->getMassFactorColumn(atom2);
852 // fg is the force on atom jb due to cutoff group's
853 // presence in switching region
854 fg = -swderiv * d_grp * mf;
855 fDecomp_->addForceToAtomColumn(atom2, fg);
856
857 if (atomListColumn.size() > 1) {
858 if (info_->usesAtomicVirial()) {
859 // find the distance between the atom
860 // and the center of the cutoff group:
861 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
862 stressTensor -= outProduct(dag, fg);
863 if (doHeatFlux_)
864 fDecomp_->addToHeatFlux( dag * dot(fg, vel2));
865 }
866 }
867 }
868 }
869 //if (!info_->usesAtomicVirial()) {
870 // stressTensor -= outProduct(d_grp, fij);
871 // if (doHeatFlux_)
872 // fDecomp_->addToHeatFlux( d_grp * dot(fij, vel2));
873 //}
874 }
875 }
876 }
877
878 if (iLoop == PREPAIR_LOOP) {
879 if (info_->requiresPrepair()) {
880
881 fDecomp_->collectIntermediateData();
882
883 for (unsigned int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
884 fDecomp_->fillSelfData(sdat, atom1);
885 interactionMan_->doPreForce(sdat);
886 }
887
888 fDecomp_->distributeIntermediateData();
889
890 }
891 }
892 }
893
894 // collects pairwise information
895 fDecomp_->collectData();
896
897 if (info_->requiresSelfCorrection()) {
898 for (unsigned int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
899 fDecomp_->fillSelfData(sdat, atom1);
900 interactionMan_->doSelfCorrection(sdat);
901 }
902 }
903
904 // collects single-atom information
905 fDecomp_->collectSelfData();
906
907 longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
908 *(fDecomp_->getPairwisePotential());
909
910 curSnapshot->setLongRangePotential(longRangePotential);
911
912 // collects single-atom information
913 fDecomp_->collectSelfData();
914
915 longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
916 *(fDecomp_->getPairwisePotential());
917
918 curSnapshot->setLongRangePotential(longRangePotential);
919
920 curSnapshot->setExcludedPotentials(*(fDecomp_->getExcludedSelfPotential()) +
921 *(fDecomp_->getExcludedPotential()));
922
923 }
924
925
926 void ForceManager::postCalculation() {
927
928 vector<Perturbation*>::iterator pi;
929 for (pi = perturbations_.begin(); pi != perturbations_.end(); ++pi) {
930 (*pi)->applyPerturbation();
931 }
932
933 SimInfo::MoleculeIterator mi;
934 Molecule* mol;
935 Molecule::RigidBodyIterator rbIter;
936 RigidBody* rb;
937 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
938
939 // collect the atomic forces onto rigid bodies
940
941 for (mol = info_->beginMolecule(mi); mol != NULL;
942 mol = info_->nextMolecule(mi)) {
943 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
944 rb = mol->nextRigidBody(rbIter)) {
945 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
946 stressTensor += rbTau;
947 }
948 }
949
950 #ifdef IS_MPI
951 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, stressTensor.getArrayPointer(), 9,
952 MPI::REALTYPE, MPI::SUM);
953 #endif
954 curSnapshot->setStressTensor(stressTensor);
955
956 }
957 } //end namespace OpenMD

Properties

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