ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1575
Committed: Fri Jun 3 21:39:49 2011 UTC (13 years, 10 months ago) by gezelter
File size: 18204 byte(s)
Log Message:
more parallel fixes

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

Properties

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