ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/brains/ForceManager.cpp
Revision: 1550
Committed: Wed Apr 27 21:49:59 2011 UTC (14 years ago) by gezelter
File size: 18663 byte(s)
Log Message:
more fortran removal

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 "parallel/ForceMatrixDecomposition.hpp"
59 #include "nonbonded/NonBondedInteraction.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, rgrp);
333 atomListRow = fDecomp_->getAtomsInGroupRow(cg1);
334 atomListColumn = fDecomp_->getAtomsInGroupColumn(cg2);
335
336 for (vector<int>::iterator ia = atomListRow.begin();
337 ia != atomListRow.end(); ++ia) {
338 atom1 = (*ia);
339
340 for (vector<int>::iterator jb = atomListColumn.begin();
341 jb != atomListColumn.end(); ++jb) {
342 atom2 = (*jb);
343
344 if (!fDecomp_->skipAtomPair(atom1, atom2)) {
345
346 idat = fDecomp_->fillInteractionData(atom1, atom2);
347
348 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
349 idat.d = d_grp;
350 idat.r2 = rgrpsq;
351 } else {
352 idat.d = fDecomp_->getInteratomicVector(atom1, atom2);
353 curSnapshot->wrapVector(idat.d);
354 idat.r2 = idat.d.lengthSquare();
355 }
356
357 idat.rij = sqrt(idat.r2);
358
359 if (iLoop == PREPAIR_LOOP) {
360 interactionMan_->doPrePair(idat);
361 } else {
362 interactionMan_->doPair(idat);
363 vij += idat.vpair;
364 fij += idat.f1;
365 tau -= outProduct(idat.d, idat.f1);
366 }
367 }
368 }
369 }
370
371 if (iLoop == PAIR_LOOP) {
372 if (in_switching_region) {
373 swderiv = vij * dswdr / rgrp;
374 fg = swderiv * d_grp;
375
376 fij += fg;
377
378 if (atomListRow.size() == 1 && atomListColumn.size() == 1) {
379 tau -= outProduct(idat.d, fg);
380 }
381
382 for (vector<int>::iterator ia = atomListRow.begin();
383 ia != atomListRow.end(); ++ia) {
384 atom1 = (*ia);
385 mf = fDecomp_->getMfactRow(atom1);
386 // fg is the force on atom ia due to cutoff group's
387 // presence in switching region
388 fg = swderiv * d_grp * mf;
389 fDecomp_->addForceToAtomRow(atom1, fg);
390
391 if (atomListRow.size() > 1) {
392 if (info_->usesAtomicVirial()) {
393 // find the distance between the atom
394 // and the center of the cutoff group:
395 dag = fDecomp_->getAtomToGroupVectorRow(atom1, cg1);
396 tau -= outProduct(dag, fg);
397 }
398 }
399 }
400 for (vector<int>::iterator jb = atomListColumn.begin();
401 jb != atomListColumn.end(); ++jb) {
402 atom2 = (*jb);
403 mf = fDecomp_->getMfactColumn(atom2);
404 // fg is the force on atom jb due to cutoff group's
405 // presence in switching region
406 fg = -swderiv * d_grp * mf;
407 fDecomp_->addForceToAtomColumn(atom2, fg);
408
409 if (atomListColumn.size() > 1) {
410 if (info_->usesAtomicVirial()) {
411 // find the distance between the atom
412 // and the center of the cutoff group:
413 dag = fDecomp_->getAtomToGroupVectorColumn(atom2, cg2);
414 tau -= outProduct(dag, fg);
415 }
416 }
417 }
418 }
419 //if (!SIM_uses_AtomicVirial) {
420 // tau -= outProduct(d_grp, fij);
421 //}
422 }
423 }
424 }
425
426 if (iLoop == PREPAIR_LOOP) {
427 if (info_->requiresPrepair()) {
428 fDecomp_->collectIntermediateData();
429 atomListLocal = fDecomp_->getAtomList();
430 for (vector<int>::iterator ia = atomListLocal.begin();
431 ia != atomListLocal.end(); ++ia) {
432 atom1 = (*ia);
433 sdat = fDecomp_->fillSelfData(atom1);
434 interactionMan_->doPreForce(sdat);
435 }
436 fDecomp_->distributeIntermediateData();
437 }
438 }
439
440 }
441
442 fDecomp_->collectData();
443
444 if (info_->requiresSkipCorrection() || info_->requiresSelfCorrection()) {
445 atomListLocal = fDecomp_->getAtomList();
446 for (vector<int>::iterator ia = atomListLocal.begin();
447 ia != atomListLocal.end(); ++ia) {
448 atom1 = (*ia);
449
450 if (info_->requiresSkipCorrection()) {
451 vector<int> skipList = fDecomp_->getSkipsForAtom(atom1);
452 for (vector<int>::iterator jb = skipList.begin();
453 jb != skipList.end(); ++jb) {
454 atom2 = (*jb);
455 idat = fDecomp_->fillSkipData(atom1, atom2);
456 interactionMan_->doSkipCorrection(idat);
457 }
458 }
459
460 if (info_->requiresSelfCorrection()) {
461 sdat = fDecomp_->fillSelfData(atom1);
462 interactionMan_->doSelfCorrection(sdat);
463 }
464 }
465 }
466
467 // dangerous to iterate over enums, but we'll live on the edge:
468 for (int i = NO_FAMILY; i != N_INTERACTION_FAMILIES; ++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[VANDERWAALS_FAMILY];
475 curSnapshot->statData[Stats::ELECTROSTATIC_POTENTIAL] = longRangePotential[ELECTROSTATIC_FAMILY];
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