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;
}
Esempio n. 3
0
/* gets negative of the acceleration vector of this disk component */
static inline mwvector miyamotoNagaiDiskAccel(const Disk* disk, mwvector pos, real r)
{
    mwvector acc;
    const real a   = disk->scaleLength;
    const real b   = disk->scaleHeight;
    const real zp  = mw_sqrt(sqr(Z(pos)) + sqr(b));
    const real azp = a + zp;

    const real rp  = sqr(X(pos)) + sqr(Y(pos)) + sqr(azp);
    const real rth = mw_sqrt(cube(rp));  /* rp ^ (3/2) */

    X(acc) = -disk->mass * X(pos) / rth;
    Y(acc) = -disk->mass * Y(pos) / rth;
    Z(acc) = -disk->mass * Z(pos) * azp / (zp * rth);

    return acc;
}
static real nbCalculateEps2(real nbody, real r0)
{
    real eps = r0 / (10.0 * mw_sqrt(nbody));
    real eps2 = sqr(eps);
    if (eps2 <= REAL_EPSILON) {
        eps2 = 2.0*REAL_EPSILON;
    }
    return eps2;
}
Esempio n. 5
0
static real emdDistL2(const real* x, const real* y, void* user_param)
{
    int i;
    int dims = (int)(size_t)user_param;
    real s = 0.0;

    for (i = 0; i < dims; i++)
    {
        real t = x[i] - y[i];

        s += t * t;
    }

    return mw_sqrt((real) s);
}
/* pickshell: pick a random point on a sphere of specified radius. */
static inline mwvector pickShell(dsfmt_t* dsfmtState, real rad)
{
    real rsq, rsc;
    mwvector vec;

    do                      /* pick point in NDIM-space */
    {
        vec = mwRandomUnitPoint(dsfmtState);
        rsq = mw_sqrv(vec);         /* compute radius squared */
    }
    while (rsq > 1.0);              /* reject if outside sphere */

    rsc = rad / mw_sqrt(rsq);       /* compute scaling factor */
    mw_incmulvs(vec, rsc);          /* rescale to radius given */

    return vec;
}
static mwvector nbGravity_Exact(const NBodyCtx* ctx, NBodyState* st, const Body* p)
{
    int i;
    const int nbody = st->nbody;
    mwvector a = ZERO_VECTOR;
    const real eps2 = ctx->eps2;

    for (i = 0; i < nbody; ++i)
    {
        const Body* b = &st->bodytab[i];

        mwvector dr = mw_subv(Pos(b), Pos(p));
        real drSq = mw_sqrv(dr) + eps2;

        real drab = mw_sqrt(drSq);
        real phii = Mass(b) / drab;
        real mor3 = phii / drSq;

        mw_incaddv(a, mw_mulvs(dr, mor3));
    }

    return a;
}
static real nbCalculateEps2(real nbody, real r0)
{
    real eps = r0 / (10.0 * mw_sqrt(nbody));
    return sqr(eps);
}
static real nbCalculateTimestep(real mass, real r0)
{
    return sqr(1/10.0) * mw_sqrt((PI_4_3 * cube(r0)) / mass);
}
Esempio n. 10
0
/*
 * 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;
}