/**
* A body in the BH tree, i.e., a leaf node
* Adapted from Olden BH by Joshua Barnes et al.
* @author Robert L. Bocchino Jr.
* @author Rakesh Komuravelli
*/
package DPJBenchmarks;
public class Body<region R> extends Node {
/**
* Type for array of bodies
*/
static arrayclass Array<region R> {
Body<R:[index]> in R:[index];
}
/**
* Velocity of body
*/
public final Vector<R> vel in R = new Vector<R>();
/**
* Acceleration of body
*/
public final Vector<R> acc in R = new Vector<R>();
/**
* Indexing for comparing result with the original code
*/
public int index;
/**
* Updated potential at body
*/
public double phi in R;
/**
* Constructor
*/
public Body() {
}
/**
* Constructor
* @param body Number of bodies
*/
public Body(Body<*> body) {
super(body);
vel.SETV(body.vel);
acc.SETV(body.acc);
phi = body.phi;
index = body.index;
}
/**
* Evaluate grav field at a given particle.
* @param hg Temporary object to hold necessary information during force calculation
* @param rsize Size of the bounding box referring to the space the bodies span
* @param root Root of the tree
*/
<region R1>void hackgrav(HGStruct<R1> hg, double rsize, Node root)
reads MP writes R, R1 {
double szsq;
szsq = rsize * rsize;
/* recursively scan tree */
walksub(root, szsq, Constants.tol*Constants.tol, hg, 0);
/* stash resulting pot. and */
phi = hg.phi0;
/* acceleration in body p */
acc.SETV(hg.acc0);
}
/**
* Recursive routine to do hackwalk operation.
* @param p pointer into body-tree
* @param dsq size of box squared
*/
protected <region R1>void walksub(Node p, double dsq, double tolsq, HGStruct<R1> hg,
int level) reads MP writes R, R1 {
/* should p be opened? */
if (p.subdivp(p, dsq, tolsq, hg)) {
/* loop over the subcells */
for (int k = 0; k < Constants.NSUB; k++) {
Node r = ((Cell) p).subp[k];
if (r != null)
walksub(r, dsq / 4.0, tolsq, hg, level+1);
}
}
else if (p != (Node) hg.pskip) {
gravsub(p, hg);
}
}
/**
* Compute a single body-body or body-cell interaction.
* @param p Node of interaction
* @param hg Temporary object to hold necessary information
*/
protected <region R1>void gravsub(Node p, HGStruct<R1> hg)
reads MP writes R, R1 {
double drabs, phii, mor3;
double drsq;
/* find separation */
hg.dr.SUBV(p.pos, hg.pos0);
/* and square of distance */
drsq = hg.dr.DOTVP(hg.dr);
/* use standard softening */
drsq += Constants.eps*Constants.eps;
/* find norm of distance */
drabs = Math.sqrt((double) drsq);
/* and contribution to phi */
phii = p.mass / drabs;
/* add to total potential */
hg.phi0 -= phii;
/* form mass / radius qubed */
mor3 = phii / drsq;
/* and contribution to acc. */
hg.ai.MULVS(hg.dr, mor3);
/* add to net acceleration */
hg.acc0.ADDV(hg.acc0, hg.ai);
}
/**
* Cannot subdivide a leaf
*/
@Override
protected <region R> boolean subdivp(Node p, double dsq, double tolsq, HGStruct<R> hg) pure {
return false;
}
/**
* Body implementation just returns mass.
*/
@Override
public double hackcofm() {
return mass;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Body: mass=");
sb.append(mass);
sb.append(",");
sb.append("pos=");
sb.append(pos);
return sb.toString();
}
}