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 73 of file LjPmeMgr.C.

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

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 158 of file LjPmeMgr.C.

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

Referenced by LjPmeCompute::computeLJpotential().

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

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

Referenced by computeLongRange().

252 {
253 #if defined(USE_LJPME) && ! defined(NAMD_FFTW_3)
254  // Part 1:
255  int i, j, k = 0;
256  for (i = 0; i < myGrid.K1 * myGrid.K2; i++) {
257  for (j = 0; j < myGrid.dim3; j++) {
258  qGrid[k++] = q_arr[i][j];
259  }
260  }
261  #ifdef NAMD_FFTW
262  #ifdef NAMD_FFTW_3
263  fftwf_execute(forward_plan_yz);
264  #else
265  rfftwnd_real_to_complex(forward_plan_yz, myGrid.K1,
266  (fftw_real *)qGrid, 1, myGrid.dim2 * myGrid.dim3,
267  0, 0, 0);
268  #endif
269  #endif
270 
271  // Part2:
272  int zdim = myGrid.dim3;
273  int ny = myGrid.dim2;
274 
275  // finish forward FFT (x dimension)
276  #ifdef NAMD_FFTW
277  #ifdef NAMD_FFTW_3
278  fftwf_execute(forward_plan_x);
279  #else
280  fftw(forward_plan_x, ny * zdim / 2, (fftw_complex *)qGrid,
281  ny * zdim / 2, 1, work, 1, 0);
282  #endif
283  #endif
284 
285  // Calculate energy and virial
286  double tempVir[6];
287  recipEnergy += myKSpace->compute_energy(qGrid, lattice, alpha, tempVir);
288  for(i = 0; i < 6; i++) {
289  recipVirial[i] += tempVir[i];
290  }
291 
292  #ifdef NAMD_FFTW
293  #ifdef NAMD_FFTW_3
294  fftwf_execute(backward_plan_x);
295  #else
296  // start backward FFT (x dimension)
297  fftw(backward_plan_x, ny * zdim / 2, (fftw_complex *)qGrid,
298  ny * zdim / 2, 1, work, 1, 0);
299  #endif
300  #endif
301 
302  // Part 3:
303  #ifdef NAMD_FFTW
304  #ifdef NAMD_FFTW_3
305  fftwf_execute(backward_plan_yz);
306  #else
307  rfftwnd_complex_to_real(backward_plan_yz, myGrid.K1,
308  (fftw_complex *)qGrid, 1, myGrid.dim2 * myGrid.dim3 / 2,
309  0, 0, 0);
310  #endif
311  #endif
312  k = 0;
313  for (i = 0; i < myGrid.K1 * myGrid.K2; i++) {
314  for (j = 0; j < myGrid.dim3; j++) {
315  q_arr[i][j] = qGrid[k++];
316  }
317  }
318 #endif // USE_LJPME
319 }
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
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 #ifndef USE_LJPME
16  NAMD_die("In order to use LJ-PME, you must build with -DUSE_LJPME");
17 #else
18 #if defined(NAMD_FFTW_3) || ! defined(NAMD_FFTW)
19  NAMD_die("LJ-PME requires FFTW 2");
20 #endif
21 #endif
22  if (initialized) {
23  NAMD_die("LjPmeMgr has already been initialized!");
24  }
25  int numRecipPes = 1;
26  selfEnergy = recipEnergy = 0.0;
27  setSelf = false;
28  numAtoms = nAtoms;
29  // Store grid informations
30  myGrid.K1 = simParams->LJPMEGridSizeX;
31  myGrid.K2 = simParams->LJPMEGridSizeY;
32  myGrid.K3 = simParams->LJPMEGridSizeZ;
33  myGrid.order = simParams->LJPMEInterpOrder;
34  myGrid.dim2 = myGrid.K2;
35  myGrid.dim3 = 2 * (myGrid.K3 / 2 + 1);
36  myGrid.block1 = (myGrid.K1 + numRecipPes - 1) / numRecipPes;
37  myGrid.block2 = (myGrid.K2 + numRecipPes - 1) / numRecipPes;
38 
39  // Allocate memory
40  myKSpace = new LjPmeKSpace(myGrid);
41  myRealSpace = new LjPmeRealSpace(myGrid, numAtoms);
42  dataArr = new double[4*numAtoms];
43  if (dataArr == 0) NAMD_die("can't allocate LJ-PME Manager dataArr buffer");
44 
45  qsize = myGrid.K1 * myGrid.dim2 * myGrid.dim3;
46  fsize = myGrid.K1 * myGrid.dim2;
47  q_arr = new float *[fsize];
48  if (q_arr == 0) NAMD_die("can't allocate LJ-PME Manager q_arr buffer");
49  memset((void *)q_arr, 0, fsize * sizeof(float *));
50 
51  // kludge so we won't segfault
52  for (int i = 0; i < fsize; i++)
53  {
54  q_arr[i] = new float[myGrid.dim3];
55  if (q_arr[i] == 0) NAMD_die("can't allocate LJ-PME Manager q_arr[i] buffer");
56  memset((void *)q_arr[i], 0, myGrid.dim3 * sizeof(float));
57  }
58  // end kludge
59 
60  f_arr = new char[fsize];
61  if (f_arr == 0) NAMD_die("can't allocate LJ-PME Manager f_arr buffer");
62  fz_arr = new char[myGrid.dim3];
63  if (fz_arr == 0) NAMD_die("can't allocate LJ-PME Manager fz_arr buffer");
64 
65  qGrid = new float[qsize];
66  if (qGrid == 0) NAMD_die("can't allocate LJ-PME Manager qGrid buffer");
67 
68  this->optimizeFFT();
69  memset((void *)qGrid, 0, qsize * sizeof(float));
70  initialized = true;
71 }
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:91
#define simParams
Definition: Output.C:129
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 91 of file LjPmeMgr.C.

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

Referenced by initialize().

91  {
92  int n[3];
93  n[0] = myGrid.K1;
94  n[1] = myGrid.K2;
95  n[2] = myGrid.K3;
96 #if defined(USE_LJPME) && ! defined(NAMD_FFTW_3)
97  /*
98  * see if using FFTW_ESTIMATE makes start up faster
99  */
100  #ifdef NAMD_FFTW
101  #ifdef NAMD_FFTW_3
102  work = new fftwf_complex[n[0]];
103 
104  iout << iINFO << "Optimizing 4 LJ-PME FFT steps. 1..." << endi;
105  forward_plan_yz = fftwf_plan_many_dft_r2c(2, n+1,
106  myGrid.K1, qGrid, NULL, 1, myGrid.dim2 * myGrid.dim3,
107  (fftwf_complex *)qGrid, NULL, 1,
108  myGrid.dim2 * (myGrid.dim3 / 2), FFTW_ESTIMATE);
109 
110  iout << " 2..." << endi;
111  int zdim = myGrid.dim3;
112  int xStride=myGrid.dim2 *( myGrid.dim3 / 2);
113  forward_plan_x = fftwf_plan_many_dft(1, n, xStride,
114  (fftwf_complex *)qGrid, NULL, xStride, 1,
115  (fftwf_complex *)qGrid, NULL, xStride, 1,
116  FFTW_FORWARD, FFTW_ESTIMATE);
117 
118  iout << " 3..." << endi;
119  backward_plan_x = fftwf_plan_many_dft(1, n, xStride,
120  (fftwf_complex *)qGrid, NULL, xStride, 1,
121  (fftwf_complex *)qGrid, NULL, xStride, 1,
122  FFTW_BACKWARD, FFTW_ESTIMATE);
123 
124  iout << " 4..." << endi;
125  backward_plan_yz = fftwf_plan_many_dft_c2r(2, n+1,
126  myGrid.K1,(fftwf_complex *)qGrid,
127  NULL, 1, myGrid.dim2 * (myGrid.dim3 / 2),
128  qGrid, NULL, 1, myGrid.dim2 * myGrid.dim3,
129  FFTW_ESTIMATE);
130  iout << " Done.\n" << endi;
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 LJ-PME.");
154  #endif
155 #endif // USE_LJPME
156 }
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 321 of file LjPmeMgr.C.

Referenced by computeLongRange().

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

◆ setScaledCoordinates()

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

Definition at line 202 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().

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