20 #include "ComputeMgr.decl.h" 27 #define MIN_DEBUG_LEVEL 1 41 int *table =
new int[ntypes*ntypes];
43 for (
int i=0; i<ntypes; i++) {
44 for (
int j=i; j<ntypes; j++) {
45 table[ntypes*i+j] = table[ntypes*j+i] = ind++;
54 DebugM(3,
"Constructing client\n");
61 ktot = (1+kxmax) * (2*kymax+1) * (2*kzmax+1);
65 int nelements = 3*pressureProfileSlabs * (numAtomTypes*(numAtomTypes+1))/2;
66 pressureProfileData =
new float[nelements];
72 masterNode = numWorkingPes - 1;
76 localPartitions = NULL;
78 expx =
new float[kxmax+1];
79 expy =
new float[kymax+1];
80 expz =
new float[kzmax+1];
82 if (CkMyPe() == masterNode) {
83 eiktotal =
new float[2 * ktot * numAtomTypes];
84 memset(eiktotal, 0, 2 * ktot * numAtomTypes*
sizeof(
float));
92 Qk =
new float[3*ktot];
106 delete [] pressureProfileData;
108 delete [] gridsForAtomType;
110 if (localAtoms) free(localAtoms);
111 if (localPartitions) free(localPartitions);
117 if ( !
patchList[0].p->flags.doFullElectrostatics )
119 for (ap = ap.
begin(); ap != ap.
end(); ap++) {
120 CompAtom *x = (*ap).positionBox->open();
121 Results *r = (*ap).forceBox->open();
122 (*ap).positionBox->close(&x);
123 (*ap).forceBox->close(&r);
134 pressureProfileThickness = lattice.
c().
z / pressureProfileSlabs;
135 pressureProfileMin = lattice.
origin().
z - 0.5*lattice.
c().
z;
142 for (ap = ap.
begin(); ap != ap.
end(); ap++) {
143 numLocalAtoms += (*ap).p->getNumAtoms();
146 localPartitions = (
int *)realloc(localPartitions, numLocalAtoms*
sizeof(
int));
149 int *part_ptr = localPartitions;
151 for (ap = ap.
begin(); ap != ap.
end(); ap++) {
152 CompAtom *x = (*ap).positionBox->open();
154 Results *r = (*ap).forceBox->open();
156 (*ap).positionBox->close(&x);
157 x = (*ap).avgPositionBox->open();
159 int numAtoms = (*ap).p->getNumAtoms();
161 for(
int i=0; i<numAtoms; ++i) {
169 data_ptr->
cg = coulomb_sqrt * x[i].
charge;
172 (*ap).positionBox->close(&x);
173 (*ap).forceBox->close(&r);
178 int msgsize = 2 * numAtomTypes * ktot;
180 memset(msg->
eik, 0, msgsize*
sizeof(
float));
181 compute_structurefactor(msg->
eik);
189 int nvecs = 2 * ktot * numAtomTypes;
190 for (
int i=0; i<nvecs; i++) {
191 eiktotal[i] += msg->
eik[i];
194 if (++recvCount == numWorkingPes) {
196 int msgsize = 2 * ktot * numAtomTypes;
198 memcpy(msg->
eik, eiktotal, msgsize*
sizeof(
float));
199 memset(eiktotal, 0, msgsize*
sizeof(
float));
206 computePprofile(msg->
eik);
208 float scalefac = 1.0 / (2 *
M_PI * lattice.
volume());
210 int nelements = 3*pressureProfileSlabs * (numAtomTypes*(numAtomTypes+1))/2;
211 for (
int i=0; i<nelements; i++) {
212 reduction->
item(i) += pressureProfileData[i] * scalefac;
217 void ComputeEwald::compute_structurefactor(
float *eik) {
219 float recipx = lattice.
a_r().
x;
220 float recipy = lattice.
b_r().
y;
221 float recipz = lattice.
c_r().
z;
223 for (i=0; i<numLocalAtoms; i++) {
225 float krx = 2 *
M_PI * localAtoms[i].
x * recipx;
226 float kry = 2 *
M_PI * localAtoms[i].
y * recipy;
227 float krz = 2 *
M_PI * localAtoms[i].
z * recipz;
228 float cg = localAtoms[i].
cg;
230 const int offset = 2*ktot*localPartitions[i];
241 for (j=1; j<= kymax; j++) {
252 for (j=1; j<= kzmax; j++) {
261 for (
int kx=0; kx <= kxmax; kx++) {
262 for (
int ky=0; ky <= 2*kymax; ky++) {
265 const int max = 2*kzmax;
266 const float exyr = exy.
r;
267 const float exyi = exy.
i;
268 const float *eikzd = (
const float *)eikz;
269 #pragma vector always 270 for (
int kz=0; kz <= max; kz++) {
271 float ezr = *eikzd++;
272 float ezi = *eikzd++;
273 float eikr = ezr*exyr - ezi*exyi;
274 float eiki = ezr*exyi + ezi*exyr;
290 static void init_exp(
float *xp,
int K,
float recip,
float kappa) {
291 float piob =
M_PI / kappa;
293 float fac = -piob*recip*recip;
294 for (
int i=0; i<= K; i++)
295 xp[i] = exp(fac*i*i);
298 void ComputeEwald::computePprofile(
const float *eik)
const {
299 float recipx = lattice.
a_r().
x;
300 float recipy = lattice.
b_r().
y;
301 float recipz = lattice.
c_r().
z;
303 init_exp(expx, kxmax, recipx, kappa);
304 init_exp(expy, kymax, recipy, kappa);
305 init_exp(expz, kzmax, recipz, kappa);
308 float piob =
M_PI / kappa;
313 for (
int kx=0; kx <= kxmax; kx++) {
314 float m11 = recipx * kx;
316 float xfac = expx[kx] * (kx ? 2 : 1);
317 for (
int ky=-kymax; ky <= kymax; ky++) {
318 float m22 = recipy * ky;
320 float xyfac = expy[abs(ky)] * xfac;
321 for (
int kz=-kzmax; kz <= kzmax; kz++) {
322 float m33 = recipz * kz;
324 float msq = m11 + m22 + m33;
325 float imsq = msq ? 1.0 / msq : 0;
326 float fac = expz[abs(kz)] * xyfac * imsq;
328 float pfac = 2*(imsq + piob);
329 Qk[ind++] = fac*(1-pfac*m11);
330 Qk[ind++] = fac*(1-pfac*m22);
331 Qk[ind++] = fac*(1-pfac*m33);
336 const int nslabs = pressureProfileSlabs;
338 int nelements = 3*nslabs * (numAtomTypes*(numAtomTypes+1))/2;
339 memset(pressureProfileData, 0, nelements*
sizeof(
float));
341 for (i=0; i<numLocalAtoms; i++) {
343 float krx = 2 *
M_PI * localAtoms[i].
x * recipx;
344 float kry = 2 *
M_PI * localAtoms[i].
y * recipy;
345 float krz = 2 *
M_PI * localAtoms[i].
z * recipz;
346 float cg = localAtoms[i].
cg;
347 int atype = localPartitions[i];
348 const int *grids = gridsForAtomType+atype*numAtomTypes;
351 int slab = (int)floor((localAtoms[i].z - pressureProfileMin)/pressureProfileThickness);
352 if (slab < 0) slab += nslabs;
353 else if (slab >= nslabs) slab -= nslabs;
354 float *pprofptr = pressureProfileData + 3*slab;
365 for (j=1; j<= kymax; j++) {
376 for (j=1; j<= kzmax; j++) {
383 const float *Qkptr = Qk;
385 const float *eikptr = eik;
386 for (
int kx=0; kx <= kxmax; kx++) {
387 for (
int ky=0; ky <= 2*kymax; ky++) {
390 const int kzmax2 = 2*kzmax+1;
391 const float exyr = exy.
r;
392 const float exyi = exy.
i;
393 const float *eikzptr = (
const float *)eikz;
394 #pragma vector always 395 for (
int kz=0; kz < kzmax2; kz++) {
396 float ezr = *eikzptr++;
397 float ezi = *eikzptr++;
398 float exyzr = ezr * exyr - ezi * exyi;
399 float exyzi = ezr * exyi + ezi * exyr;
405 for (
int igrid=0; igrid<numAtomTypes; igrid++) {
406 float eikr = eikptr[igrid*2*ktot ];
407 float eiki = eikptr[igrid*2*ktot+1];
408 int grid = grids[igrid];
409 int offset = 3*nslabs*grid;
411 float E = exyzr * eikr + exyzi * eiki;
412 float vx = Qkptr[0] * E;
413 float vy = Qkptr[1] * E;
414 float vz = Qkptr[2] * E;
415 pprofptr[offset ] += vx;
416 pprofptr[offset+1] += vy;
417 pprofptr[offset+2] += vz;
static void init_exp(float *xp, int K, float recip, float kappa)
void recvData(ComputeEwaldMsg *)
void recvResults(ComputeEwaldMsg *)
int pressureProfileEwaldX
NAMD_HOST_DEVICE Vector c() const
static BigReal dielectric_1
static int * generateAtomTypeTable(int ntypes)
static PatchMap * Object()
SimParameters * simParameters
ComputeHomePatchList patchList
ComputeEwald(ComputeID, ComputeMgr *)
SubmitReduction * willSubmit(int setID, int size=-1)
ResizeArrayIter< T > begin(void) const
static ReductionMgr * Object(void)
void sendComputeEwaldData(ComputeEwaldMsg *)
NAMD_HOST_DEVICE BigReal volume(void) const
NAMD_HOST_DEVICE Vector a_r() const
NAMD_HOST_DEVICE Vector b_r() const
NAMD_HOST_DEVICE Vector c_r() const
int pressureProfileEwaldY
int pressureProfileAtomTypes
floatcomplex star() const
NAMD_HOST_DEVICE Vector wrap_delta(const Position &pos1) const
ResizeArrayIter< T > end(void) const
NAMD_HOST_DEVICE Vector origin() const
void sendComputeEwaldResults(ComputeEwaldMsg *)
int pressureProfileEwaldZ