示例#1
0
void convert_inputs(double in_params[][2], double* out_params) {
    out_params[0] = convert_mass(in_params[0][0], in_params[0][1]);
    out_params[1] = convert_length(in_params[1][0], in_params[1][1]);
    out_params[2] = convert_energy(in_params[2][0], in_params[2][1]);
    if (DEBUG) {
        for (int i = 0; i < 3; i++) {
            printf("%3.8f\r\n", out_params[i]);
        }
    }

}
示例#2
0
int check_fast_approaches(  struct particle *parts,
                            struct particle *p, struct particle *pk/*,
                            double r_2*/)
{
    _enter_function(_UL_TIMESTEP, _UL_TIMESTEP_CHECK_FAST_APPROACHES);
    int i, collision=0;
    double temp, r_close_2=-1., r_temp_2, t_close, dt=.0, dt2=.0, dt3=.0, dt4=.0, dt5=.0;
    double *px=p->x, *pv=p->v, *pkx, *pkv, r_2;
    double x[3], v[3], a[3], a_[3];

    assert(p != pk);
    add_over(1, &count_approach_checks, &count_approach_checks_over);

    if(pk->active)
    {
        pkx = pk->x;
        pkv = pk->v;
    }

    else
        // have to use predicted x, v and corrected derivatives
    {
#ifndef USE_GRAPE
        pkx = pk->xp;
#else
        pkx = pk->x;
#endif
        pkv = pk->v;
        dt = p->t - pk->t;
        dt2 = .5 * dt * dt;
        dt3 = dt * dt2 * _1_3;
        dt4 = .25 * dt * dt3;
        dt5 = .2 * dt * dt4;
    }

    for(i = 0; i < 3; i++)
    {
        if( 1
#ifdef USE_GRAPE
                && pk->active
#endif
          )
        {
            x[i]  = px[i] - pkx[i];
        }
        else
        {
            x[i]  = px[i] - (pkx[i]
                             + dt * pk->v[i]
                             + dt2 * (pk->a[i] + pk->ha[i])
                             + dt3 * (pk->a_[i] + pk->ha_[i])
                             + dt4 * (pk->a_2[i] + pk->ha_2[i])
#ifndef USE_GRAPE
                             + dt5 * (pk->a_3[i] + pk->ha_3[i])
#endif
                            );
        }

        if(pk->active)
        {
            v[i] = pv[i] - pkv[i];
            a[i]  = p->ha[i]  + p->a[i]  - pk->ha[i]  - pk->a[i];
            a_[i] = p->ha_[i] + p->a_[i] - pk->ha_[i] - pk->a_[i];
        }

        else
        {
            v[i] = pv[i] - (pkv[i]
                            + dt * (pk->a[i] + pk->ha[i])
                            + dt2 * (pk->a_[i] + pk->ha_[i])
                            + dt3 * (pk->a_2[i] + pk->ha_2[i])
#ifndef USE_GRAPE
                            + dt4 * (pk->a_3[i] + pk->ha_3[i])
#endif
                           );
            a[i]  = p->ha[i]  + p->a[i]  - (pk->a[i] + pk->ha[i]
                                            + dt * (pk->a_[i] + pk->ha_[i])
                                            + dt2 * (pk->a_2[i] + pk->ha_2[i])
#ifndef USE_GRAPE
                                            + dt3 * (pk->a_3[i] + pk->ha_3[i])
#endif
                                           );
            a_[i] = p->ha_[i] + p->a_[i] - (pk->a_[i] + pk->ha_[i]
                                            + dt * (pk->a_2[i] + pk->ha_2[i])
#ifndef USE_GRAPE
                                            + dt2* (pk->a_3[i] + pk->ha_3[i])
#endif
                                           );
        }
    }

    r_2 = scal_prod(x, x);
    // linear approximation of time of closest encounter
    //t_close = -scal_prod(x, v) / scal_prod(v, v);
    // 2nd order approximation of time of closest encounter

    double xv, xa, v2, va, a2, _p, _q, _p3, _q2, _d, _u, _v, dy, t2, t3, _1_a2;
    xv = scal_prod(x, v);
    xa = scal_prod(x, a);
    v2 = scal_prod(v, v);
    va = scal_prod(v, a);
    a2 = scal_prod(a, a);
    _1_a2 = 1. / a2;
    dy = - va * _1_a2;
    _p = (a2 * 2.* (v2 + xa) - 3. * va * va) * (_1_a2 * _1_a2);
    _p3 = _p * _p * _p;
    _q = (2. * va * va * va - va * 2.*(v2 + xa) * a2 + 2. * xv * a2 * a2) * (_1_a2 * _1_a2 * _1_a2);
    _q2 = _q * _q;
    _d = 4. * _p3 + 27. * _q2;

    if(_d > 0)
    {
        _u = -.5 * _q;
        _v = sqrt(.25 * _q2 + _p3 * _1_27);
        t_close = cbrt(_u + _v) + cbrt(_u - _v) + dy;
    }
    else if(_d == 0)
    {
        t_close = cbrt(.5 * _q)  + dy;
        t3      = cbrt(-4. * _q) + dy;
        if(t3 > 0 && (t3 < t_close || t_close <= 0))
        {
            t_close = t3;
        }
    }

    else // _d < 0
    {
        _u = sqrt(-4. *_1_3 * _p);
        _v = acos(-.5 * _q * sqrt(-27. / _p3)) * _1_3;
        t_close =  _u *  _v               + dy;
        t2      = -_u * (_v + M_PI * _1_3) + dy;
        t3      = -_u * (_v - M_PI * _1_3) + dy;
        if(t2 > 0 && (t2 < t_close || t_close <= 0)) t_close = t2;
        if(t3 > 0 && (t3 < t_close || t_close <= 0)) t_close = t3;
    }
    while(1)
    {
        // check distance after next step
        r_temp_2 = .0;
        for(i = 0; i < DIMENSIONS; i++)
        {
            temp = x[i] + p->dt * (v[i] + p->dt * .5 * (a[i] /*+ p->dt / 3. * a_[i]*/));
            r_temp_2 += temp * temp;
        }

        if(r_2 > r_temp_2 * MAX_APPROACH_FACTOR_2 || r_2 * MAX_APPROACH_FACTOR_2 < r_temp_2)
        {
            add_over(1, &count_approach_reduce_t, &count_approach_reduce_t_over);
#ifdef DEBUG_ALL
            fprintf(get_file(FILE_DEBUG),
                    "\t# halving dt: approach  m%d - m%d: \tr(t=%1.6e)=%1.2e\t\tr(t=%1.6e)=%1.2e\n",
                    pk->name, p->name,
                    t_total(p->t), convert_length(sqrt(r_2), 0),
                    t_total(p->t+p->dt), convert_length(sqrt(r_temp_2), 0));
            fflush(get_file(FILE_DEBUG));
#endif
            p->dt *= .5;

#ifdef SYNCHRONIZE_APPROACHING_TIMESTEPS
            if(!pk->active)
            {
                while(pk->htlast + .5 * pk->dt > p->t + p->dt + DT_TOLERANCE)
                {
                    pk->dt *= .5;
#ifdef DEBUG_ALL
                    fprintf(get_file(FILE_DEBUG),
                            "#### [t=%1.12e] shrinking timestep for m%d as of close encounter with m%d to %e ####\n",
                            t_total(p->t),
                            pk->name,
                            p->name,
                            t_total(pk->dt));
                    fflush(get_file(FILE_DEBUG));
#endif
                }
            }
#endif

            continue;
        }

        if(r_2 < 9. * C_2G_C2 * C_2G_C2 * (pk->m + p->m) * (pk->m + p->m))
        {
            // collision in 3 Schwarzschild-radii
            collision = 1;
            fprintf(get_file(FILE_WARNING), "#### [t=%1.12e] COLLISION of m%d and m%d at %1.12e: %e (r_S = %e) ####\n",
                    t_total(p->t),
                    p->name,
                    pk->name,
                    t_total(p->t + t_close),
                    convert_length(sqrt(r_2), 0),
                    convert_length(C_2G_C2 * (pk->m + p->m), 0));
            fflush(get_file(FILE_WARNING));
        }


        if(t_close > .0 && t_close < p->dt)
        {
            // close encounter will happen _during_ next step, now calculate distance
            if(r_close_2 <.0)
            {
                r_close_2 = .0;
                for(i = 0; i < DIMENSIONS; i++)
                {
                    temp = (x[i] + t_close * (v[i] + .5 * t_close * a[i]));
                    r_close_2 += temp * temp;
                }
            }
            if(r_close_2 < square(3. * C_2G_C2 * (pk->m + p->m)))
            {
                // collision in 3 Schwarzschild-radii
                collision = 1;
                fprintf(get_file(FILE_WARNING), "#### [t=%1.12e] COLLISION of m%d and m%d at %1.12e: %e (r_S = %e) ####\n",
                        t_total(p->t),
                        p->name,
                        pk->name,
                        t_total(p->t + t_close),
                        convert_length(sqrt(r_close_2), 0),
                        convert_length(C_2G_C2 * (pk->m + p->m), 0));
                fflush(get_file(FILE_WARNING));
            }

            // approach to small multiple of impact parameter:
            // r'_12 < warn_fact * b = warn_fact * 2 * r_1 * m / M

#ifdef WARN_CLOSEENC
            if(r_close_2 * parts->m * parts->m < square(WARN_APPROACH_FACT * 2 * pk->m) * scal_prod(p->xp, p->xp)
                    && (N_MAX_DETAIL < -1 || p->name <= N_MAX_DETAIL || pk->name <= N_MAX_DETAIL)
              )
            {
                fprintf(get_file(FILE_WARNING),
                        "\t# predicted close encounter m%d - m%d: \tr(t=%1.6e)=%1.2e\t\tr(t=%1.6e)=%1.2e=%1.2fb\tp.dt=%1.2e\tpk->dt=%1.2e (%1.2e el.) [%d:%d]\n",
                        pk->name, p->name,
                        t_total(p->t), convert_length(sqrt(r_2), 0),
                        t_total(p->t + t_close), convert_length(sqrt(r_close_2), 0),
                        sqrt(r_close_2) / (2. * v_abs(p->xp) * pk->m) * parts->m,
                        convert_time(p->dt, 0),
                        convert_time(pk->dt, 0),
                        convert_time(p->t - pk->t, 0),
                        pk->nearestneighbour, p->nearestneighbour);
                fprintf(get_file(FILE_WARNING),
                        " PCE %1.12e\t%d\t%e\t%1.10e\t%1.10e\t%1.10e\t%1.10e\t%1.10e\t%1.10e\t%d\t%e\t%1.10e\t%1.10e\t%1.10e\t%1.10e\t%1.10e\t%1.10e\n",
                        t_total(p->t),
                        pk->name, convert_mass(pk->m, 0),
                        convert_length(pkx[0], 0), convert_length(pkx[1], 0), convert_length(pkx[2], 0),
                        convert_length(convert_time(pkv[0], 1), 0), convert_length(convert_time(pkv[1], 1), 0), convert_length(convert_time(pkv[2], 1), 0),
                        p->name, convert_mass(p->m, 0),
                        convert_length(px[0], 0), convert_length(px[1], 0), convert_length(px[2], 0),
                        convert_length(convert_time(pv[0], 1), 0), convert_length(convert_time(pv[1], 1), 0), convert_length(convert_time(pv[2], 1), 0)
                       );
                fflush(get_file(FILE_WARNING));
            }
#endif

            if(r_2 > MAX_APPROACH_FACTOR_2 * r_close_2)
            {
                add_over(1, &count_approach_reduce_t, &count_approach_reduce_t_over);
#ifdef DEBUG_ALL
                fprintf(get_file(FILE_DEBUG),
                        "\t# halving dt: encounter m%d - m%d: \tr(t=%1.6e)=%1.2e\t\tr(t=%1.6e)=%1.2e\tstep: t=%1.6e\n",
                        pk->name, p->name,
                        t_total(p->t), convert_length(sqrt(r_2), 0),
                        t_total(p->t + t_close), convert_length(sqrt(r_close_2), 0),
                        t_total(p->t + p->dt));
                fflush(get_file(FILE_DEBUG));
#endif
                p->dt *= .5;

#ifdef SYNCHRONIZE_APPROACHING_TIMESTEPS
                if(!pk->active)
                    while(pk->htlast + .5 * pk->dt > p->t + p->dt + DT_TOLERANCE)
                    {
                        pk->dt *= .5;
#ifdef DEBUG_ALL
                        fprintf(get_file(FILE_DEBUG),
                                "####  shrinking. timestep for m%d as of close encounter with m%d to %e ####\n",
                                t_total(p->t),
                                pk->name,
                                p->name,
                                t_total(pk->dt));
#endif
                    }
#endif
                continue;
            }
        }
        break;
    }

    _exit_function();
    return collision;
}