GteParticleSystem.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <Mathematics/GteVector.h>
11 #include <limits>
12 #include <vector>
13 
14 namespace gte
15 {
16 
17 template <int N, typename Real>
19 {
20 public:
21  // Construction and destruction. If a particle is to be immovable, set
22  // its mass to std::numeric_limits<Real>::max().
23  virtual ~ParticleSystem();
24  ParticleSystem(int numParticles, Real step);
25 
26  // Member access.
27  inline int GetNumParticles() const;
28  void SetMass(int i, Real mass);
29  inline void SetPosition(int i, Vector<N, Real> const& position);
30  inline void SetVelocity(int i, Vector<N, Real> const& velocity);
31  void SetStep(Real step);
32  inline Real const& GetMass(int i) const;
33  inline Vector<N, Real> const& GetPosition(int i) const;
34  inline Vector<N, Real> const& GetVelocity(int i) const;
35  inline Real GetStep() const;
36 
37  // Update the particle positions based on current time and particle state.
38  // The Acceleration(...) function is called in this update for each
39  // particle. This function is virtual so that derived classes can perform
40  // pre-update and/or post-update semantics.
41  virtual void Update(Real time);
42 
43 protected:
44  // Callback for acceleration (ODE solver uses x" = F/m) applied to
45  // particle i. The positions and velocities are not necessarily
46  // mPosition and mVelocity, because the ODE solver evaluates the
47  // impulse function at intermediate positions.
48  virtual Vector<N, Real> Acceleration(int i, Real time,
49  std::vector<Vector<N, Real>> const& position,
50  std::vector<Vector<N, Real>> const& velocity) = 0;
51 
53  std::vector<Real> mMass, mInvMass;
54  std::vector<Vector<N, Real>> mPosition, mVelocity;
56 
57  // Temporary storage for the Runge-Kutta differential equation solver.
58  struct Temporary
59  {
61  };
62  std::vector<Vector<N, Real>> mPTmp, mVTmp;
63  std::vector<Temporary> mPAllTmp, mVAllTmp;
64 };
65 
66 
67 template <int N, typename Real>
69 {
70 }
71 
72 template <int N, typename Real> inline
73 ParticleSystem<N, Real>::ParticleSystem(int numParticles, Real step)
74 :
75 mNumParticles(numParticles),
76 mMass(numParticles),
77 mInvMass(numParticles),
78 mPosition(numParticles),
79 mVelocity(numParticles),
80 mStep(step),
81 mHalfStep(step / (Real)2),
82 mSixthStep(step / (Real)6),
83 mPTmp(numParticles),
84 mVTmp(numParticles),
85 mPAllTmp(numParticles),
86 mVAllTmp(numParticles)
87 {
88  std::fill(mMass.begin(), mMass.end(), (Real)0);
89  std::fill(mInvMass.begin(), mInvMass.end(), (Real)0);
90  std::fill(mPosition.begin(), mPosition.end(), Vector<N, Real>::Zero());
91  std::fill(mVelocity.begin(), mVelocity.end(), Vector<N, Real>::Zero());
92 }
93 
94 template <int N, typename Real> inline
96 {
97  return mNumParticles;
98 }
99 
100 template <int N, typename Real>
101 void ParticleSystem<N, Real>::SetMass(int i, Real mass)
102 {
103  if ((Real)0 < mass && mass < std::numeric_limits<Real>::max())
104  {
105  mMass[i] = mass;
106  mInvMass[i] = ((Real)1) / mass;
107  }
108  else
109  {
110  mMass[i] = std::numeric_limits<Real>::max();
111  mInvMass[i] = (Real)0;
112  }
113 }
114 
115 template <int N, typename Real> inline
117 Vector<N, Real> const& position)
118 {
119  mPosition[i] = position;
120 }
121 
122 template <int N, typename Real> inline
124 Vector<N, Real> const& velocity)
125 {
126  mVelocity[i] = velocity;
127 }
128 
129 template <int N, typename Real>
131 {
132  mStep = step;
133  mHalfStep = mStep / (Real)2;
134  mSixthStep = mStep / (Real)6;
135 }
136 
137 template <int N, typename Real> inline
138 Real const& ParticleSystem<N, Real>::GetMass(int i) const
139 {
140  return mMass[i];
141 }
142 
143 template <int N, typename Real> inline
145 {
146  return mPosition[i];
147 }
148 
149 template <int N, typename Real> inline
151 {
152  return mVelocity[i];
153 }
154 
155 template <int N, typename Real> inline
157 {
158  return mStep;
159 }
160 
161 template <int N, typename Real>
163 {
164  // Runge-Kutta fourth-order solver.
165  Real halfTime = time + mHalfStep;
166  Real fullTime = time + mStep;
167 
168  // Compute the first step.
169  int i;
170  for (i = 0; i < mNumParticles; ++i)
171  {
172  if (mInvMass[i] >(Real)0)
173  {
174  mPAllTmp[i].d1 = mVelocity[i];
175  mVAllTmp[i].d1 = Acceleration(i, time, mPosition, mVelocity);
176  }
177  }
178  for (i = 0; i < mNumParticles; ++i)
179  {
180  if (mInvMass[i] >(Real)0)
181  {
182  mPTmp[i] = mPosition[i] + mHalfStep * mPAllTmp[i].d1;
183  mVTmp[i] = mVelocity[i] + mHalfStep * mVAllTmp[i].d1;
184  }
185  else
186  {
187  mPTmp[i] = mPosition[i];
188  mVTmp[i].MakeZero();
189  }
190  }
191 
192  // Compute the second step.
193  for (i = 0; i < mNumParticles; ++i)
194  {
195  if (mInvMass[i] >(Real)0)
196  {
197  mPAllTmp[i].d2 = mVTmp[i];
198  mVAllTmp[i].d2 = Acceleration(i, halfTime, mPTmp, mVTmp);
199  }
200  }
201  for (i = 0; i < mNumParticles; ++i)
202  {
203  if (mInvMass[i] >(Real)0)
204  {
205  mPTmp[i] = mPosition[i] + mHalfStep * mPAllTmp[i].d2;
206  mVTmp[i] = mVelocity[i] + mHalfStep * mVAllTmp[i].d2;
207  }
208  else
209  {
210  mPTmp[i] = mPosition[i];
211  mVTmp[i].MakeZero();
212  }
213  }
214 
215  // Compute the third step.
216  for (i = 0; i < mNumParticles; ++i)
217  {
218  if (mInvMass[i] >(Real)0)
219  {
220  mPAllTmp[i].d3 = mVTmp[i];
221  mVAllTmp[i].d3 = Acceleration(i, halfTime, mPTmp, mVTmp);
222  }
223  }
224  for (i = 0; i < mNumParticles; ++i)
225  {
226  if (mInvMass[i] >(Real)0)
227  {
228  mPTmp[i] = mPosition[i] + mStep * mPAllTmp[i].d3;
229  mVTmp[i] = mVelocity[i] + mStep * mVAllTmp[i].d3;
230  }
231  else
232  {
233  mPTmp[i] = mPosition[i];
234  mVTmp[i].MakeZero();
235  }
236  }
237 
238  // Compute the fourth step.
239  for (i = 0; i < mNumParticles; ++i)
240  {
241  if (mInvMass[i] >(Real)0)
242  {
243  mPAllTmp[i].d4 = mVTmp[i];
244  mVAllTmp[i].d4 = Acceleration(i, fullTime, mPTmp, mVTmp);
245  }
246  }
247  for (i = 0; i < mNumParticles; ++i)
248  {
249  if (mInvMass[i] >(Real)0)
250  {
251  mPosition[i] += mSixthStep * (mPAllTmp[i].d1 +
252  ((Real)2) * (mPAllTmp[i].d2 + mPAllTmp[i].d3) +
253  mPAllTmp[i].d4);
254 
255  mVelocity[i] += mSixthStep * (mVAllTmp[i].d1 +
256  ((Real)2) * (mVAllTmp[i].d2 + mVAllTmp[i].d3) +
257  mVAllTmp[i].d4);
258  }
259  }
260 }
261 
262 
263 }
virtual void Update(Real time)
Real const & GetMass(int i) const
std::vector< Vector< N, Real > > mPTmp
std::vector< Real > mMass
std::vector< Temporary > mPAllTmp
std::vector< Vector< N, Real > > mVelocity
void SetMass(int i, Real mass)
static Vector Zero()
Definition: GteVector.h:295
std::vector< Temporary > mVAllTmp
ParticleSystem(int numParticles, Real step)
void SetVelocity(int i, Vector< N, Real > const &velocity)
virtual Vector< N, Real > Acceleration(int i, Real time, std::vector< Vector< N, Real >> const &position, std::vector< Vector< N, Real >> const &velocity)=0
Vector< N, Real > const & GetVelocity(int i) const
int GetNumParticles() const
void SetPosition(int i, Vector< N, Real > const &position)
std::vector< Real > mInvMass
std::vector< Vector< N, Real > > mPosition
void SetStep(Real step)
std::vector< Vector< N, Real > > mVTmp
Vector< N, Real > const & GetPosition(int i) const


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01