13 #include "ComputeFmmSerialMgr.decl.h" 18 #include "ComputeMgr.decl.h" 20 #define MIN_DEBUG_LEVEL 3 41 extern "C" void fmmlap_uni_(
88 CProxy_ComputeFmmSerialMgr fmmProxy;
103 double *chargebuffer;
105 double (*posbuffer)[3];
106 double (*forcebuffer)[3];
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)
115 CkpvAccess(BOCclass_group).computeFmmSerialMgr = thisgroup;
120 for (
int i=0; i < numSources; i++)
delete coordMsgs[i];
125 if (chargebuffer)
delete[] chargebuffer;
126 if (epotbuffer)
delete[] epotbuffer;
127 if (posbuffer)
delete[] posbuffer;
128 if (forcebuffer)
delete[] forcebuffer;
134 CProxy_ComputeFmmSerialMgr::ckLocalBranch(
135 CkpvAccess(BOCclass_group).computeFmmSerialMgr)->setCompute(
this);
148 if ( !
patchList[0].p->flags.doFullElectrostatics )
150 for (ap = ap.
begin(); ap != ap.
end(); ap++) {
151 CompAtom *x = (*ap).positionBox->open();
152 Results *r = (*ap).forceBox->open();
153 (*ap).positionBox->close(&x);
154 (*ap).forceBox->close(&r);
161 int numLocalAtoms = 0;
162 for (ap = ap.
begin(); ap != ap.
end(); ap++) {
163 numLocalAtoms += (*ap).p->getNumAtoms();
173 for (ap = ap.
begin(); ap != ap.
end(); ap++) {
174 CompAtom *x = (*ap).positionBox->open();
177 (*ap).positionBox->close(&x);
178 x = (*ap).avgPositionBox->open();
180 int numAtoms = (*ap).p->getNumAtoms();
182 for(
int i=0; i < numAtoms; i++)
186 data_ptr->
id = xExt[i].
id;
190 if (
patchList[0].p->flags.doMolly ) { (*ap).avgPositionBox->close(&x); }
191 else { (*ap).positionBox->close(&x); }
194 CProxy_ComputeFmmSerialMgr fmmProxy(
195 CkpvAccess(BOCclass_group).computeFmmSerialMgr);
196 fmmProxy[0].recvCoord(msg);
202 if ( ! numSources ) {
205 for ( i=0; i<numSources; ++i ) { coordMsgs[i] = 0; }
212 for ( i=0; i < msg->
numAtoms; ++i ) {
216 coordMsgs[numArrived] = msg;
219 if ( numArrived < numSources )
return;
227 double virial[3][3] = { 0 };
237 if (lattice.
a_p() || lattice.
b_p() || lattice.
c_p()) {
238 NAMD_die(
"FMM solver requires non-periodic boundaries");
248 nlevels = (int) floor(log((
double)numAtoms) / log(8.) + 0.5);
253 NAMD_die(
"setting up FMM with no atoms");
257 for (i = 1; i < numAtoms; i++) {
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;
267 if (padding <= 0) padding = 0.01;
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;
274 center = 0.5*(min + max);
275 iout <<
iINFO <<
"FMM scaling length set to " << len <<
" A\n" <<
endi;
276 iout <<
iINFO <<
"FMM center set to " << center <<
"\n" <<
endi;
279 chargebuffer =
new double[numAtoms];
280 epotbuffer =
new double[numAtoms];
281 posbuffer =
new double[numAtoms][3];
282 forcebuffer =
new double[numAtoms][3];
283 if (chargebuffer == 0 || epotbuffer == 0 ||
284 posbuffer == 0 || forcebuffer == 0) {
285 NAMD_die(
"can't allocate buffer space for FMM data");
290 for (i = 0; i < numAtoms; i++) {
291 chargebuffer[i] = celec * coord[i].
charge;
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);
306 fmmlap_uni_(&numAtoms, posbuffer, chargebuffer, epotbuffer, forcebuffer,
309 NAMD_die(
"Must link to FMM library to use FMM\n");
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];
323 for (
int j=0; j < numSources; j++) {
328 for (
int i=0; i < cmsg->
numAtoms; i++) {
334 for (
int k=0; k < 3; k++) {
335 for (
int l=0; l < 3; l++) {
336 fmsg->
virial[k][l] = virial[k][l];
342 for (
int k=0; k < 3; k++) {
343 for (
int l=0; l < 3; l++) {
367 for (ap = ap.
begin(); ap != ap.
end(); ap++) {
368 Results *r = (*ap).forceBox->open();
370 int numAtoms = (*ap).p->getNumAtoms();
372 for(
int i=0; i<numAtoms; ++i) {
373 f[i].
x += results_ptr->
x;
374 f[i].
y += results_ptr->
y;
375 f[i].
z += results_ptr->
z;
379 (*ap).forceBox->close(&r);
383 reduction->
item(REDUCTION_VIRIAL_SLOW_XX) += msg->
virial[0][0];
384 reduction->
item(REDUCTION_VIRIAL_SLOW_XY) += msg->
virial[0][1];
385 reduction->
item(REDUCTION_VIRIAL_SLOW_XZ) += msg->
virial[0][2];
386 reduction->
item(REDUCTION_VIRIAL_SLOW_YX) += msg->
virial[1][0];
387 reduction->
item(REDUCTION_VIRIAL_SLOW_YY) += msg->
virial[1][1];
388 reduction->
item(REDUCTION_VIRIAL_SLOW_YZ) += msg->
virial[1][2];
389 reduction->
item(REDUCTION_VIRIAL_SLOW_ZX) += msg->
virial[2][0];
390 reduction->
item(REDUCTION_VIRIAL_SLOW_ZY) += msg->
virial[2][1];
391 reduction->
item(REDUCTION_VIRIAL_SLOW_ZZ) += msg->
virial[2][2];
395 #include "ComputeFmmSerialMgr.def.h"
std::ostream & iINFO(std::ostream &s)
virtual ~ComputeFmmSerial()
NAMD_HOST_DEVICE int c_p() const
static PatchMap * Object()
SimParameters * simParameters
ComputeHomePatchList patchList
std::ostream & endi(std::ostream &s)
void recvCoord(FmmSerialCoordMsg *)
SubmitReduction * willSubmit(int setID, int size=-1)
ResizeArrayIter< T > begin(void) const
static ReductionMgr * Object(void)
NAMD_HOST_DEVICE int b_p() const
void setCompute(ComputeFmmSerial *c)
ComputeFmmSerialAtom * coord
ComputeFmmSerial(ComputeID c)
NAMD_HOST_DEVICE int a_p() const
void NAMD_die(const char *err_msg)
void saveResults(FmmSerialForceMsg *)
void recvForce(FmmSerialForceMsg *)
ResizeArrayIter< T > end(void) const