NAMD
Public Member Functions | List of all members
LjPmeMgr Class Reference

#include <LjPmeMgr.h>

Public Member Functions

 LjPmeMgr ()
 
 ~LjPmeMgr ()
 
void initialize (const SimParameters *simParams, const int nAtoms)
 
void computeLongRange (const double *ljPmeCoord, const Lattice &lattice, const double &alphaLJ, double *force, double &energy, double virial[][3], bool doEnergy)
 
void optimizeFFT ()
 
void setScaledCoordinates (const double *refPos, const Lattice &lattice)
 
void gridCalculation (const double &alpha, const Lattice &lattice)
 
double selfCompute (const double &alphaLJ)
 

Detailed Description

Definition at line 48 of file LjPmeMgr.h.

Constructor & Destructor Documentation

◆ LjPmeMgr()

LjPmeMgr::LjPmeMgr ( )
inline

Definition at line 50 of file LjPmeMgr.h.

50  : myRealSpace(0), myKSpace(0), dataArr(0), qGrid(0),
51  q_arr(0), f_arr(0), fz_arr(0) {
52  setSelf = false;
53  initialized = false;
54  numAtoms = 0;
55  }

◆ ~LjPmeMgr()

LjPmeMgr::~LjPmeMgr ( )

Definition at line 69 of file LjPmeMgr.C.

69  {
70  setSelf = false;
71  initialized = false;
72  if (myRealSpace) delete myRealSpace;
73  if (myKSpace) delete myKSpace;
74  if (dataArr) delete [] dataArr;
75  if (qGrid) delete [] qGrid;
76  if (f_arr) delete [] f_arr;
77  if (fz_arr) delete [] fz_arr;
78  if (work) delete [] work;
79 
80  for (int i = 0; i < fsize; ++i) {
81  if (q_arr[i]) {
82  delete [] q_arr[i];
83  }
84  }
85 }

Member Function Documentation

◆ computeLongRange()

void LjPmeMgr::computeLongRange ( const double *  ljPmeCoord,
const Lattice lattice,
const double &  alphaLJ,
double *  force,
double &  energy,
double  virial[][3],
bool  doEnergy 
)

Definition at line 157 of file LjPmeMgr.C.

References LjPmeRealSpace::compute_scaledForces(), LjPmeGrid::dim3, LjPmeRealSpace::fill_charges(), gridCalculation(), selfCompute(), and setScaledCoordinates().

Referenced by LjPmeCompute::computeLJpotential().

160  {
161  for (int i = 0; i < fsize; ++i) {
162  if (q_arr[i]) {
163  memset((void *)(q_arr[i]), 0, myGrid.dim3 * sizeof(float));
164  }
165  }
166  //memset((void *)qGrid, 0, qsize * sizeof(float)); // Do I need this?
167  memset((void *)f_arr, 0, fsize * sizeof(char));
168  memset((void *)fz_arr, 0, myGrid.dim3 * sizeof(char));
169  recipEnergy = 0.0;
170  for(int i = 0; i < 6; i++) {
171  recipVirial[i] = 0.0;
172  }
173 
174  // Store the charge and scaled coordinates in dataArr buffer
175  this->setScaledCoordinates(ljPmeCoord, lattice);
176  // Compute and store the self term
177  if(!setSelf) {
178  selfEnergy = this->selfCompute(alphaLJ);
179  setSelf = true;
180  }
181  // Split charges into the grid
182  myRealSpace->fill_charges(q_arr, f_arr, fz_arr, dataArr);
183  this->gridCalculation(alphaLJ, lattice);
184  myRealSpace->compute_scaledForces(q_arr, dataArr, force, lattice);
185 
186  // Add energy and virial
187  if(doEnergy) {
188  energy += recipEnergy + selfEnergy;
189  virial[0][0] += recipVirial[0];
190  virial[0][1] += recipVirial[1];
191  virial[0][2] += recipVirial[2];
192  virial[1][0] += recipVirial[1];
193  virial[1][1] += recipVirial[3];
194  virial[1][2] += recipVirial[4];
195  virial[2][0] += recipVirial[2];
196  virial[2][1] += recipVirial[4];
197  virial[2][2] += recipVirial[5];
198  }
199 }
void compute_scaledForces(const float *const *q_arr, double *pos, double *force, const Lattice &lattice)
void gridCalculation(const double &alpha, const Lattice &lattice)
Definition: LjPmeMgr.C:250
void setScaledCoordinates(const double *refPos, const Lattice &lattice)
Definition: LjPmeMgr.C:201
int dim3
Definition: LjPmeBase.h:22
double selfCompute(const double &alphaLJ)
Definition: LjPmeMgr.C:323
void fill_charges(float **q_arr, char *f_arr, char *fz_arr, double *p)

◆ gridCalculation()

void LjPmeMgr::gridCalculation ( const double &  alpha,
const Lattice lattice 
)

Calculates and return the self-energy term for LJ-PME

Definition at line 250 of file LjPmeMgr.C.

References LjPmeKSpace::compute_energy(), LjPmeGrid::dim2, LjPmeGrid::dim3, LjPmeGrid::K1, LjPmeGrid::K2, and NAMD_die().

Referenced by computeLongRange().

251 {
252  // place compatibility guards around function until we get FFTW3 working
253 #ifdef NAMD_FFTW_3
254  NAMD_die("LJPMESerial requires FFTW 2");
255 #else
256  // Part 1:
257  int i, j, k = 0;
258  for (i = 0; i < myGrid.K1 * myGrid.K2; i++) {
259  for (j = 0; j < myGrid.dim3; j++) {
260  qGrid[k++] = q_arr[i][j];
261  }
262  }
263  #ifdef NAMD_FFTW
264  #ifdef NAMD_FFTW_3
265  fftwf_execute(forward_plan_yz);
266  #else
267  rfftwnd_real_to_complex(forward_plan_yz, myGrid.K1,
268  (fftw_real *)qGrid, 1, myGrid.dim2 * myGrid.dim3,
269  0, 0, 0);
270  #endif
271  #endif
272 
273  // Part2:
274  int zdim = myGrid.dim3;
275  int ny = myGrid.dim2;
276 
277  // finish forward FFT (x dimension)
278  #ifdef NAMD_FFTW
279  #ifdef NAMD_FFTW_3
280  fftwf_execute(forward_plan_x);
281  #else
282  fftw(forward_plan_x, ny * zdim / 2, (fftw_complex *)qGrid,
283  ny * zdim / 2, 1, work, 1, 0);
284  #endif
285  #endif
286 
287  // Calculate energy and virial
288  double tempVir[6];
289  recipEnergy += myKSpace->compute_energy(qGrid, lattice, alpha, tempVir);
290  for(i = 0; i < 6; i++) {
291  recipVirial[i] += tempVir[i];
292  }
293 
294  #ifdef NAMD_FFTW
295  #ifdef NAMD_FFTW_3
296  fftwf_execute(backward_plan_x);
297  #else
298  // start backward FFT (x dimension)
299  fftw(backward_plan_x, ny * zdim / 2, (fftw_complex *)qGrid,
300  ny * zdim / 2, 1, work, 1, 0);
301  #endif
302  #endif
303 
304  // Part 3:
305  #ifdef NAMD_FFTW
306  #ifdef NAMD_FFTW_3
307  fftwf_execute(backward_plan_yz);
308  #else
309  rfftwnd_complex_to_real(backward_plan_yz, myGrid.K1,
310  (fftw_complex *)qGrid, 1, myGrid.dim2 * myGrid.dim3 / 2,
311  0, 0, 0);
312  #endif
313  #endif
314  k = 0;
315  for (i = 0; i < myGrid.K1 * myGrid.K2; i++) {
316  for (j = 0; j < myGrid.dim3; j++) {
317  q_arr[i][j] = qGrid[k++];
318  }
319  }
320 #endif
321 }
int dim2
Definition: LjPmeBase.h:22
int dim3
Definition: LjPmeBase.h:22
double compute_energy(float *q_arr, const Lattice &lattice, double ewald, double *virial)
Definition: LjPmeKSpace.C:52
void NAMD_die(const char *err_msg)
Definition: common.C:147
int K1
Definition: LjPmeBase.h:21
int K2
Definition: LjPmeBase.h:21

◆ initialize()

void LjPmeMgr::initialize ( const SimParameters simParams,
const int  nAtoms 
)

Calculate and add force and energy for reciprocal LJ-PME

Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000 by The Board of Trustees of the University of Illinois. All rights reserved.

Definition at line 14 of file LjPmeMgr.C.

References LjPmeGrid::block1, LjPmeGrid::block2, LjPmeGrid::dim2, LjPmeGrid::dim3, LjPmeGrid::K1, LjPmeGrid::K2, LjPmeGrid::K3, NAMD_die(), optimizeFFT(), LjPmeGrid::order, and simParams.

Referenced by LjPmeCompute::initialize().

14  {
15 #if defined(NAMD_FFTW_3) || ! defined(NAMD_FFTW)
16  NAMD_die("LJPMESerial requires FFTW 2");
17 #endif
18  if (initialized) {
19  NAMD_die("LjPmeMgr has already been initialized!");
20  }
21  int numRecipPes = 1;
22  selfEnergy = recipEnergy = 0.0;
23  setSelf = false;
24  numAtoms = nAtoms;
25  // Store grid informations
26  myGrid.K1 = simParams->LJPMEGridSizeX;
27  myGrid.K2 = simParams->LJPMEGridSizeY;
28  myGrid.K3 = simParams->LJPMEGridSizeZ;
29  myGrid.order = simParams->LJPMEInterpOrder;
30  myGrid.dim2 = myGrid.K2;
31  myGrid.dim3 = 2 * (myGrid.K3 / 2 + 1);
32  myGrid.block1 = (myGrid.K1 + numRecipPes - 1) / numRecipPes;
33  myGrid.block2 = (myGrid.K2 + numRecipPes - 1) / numRecipPes;
34 
35  // Allocate memory
36  myKSpace = new LjPmeKSpace(myGrid);
37  myRealSpace = new LjPmeRealSpace(myGrid, numAtoms);
38  dataArr = new double[4*numAtoms];
39  if (dataArr == 0) NAMD_die("can't allocate LJ-PME Manager dataArr buffer");
40 
41  qsize = myGrid.K1 * myGrid.dim2 * myGrid.dim3;
42  fsize = myGrid.K1 * myGrid.dim2;
43  q_arr = new float *[fsize];
44  if (q_arr == 0) NAMD_die("can't allocate LJ-PME Manager q_arr buffer");
45  memset((void *)q_arr, 0, fsize * sizeof(float *));
46 
47  // kludge so we won't segfault
48  for (int i = 0; i < fsize; i++)
49  {
50  q_arr[i] = new float[myGrid.dim3];
51  if (q_arr[i] == 0) NAMD_die("can't allocate LJ-PME Manager q_arr[i] buffer");
52  memset((void *)q_arr[i], 0, myGrid.dim3 * sizeof(float));
53  }
54  // end kludge
55 
56  f_arr = new char[fsize];
57  if (f_arr == 0) NAMD_die("can't allocate LJ-PME Manager f_arr buffer");
58  fz_arr = new char[myGrid.dim3];
59  if (fz_arr == 0) NAMD_die("can't allocate LJ-PME Manager fz_arr buffer");
60 
61  qGrid = new float[qsize];
62  if (qGrid == 0) NAMD_die("can't allocate LJ-PME Manager qGrid buffer");
63 
64  this->optimizeFFT();
65  memset((void *)qGrid, 0, qsize * sizeof(float));
66  initialized = true;
67 }
int dim2
Definition: LjPmeBase.h:22
int dim3
Definition: LjPmeBase.h:22
void NAMD_die(const char *err_msg)
Definition: common.C:147
int K3
Definition: LjPmeBase.h:21
void optimizeFFT()
Definition: LjPmeMgr.C:87
#define simParams
Definition: Output.C:131
int block2
Definition: LjPmeBase.h:24
int block1
Definition: LjPmeBase.h:24
int K1
Definition: LjPmeBase.h:21
int K2
Definition: LjPmeBase.h:21
int order
Definition: LjPmeBase.h:23

◆ optimizeFFT()

void LjPmeMgr::optimizeFFT ( )

Store the charge and scaled coordinates into dataArr buffer

Definition at line 87 of file LjPmeMgr.C.

References LjPmeGrid::dim2, LjPmeGrid::dim3, endi(), iINFO(), iout, LjPmeGrid::K1, LjPmeGrid::K2, LjPmeGrid::K3, and NAMD_die().

Referenced by initialize().

87  {
88  int n[3];
89  n[0] = myGrid.K1;
90  n[1] = myGrid.K2;
91  n[2] = myGrid.K3;
92  /*
93  * see if using FFTW_ESTIMATE makes start up faster
94  */
95  #ifdef NAMD_FFTW
96  #ifdef NAMD_FFTW_3
97  // place compatibility guards until we get FFTW3 working
98 #if 0
99  work = new fftwf_complex[n[0]];
100 
101  iout << iINFO << "Optimizing 4 LJ-PME FFT steps. 1..." << endi;
102  forward_plan_yz = fftwf_plan_many_dft_r2c(2, n+1,
103  myGrid.K1, qGrid, NULL, 1, myGrid.dim2 * myGrid.dim3,
104  (fftwf_complex *)qGrid, NULL, 1,
105  myGrid.dim2 * (myGrid.dim3 / 2), FFTW_ESTIMATE);
106 
107  iout << " 2..." << endi;
108  int zdim = myGrid.dim3;
109  int xStride=myGrid.dim2 *( myGrid.dim3 / 2);
110  forward_plan_x = fftwf_plan_many_dft(1, n, xStride,
111  (fftwf_complex *)qGrid, NULL, xStride, 1,
112  (fftwf_complex *)qGrid, NULL, xStride, 1,
113  FFTW_FORWARD, FFTW_ESTIMATE);
114 
115  iout << " 3..." << endi;
116  backward_plan_x = fftwf_plan_many_dft(1, n, xStride,
117  (fftwf_complex *)qGrid, NULL, xStride, 1,
118  (fftwf_complex *)qGrid, NULL, xStride, 1,
119  FFTW_BACKWARD, FFTW_ESTIMATE);
120 
121  iout << " 4..." << endi;
122  backward_plan_yz = fftwf_plan_many_dft_c2r(2, n+1,
123  myGrid.K1,(fftwf_complex *)qGrid,
124  NULL, 1, myGrid.dim2 * (myGrid.dim3 / 2),
125  qGrid, NULL, 1, myGrid.dim2 * myGrid.dim3,
126  FFTW_ESTIMATE);
127  iout << " Done.\n" << endi;
128 #else
129  NAMD_die("LJPMESerial requires FFTW 2");
130 #endif
131  #else
132  work = new fftw_complex[n[0]];
133 
134  iout << iINFO << "Optimizing 4 LJ-PME FFT steps. 1..." << endi;
135  forward_plan_yz = rfftwnd_create_plan_specific(2, n+1, FFTW_REAL_TO_COMPLEX,
136  FFTW_ESTIMATE | FFTW_IN_PLACE | FFTW_USE_WISDOM,
137  qGrid, 1, 0, 0);
138  iout << " 2..." << endi;
139  forward_plan_x = fftw_create_plan_specific(n[0], FFTW_FORWARD,
140  FFTW_ESTIMATE | FFTW_IN_PLACE | FFTW_USE_WISDOM, (fftw_complex *)qGrid,
141  myGrid.dim2 * myGrid.dim3 / 2, work, 1);
142  iout << " 3..." << endi;
143  backward_plan_x = fftw_create_plan_specific(n[0], FFTW_BACKWARD,
144  FFTW_ESTIMATE | FFTW_IN_PLACE | FFTW_USE_WISDOM, (fftw_complex *)qGrid,
145  myGrid.dim2 * myGrid.dim3 / 2, work, 1);
146  iout << " 4..." << endi;
147  backward_plan_yz = rfftwnd_create_plan_specific(2, n + 1, FFTW_COMPLEX_TO_REAL,
148  FFTW_ESTIMATE | FFTW_IN_PLACE | FFTW_USE_WISDOM,
149  qGrid, 1, 0, 0);
150  iout << " Done.\n" << endi;
151  #endif
152  #else
153  NAMD_die("Sorry, FFTW must be compiled in to use LJPMESerial.");
154  #endif
155 }
std::ostream & iINFO(std::ostream &s)
Definition: InfoStream.C:81
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
#define iout
Definition: InfoStream.h:51
int dim2
Definition: LjPmeBase.h:22
int dim3
Definition: LjPmeBase.h:22
void NAMD_die(const char *err_msg)
Definition: common.C:147
int K3
Definition: LjPmeBase.h:21
int K1
Definition: LjPmeBase.h:21
int K2
Definition: LjPmeBase.h:21

◆ selfCompute()

double LjPmeMgr::selfCompute ( const double &  alphaLJ)

Definition at line 323 of file LjPmeMgr.C.

Referenced by computeLongRange().

323  {
324  double energy = 0.0;
325  double c3Term;
326  double alpha6 = pow(alphaLJ, 6.0);
327  for(int i=0; i < numAtoms; i++) {
328  c3Term = dataArr[4*i+3];
329  energy += c3Term*c3Term;
330  }
331  return (energy * alpha6 / 12.0);
332 }

◆ setScaledCoordinates()

void LjPmeMgr::setScaledCoordinates ( const double *  refPos,
const Lattice lattice 
)

Definition at line 201 of file LjPmeMgr.C.

References Lattice::a_r(), Lattice::b_r(), Lattice::c_r(), LjPmeGrid::K1, LjPmeGrid::K2, LjPmeGrid::K3, LjPmeGrid::order, Lattice::origin(), Vector::x, Vector::y, and Vector::z.

Referenced by computeLongRange().

201  {
202  Vector origin = lattice.origin();
203  Vector recip1 = lattice.a_r();
204  Vector recip2 = lattice.b_r();
205  Vector recip3 = lattice.c_r();
206  double ox = origin.x;
207  double oy = origin.y;
208  double oz = origin.z;
209  double r1x = recip1.x;
210  double r1y = recip1.y;
211  double r1z = recip1.z;
212  double r2x = recip2.x;
213  double r2y = recip2.y;
214  double r2z = recip2.z;
215  double r3x = recip3.x;
216  double r3y = recip3.y;
217  double r3z = recip3.z;
218  int K1 = myGrid.K1;
219  int K2 = myGrid.K2;
220  int K3 = myGrid.K3;
221  double shift1 = ((K1 + myGrid.order - 1)/2)/(double)K1;
222  double shift2 = ((K2 + myGrid.order - 1)/2)/(double)K2;
223  double shift3 = ((K3 + myGrid.order - 1)/2)/(double)K3;
224 
225  for (int i=0; i<numAtoms; i++) {
226  int index = 4*i;
227  double px = refPos[index] - ox;
228  double py = refPos[index+1] - oy;
229  double pz = refPos[index+2] - oz;
230  double c3Term = refPos[index+3];
231  double sx = shift1 + px*r1x + py*r1y + pz*r1z;
232  double sy = shift2 + px*r2x + py*r2y + pz*r2z;
233  double sz = shift3 + px*r3x + py*r3y + pz*r3z;
234  px = K1 * ( sx - floor(sx) );
235  py = K2 * ( sy - floor(sy) );
236  pz = K3 * ( sz - floor(sz) );
237  // Check for rare rounding condition where K * ( 1 - epsilon ) == K
238  // which was observed with g++ on Intel x86 architecture.
239  if ( px == K1 ) px = 0;
240  if ( py == K2 ) py = 0;
241  if ( pz == K3 ) pz = 0;
242 
243  dataArr[index] = px;
244  dataArr[index+1] = py;
245  dataArr[index+2] = pz;
246  dataArr[index+3] = c3Term;
247  }
248 }
Definition: Vector.h:72
BigReal z
Definition: Vector.h:74
BigReal x
Definition: Vector.h:74
NAMD_HOST_DEVICE Vector a_r() const
Definition: Lattice.h:284
NAMD_HOST_DEVICE Vector b_r() const
Definition: Lattice.h:285
int K3
Definition: LjPmeBase.h:21
NAMD_HOST_DEVICE Vector c_r() const
Definition: Lattice.h:286
BigReal y
Definition: Vector.h:74
int K1
Definition: LjPmeBase.h:21
int K2
Definition: LjPmeBase.h:21
NAMD_HOST_DEVICE Vector origin() const
Definition: Lattice.h:278
int order
Definition: LjPmeBase.h:23

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