static inline real isotropicRandomR(dsfmt_t* dsfmtState, real scaleRad1, real scaleRad2, real Mass1, real Mass2) { // Rejection sampling radius generation real RHO_MAX = 3/(4*M_PI) * (Mass1/(mw_pow(scaleRad1,3)) + Mass2/(mw_pow(scaleRad2,3))); mwbool GOOD_RADIUS = 0; // Arbitrarily define sample range to be [0, 5(a1 + a2) real r; while (GOOD_RADIUS != 1) { r = mwXrandom(dsfmtState,0.0, 3*(scaleRad1 + scaleRad2)); real u = (real)mwXrandom(dsfmtState,0.0,1.0); real val = 3/(4*M_PI)*(Mass1/(mw_pow(scaleRad1,3)) *mw_pow(1 + mw_pow(r,2)/mw_pow(scaleRad1,2),-5/2) + Mass2/(mw_pow(scaleRad2,3))*mw_pow(1 + mw_pow(r,2)/mw_pow(scaleRad2,2),-5/2)); if (val/RHO_MAX > u) { GOOD_RADIUS = 1; } } return r; }
/* The estimate formula has the unfortunate property of being negative for small n. This will be the most negative. Add this as an extra boost to prevent negative flops estimates. */ static real worstFlops(real cQ, real d, real f) { real a = mw_pow(2.0, 3.0 - 3.0 * d / cQ); real b = (cQ - d) * mw_log(8.0); real c = cQ * mw_log(mw_pow(8.0, 1.0 - d / cQ)); return -a * sqr(f) * (cQ + b - c) / (M_E * mw_log(8.0)); }
real propability_match(int n, int k, real pobs){ real result; result = choose(n, k); result *= mw_pow(pobs, (real)k); result *= mw_pow((1-pobs), (real)(n-k)); result = mw_log(result); return result; }
static inline real isotropicRandomV(real r, real scaleRad1, real scaleRad2, real Mass1, real Mass2) { real val; val = mw_sqrt(Mass1/mw_sqrt(mw_pow(r,2) + mw_pow(scaleRad1,2)) + Mass2/mw_sqrt(mw_pow(r,2) + mw_pow(scaleRad2,2))); return val; }
/* generatePlummer: generate Plummer model initial conditions for test * runs, scaled to units such that M = -4E = G = 1 (Henon, Heggie, * etc). See Aarseth, SJ, Henon, M, & Wielen, R (1974) Astr & Ap, 37, * 183. */ static int nbGenerateIsotropicCore(lua_State* luaSt, dsfmt_t* prng, unsigned int nbody, real mass1, real mass2, mwbool ignore, mwvector rShift, mwvector vShift, real radiusScale1, real radiusScale2) { unsigned int i; int table; Body b; real r, velScale; real mass = mass1 + mass2; real radiusScale = mw_sqrt(mw_pow(radiusScale1,2) + mw_pow(radiusScale2,2)); memset(&b, 0, sizeof(b)); velScale = mw_sqrt(mass / radiusScale); /* and recip. speed scale */ b.bodynode.type = BODY(ignore); /* Same for all in the model */ b.bodynode.mass = mass / nbody; /* Mass per particle */ lua_createtable(luaSt, nbody, 0); table = lua_gettop(luaSt); for (i = 0; i < nbody; ++i) { do { r = isotropicRandomR(prng, radiusScale1, radiusScale2, mass1, mass2); /* FIXME: We should avoid the divide by 0.0 by multiplying * the original random number by 0.9999.. but I'm too lazy * to change the tests. Same with other models */ } while (isinf(r)); b.bodynode.pos = isotropicBodyPosition(prng, rShift, r); b.vel = isotropicBodyVelocity(prng, r, vShift, velScale, radiusScale1, radiusScale2, mass1, mass2); assert(nbPositionValid(b.bodynode.pos)); pushBody(luaSt, &b); // printf("Body %d is pushed. \n",i); lua_rawseti(luaSt, table, i + 1); } return 1; }
/* For using a combination of light and dark models to generate timestep */ static real plummerTimestepIntegral(real smalla, real biga, real Md, real step) { /* Calculate the enclosed mass of the big sphere within the little sphere's scale length */ real encMass, val, r; encMass = 0.0; for (r = 0.0; r <= smalla; r += step) { val = sqr(r) / mw_pow(sqr(r) + sqr(biga), 2.5); encMass += val * step; } encMass *= 3.0 * Md * sqr(biga); return encMass; }