File: PhysicsModule.cpp

package info (click to toggle)
libwildmagic 5.17%2Bcleaned1-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 90,124 kB
  • sloc: cpp: 215,940; csh: 637; sh: 91; makefile: 40
file content (134 lines) | stat: -rw-r--r-- 4,404 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Geometric Tools, LLC
// Copyright (c) 1998-2014
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
//
// File Version: 5.0.0 (2010/01/01)

#include "PhysicsModule.h"
#include "Wm5Math.h"
#include "Wm5Memory.h"
#include "Wm5OdeRungeKutta4.h"

//----------------------------------------------------------------------------
PhysicsModule::PhysicsModule ()
    :
    Gravity(0.0),
    Mass(0.0),
    mTime(0.0),
    mDeltaTime(0.0),
    mEccentricity(0.0),
    mRho(0.0),
    mMajorAxis(0.0),
    mMinorAxis(0.0),
    mSolver(0)
{
    mState[0] = 0.0;
    mState[1] = 0.0;
    mState[2] = 0.0;
    mState[3] = 0.0;
    mAux[0] = 0.0;
    mAux[1] = 0.0;
    mAux[2] = 0.0;
    mAux[3] = 0.0;
    mAux[4] = 0.0;
}
//----------------------------------------------------------------------------
PhysicsModule::~PhysicsModule ()
{
    delete0(mSolver);
}
//----------------------------------------------------------------------------
void PhysicsModule::Initialize (double time, double deltaTime, double radius,
    double theta, double radiusDot, double thetaDot)
{
    mTime = time;
    mDeltaTime = deltaTime;

    // state variables
    mState[0] = theta;
    mState[1] = thetaDot;
    mState[2] = radius;
    mState[3] = radiusDot;

    // Compute c0 and c1 in the potential energy function V(theta).
    double gm = Gravity*Mass;
    double gm2 = gm*Mass;
    double radiusSqr = radius*radius;
    double alpha = Mass*radiusSqr*thetaDot;
    double g2m4da2 = gm2*gm2/(alpha*alpha);
    double v0 = -gm/radius;
    double dv0 = gm2*radiusDot/alpha;
    double v0Plus = v0 + g2m4da2;
    double sinTheta0 = Mathd::Sin(theta);
    double cosTheta0 = Mathd::Cos(theta);
    double c0 = v0Plus*sinTheta0 + dv0*cosTheta0;
    double c1 = v0Plus*cosTheta0 - dv0*sinTheta0;

    // Auxiliary variables needed by function DTheta(...).
    mAux[0] = c0;
    mAux[1] = c1;
    mAux[2] = g2m4da2;
    mAux[3] = alpha/(gm*gm2);

    // ellipse parameters
    double gamma0 = radiusSqr*Mathd::FAbs(thetaDot);
    double tmp0 = radiusSqr*radius*thetaDot*thetaDot - gm;
    double tmp1 = radiusSqr*radiusDot*thetaDot;
    double gamma1 = Mathd::Sqrt(tmp0*tmp0 + tmp1*tmp1);
    mEccentricity = gamma1/gm;
    mRho = gamma0*gamma0/gamma1;
    double tmp2 = 1.0 - mEccentricity*mEccentricity;
    assertion(tmp2 > 0.0, "Invalid eccentricity.\n");
    mMajorAxis = mRho*mEccentricity/tmp2;
    mMinorAxis = mMajorAxis*Mathd::Sqrt(tmp2);

    // RK4 differential equation solver.  Since mSolver is a base class
    // pointer, you can instead create a solver of whatever class you prefer.
    delete0(mSolver);
    mSolver = new0 OdeRungeKutta4d(1, mDeltaTime, OdeFunction, mAux);
}
//----------------------------------------------------------------------------
double PhysicsModule::GetPeriod () const
{
    double powValue = Mathd::Pow(mMajorAxis, 1.5);
    double sqrtValue = Mathd::Sqrt(Gravity*Mass);
    return Mathd::TWO_PI*powValue/sqrtValue;
}
//----------------------------------------------------------------------------
void PhysicsModule::Update ()
{
    if (mSolver)
    {
        // Apply a single step of the ODE solver.
        mSolver->Update(mTime, mState, mTime, mState);

        // Compute dot(theta) for application access.
        double sn = Mathd::Sin(mState[0]);
        double cs = Mathd::Cos(mState[0]);
        double v = mAux[0]*sn + mAux[1]*cs - mAux[2];
        mState[1] = mAux[3]*v*v;

        // Compute radius for application access.
        mState[2] = mEccentricity*mRho/(1.0 + mEccentricity*cs);

        // Compute dot(radius) for application access.
        mState[3] = mState[2]*mState[2]*mState[1]*sn/mRho;
    }
}
//----------------------------------------------------------------------------
void PhysicsModule::OdeFunction (double, const double* state, void* data,
    double* output)
{
    double* aux = (double*)data;

    double sn = Mathd::Sin(state[2]);
    double cs = Mathd::Cos(state[2]);
    double v = aux[0]*sn + aux[1]*cs - aux[2];
    double thetaDotFunction = aux[3]*v*v;

    // dot(theta) function
    output[0] = thetaDotFunction;
}
//----------------------------------------------------------------------------