ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1554
Committed: Sat Apr 30 02:54:02 2011 UTC (14 years ago) by gezelter
File size: 18763 byte(s)
Log Message:
For efficiency, pointers instead of objects will be passed during main
force loop. 


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 #include "brains/ForceManager.hpp"
51 #include "primitives/Molecule.hpp"
52 #define __OPENMD_C
53 #include "utils/simError.h"
54 #include "primitives/Bond.hpp"
55 #include "primitives/Bend.hpp"
56 #include "primitives/Torsion.hpp"
57 #include "primitives/Inversion.hpp"
58 #include "nonbonded/NonBondedInteraction.hpp"
59 #include "parallel/ForceMatrixDecomposition.hpp"
60
61 using namespace std;
62 namespace OpenMD {
63
64 ForceManager::ForceManager(SimInfo * info) : info_(info) {
65
66 #ifdef IS_MPI
67 fDecomp_ = new ForceMatrixDecomposition(info_);
68 #else
69 // fDecomp_ = new ForceSerialDecomposition(info);
70 #endif
71 }
72
73 void ForceManager::calcForces() {
74
75 if (!info_->isFortranInitialized()) {
76 info_->update();
77 interactionMan_->setSimInfo(info_);
78 interactionMan_->initialize();
79 swfun_ = interactionMan_->getSwitchingFunction();
80 fDecomp_->distributeInitialData();
81 info_->setupFortran();
82 }
83
84 preCalculation();
85 shortRangeInteractions();
86 longRangeInteractions();
87 postCalculation();
88
89 }
90
91 void ForceManager::preCalculation() {
92 SimInfo::MoleculeIterator mi;
93 Molecule* mol;
94 Molecule::AtomIterator ai;
95 Atom* atom;
96 Molecule::RigidBodyIterator rbIter;
97 RigidBody* rb;
98 Molecule::CutoffGroupIterator ci;
99 CutoffGroup* cg;
100
101 // forces are zeroed here, before any are accumulated.
102
103 for (mol = info_->beginMolecule(mi); mol != NULL;
104 mol = info_->nextMolecule(mi)) {
105 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
106 atom->zeroForcesAndTorques();
107 }
108
109 //change the positions of atoms which belong to the rigidbodies
110 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
111 rb = mol->nextRigidBody(rbIter)) {
112 rb->zeroForcesAndTorques();
113 }
114
115 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
116 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
117 cg = mol->nextCutoffGroup(ci)) {
118 //calculate the center of mass of cutoff group
119 cg->updateCOM();
120 }
121 }
122 }
123
124 // Zero out the stress tensor
125 tau *= 0.0;
126
127 }
128
129 void ForceManager::shortRangeInteractions() {
130 Molecule* mol;
131 RigidBody* rb;
132 Bond* bond;
133 Bend* bend;
134 Torsion* torsion;
135 Inversion* inversion;
136 SimInfo::MoleculeIterator mi;
137 Molecule::RigidBodyIterator rbIter;
138 Molecule::BondIterator bondIter;;
139 Molecule::BendIterator bendIter;
140 Molecule::TorsionIterator torsionIter;
141 Molecule::InversionIterator inversionIter;
142 RealType bondPotential = 0.0;
143 RealType bendPotential = 0.0;
144 RealType torsionPotential = 0.0;
145 RealType inversionPotential = 0.0;
146
147 //calculate short range interactions
148 for (mol = info_->beginMolecule(mi); mol != NULL;
149 mol = info_->nextMolecule(mi)) {
150
151 //change the positions of atoms which belong to the rigidbodies
152 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
153 rb = mol->nextRigidBody(rbIter)) {
154 rb->updateAtoms();
155 }
156
157 for (bond = mol->beginBond(bondIter); bond != NULL;
158 bond = mol->nextBond(bondIter)) {
159 bond->calcForce();
160 bondPotential += bond->getPotential();
161 }
162
163 for (bend = mol->beginBend(bendIter); bend != NULL;
164 bend = mol->nextBend(bendIter)) {
165
166 RealType angle;
167 bend->calcForce(angle);
168 RealType currBendPot = bend->getPotential();
169
170 bendPotential += bend->getPotential();
171 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
172 if (i == bendDataSets.end()) {
173 BendDataSet dataSet;
174 dataSet.prev.angle = dataSet.curr.angle = angle;
175 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
176 dataSet.deltaV = 0.0;
177 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend, dataSet));
178 }else {
179 i->second.prev.angle = i->second.curr.angle;
180 i->second.prev.potential = i->second.curr.potential;
181 i->second.curr.angle = angle;
182 i->second.curr.potential = currBendPot;
183 i->second.deltaV = fabs(i->second.curr.potential -
184 i->second.prev.potential);
185 }
186 }
187
188 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
189 torsion = mol->nextTorsion(torsionIter)) {
190 RealType angle;
191 torsion->calcForce(angle);
192 RealType currTorsionPot = torsion->getPotential();
193 torsionPotential += torsion->getPotential();
194 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
195 if (i == torsionDataSets.end()) {
196 TorsionDataSet dataSet;
197 dataSet.prev.angle = dataSet.curr.angle = angle;
198 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
199 dataSet.deltaV = 0.0;
200 torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
201 }else {
202 i->second.prev.angle = i->second.curr.angle;
203 i->second.prev.potential = i->second.curr.potential;
204 i->second.curr.angle = angle;
205 i->second.curr.potential = currTorsionPot;
206 i->second.deltaV = fabs(i->second.curr.potential -
207 i->second.prev.potential);
208 }
209 }
210
211 for (inversion = mol->beginInversion(inversionIter);
212 inversion != NULL;
213 inversion = mol->nextInversion(inversionIter)) {
214 RealType angle;
215 inversion->calcForce(angle);
216 RealType currInversionPot = inversion->getPotential();
217 inversionPotential += inversion->getPotential();
218 map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
219 if (i == inversionDataSets.end()) {
220 InversionDataSet dataSet;
221 dataSet.prev.angle = dataSet.curr.angle = angle;
222 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
223 dataSet.deltaV = 0.0;
224 inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
225 }else {
226 i->second.prev.angle = i->second.curr.angle;
227 i->second.prev.potential = i->second.curr.potential;
228 i->second.curr.angle = angle;
229 i->second.curr.potential = currInversionPot;
230 i->second.deltaV = fabs(i->second.curr.potential -
231 i->second.prev.potential);
232 }
233 }
234 }
235
236 RealType shortRangePotential = bondPotential + bendPotential +
237 torsionPotential + inversionPotential;
238 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
239 curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential;
240 curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential;
241 curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential;
242 curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential;
243 curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential;
244 }
245
246 void ForceManager::longRangeInteractions() {
247
248 // some of this initial stuff will go away:
249 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
250 DataStorage* config = &(curSnapshot->atomData);
251 DataStorage* cgConfig = &(curSnapshot->cgData);
252 RealType* frc = config->getArrayPointer(DataStorage::dslForce);
253 RealType* pos = config->getArrayPointer(DataStorage::dslPosition);
254 RealType* trq = config->getArrayPointer(DataStorage::dslTorque);
255 RealType* A = config->getArrayPointer(DataStorage::dslAmat);
256 RealType* electroFrame = config->getArrayPointer(DataStorage::dslElectroFrame);
257 RealType* particlePot = config->getArrayPointer(DataStorage::dslParticlePot);
258 RealType* rc;
259
260 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
261 rc = cgConfig->getArrayPointer(DataStorage::dslPosition);
262 } else {
263 // center of mass of the group is the same as position of the atom
264 // if cutoff group does not exist
265 rc = pos;
266 }
267
268 //initialize data before passing to fortran
269 RealType longRangePotential[N_INTERACTION_FAMILIES];
270 RealType lrPot = 0.0;
271 int isError = 0;
272
273 // dangerous to iterate over enums, but we'll live on the edge:
274 for (int i = NO_FAMILY; i != N_INTERACTION_FAMILIES; ++i){
275 longRangePotential[i]=0.0; //Initialize array
276 }
277
278 // new stuff starts here:
279
280 fDecomp_->distributeData();
281
282 int cg1, cg2, atom1, atom2;
283 Vector3d d_grp, dag;
284 RealType rgrpsq, rgrp;
285 RealType vij;
286 Vector3d fij, fg;
287 pair<int, int> gtypes;
288 RealType rCutSq;
289 bool in_switching_region;
290 RealType sw, dswdr, swderiv;
291 vector<int> atomListColumn, atomListRow, atomListLocal;
292 InteractionData idat;
293 SelfData sdat;
294 RealType mf;
295
296 int loopStart, loopEnd;
297
298 loopEnd = PAIR_LOOP;
299 if (info_->requiresPrepair() ) {
300 loopStart = PREPAIR_LOOP;
301 } else {
302 loopStart = PAIR_LOOP;
303 }
304
305 for (int iLoop = loopStart; iLoop < loopEnd; iLoop++) {
306
307 if (iLoop == loopStart) {
308 bool update_nlist = fDecomp_->checkNeighborList();
309 if (update_nlist)
310 neighborList = fDecomp_->buildNeighborList();
311 }
312
313 for (vector<pair<int, int> >::iterator it = neighborList.begin();
314 it != neighborList.end(); ++it) {
315
316 cg1 = (*it).first;
317 cg2 = (*it).second;
318
319 gtypes = fDecomp_->getGroupTypes(cg1, cg2);
320 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
321 curSnapshot->wrapVector(d_grp);
322 rgrpsq = d_grp.lengthSquare();
323 rCutSq = groupCutoffMap[gtypes].first;
324
325 if (rgrpsq < rCutSq) {
326 *(idat.rcut) = groupCutoffMap[gtypes].second;
327 if (iLoop == PAIR_LOOP) {
328 vij *= 0.0;
329 fij = V3Zero;
330 }
331
332 in_switching_region = swfun_->getSwitch(rgrpsq, *(idat.sw), dswdr,
333 rgrp);
334 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
335 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
336
337 for (vector<int>::iterator ia = atomListRow.begin();
338 ia != atomListRow.end(); ++ia) {
339 atom1 = (*ia);
340
341 for (vector<int>::iterator jb = atomListColumn.begin();
342 jb != atomListColumn.end(); ++jb) {
343 atom2 = (*jb);
344
345 if (!fDecomp_->skipAtomPair(atom1, atom2)) {
346
347 idat = fDecomp_->fillInteractionData(atom1, atom2);
348
349 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
350 *(idat.d) = d_grp;
351 *(idat.r2) = rgrpsq;
352 } else {
353 *(idat.d) = fDecomp_->getInteratomicVector(atom1, atom2);
354 curSnapshot->wrapVector( *(idat.d) );
355 *(idat.r2) = idat.d->lengthSquare();
356 }
357
358 *(idat.rij) = sqrt( *(idat.r2) );
359
360 if (iLoop == PREPAIR_LOOP) {
361 interactionMan_->doPrePair(idat);
362 } else {
363 interactionMan_->doPair(idat);
364 vij += *(idat.vpair);
365 fij += *(idat.f1);
366 tau -= outProduct( *(idat.d), *(idat.f1));
367 }
368 }
369 }
370 }
371
372 if (iLoop == PAIR_LOOP) {
373 if (in_switching_region) {
374 swderiv = vij * dswdr / rgrp;
375 fg = swderiv * d_grp;
376
377 fij += fg;
378
379 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
380 tau -= outProduct( *(idat.d), fg);
381 }
382
383 for (vector<int>::iterator ia = atomListRow.begin();
384 ia != atomListRow.end(); ++ia) {
385 atom1 = (*ia);
386 mf = fDecomp_->getMfactRow(atom1);
387 // fg is the force on atom ia due to cutoff group's
388 // presence in switching region
389 fg = swderiv * d_grp * mf;
390 fDecomp_->addForceToAtomRow(atom1, fg);
391
392 if (atomListRow.size() > 1) {
393 if (info_->usesAtomicVirial()) {
394 // find the distance between the atom
395 // and the center of the cutoff group:
396 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
397 tau -= outProduct(dag, fg);
398 }
399 }
400 }
401 for (vector<int>::iterator jb = atomListColumn.begin();
402 jb != atomListColumn.end(); ++jb) {
403 atom2 = (*jb);
404 mf = fDecomp_->getMfactColumn(atom2);
405 // fg is the force on atom jb due to cutoff group's
406 // presence in switching region
407 fg = -swderiv * d_grp * mf;
408 fDecomp_->addForceToAtomColumn(atom2, fg);
409
410 if (atomListColumn.size() > 1) {
411 if (info_->usesAtomicVirial()) {
412 // find the distance between the atom
413 // and the center of the cutoff group:
414 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
415 tau -= outProduct(dag, fg);
416 }
417 }
418 }
419 }
420 //if (!SIM_uses_AtomicVirial) {
421 // tau -= outProduct(d_grp, fij);
422 //}
423 }
424 }
425 }
426
427 if (iLoop == PREPAIR_LOOP) {
428 if (info_->requiresPrepair()) {
429 fDecomp_->collectIntermediateData();
430 atomListLocal = fDecomp_->getAtomList();
431 for (vector<int>::iterator ia = atomListLocal.begin();
432 ia != atomListLocal.end(); ++ia) {
433 atom1 = (*ia);
434 sdat = fDecomp_->fillSelfData(atom1);
435 interactionMan_->doPreForce(sdat);
436 }
437 fDecomp_->distributeIntermediateData();
438 }
439 }
440
441 }
442
443 fDecomp_->collectData();
444
445 if (info_->requiresSkipCorrection() || info_->requiresSelfCorrection()) {
446 atomListLocal = fDecomp_->getAtomList();
447 for (vector<int>::iterator ia = atomListLocal.begin();
448 ia != atomListLocal.end(); ++ia) {
449 atom1 = (*ia);
450
451 if (info_->requiresSkipCorrection()) {
452 vector<int> skipList = fDecomp_->getSkipsForAtom(atom1);
453 for (vector<int>::iterator jb = skipList.begin();
454 jb != skipList.end(); ++jb) {
455 atom2 = (*jb);
456 idat = fDecomp_->fillSkipData(atom1, atom2);
457 interactionMan_->doSkipCorrection(idat);
458 }
459 }
460
461 if (info_->requiresSelfCorrection()) {
462 sdat = fDecomp_->fillSelfData(atom1);
463 interactionMan_->doSelfCorrection(sdat);
464 }
465 }
466 }
467
468 // dangerous to iterate over enums, but we'll live on the edge:
469 for (int i = NO_FAMILY; i != N_INTERACTION_FAMILIES; ++i){
470 lrPot += longRangePotential[i]; //Quick hack
471 }
472
473 //store the tau and long range potential
474 curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
475 curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VANDERWAALS_FAMILY];
476 curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
477 }
478
479
480 void ForceManager::postCalculation() {
481 SimInfo::MoleculeIterator mi;
482 Molecule* mol;
483 Molecule::RigidBodyIterator rbIter;
484 RigidBody* rb;
485 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
486
487 // collect the atomic forces onto rigid bodies
488
489 for (mol = info_->beginMolecule(mi); mol != NULL;
490 mol = info_->nextMolecule(mi)) {
491 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
492 rb = mol->nextRigidBody(rbIter)) {
493 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
494 tau += rbTau;
495 }
496 }
497
498 #ifdef IS_MPI
499 Mat3x3d tmpTau(tau);
500 MPI_Allreduce(tmpTau.getArrayPointer(), tau.getArrayPointer(),
501 9, MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
502 #endif
503 curSnapshot->statData.setTau(tau);
504 }
505
506 } //end namespace OpenMD

Properties

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