local void sumforces(bodyptr btab, int nbody, bodyptr gtab, int ngrav, real eps2) { bodyptr bp, gp; double phi0, acc0[NDIM]; vector pos0, dr; real dr2, dr2i, dr1i, mdr1i, mdr3i; for (bp = btab; bp < NthBody(btab, nbody); bp = NextBody(bp)) { phi0 = 0.0; CLRV(acc0); SETV(pos0, Pos(bp)); for (gp = gtab; gp < NthBody(gtab, ngrav); gp = NextBody(gp)) { DOTPSUBV(dr2, dr, Pos(gp), pos0); dr2i = ((real) 1.0) / (dr2 + eps2); dr1i = rsqrt(dr2i); mdr1i = Mass(gp) * dr1i; mdr3i = mdr1i * dr2i; phi0 -= mdr1i; ADDMULVS(acc0, dr, mdr3i); } Phi(bp) = phi0; SETV(Acc(bp), acc0); } }
local void sum1force(bodyptr btab, int nbody, int i0, real eps2) { bodyptr bp0, bp; double phi0, acc0[NDIM]; vector pos0, dr; real dr2, drab, mri, mr3i; int j; bp0 = NthBody(btab, i0); phi0 = 0.0; CLRV(acc0); SETV(pos0, Pos(bp0)); for (j = 0; j < nbody; j++) if (j != i0) { bp = NthBody(btab, j); DOTPSUBV(dr2, dr, Pos(bp), pos0); dr2 += eps2; drab = rsqrt(dr2); mri = Mass(bp) / drab; phi0 -= mri; mr3i = mri / dr2; ADDMULVS(acc0, dr, mr3i); } Phi(bp0) = phi0; SETV(Acc(bp0), acc0); }
local void sumcell(cellptr start, cellptr finish, vector pos0, real *phi0, vector acc0) { real eps2, eps2thrd, dr2, dr2i, dr1i, mdr1i, mdr3i, qdr2, dr5i, phi_q; vector dr, qdr; eps2 = eps * eps; // premultiply softening eps2thrd = eps2 / 3.0; // predivide for soft corr for (cellptr p = start; p < finish; p++) { // loop over node list DOTPSUBV(dr2, dr, Pos(p), pos0); // do mono part of force dr2i = ((real) 1.0) / (dr2 + eps2); // perform only division dr1i = rsqrt(dr2i); // set inverse soft distance mdr1i = Mass(p) * dr1i; // form mono potential mdr3i = mdr1i * dr2i; // get scale factor for dr DOTPMULMV(qdr2, qdr, Quad(p), dr); // do quad part of force #if defined(SOFTCORR) qdr2 -= eps2thrd * Trace(p); // apply Keigo's correction #endif dr5i = ((real) 3.0) * dr2i * dr2i * dr1i; // factor 3 saves a multiply phi_q = ((real) 0.5) * dr5i * qdr2; // form quad potential mdr3i += ((real) 5.0) * phi_q * dr2i; // adjust radial term *phi0 -= mdr1i + phi_q; // sum mono and quad pot ADDMULVS2(acc0, dr, mdr3i, qdr, - dr5i); // sum mono and quad acc } }
local void sumnode(cellptr start, cellptr finish, vector pos0, real *phi0, vector acc0) { real eps2, dr2, dr2i, dr1i, mdr1i, mdr3i; vector dr; eps2 = eps * eps; // premultiply softening for (cellptr p = start; p < finish; p++) { // loop over node list DOTPSUBV(dr2, dr, Pos(p), pos0); // compute sep. vector // and square of distance dr2i = ((real) 1.0) / (dr2 + eps2); // perform only division dr1i = rsqrt(dr2i); // set inverse soft distance mdr1i = Mass(p) * dr1i; // form partial potential mdr3i = mdr1i * dr2i; // form scale factor for dr *phi0 -= mdr1i; // sum potential ADDMULVS(acc0, dr, mdr3i); // sum acceleration } }
local void sumnode(cellptr start, cellptr finish, vector pos0, real *phi0, vector acc0) { cellptr p; real eps2, dr2, drab, phi_p, mr3i; vector dr; eps2 = eps * eps; /* avoid extra multiplys */ for (p = start; p < finish; p++) { /* loop over node list */ DOTPSUBV(dr2, dr, Pos(p), pos0); /* compute separation */ /* and distance squared */ dr2 += eps2; /* add standard softening */ drab = rsqrt(dr2); /* form scalar "distance" */ phi_p = Mass(p) / drab; /* get partial potential */ *phi0 -= phi_p; /* decrement tot potential */ mr3i = phi_p / dr2; /* form scale factor for dr */ ADDMULVS(acc0, dr, mr3i); /* sum partial acceleration */ } }
local void sumcell(cellptr start, cellptr finish, vector pos0, real *phi0, vector acc0) { cellptr p; real eps2, dr2, drab, phi_p, mr3i, drqdr, dr5i, phi_q; vector dr, qdr; eps2 = eps * eps; for (p = start; p < finish; p++) { /* loop over node list */ DOTPSUBV(dr2, dr, Pos(p), pos0); /* do mono part of force */ dr2 += eps2; drab = rsqrt(dr2); phi_p = Mass(p) / drab; mr3i = phi_p / dr2; DOTPMULMV(drqdr, qdr, Quad(p), dr); /* do quad part of force */ dr5i = ((real) 1.0) / (dr2 * dr2 * drab); phi_q = ((real) 0.5) * dr5i * drqdr; *phi0 -= phi_p + phi_q; /* add mono and quad pot */ mr3i += ((real) 5.0) * phi_q / dr2; ADDMULVS2(acc0, dr, mr3i, qdr, -dr5i); /* add mono and quad acc */ } }