ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1866
Committed: Thu Apr 25 14:32:56 2013 UTC (12 years ago) by gezelter
File size: 36412 byte(s)
Log Message:
Fixes for Qhull static build strangeness

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

Properties

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