ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1868
Committed: Tue Apr 30 15:56:54 2013 UTC (12 years ago) by gezelter
File size: 36593 byte(s)
Log Message:
CLearing out some memory leaks

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

Properties

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