ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/ForceManager.cpp
Revision: 1880
Committed: Mon Jun 17 18:28:30 2013 UTC (11 years, 10 months ago) by gezelter
File size: 36930 byte(s)
Log Message:
Preparing for official 2.1 release (clean-up)

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

Properties

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