Beispiel #1
0
    public double Evolve(double time, GravityState gravityState, ref byte[] info)
    {
        double[] mass = gravityState.m;
        double[,] pos     = gravityState.r;
        this.gravityState = gravityState;
        t_offset          = 0;
        t_evolveStart     = gravityState.GetPhysicsTime();

        int nloops = 0;

        if (dt > time)
        {
            dt = time;
        }

        while (t_offset < time)
        {
            // If only one body collision time will be MAXFLOAT
            t_offset += dt;
            Evolve_step(ref mass, ref pos, ref info);
            // timestep adjustement, relative to initial collision time
            coll_time_avg = COLL_AVERAGE_FACTOR * coll_time_avg + (1 - COLL_AVERAGE_FACTOR) * coll_time;
            dt            = dtInitial * coll_time_avg / coll_time_initial;
            if (dt > maxDt)
            {
                dt = maxDt;
            }
            else if (dt < minDt)
            {
                dt = minDt;
            }
            nloops++;
        }
#pragma warning disable 162        // disable unreachable code warning
        if (GravityEngine.DEBUG)
        {
            if (logCount++ > LOG_INTERVAL)
            {
                logCount = 0;
                Debug.LogFormat("time={0} dt={1} coll_time={2} coll_factor={3} coll_time_initial={4} nloops={5} numbodies={6}",
                                time, dt, coll_time, coll_time_avg / coll_time_initial, coll_time_initial, nloops, numBodies);
            }
        }
#pragma warning restore 162
        return(t_offset);
    }
Beispiel #2
0
    /// <summary>
    /// Evolves using the force delegate. Internals differ slightly and for effeciency do not want
    /// a conditional on forceDelegate in the inner loop.
    ///
    /// </summary>
    /// <returns>The force delegate.</returns>
    /// <param name="time">Time.</param>
    /// <param name="m">M.</param>
    /// <param name="r">The red component.</param>
    /// <param name="info">Info.</param>
    private double EvolveForceDelegate(double time, GravityState gravityState, ref byte[] info)
    {
        int numSteps = 0;

        double[] m = gravityState.m;
        double[,] r = gravityState.r;
        // advance acceleration
        double r2;
        double r_sep;
        double f;

        double timeNow = gravityState.GetPhysicsTime();
        double dummy   = 0;

        // If objects are fixed want to use their mass but not update their position
        // Better to calc their acceleration and ignore than add an if statement to core loop.
        for (double t = 0; t < time; t += dt)
        {
            numSteps++;
            // Update v and r
            for (int i = 0; i < numBodies; i++)
            {
                if ((info[i] & GravityEngine.INACTIVE_OR_FIXED) == 0)
                {
                    v[i, 0] += a[i, 0] * 0.5 * dt;
                    r[i, 0] += v[i, 0] * dt;
                    v[i, 1] += a[i, 1] * 0.5 * dt;
                    r[i, 1] += v[i, 1] * dt;
                    v[i, 2] += a[i, 2] * 0.5 * dt;
                    r[i, 2] += v[i, 2] * dt;
                }
            }

            // a = 0
            // a = 0 or init with eternal value
            for (int i = 0; i < numBodies; i++)
            {
                if (externalAccel[i] != null)
                {
                    double[] e_accel = externalAccel[i].acceleration(timeNow + t, gravityState, ref dummy);
                    a[i, 0] = e_accel[0];
                    a[i, 1] = e_accel[1];
                    a[i, 2] = e_accel[2];
                }
                else
                {
                    a[i, 0] = 0.0;
                    a[i, 1] = 0.0;
                    a[i, 2] = 0.0;
                }
            }
            // calc a
            for (int i = 0; i < numBodies; i++)
            {
                if ((info[i] & GravityEngine.INACTIVE) == 0)
                {
                    for (int j = i + 1; j < numBodies; j++)
                    {
                        if ((info[j] & GravityEngine.INACTIVE) == 0)
                        {
                            // O(N^2) in here, unpack loops to optimize
                            r2       = 0;
                            rji[0]   = r[j, 0] - r[i, 0];
                            r2      += rji[0] * rji[0];
                            rji[1]   = r[j, 1] - r[i, 1];
                            r2      += rji[1] * rji[1];
                            rji[2]   = r[j, 2] - r[i, 2];
                            r2      += rji[2] * rji[2];
                            r_sep    = System.Math.Sqrt(r2) + EPSILON;
                            f        = forceDelegate.CalcPseudoForce(r_sep, i, j);
                            a[i, 0] += m[j] * f * (rji[0] / r_sep);
                            a[i, 1] += m[j] * f * (rji[1] / r_sep);
                            a[i, 2] += m[j] * f * (rji[2] / r_sep);

                            a[j, 0] -= m[i] * f * (rji[0] / r_sep);
                            a[j, 1] -= m[i] * f * (rji[1] / r_sep);
                            a[j, 2] -= m[i] * f * (rji[2] / r_sep);
                        }
                    }
                }
            }
            // update velocity
            for (int i = 0; i < numBodies; i++)
            {
                if ((info[i] & GravityEngine.FIXED_MOTION) == 0)
                {
                    v[i, 0] += a[i, 0] * 0.5 * dt;
                    v[i, 1] += a[i, 1] * 0.5 * dt;
                    v[i, 2] += a[i, 2] * 0.5 * dt;
                    //DebugBody(i, ref m, ref r, "evolve");
                }
            }
            // coll_time code
        }
        return(numSteps * dt);
    }