NAMD
Public Member Functions | List of all members
ComputeFmmSerialMgr Class Reference
Inheritance diagram for ComputeFmmSerialMgr:

Public Member Functions

 ComputeFmmSerialMgr ()
 
 ~ComputeFmmSerialMgr ()
 
void setCompute (ComputeFmmSerial *c)
 
void recvCoord (FmmSerialCoordMsg *)
 
void recvForce (FmmSerialForceMsg *)
 

Detailed Description

Definition at line 77 of file ComputeFmmSerial.C.

Constructor & Destructor Documentation

ComputeFmmSerialMgr::ComputeFmmSerialMgr ( )

Definition at line 109 of file ComputeFmmSerial.C.

109  :
110  fmmProxy(thisgroup), fmmCompute(0), numSources(0), numArrived(0),
111  coordMsgs(0), coord(0), force(0), oldmsg(0), numAtoms(0),
112  fmmsolver(0), nlevels(0), scaling(0), center(0),
113  chargebuffer(0), epotbuffer(0), posbuffer(0), forcebuffer(0)
114 {
115  CkpvAccess(BOCclass_group).computeFmmSerialMgr = thisgroup;
116 }
ComputeFmmSerialMgr::~ComputeFmmSerialMgr ( )

Definition at line 118 of file ComputeFmmSerial.C.

119 {
120  for (int i=0; i < numSources; i++) delete coordMsgs[i];
121  delete [] coordMsgs;
122  delete [] coord;
123  delete [] force;
124  delete oldmsg;
125  if (chargebuffer) delete[] chargebuffer;
126  if (epotbuffer) delete[] epotbuffer;
127  if (posbuffer) delete[] posbuffer;
128  if (forcebuffer) delete[] forcebuffer;
129 }

Member Function Documentation

void ComputeFmmSerialMgr::recvCoord ( FmmSerialCoordMsg msg)

Definition at line 200 of file ComputeFmmSerial.C.

References Lattice::a_p(), Lattice::b_p(), Lattice::c_p(), ComputeFmmSerialAtom::charge, FmmSerialCoordMsg::coord, COULOMB, SimParameters::dielectric, endi(), FmmSerialForceMsg::energy, SimParameters::FMMLevels, SimParameters::FMMPadding, FmmSerialForceMsg::force, ComputeFmmSerialAtom::id, iINFO(), iout, FmmSerialCoordMsg::lattice, Node::molecule, NAMD_die(), FmmSerialCoordMsg::numAtoms, Molecule::numAtoms, PatchMap::Object(), Node::Object(), ComputeFmmSerialAtom::position, Node::simParameters, simParams, FmmSerialCoordMsg::sourceNode, FmmSerialForceMsg::virial, Vector::x, Vector::y, and Vector::z.

200  {
201  int i;
202  if ( ! numSources ) {
203  numSources = (PatchMap::Object())->numNodesWithPatches();
204  coordMsgs = new FmmSerialCoordMsg*[numSources];
205  for ( i=0; i<numSources; ++i ) { coordMsgs[i] = 0; }
206  numArrived = 0;
207  numAtoms = Node::Object()->molecule->numAtoms;
208  coord = new ComputeFmmSerialAtom[numAtoms];
209  force = new FmmSerialForce[numAtoms];
210  }
211 
212  for ( i=0; i < msg->numAtoms; ++i ) {
213  coord[msg->coord[i].id] = msg->coord[i];
214  }
215 
216  coordMsgs[numArrived] = msg;
217  ++numArrived;
218 
219  if ( numArrived < numSources ) return;
220  numArrived = 0;
221 
222  // ALL DATA ARRIVED --- CALCULATE FORCES
223  Lattice lattice = msg->lattice;
225 
226  double energy = 0;
227  double virial[3][3] = { 0 }; // FMM does not calculate virial
228 
229  int rc = 0; // return code
230 
231  if ( ! fmmsolver ) {
232  //
233  // setup FMM solver
234  //
235 
236  // check boundary conditions
237  if (lattice.a_p() || lattice.b_p() || lattice.c_p()) {
238  NAMD_die("FMM solver requires non-periodic boundaries");
239  }
240 
241  // setup number of levels
242  if (simParams->FMMLevels > 0) {
243  // explicitly set in config file
244  nlevels = simParams->FMMLevels;
245  }
246  else {
247  // otherwise estimate number of levels as round(log_8(numAtoms))
248  nlevels = (int) floor(log((double)numAtoms) / log(8.) + 0.5);
249  }
250 
251  // find bounding cube length
252  if (numAtoms <= 0) {
253  NAMD_die("setting up FMM with no atoms");
254  }
255  Vector min, max;
256  min = max = coord[0].position;
257  for (i = 1; i < numAtoms; i++) {
258  Vector r = coord[i].position;
259  if (r.x < min.x) min.x = r.x;
260  else if (r.x > max.x) max.x = r.x;
261  if (r.y < min.y) min.y = r.y;
262  else if (r.y > max.y) max.y = r.y;
263  if (r.z < min.z) min.z = r.z;
264  else if (r.z > max.z) max.z = r.z;
265  }
266  double padding = simParams->FMMPadding;
267  if (padding <= 0) padding = 0.01; // pad by at least a delta margin
268  min -= padding;
269  max += padding;
270  double len = max.x - min.x;
271  if (len < max.y - min.y) len = max.y - min.y;
272  if (len < max.z - min.z) len = max.z - min.z;
273  scaling = 1.0 / len; // scale coordinates by length of the cube
274  center = 0.5*(min + max); // center of cube
275  iout << iINFO << "FMM scaling length set to " << len << " A\n" << endi;
276  iout << iINFO << "FMM center set to " << center << "\n" << endi;
277 
278  // allocate buffer space
279  chargebuffer = new double[numAtoms]; // double *
280  epotbuffer = new double[numAtoms]; // double *
281  posbuffer = new double[numAtoms][3]; // double(*)[3]
282  forcebuffer = new double[numAtoms][3]; // double(*)[3]
283  if (chargebuffer == 0 || epotbuffer == 0 ||
284  posbuffer == 0 || forcebuffer == 0) {
285  NAMD_die("can't allocate buffer space for FMM data");
286  }
287 
288  // scale the charges - these won't change
289  double celec = sqrt(COULOMB / simParams->dielectric);
290  for (i = 0; i < numAtoms; i++) {
291  chargebuffer[i] = celec * coord[i].charge;
292  }
293  fmmsolver = 1; // is setup
294  }
295 
296  // translate and scale positions into [-1/2,1/2]^3
297  for (i = 0; i < numAtoms; i++) {
298  posbuffer[i][0] = scaling*(coord[i].position.x - center.x);
299  posbuffer[i][1] = scaling*(coord[i].position.y - center.y);
300  posbuffer[i][2] = scaling*(coord[i].position.z - center.z);
301  }
302 
303  // call the FMM solver
304  int errcode = 0;
305 #ifdef FMM_SOLVER
306  fmmlap_uni_(&numAtoms, posbuffer, chargebuffer, epotbuffer, forcebuffer,
307  &nlevels, &errcode);
308 #else
309  NAMD_die("Must link to FMM library to use FMM\n");
310 #endif
311 
312  // scale force and potentials
313  for (i = 0; i < numAtoms; i++) {
314  double qs = chargebuffer[i] * scaling;
315  force[i].x = qs * scaling * forcebuffer[i][0];
316  force[i].y = qs * scaling * forcebuffer[i][1];
317  force[i].z = qs * scaling * forcebuffer[i][2];
318  energy += qs * epotbuffer[i];
319  }
320  energy *= 0.5;
321 
322  // distribute forces
323  for (int j=0; j < numSources; j++) {
324  FmmSerialCoordMsg *cmsg = coordMsgs[j];
325  coordMsgs[j] = 0;
326  FmmSerialForceMsg *fmsg = new (cmsg->numAtoms, 0) FmmSerialForceMsg;
327 
328  for (int i=0; i < cmsg->numAtoms; i++) {
329  fmsg->force[i] = force[cmsg->coord[i].id];
330  }
331 
332  if ( ! j ) { // set virial and energy only for first message
333  fmsg->energy = energy;
334  for (int k=0; k < 3; k++) {
335  for (int l=0; l < 3; l++) {
336  fmsg->virial[k][l] = virial[k][l];
337  }
338  }
339  }
340  else { // set other messages to zero, add into reduction only once
341  fmsg->energy = 0;
342  for (int k=0; k < 3; k++) {
343  for (int l=0; l < 3; l++) {
344  fmsg->virial[k][l] = 0;
345  }
346  }
347  }
348 
349  fmmProxy[cmsg->sourceNode].recvForce(fmsg);
350  delete cmsg;
351  }
352 }
static Node * Object()
Definition: Node.h:86
std::ostream & iINFO(std::ostream &s)
Definition: InfoStream.C:107
FmmSerialForce * force
static PatchMap * Object()
Definition: PatchMap.h:27
Definition: Vector.h:64
SimParameters * simParameters
Definition: Node.h:178
#define COULOMB
Definition: common.h:44
BigReal z
Definition: Vector.h:66
#define iout
Definition: InfoStream.h:87
BigReal FMMPadding
ComputeFmmSerialAtom * coord
BigReal virial[3][3]
BigReal x
Definition: Vector.h:66
int numAtoms
Definition: Molecule.h:556
void NAMD_die(const char *err_msg)
Definition: common.C:83
#define simParams
Definition: Output.C:127
BigReal y
Definition: Vector.h:66
BigReal dielectric
infostream & endi(infostream &s)
Definition: InfoStream.C:38
int b_p() const
Definition: Lattice.h:274
int a_p() const
Definition: Lattice.h:273
Molecule * molecule
Definition: Node.h:176
int c_p() const
Definition: Lattice.h:275
void ComputeFmmSerialMgr::recvForce ( FmmSerialForceMsg msg)

Definition at line 354 of file ComputeFmmSerial.C.

References ComputeFmmSerial::saveResults().

354  {
355  fmmCompute->saveResults(msg);
356  delete oldmsg;
357  oldmsg = msg;
358 }
void saveResults(FmmSerialForceMsg *)
void ComputeFmmSerialMgr::setCompute ( ComputeFmmSerial c)
inline

Definition at line 82 of file ComputeFmmSerial.C.

82 { fmmCompute = c; }

The documentation for this class was generated from the following file: