ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1549
Committed: Wed Apr 27 18:38:15 2011 UTC (14 years ago) by gezelter
File size: 18554 byte(s)
Log Message:
a few more tweaks   We're getting somewhat closer to deleting fortran.

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 #include "UseTheForce/doForces_interface.h"
53 #define __OPENMD_C
54 #include "UseTheForce/DarkSide/fInteractionMap.h"
55 #include "utils/simError.h"
56 #include "primitives/Bond.hpp"
57 #include "primitives/Bend.hpp"
58 #include "primitives/Torsion.hpp"
59 #include "primitives/Inversion.hpp"
60 #include "parallel/ForceMatrixDecomposition.hpp"
61 //#include "parallel/ForceSerialDecomposition.hpp"
62
63 using namespace std;
64 namespace OpenMD {
65
66 ForceManager::ForceManager(SimInfo * info) : info_(info) {
67
68 #ifdef IS_MPI
69 fDecomp_ = new ForceMatrixDecomposition(info_);
70 #else
71 // fDecomp_ = new ForceSerialDecomposition(info);
72 #endif
73 }
74
75 void ForceManager::calcForces() {
76
77 if (!info_->isFortranInitialized()) {
78 info_->update();
79 interactionMan_->setSimInfo(info_);
80 interactionMan_->initialize();
81 swfun_ = interactionMan_->getSwitchingFunction();
82 fDecomp_->distributeInitialData();
83 info_->setupFortran();
84 }
85
86 preCalculation();
87 shortRangeInteractions();
88 longRangeInteractions();
89 postCalculation();
90
91 }
92
93 void ForceManager::preCalculation() {
94 SimInfo::MoleculeIterator mi;
95 Molecule* mol;
96 Molecule::AtomIterator ai;
97 Atom* atom;
98 Molecule::RigidBodyIterator rbIter;
99 RigidBody* rb;
100 Molecule::CutoffGroupIterator ci;
101 CutoffGroup* cg;
102
103 // forces are zeroed here, before any are accumulated.
104
105 for (mol = info_->beginMolecule(mi); mol != NULL;
106 mol = info_->nextMolecule(mi)) {
107 for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) {
108 atom->zeroForcesAndTorques();
109 }
110
111 //change the positions of atoms which belong to the rigidbodies
112 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
113 rb = mol->nextRigidBody(rbIter)) {
114 rb->zeroForcesAndTorques();
115 }
116
117 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
118 for(cg = mol->beginCutoffGroup(ci); cg != NULL;
119 cg = mol->nextCutoffGroup(ci)) {
120 //calculate the center of mass of cutoff group
121 cg->updateCOM();
122 }
123 }
124 }
125
126 // Zero out the stress tensor
127 tau *= 0.0;
128
129 }
130
131 void ForceManager::shortRangeInteractions() {
132 Molecule* mol;
133 RigidBody* rb;
134 Bond* bond;
135 Bend* bend;
136 Torsion* torsion;
137 Inversion* inversion;
138 SimInfo::MoleculeIterator mi;
139 Molecule::RigidBodyIterator rbIter;
140 Molecule::BondIterator bondIter;;
141 Molecule::BendIterator bendIter;
142 Molecule::TorsionIterator torsionIter;
143 Molecule::InversionIterator inversionIter;
144 RealType bondPotential = 0.0;
145 RealType bendPotential = 0.0;
146 RealType torsionPotential = 0.0;
147 RealType inversionPotential = 0.0;
148
149 //calculate short range interactions
150 for (mol = info_->beginMolecule(mi); mol != NULL;
151 mol = info_->nextMolecule(mi)) {
152
153 //change the positions of atoms which belong to the rigidbodies
154 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
155 rb = mol->nextRigidBody(rbIter)) {
156 rb->updateAtoms();
157 }
158
159 for (bond = mol->beginBond(bondIter); bond != NULL;
160 bond = mol->nextBond(bondIter)) {
161 bond->calcForce();
162 bondPotential += bond->getPotential();
163 }
164
165 for (bend = mol->beginBend(bendIter); bend != NULL;
166 bend = mol->nextBend(bendIter)) {
167
168 RealType angle;
169 bend->calcForce(angle);
170 RealType currBendPot = bend->getPotential();
171
172 bendPotential += bend->getPotential();
173 map<Bend*, BendDataSet>::iterator i = bendDataSets.find(bend);
174 if (i == bendDataSets.end()) {
175 BendDataSet dataSet;
176 dataSet.prev.angle = dataSet.curr.angle = angle;
177 dataSet.prev.potential = dataSet.curr.potential = currBendPot;
178 dataSet.deltaV = 0.0;
179 bendDataSets.insert(map<Bend*, BendDataSet>::value_type(bend, dataSet));
180 }else {
181 i->second.prev.angle = i->second.curr.angle;
182 i->second.prev.potential = i->second.curr.potential;
183 i->second.curr.angle = angle;
184 i->second.curr.potential = currBendPot;
185 i->second.deltaV = fabs(i->second.curr.potential -
186 i->second.prev.potential);
187 }
188 }
189
190 for (torsion = mol->beginTorsion(torsionIter); torsion != NULL;
191 torsion = mol->nextTorsion(torsionIter)) {
192 RealType angle;
193 torsion->calcForce(angle);
194 RealType currTorsionPot = torsion->getPotential();
195 torsionPotential += torsion->getPotential();
196 map<Torsion*, TorsionDataSet>::iterator i = torsionDataSets.find(torsion);
197 if (i == torsionDataSets.end()) {
198 TorsionDataSet dataSet;
199 dataSet.prev.angle = dataSet.curr.angle = angle;
200 dataSet.prev.potential = dataSet.curr.potential = currTorsionPot;
201 dataSet.deltaV = 0.0;
202 torsionDataSets.insert(map<Torsion*, TorsionDataSet>::value_type(torsion, dataSet));
203 }else {
204 i->second.prev.angle = i->second.curr.angle;
205 i->second.prev.potential = i->second.curr.potential;
206 i->second.curr.angle = angle;
207 i->second.curr.potential = currTorsionPot;
208 i->second.deltaV = fabs(i->second.curr.potential -
209 i->second.prev.potential);
210 }
211 }
212
213 for (inversion = mol->beginInversion(inversionIter);
214 inversion != NULL;
215 inversion = mol->nextInversion(inversionIter)) {
216 RealType angle;
217 inversion->calcForce(angle);
218 RealType currInversionPot = inversion->getPotential();
219 inversionPotential += inversion->getPotential();
220 map<Inversion*, InversionDataSet>::iterator i = inversionDataSets.find(inversion);
221 if (i == inversionDataSets.end()) {
222 InversionDataSet dataSet;
223 dataSet.prev.angle = dataSet.curr.angle = angle;
224 dataSet.prev.potential = dataSet.curr.potential = currInversionPot;
225 dataSet.deltaV = 0.0;
226 inversionDataSets.insert(map<Inversion*, InversionDataSet>::value_type(inversion, dataSet));
227 }else {
228 i->second.prev.angle = i->second.curr.angle;
229 i->second.prev.potential = i->second.curr.potential;
230 i->second.curr.angle = angle;
231 i->second.curr.potential = currInversionPot;
232 i->second.deltaV = fabs(i->second.curr.potential -
233 i->second.prev.potential);
234 }
235 }
236 }
237
238 RealType shortRangePotential = bondPotential + bendPotential +
239 torsionPotential + inversionPotential;
240 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
241 curSnapshot->statData[Stats::SHORT_RANGE_POTENTIAL] = shortRangePotential;
242 curSnapshot->statData[Stats::BOND_POTENTIAL] = bondPotential;
243 curSnapshot->statData[Stats::BEND_POTENTIAL] = bendPotential;
244 curSnapshot->statData[Stats::DIHEDRAL_POTENTIAL] = torsionPotential;
245 curSnapshot->statData[Stats::INVERSION_POTENTIAL] = inversionPotential;
246 }
247
248 void ForceManager::longRangeInteractions() {
249
250 // some of this initial stuff will go away:
251 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
252 DataStorage* config = &(curSnapshot->atomData);
253 DataStorage* cgConfig = &(curSnapshot->cgData);
254 RealType* frc = config->getArrayPointer(DataStorage::dslForce);
255 RealType* pos = config->getArrayPointer(DataStorage::dslPosition);
256 RealType* trq = config->getArrayPointer(DataStorage::dslTorque);
257 RealType* A = config->getArrayPointer(DataStorage::dslAmat);
258 RealType* electroFrame = config->getArrayPointer(DataStorage::dslElectroFrame);
259 RealType* particlePot = config->getArrayPointer(DataStorage::dslParticlePot);
260 RealType* rc;
261
262 if(info_->getNGlobalCutoffGroups() != info_->getNGlobalAtoms()){
263 rc = cgConfig->getArrayPointer(DataStorage::dslPosition);
264 } else {
265 // center of mass of the group is the same as position of the atom
266 // if cutoff group does not exist
267 rc = pos;
268 }
269
270 //initialize data before passing to fortran
271 RealType longRangePotential[LR_POT_TYPES];
272 RealType lrPot = 0.0;
273 int isError = 0;
274
275 for (int i=0; i<LR_POT_TYPES;i++){
276 longRangePotential[i]=0.0; //Initialize array
277 }
278
279 // new stuff starts here:
280
281 fDecomp_->distributeData();
282
283 int cg1, cg2, atom1, atom2;
284 Vector3d d_grp, dag;
285 RealType rgrpsq, rgrp;
286 RealType vij;
287 Vector3d fij, fg;
288 pair<int, int> gtypes;
289 RealType rCutSq;
290 bool in_switching_region;
291 RealType sw, dswdr, swderiv;
292 vector<int> atomListColumn, atomListRow, atomListLocal;
293 InteractionData idat;
294 SelfData sdat;
295 RealType mf;
296
297 int loopStart, loopEnd;
298
299 loopEnd = PAIR_LOOP;
300 if (info_->requiresPrepair() ) {
301 loopStart = PREPAIR_LOOP;
302 } else {
303 loopStart = PAIR_LOOP;
304 }
305
306 for (int iLoop = loopStart; iLoop < loopEnd; iLoop++) {
307
308 if (iLoop == loopStart) {
309 bool update_nlist = fDecomp_->checkNeighborList();
310 if (update_nlist)
311 neighborList = fDecomp_->buildNeighborList();
312 }
313
314 for (vector<pair<int, int> >::iterator it = neighborList.begin();
315 it != neighborList.end(); ++it) {
316
317 cg1 = (*it).first;
318 cg2 = (*it).second;
319
320 gtypes = fDecomp_->getGroupTypes(cg1, cg2);
321 d_grp = fDecomp_->getIntergroupVector(cg1, cg2);
322 curSnapshot->wrapVector(d_grp);
323 rgrpsq = d_grp.lengthSquare();
324 rCutSq = groupCutoffMap[gtypes].first;
325
326 if (rgrpsq < rCutSq) {
327 idat.rcut = groupCutoffMap[gtypes].second;
328 if (iLoop == PAIR_LOOP) {
329 vij *= 0.0;
330 fij = V3Zero;
331 }
332
333 in_switching_region = swfun_->getSwitch(rgrpsq, idat.sw, dswdr, 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 for (int i=0; i<LR_POT_TYPES;i++){
469 lrPot += longRangePotential[i]; //Quick hack
470 }
471
472 //store the tau and long range potential
473 curSnapshot->statData[Stats::LONG_RANGE_POTENTIAL] = lrPot;
474 curSnapshot->statData[Stats::VANDERWAALS_POTENTIAL] = longRangePotential[VDW_POT];
475 curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_POT];
476 }
477
478
479 void ForceManager::postCalculation() {
480 SimInfo::MoleculeIterator mi;
481 Molecule* mol;
482 Molecule::RigidBodyIterator rbIter;
483 RigidBody* rb;
484 Snapshot* curSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
485
486 // collect the atomic forces onto rigid bodies
487
488 for (mol = info_->beginMolecule(mi); mol != NULL;
489 mol = info_->nextMolecule(mi)) {
490 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
491 rb = mol->nextRigidBody(rbIter)) {
492 Mat3x3d rbTau = rb->calcForcesAndTorquesAndVirial();
493 tau += rbTau;
494 }
495 }
496
497 #ifdef IS_MPI
498 Mat3x3d tmpTau(tau);
499 MPI_Allreduce(tmpTau.getArrayPointer(), tau.getArrayPointer(),
500 9, MPI_REALTYPE, MPI_SUM, MPI_COMM_WORLD);
501 #endif
502 curSnapshot->statData.setTau(tau);
503 }
504
505 } //end namespace OpenMD

Properties

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