local bool subdivp(nodeptr n) { cellptr SAFE q = TC(n); SUBV(dr, PosC(q), pos0); /* compute displacement */ DOTVP(drsq, dr, dr); /* and find dist squared */ qmem = q; /* remember we know them */ return (drsq < Rcrit2(q)); /* apply standard rule */ }
char* showCell(const NBodyCell* c) { char* buf; char* posBuf; if (!c) return NULL; posBuf = showVector(Pos(c)); if (0 > asprintf(&buf, "NBodyCell = {\n" " cellnode = {\n" " pos = %s\n" " next = %p\n" " mass = %f\n" " type = %d\n" " }\n" " rcrit2 = %f\n" " more = %p\n" " stuff = {\n" " .quad = {\n" " .xx = %f, .xy = %f, .xz = %f,\n" " .yy = %f, .yz = %f,\n" " .zz = %f\n" " },\n" "\n" " .subp = {\n" " %p, %p, %p, %p,\n" " %p, %p, %p, %p\n" " }\n" " }\n" "}\n", posBuf, (void*) Next(c), Mass(c), Type(c), Rcrit2(c), (void*) More(c), Quad(c).xx, Quad(c).xy, Quad(c).xz, Quad(c).yy, Quad(c).yz, Quad(c).zz, (void*) Subp(c)[0], (void*) Subp(c)[1], (void*) Subp(c)[2], (void*) Subp(c)[3], (void*) Subp(c)[5], (void*) Subp(c)[5], (void*) Subp(c)[6], (void*) Subp(c)[7] )) { mw_fail("asprintf() failed\n"); } free(posBuf); return buf; }
local bool accept(nodeptr c, real psize, vector pmid) { real dmax, dsq, dk; int k; dmax = psize; /* init maximum distance */ dsq = 0.0; /* and squared min distance */ for (k = 0; k < NDIM; k++) { /* loop over space dims */ dk = Pos(c)[k] - pmid[k]; /* form distance to midpnt */ if (dk < 0) /* and get absolute value */ dk = - dk; if (dk > dmax) /* keep track of max value */ dmax = dk; dk -= ((real) 0.5) * psize; /* allow for size of cell */ if (dk > 0) dsq += dk * dk; /* sum min dist to cell ^2 */ } return (dsq > Rcrit2(c) && /* test angular criterion */ dmax > ((real) 1.5) * psize); /* and adjacency criterion */ }
local bool accept(nodeptr c, real psize, vector pmid) { real dmax, dsq, dk; int k; dmax = psize; // init maximum distance dsq = 0.0; // and squared min distance for (k = 0; k < NDIM; k++) { // loop over space dims dk = Pos(c)[k] - pmid[k]; // form distance to midpnt if (dk < 0) // and get absolute value dk = - dk; if (dk > dmax) // keep track of max value dmax = dk; dk -= ((real) 0.5) * psize; // allow for size of cell if (dk > 0) dsq += dk * dk; // sum (min dist to cell)^2 } return (dsq > Rcrit2(c) && // test angular criterion dmax > ((real) 1.5) * psize); // and adjacency criterion }
/* * nbodyGravity: Walk the tree starting at the root to do force * calculations. * * * Random notes: * - Not inlined without inline from multiple calls in * mapForceBody(). Measurably better with the inline, but only * slightly. */ static inline mwvector nbGravity(const NBodyCtx* ctx, NBodyState* st, const Body* p) { mwbool skipSelf = FALSE; mwvector pos0 = Pos(p); mwvector acc0 = ZERO_VECTOR; const NBodyNode* q = (const NBodyNode*) st->tree.root; /* Start at the root */ while (q != NULL) /* while not at end of scan */ { mwvector dr = mw_subv(Pos(q), pos0); /* Then compute distance */ real drSq = mw_sqrv(dr); /* and distance squared */ if (isBody(q) || (drSq >= Rcrit2(q))) /* If is a body or far enough away to approximate */ { if (mw_likely((const Body*) q != p)) /* self-interaction? */ { real drab, phii, mor3; /* Compute gravity */ drSq += ctx->eps2; /* use standard softening */ drab = mw_sqrt(drSq); phii = Mass(q) / drab; mor3 = phii / drSq; acc0.x += mor3 * dr.x; acc0.y += mor3 * dr.y; acc0.z += mor3 * dr.z; if (ctx->useQuad && isCell(q)) /* if cell, add quad term */ { real dr5inv, drQdr, phiQ; mwvector Qdr; /* form Q * dr */ Qdr.x = Quad(q).xx * dr.x + Quad(q).xy * dr.y + Quad(q).xz * dr.z; Qdr.y = Quad(q).xy * dr.x + Quad(q).yy * dr.y + Quad(q).yz * dr.z; Qdr.z = Quad(q).xz * dr.x + Quad(q).yz * dr.y + Quad(q).zz * dr.z; /* form dr * Q * dr */ drQdr = Qdr.x * dr.x + Qdr.y * dr.y + Qdr.z * dr.z; dr5inv = 1.0 / (sqr(drSq) * drab); /* form dr^-5 */ /* get quad. part of phi */ phiQ = 2.5 * (dr5inv * drQdr) / drSq; acc0.x += phiQ * dr.x; acc0.y += phiQ * dr.y; acc0.z += phiQ * dr.z; /* acceleration */ acc0.x -= dr5inv * Qdr.x; acc0.y -= dr5inv * Qdr.y; acc0.z -= dr5inv * Qdr.z; } } else { skipSelf = TRUE; /* Encountered self */ } q = Next(q); /* Follow next link */ } else { q = More(q); /* Follow to the next level if need to go deeper */ } } if (!skipSelf) { /* If a body does not encounter itself in its traversal of the * tree, it is "tree incest" */ nbReportTreeIncest(ctx, st); } return acc0; }