ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/brains/ForceManager.cpp
Revision: 2067
Committed: Thu Mar 5 15:35:37 2015 UTC (10 years, 1 month ago) by gezelter
File size: 36892 byte(s)
Log Message:
Trying to eliminate some g++ warnings

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

Properties

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