ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1618
Committed: Mon Sep 12 17:09:26 2011 UTC (13 years, 7 months ago) by gezelter
File size: 31499 byte(s)
Log Message:
Build fixes for qhull 2011, fixes for compilation with PGI.


File Contents

# Content
1 /*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * This software is provided "AS IS," without a warranty of any
18 * kind. All express or implied conditions, representations and
19 * warranties, including any implied warranty of merchantability,
20 * fitness for a particular purpose or non-infringement, are hereby
21 * excluded. The University of Notre Dame and its licensors shall not
22 * be liable for any damages suffered by licensee as a result of
23 * using, modifying or distributing the software or its
24 * derivatives. In no event will the University of Notre Dame or its
25 * licensors be liable for any lost revenue, profit or data, or for
26 * direct, indirect, special, consequential, incidental or punitive
27 * damages, however caused and regardless of the theory of liability,
28 * arising out of the use of or inability to use software, even if the
29 * University of Notre Dame has been advised of the possibility of
30 * such damages.
31 *
32 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33 * research, please cite the appropriate papers when you publish your
34 * work. Good starting points are:
35 *
36 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).
39 * [4] Vardeman & Gezelter, in progress (2009).
40 */
41
42 /**
43 * @file ForceManager.cpp
44 * @author tlin
45 * @date 11/09/2004
46 * @time 10:39am
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 "parallel/ForceMatrixDecomposition.hpp"
61
62 #include <cstdio>
63 #include <iostream>
64 #include <iomanip>
65
66 using namespace std;
67 namespace OpenMD {
68
69 ForceManager::ForceManager(SimInfo * info) : info_(info) {
70 forceField_ = info_->getForceField();
71 interactionMan_ = new InteractionManager();
72 fDecomp_ = new ForceMatrixDecomposition(info_, interactionMan_);
73 }
74
75 /**
76 * setupCutoffs
77 *
78 * Sets the values of cutoffRadius, switchingRadius, cutoffMethod,
79 * and cutoffPolicy
80 *
81 * cutoffRadius : realType
82 * If the cutoffRadius was explicitly set, use that value.
83 * If the cutoffRadius was not explicitly set:
84 * Are there electrostatic atoms? Use 12.0 Angstroms.
85 * No electrostatic atoms? Poll the atom types present in the
86 * simulation for suggested cutoff values (e.g. 2.5 * sigma).
87 * Use the maximum suggested value that was found.
88 *
89 * cutoffMethod : (one of HARD, SWITCHED, SHIFTED_FORCE,
90 * or SHIFTED_POTENTIAL)
91 * If cutoffMethod was explicitly set, use that choice.
92 * If cutoffMethod was not explicitly set, use SHIFTED_FORCE
93 *
94 * cutoffPolicy : (one of MIX, MAX, TRADITIONAL)
95 * If cutoffPolicy was explicitly set, use that choice.
96 * If cutoffPolicy was not explicitly set, use TRADITIONAL
97 *
98 * switchingRadius : realType
99 * If the cutoffMethod was set to SWITCHED:
100 * If the switchingRadius was explicitly set, use that value
101 * (but do a sanity check first).
102 * If the switchingRadius was not explicitly set: use 0.85 *
103 * cutoffRadius_
104 * If the cutoffMethod was not set to SWITCHED:
105 * Set switchingRadius equal to cutoffRadius for safety.
106 */
107 void ForceManager::setupCutoffs() {
108
109 Globals* simParams_ = info_->getSimParams();
110 ForceFieldOptions& forceFieldOptions_ = forceField_->getForceFieldOptions();
111 int mdFileVersion;
112
113 if (simParams_->haveMDfileVersion())
114 mdFileVersion = simParams_->getMDfileVersion();
115 else
116 mdFileVersion = 0;
117
118 if (simParams_->haveCutoffRadius()) {
119 rCut_ = simParams_->getCutoffRadius();
120 } else {
121 if (info_->usesElectrostaticAtoms()) {
122 sprintf(painCave.errMsg,
123 "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
124 "\tOpenMD will use a default value of 12.0 angstroms"
125 "\tfor the cutoffRadius.\n");
126 painCave.isFatal = 0;
127 painCave.severity = OPENMD_INFO;
128 simError();
129 rCut_ = 12.0;
130 } else {
131 RealType thisCut;
132 set<AtomType*>::iterator i;
133 set<AtomType*> atomTypes;
134 atomTypes = info_->getSimulatedAtomTypes();
135 for (i = atomTypes.begin(); i != atomTypes.end(); ++i) {
136 thisCut = interactionMan_->getSuggestedCutoffRadius((*i));
137 rCut_ = max(thisCut, rCut_);
138 }
139 sprintf(painCave.errMsg,
140 "ForceManager::setupCutoffs: No value was set for the cutoffRadius.\n"
141 "\tOpenMD will use %lf angstroms.\n",
142 rCut_);
143 painCave.isFatal = 0;
144 painCave.severity = OPENMD_INFO;
145 simError();
146 }
147 }
148
149 fDecomp_->setUserCutoff(rCut_);
150 interactionMan_->setCutoffRadius(rCut_);
151
152 map<string, CutoffMethod> stringToCutoffMethod;
153 stringToCutoffMethod["HARD"] = HARD;
154 stringToCutoffMethod["SWITCHED"] = SWITCHED;
155 stringToCutoffMethod["SHIFTED_POTENTIAL"] = SHIFTED_POTENTIAL;
156 stringToCutoffMethod["SHIFTED_FORCE"] = SHIFTED_FORCE;
157
158 if (simParams_->haveCutoffMethod()) {
159 string cutMeth = toUpperCopy(simParams_->getCutoffMethod());
160 map<string, CutoffMethod>::iterator i;
161 i = stringToCutoffMethod.find(cutMeth);
162 if (i == stringToCutoffMethod.end()) {
163 sprintf(painCave.errMsg,
164 "ForceManager::setupCutoffs: Could not find chosen cutoffMethod %s\n"
165 "\tShould be one of: "
166 "HARD, SWITCHED, SHIFTED_POTENTIAL, or SHIFTED_FORCE\n",
167 cutMeth.c_str());
168 painCave.isFatal = 1;
169 painCave.severity = OPENMD_ERROR;
170 simError();
171 } else {
172 cutoffMethod_ = i->second;
173 }
174 } else {
175 if (mdFileVersion > 1) {
176 sprintf(painCave.errMsg,
177 "ForceManager::setupCutoffs: No value was set for the cutoffMethod.\n"
178 "\tOpenMD will use SHIFTED_FORCE.\n");
179 painCave.isFatal = 0;
180 painCave.severity = OPENMD_INFO;
181 simError();
182 cutoffMethod_ = SHIFTED_FORCE;
183 } else {
184 // handle the case where the old file version was in play
185 // (there should be no cutoffMethod, so we have to deduce it
186 // from other data).
187
188 sprintf(painCave.errMsg,
189 "ForceManager::setupCutoffs : DEPRECATED FILE FORMAT!\n"
190 "\tOpenMD found a file which does not set a cutoffMethod.\n"
191 "\tOpenMD will attempt to deduce a cutoffMethod using the\n"
192 "\tbehavior of the older (version 1) code. To remove this\n"
193 "\twarning, add an explicit cutoffMethod and change the top\n"
194 "\tof the file so that it begins with <OpenMD version=2>\n");
195 painCave.isFatal = 0;
196 painCave.severity = OPENMD_WARNING;
197 simError();
198
199 // The old file version tethered the shifting behavior to the
200 // electrostaticSummationMethod keyword.
201
202 if (simParams_->haveElectrostaticSummationMethod()) {
203 std::string myMethod = simParams_->getElectrostaticSummationMethod();
204 toUpper(myMethod);
205
206 if (myMethod == "SHIFTED_POTENTIAL") {
207 cutoffMethod_ = SHIFTED_POTENTIAL;
208 } else if (myMethod == "SHIFTED_FORCE") {
209 cutoffMethod_ = SHIFTED_FORCE;
210 }
211
212 if (simParams_->haveSwitchingRadius())
213 rSwitch_ = simParams_->getSwitchingRadius();
214
215 if (myMethod == "SHIFTED_POTENTIAL" || myMethod == "SHIFTED_FORCE") {
216 if (simParams_->haveSwitchingRadius()){
217 sprintf(painCave.errMsg,
218 "ForceManager::setupCutoffs : DEPRECATED ERROR MESSAGE\n"
219 "\tA value was set for the switchingRadius\n"
220 "\teven though the electrostaticSummationMethod was\n"
221 "\tset to %s\n", myMethod.c_str());
222 painCave.severity = OPENMD_WARNING;
223 painCave.isFatal = 1;
224 simError();
225 }
226 }
227 if (abs(rCut_ - rSwitch_) < 0.0001) {
228 if (cutoffMethod_ == SHIFTED_FORCE) {
229 sprintf(painCave.errMsg,
230 "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
231 "\tcutoffRadius and switchingRadius are set to the\n"
232 "\tsame value. OpenMD will use shifted force\n"
233 "\tpotentials instead of switching functions.\n");
234 painCave.isFatal = 0;
235 painCave.severity = OPENMD_WARNING;
236 simError();
237 } else {
238 cutoffMethod_ = SHIFTED_POTENTIAL;
239 sprintf(painCave.errMsg,
240 "ForceManager::setupCutoffs : DEPRECATED BEHAVIOR\n"
241 "\tcutoffRadius and switchingRadius are set to the\n"
242 "\tsame value. OpenMD will use shifted potentials\n"
243 "\tinstead of switching functions.\n");
244 painCave.isFatal = 0;
245 painCave.severity = OPENMD_WARNING;
246 simError();
247 }
248 }
249 }
250 }
251 }
252
253 map<string, CutoffPolicy> stringToCutoffPolicy;
254 stringToCutoffPolicy["MIX"] = MIX;
255 stringToCutoffPolicy["MAX"] = MAX;
256 stringToCutoffPolicy["TRADITIONAL"] = TRADITIONAL;
257
258 std::string cutPolicy;
259 if (forceFieldOptions_.haveCutoffPolicy()){
260 cutPolicy = forceFieldOptions_.getCutoffPolicy();
261 }else if (simParams_->haveCutoffPolicy()) {
262 cutPolicy = simParams_->getCutoffPolicy();
263 }
264
265 if (!cutPolicy.empty()){
266 toUpper(cutPolicy);
267 map<string, CutoffPolicy>::iterator i;
268 i = stringToCutoffPolicy.find(cutPolicy);
269
270 if (i == stringToCutoffPolicy.end()) {
271 sprintf(painCave.errMsg,
272 "ForceManager::setupCutoffs: Could not find chosen cutoffPolicy %s\n"
273 "\tShould be one of: "
274 "MIX, MAX, or TRADITIONAL\n",
275 cutPolicy.c_str());
276 painCave.isFatal = 1;
277 painCave.severity = OPENMD_ERROR;
278 simError();
279 } else {
280 cutoffPolicy_ = i->second;
281 }
282 } else {
283 sprintf(painCave.errMsg,
284 "ForceManager::setupCutoffs: No value was set for the cutoffPolicy.\n"
285 "\tOpenMD will use TRADITIONAL.\n");
286 painCave.isFatal = 0;
287 painCave.severity = OPENMD_INFO;
288 simError();
289 cutoffPolicy_ = TRADITIONAL;
290 }
291
292 fDecomp_->setCutoffPolicy(cutoffPolicy_);
293
294 // create the switching function object:
295
296 switcher_ = new SwitchingFunction();
297
298 if (cutoffMethod_ == SWITCHED) {
299 if (simParams_->haveSwitchingRadius()) {
300 rSwitch_ = simParams_->getSwitchingRadius();
301 if (rSwitch_ > rCut_) {
302 sprintf(painCave.errMsg,
303 "ForceManager::setupCutoffs: switchingRadius (%f) is larger "
304 "than the cutoffRadius(%f)\n", rSwitch_, rCut_);
305 painCave.isFatal = 1;
306 painCave.severity = OPENMD_ERROR;
307 simError();
308 }
309 } else {
310 rSwitch_ = 0.85 * rCut_;
311 sprintf(painCave.errMsg,
312 "ForceManager::setupCutoffs: No value was set for the switchingRadius.\n"
313 "\tOpenMD will use a default value of 85 percent of the cutoffRadius.\n"
314 "\tswitchingRadius = %f. for this simulation\n", rSwitch_);
315 painCave.isFatal = 0;
316 painCave.severity = OPENMD_WARNING;
317 simError();
318 }
319 } else {
320 if (mdFileVersion > 1) {
321 // throw an error if we define a switching radius and don't need one.
322 // older file versions should not do this.
323 if (simParams_->haveSwitchingRadius()) {
324 map<string, CutoffMethod>::const_iterator it;
325 string theMeth;
326 for (it = stringToCutoffMethod.begin();
327 it != stringToCutoffMethod.end(); ++it) {
328 if (it->second == cutoffMethod_) {
329 theMeth = it->first;
330 break;
331 }
332 }
333 sprintf(painCave.errMsg,
334 "ForceManager::setupCutoffs: the cutoffMethod (%s)\n"
335 "\tis not set to SWITCHED, so switchingRadius value\n"
336 "\twill be ignored for this simulation\n", theMeth.c_str());
337 painCave.isFatal = 0;
338 painCave.severity = OPENMD_WARNING;
339 simError();
340 }
341 }
342 rSwitch_ = rCut_;
343 }
344
345 // Default to cubic switching function.
346 sft_ = cubic;
347 if (simParams_->haveSwitchingFunctionType()) {
348 string funcType = simParams_->getSwitchingFunctionType();
349 toUpper(funcType);
350 if (funcType == "CUBIC") {
351 sft_ = cubic;
352 } else {
353 if (funcType == "FIFTH_ORDER_POLYNOMIAL") {
354 sft_ = fifth_order_poly;
355 } else {
356 // throw error
357 sprintf( painCave.errMsg,
358 "ForceManager::setupSwitching : Unknown switchingFunctionType. (Input file specified %s .)\n"
359 "\tswitchingFunctionType must be one of: "
360 "\"cubic\" or \"fifth_order_polynomial\".",
361 funcType.c_str() );
362 painCave.isFatal = 1;
363 painCave.severity = OPENMD_ERROR;
364 simError();
365 }
366 }
367 }
368 switcher_->setSwitchType(sft_);
369 switcher_->setSwitch(rSwitch_, rCut_);
370 interactionMan_->setSwitchingRadius(rSwitch_);
371 }
372
373
374
375
376 void ForceManager::initialize() {
377
378 if (!info_->isTopologyDone()) {
379
380 info_->update();
381 interactionMan_->setSimInfo(info_);
382 interactionMan_->initialize();
383
384 // We want to delay the cutoffs until after the interaction
385 // manager has set up the atom-atom interactions so that we can
386 // query them for suggested cutoff values
387 setupCutoffs();
388
389 info_->prepareTopology();
390 }
391
392 ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
393
394 // Force fields can set options on how to scale van der Waals and
395 // electrostatic interactions for atoms connected via bonds, bends
396 // and torsions in this case the topological distance between
397 // atoms is:
398 // 0 = topologically unconnected
399 // 1 = bonded together
400 // 2 = connected via a bend
401 // 3 = connected via a torsion
402
403 vdwScale_.reserve(4);
404 fill(vdwScale_.begin(), vdwScale_.end(), 0.0);
405
406 electrostaticScale_.reserve(4);
407 fill(electrostaticScale_.begin(), electrostaticScale_.end(), 0.0);
408
409 vdwScale_[0] = 1.0;
410 vdwScale_[1] = fopts.getvdw12scale();
411 vdwScale_[2] = fopts.getvdw13scale();
412 vdwScale_[3] = fopts.getvdw14scale();
413
414 electrostaticScale_[0] = 1.0;
415 electrostaticScale_[1] = fopts.getelectrostatic12scale();
416 electrostaticScale_[2] = fopts.getelectrostatic13scale();
417 electrostaticScale_[3] = fopts.getelectrostatic14scale();
418
419 fDecomp_->distributeInitialData();
420
421 initialized_ = true;
422
423 }
424
425 void ForceManager::calcForces() {
426
427 if (!initialized_) initialize();
428
429 preCalculation();
430 shortRangeInteractions();
431 longRangeInteractions();
432 postCalculation();
433 }
434
435 void ForceManager::preCalculation() {
436 SimInfo::MoleculeIterator mi;
437 Molecule* mol;
438 Molecule::AtomIterator ai;
439 Atom* atom;
440 Molecule::RigidBodyIterator rbIter;
441 RigidBody* rb;
442 Molecule::CutoffGroupIterator ci;
443 CutoffGroup* cg;
444
445 // forces are zeroed here, before any are accumulated.
446
447 for (mol = info_->beginMolecule(mi); mol != NULL;
448 mol = info_->nextMolecule(mi)) {
449 for(atom = mol->beginAtom(ai); atom != NULL;
450 atom = mol->nextAtom(ai)) {
451 atom->zeroForcesAndTorques();
452 }
453
454 //change the positions of atoms which belong to the rigidbodies
455 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
456 rb = mol->nextRigidBody(rbIter)) {
457 rb->zeroForcesAndTorques();
458 }
459
460 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
461 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
462 cg = mol->nextCutoffGroup(ci)) {
463 //calculate the center of mass of cutoff group
464 cg->updateCOM();
465 }
466 }
467 }
468
469 // Zero out the stress tensor
470 tau *= 0.0;
471
472 }
473
474 void ForceManager::shortRangeInteractions() {
475 Molecule* mol;
476 RigidBody* rb;
477 Bond* bond;
478 Bend* bend;
479 Torsion* torsion;
480 Inversion* inversion;
481 SimInfo::MoleculeIterator mi;
482 Molecule::RigidBodyIterator rbIter;
483 Molecule::BondIterator bondIter;;
484 Molecule::BendIterator bendIter;
485 Molecule::TorsionIterator torsionIter;
486 Molecule::InversionIterator inversionIter;
487 RealType bondPotential = 0.0;
488 RealType bendPotential = 0.0;
489 RealType torsionPotential = 0.0;
490 RealType inversionPotential = 0.0;
491
492 //calculate short range interactions
493 for (mol = info_->beginMolecule(mi); mol != NULL;
494 mol = info_->nextMolecule(mi)) {
495
496 //change the positions of atoms which belong to the rigidbodies
497 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
498 rb = mol->nextRigidBody(rbIter)) {
499 rb->updateAtoms();
500 }
501
502 for (bond = mol->beginBond(bondIter); bond != NULL;
503 bond = mol->nextBond(bondIter)) {
504 bond->calcForce();
505 bondPotential += bond->getPotential();
506 }
507
508 for (bend = mol->beginBend(bendIter); bend != NULL;
509 bend = mol->nextBend(bendIter)) {
510
511 RealType angle;
512 bend->calcForce(angle);
513 RealType currBendPot = bend->getPotential();
514
515 bendPotential += bend->getPotential();
516 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
517 if (i == bendDataSets.end()) {
518 BendDataSet dataSet;
519 dataSet.prev.angle = dataSet.curr.angle = angle;
520 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
521 dataSet.deltaV = 0.0;
522 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend,
523 dataSet));
524 }else {
525 i->second.prev.angle = i->second.curr.angle;
526 i->second.prev.potential = i->second.curr.potential;
527 i->second.curr.angle = angle;
528 i->second.curr.potential = currBendPot;
529 i->second.deltaV = fabs(i->second.curr.potential -
530 i->second.prev.potential);
531 }
532 }
533
534 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
535 torsion = mol->nextTorsion(torsionIter)) {
536 RealType angle;
537 torsion->calcForce(angle);
538 RealType currTorsionPot = torsion->getPotential();
539 torsionPotential += torsion->getPotential();
540 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
541 if (i == torsionDataSets.end()) {
542 TorsionDataSet dataSet;
543 dataSet.prev.angle = dataSet.curr.angle = angle;
544 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
545 dataSet.deltaV = 0.0;
546 torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
547 }else {
548 i->second.prev.angle = i->second.curr.angle;
549 i->second.prev.potential = i->second.curr.potential;
550 i->second.curr.angle = angle;
551 i->second.curr.potential = currTorsionPot;
552 i->second.deltaV = fabs(i->second.curr.potential -
553 i->second.prev.potential);
554 }
555 }
556
557 for (inversion = mol->beginInversion(inversionIter);
558 inversion != NULL;
559 inversion = mol->nextInversion(inversionIter)) {
560 RealType angle;
561 inversion->calcForce(angle);
562 RealType currInversionPot = inversion->getPotential();
563 inversionPotential += inversion->getPotential();
564 map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
565 if (i == inversionDataSets.end()) {
566 InversionDataSet dataSet;
567 dataSet.prev.angle = dataSet.curr.angle = angle;
568 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
569 dataSet.deltaV = 0.0;
570 inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
571 }else {
572 i->second.prev.angle = i->second.curr.angle;
573 i->second.prev.potential = i->second.curr.potential;
574 i->second.curr.angle = angle;
575 i->second.curr.potential = currInversionPot;
576 i->second.deltaV = fabs(i->second.curr.potential -
577 i->second.prev.potential);
578 }
579 }
580 }
581
582 RealType shortRangePotential = bondPotential + bendPotential +
583 torsionPotential + inversionPotential;
584 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
585 curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential;
586 curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential;
587 curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential;
588 curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential;
589 curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential;
590 }
591
592 void ForceManager::longRangeInteractions() {
593
594 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
595 DataStorage* config = &(curSnapshot->atomData);
596 DataStorage* cgConfig = &(curSnapshot->cgData);
597
598 //calculate the center of mass of cutoff group
599
600 SimInfo::MoleculeIterator mi;
601 Molecule* mol;
602 Molecule::CutoffGroupIterator ci;
603 CutoffGroup* cg;
604
605 if(info_->getNCutoffGroups() > 0){
606 for (mol = info_->beginMolecule(mi); mol != NULL;
607 mol = info_->nextMolecule(mi)) {
608 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
609 cg = mol->nextCutoffGroup(ci)) {
610 cg->updateCOM();
611 }
612 }
613 } else {
614 // center of mass of the group is the same as position of the atom
615 // if cutoff group does not exist
616 cgConfig->position = config->position;
617 }
618
619 fDecomp_->zeroWorkArrays();
620 fDecomp_->distributeData();
621
622 int cg1, cg2, atom1, atom2, topoDist;
623 Vector3d d_grp, dag, d;
624 RealType rgrpsq, rgrp, r2, r;
625 RealType electroMult, vdwMult;
626 RealType vij;
627 Vector3d fij, fg, f1;
628 tuple3<RealType, RealType, RealType> cuts;
629 RealType rCutSq;
630 bool in_switching_region;
631 RealType sw, dswdr, swderiv;
632 vector<int> atomListColumn, atomListRow, atomListLocal;
633 InteractionData idat;
634 SelfData sdat;
635 RealType mf;
636 RealType lrPot;
637 RealType vpair;
638 potVec longRangePotential(0.0);
639 potVec workPot(0.0);
640
641 int loopStart, loopEnd;
642
643 idat.vdwMult = &vdwMult;
644 idat.electroMult = &electroMult;
645 idat.pot = &workPot;
646 sdat.pot = fDecomp_->getEmbeddingPotential();
647 idat.vpair = &vpair;
648 idat.f1 = &f1;
649 idat.sw = &sw;
650 idat.shiftedPot = (cutoffMethod_ == SHIFTED_POTENTIAL) ? true : false;
651 idat.shiftedForce = (cutoffMethod_ == SHIFTED_FORCE) ? true : false;
652
653 loopEnd = PAIR_LOOP;
654 if (info_->requiresPrepair() ) {
655 loopStart = PREPAIR_LOOP;
656 } else {
657 loopStart = PAIR_LOOP;
658 }
659
660 for (int iLoop = loopStart; iLoop <= loopEnd; iLoop++) {
661
662 if (iLoop == loopStart) {
663 bool update_nlist = fDecomp_->checkNeighborList();
664 if (update_nlist)
665 neighborList = fDecomp_->buildNeighborList();
666 }
667
668 for (vector<pair<int, int> >::iterator it = neighborList.begin();
669 it != neighborList.end(); ++it) {
670
671 cg1 = (*it).first;
672 cg2 = (*it).second;
673
674 cuts = fDecomp_->getGroupCutoffs(cg1, cg2);
675
676 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
677
678 curSnapshot->wrapVector(d_grp);
679 rgrpsq = d_grp.lengthSquare();
680 rCutSq = cuts.second;
681
682 if (rgrpsq < rCutSq) {
683 idat.rcut = &cuts.first;
684 if (iLoop == PAIR_LOOP) {
685 vij = 0.0;
686 fij = V3Zero;
687 }
688
689 in_switching_region = switcher_->getSwitch(rgrpsq, sw, dswdr,
690 rgrp);
691
692 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
693 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
694
695 for (vector<int>::iterator ia = atomListRow.begin();
696 ia != atomListRow.end(); ++ia) {
697 atom1 = (*ia);
698
699 for (vector<int>::iterator jb = atomListColumn.begin();
700 jb != atomListColumn.end(); ++jb) {
701 atom2 = (*jb);
702
703 if (!fDecomp_->skipAtomPair(atom1, atom2)) {
704 vpair = 0.0;
705 workPot = 0.0;
706 f1 = V3Zero;
707
708 fDecomp_->fillInteractionData(idat, atom1, atom2);
709
710 topoDist = fDecomp_->getTopologicalDistance(atom1, atom2);
711 vdwMult = vdwScale_[topoDist];
712 electroMult = electrostaticScale_[topoDist];
713
714 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
715 idat.d = &d_grp;
716 idat.r2 = &rgrpsq;
717 } else {
718 d = fDecomp_->getInteratomicVector(atom1, atom2);
719 curSnapshot->wrapVector( d );
720 r2 = d.lengthSquare();
721 idat.d = &d;
722 idat.r2 = &r2;
723 }
724
725 r = sqrt( *(idat.r2) );
726 idat.rij = &r;
727
728 if (iLoop == PREPAIR_LOOP) {
729 interactionMan_->doPrePair(idat);
730 } else {
731 interactionMan_->doPair(idat);
732 fDecomp_->unpackInteractionData(idat, atom1, atom2);
733 vij += vpair;
734 fij += f1;
735 tau -= outProduct( *(idat.d), f1);
736 }
737 }
738 }
739 }
740
741 if (iLoop == PAIR_LOOP) {
742 if (in_switching_region) {
743 swderiv = vij * dswdr / rgrp;
744 fg = swderiv * d_grp;
745 fij += fg;
746
747 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
748 tau -= outProduct( *(idat.d), fg);
749 }
750
751 for (vector<int>::iterator ia = atomListRow.begin();
752 ia != atomListRow.end(); ++ia) {
753 atom1 = (*ia);
754 mf = fDecomp_->getMassFactorRow(atom1);
755 // fg is the force on atom ia due to cutoff group's
756 // presence in switching region
757 fg = swderiv * d_grp * mf;
758 fDecomp_->addForceToAtomRow(atom1, fg);
759 if (atomListRow.size() > 1) {
760 if (info_->usesAtomicVirial()) {
761 // find the distance between the atom
762 // and the center of the cutoff group:
763 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
764 tau -= outProduct(dag, fg);
765 }
766 }
767 }
768 for (vector<int>::iterator jb = atomListColumn.begin();
769 jb != atomListColumn.end(); ++jb) {
770 atom2 = (*jb);
771 mf = fDecomp_->getMassFactorColumn(atom2);
772 // fg is the force on atom jb due to cutoff group's
773 // presence in switching region
774 fg = -swderiv * d_grp * mf;
775 fDecomp_->addForceToAtomColumn(atom2, fg);
776
777 if (atomListColumn.size() > 1) {
778 if (info_->usesAtomicVirial()) {
779 // find the distance between the atom
780 // and the center of the cutoff group:
781 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
782 tau -= outProduct(dag, fg);
783 }
784 }
785 }
786 }
787 //if (!info_->usesAtomicVirial()) {
788 // tau -= outProduct(d_grp, fij);
789 //}
790 }
791 }
792 }
793
794 if (iLoop == PREPAIR_LOOP) {
795 if (info_->requiresPrepair()) {
796
797 fDecomp_->collectIntermediateData();
798
799 for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
800 fDecomp_->fillSelfData(sdat, atom1);
801 interactionMan_->doPreForce(sdat);
802 }
803
804 fDecomp_->distributeIntermediateData();
805
806 }
807 }
808 }
809
810 fDecomp_->collectData();
811
812 if (info_->requiresSelfCorrection()) {
813
814 for (int atom1 = 0; atom1 < info_->getNAtoms(); atom1++) {
815 fDecomp_->fillSelfData(sdat, atom1);
816 interactionMan_->doSelfCorrection(sdat);
817 }
818
819 }
820
821 longRangePotential = *(fDecomp_->getEmbeddingPotential()) +
822 *(fDecomp_->getPairwisePotential());
823
824 lrPot = longRangePotential.sum();
825
826 //store the tau and long range potential
827 curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
828 curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
829 curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
830 }
831
832
833 void ForceManager::postCalculation() {
834 SimInfo::MoleculeIterator mi;
835 Molecule* mol;
836 Molecule::RigidBodyIterator rbIter;
837 RigidBody* rb;
838 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
839
840 // collect the atomic forces onto rigid bodies
841
842 for (mol = info_->beginMolecule(mi); mol != NULL;
843 mol = info_->nextMolecule(mi)) {
844 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
845 rb = mol->nextRigidBody(rbIter)) {
846 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
847 tau += rbTau;
848 }
849 }
850
851 #ifdef IS_MPI
852 Mat3x3d tmpTau(tau);
853 MPI_Allreduce(tmpTau.getArrayPointer(), tau.getArrayPointer(),
854 9, MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
855 #endif
856 curSnapshot->statData.setTau(tau);
857 }
858
859 } //end namespace OpenMD

Properties

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