PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
Bdf.h
Go to the documentation of this file.
1
10
11#ifndef PBAT_SIM_INTEGRATION_BDF_H
12#define PBAT_SIM_INTEGRATION_BDF_H
13
14#include "pbat/Aliases.h"
17#include "pbat/common/Modulo.h"
18#include "pbat/io/Archive.h"
19
20#include <cassert>
21#include <exception>
22#include <tuple>
23
24namespace pbat::sim::integration {
25
75template <class TScalar = Scalar, class TIndex = Index>
76class Bdf
77{
78 public:
79 using ScalarType = TScalar;
80 using IndexType = TIndex;
81
90 Bdf(int step = 1, int order = 2);
91
92 Eigen::Matrix<ScalarType, Eigen::Dynamic, Eigen::Dynamic>
96 Eigen::Matrix<ScalarType, Eigen::Dynamic, Eigen::Dynamic>
102
107 [[maybe_unused]] auto Order() const { return mOrder; }
112 [[maybe_unused]] auto Step() const { return mStep; }
117 [[maybe_unused]] auto Dimensions() const { return xt.rows(); }
122 [[maybe_unused]] auto TimeStep() const { return h; }
128 [[maybe_unused]] auto Inertia(int o) const { return xtilde.col(o); }
135 auto State(int k, int o = 0) const -> decltype(xt.col(0));
142 auto State(int k, int o = 0) -> decltype(xt.col(0));
148 auto CurrentState(int o = 0) const -> decltype(xt.col(0));
154 auto CurrentState(int o = 0) -> decltype(xt.col(0));
159 [[maybe_unused]] auto Alpha() const { return mAlpha(Eigen::seqN(0, mStep)); }
164 [[maybe_unused]] auto Beta() const { return mBeta; }
169 [[maybe_unused]] auto BetaTilde() const { return mBeta * h; }
170
176 void SetOrder(int order);
182 void SetStep(int step);
201 template <class TDerivedX>
202 void SetInitialConditions(Eigen::DenseBase<TDerivedX> const& x0);
209 template <class... TDerivedX>
210 void SetInitialConditions(Eigen::DenseBase<TDerivedX> const&... x0);
216 template <class TDerivedX>
217 void Step(Eigen::DenseBase<TDerivedX> const& x);
224 template <class... TDerivedX>
225 void Step(Eigen::DenseBase<TDerivedX> const&... xs);
229 [[maybe_unused]] void Tick() { ++ti; }
234 void Serialize(io::Archive& archive) const;
239 void Deserialize(io::Archive const& archive);
240
241 private:
242 int mOrder;
243 int mStep;
244 Eigen::Vector<ScalarType, 6>
245 mAlpha;
247 mBeta;
248};
249
250template <class TScalar, class TIndex>
251Bdf<TScalar, TIndex>::Bdf(int step, int order)
252 : xt(), xtilde(), ti(0), h(Scalar(0.01)), mOrder(), mStep(), mAlpha(), mBeta()
253{
254 SetStep(step);
255 SetOrder(order);
256}
257
258template <class TScalar, class TIndex>
259auto Bdf<TScalar, TIndex>::State(int k, int o) const -> decltype(xt.col(0))
260{
261 if (k < 0 || k > mStep)
262 {
263 throw std::out_of_range("0 <= k <= s");
264 }
265 if (o < 0 || o >= mOrder)
266 {
267 throw std::out_of_range("0 <= o < order");
268 }
269 auto kt = common::Modulo(ti /*- mStep*/ + k, mStep);
270 return xt.col(o * mStep + kt);
271}
272
273template <class TScalar, class TIndex>
274auto Bdf<TScalar, TIndex>::State(int k, int o) -> decltype(xt.col(0))
275{
276 if (k < 0 || k > mStep)
277 {
278 throw std::out_of_range("0 <= k <= s");
279 }
280 if (o < 0 || o >= mOrder)
281 {
282 throw std::out_of_range("0 <= o < order");
283 }
284 auto kt = common::Modulo(ti /*- mStep*/ + k, mStep);
285 return xt.col(o * mStep + kt);
286}
287
288template <class TScalar, class TIndex>
289auto Bdf<TScalar, TIndex>::CurrentState(int o) const -> decltype(xt.col(0))
290{
291 return State(mStep - 1, o);
292}
293
294template <class TScalar, class TIndex>
295auto Bdf<TScalar, TIndex>::CurrentState(int o) -> decltype(xt.col(0))
296{
297 return State(mStep - 1, o);
298}
299
300template <class TScalar, class TIndex>
302{
303 if (order <= 0)
304 {
305 throw std::invalid_argument("order > 0");
306 }
307 mOrder = order;
308}
309
310template <class TScalar, class TIndex>
312{
313 if (step < 1 || step > 6)
314 {
315 throw std::invalid_argument("0 < s < 7.");
316 }
317 mStep = step;
318 mAlpha.setZero();
319 switch (mStep)
320 {
321 case 1:
322 mAlpha(0) = Scalar(-1);
323 mBeta = Scalar(1);
324 break;
325 case 2:
326 mAlpha(0) = Scalar(1) / 3;
327 mAlpha(1) = Scalar(-4) / 3;
328 mBeta = Scalar(2) / 3;
329 break;
330 case 3:
331 mAlpha(0) = Scalar(-2) / 11;
332 mAlpha(1) = Scalar(9) / 11;
333 mAlpha(2) = Scalar(-18) / 11;
334 mBeta = Scalar(6) / 11;
335 break;
336 case 4:
337 mAlpha(0) = Scalar(3) / 25;
338 mAlpha(1) = Scalar(-16) / 25;
339 mAlpha(2) = Scalar(36) / 25;
340 mAlpha(3) = Scalar(-48) / 25;
341 mBeta = Scalar(12) / 25;
342 break;
343 case 5:
344 mAlpha(0) = Scalar(-12) / 137;
345 mAlpha(1) = Scalar(75) / 137;
346 mAlpha(2) = Scalar(-200) / 137;
347 mAlpha(3) = Scalar(300) / 137;
348 mAlpha(4) = Scalar(-300) / 137;
349 mBeta = Scalar(60) / 137;
350 break;
351 case 6:
352 mAlpha(0) = Scalar(10) / 147;
353 mAlpha(1) = Scalar(-72) / 147;
354 mAlpha(2) = Scalar(225) / 147;
355 mAlpha(3) = Scalar(-400) / 147;
356 mAlpha(4) = Scalar(450) / 147;
357 mAlpha(5) = Scalar(-360) / 147;
358 mBeta = Scalar(60) / 147;
359 break;
360 }
361}
362
363template <class TScalar, class TIndex>
365{
366 if (dt <= 0)
367 {
368 throw std::invalid_argument("dt > 0");
369 }
370 h = dt;
371}
372
373template <class TScalar, class TIndex>
375{
376 xtilde.setZero();
377 for (auto o = 0; o < mOrder; ++o)
378 for (auto k = 0; k < mStep; ++k)
379 xtilde.col(o) += mAlpha(k) * State(k, o);
380}
381
382template <class TScalar, class TIndex>
383template <class TDerivedX>
384inline void Bdf<TScalar, TIndex>::SetInitialConditions(Eigen::DenseBase<TDerivedX> const& x0)
385{
386 ti = 0;
387 auto n = x0.rows();
388 xt.resize(n, mStep * mOrder);
389 xtilde.resize(n, mOrder);
390 for (auto o = 0; o < mOrder; ++o)
391 xt.middleCols(o * mStep, mStep).colwise() = x0.col(o);
392}
393
394template <class TScalar, class TIndex>
395template <class... TDerivedX>
396inline void Bdf<TScalar, TIndex>::SetInitialConditions(Eigen::DenseBase<TDerivedX> const&... x0)
397{
398 auto constexpr nDerivs = sizeof...(TDerivedX);
399 assert(nDerivs == mOrder);
400 std::tuple<decltype(x0)...> tup{x0...};
401 ti = 0;
402 auto n = std::get<0>(tup).rows();
403 xt.resize(n, mStep * mOrder);
404 xtilde.resize(n, mOrder);
405#include "pbat/warning/Push.h"
406#include "pbat/warning/SignConversion.h"
408 [&]<auto o>() { xt.middleCols(o * mStep, mStep).colwise() = std::get<o>(tup); });
409#include "pbat/warning/Pop.h"
410}
411
412template <class TScalar, class TIndex>
413template <class TDerivedX>
414inline void Bdf<TScalar, TIndex>::Step(Eigen::DenseBase<TDerivedX> const& x)
415{
416 Tick();
417 for (auto o = 0; o < mOrder; ++o)
418 CurrentState(o) = x.col(o);
419}
420
421template <class TScalar, class TIndex>
422template <class... TDerivedX>
423inline void Bdf<TScalar, TIndex>::Step(Eigen::DenseBase<TDerivedX> const&... x)
424{
425 auto constexpr nDerivs = sizeof...(TDerivedX);
426 assert(nDerivs == mOrder);
427 Tick();
428 std::tuple<decltype(x)...> tup{x...};
429 common::ForRange<0, nDerivs>([&]<auto o>() { CurrentState(o) = std::get<o>(tup); });
430}
431
432template <class TScalar, class TIndex>
434{
435 io::Archive bdfArchive = archive["pbat.sim.integration.Bdf"];
436 bdfArchive.WriteData("xt", xt);
437 bdfArchive.WriteData("xtilde", xtilde);
438 bdfArchive.WriteMetaData("h", h);
439 bdfArchive.WriteMetaData("ti", ti);
440 bdfArchive.WriteMetaData("order", mOrder);
441 bdfArchive.WriteMetaData("step", mStep);
442 bdfArchive.WriteMetaData("alpha", mAlpha);
443 bdfArchive.WriteMetaData("beta", mBeta);
444}
445
446template <class TScalar, class TIndex>
448{
449 io::Archive const group = archive["pbat.sim.integration.Bdf"];
450 xt = group.ReadData<MatrixX>("xt");
451 xtilde = group.ReadData<MatrixX>("xtilde");
452 h = group.ReadMetaData<Scalar>("h");
453 ti = group.ReadMetaData<Index>("ti");
454 mOrder = group.ReadMetaData<int>("order");
455 mStep = group.ReadMetaData<int>("step");
456 mAlpha = group.ReadMetaData<Vector<6>>("alpha");
457 mBeta = group.ReadMetaData<Scalar>("beta");
458}
459
460} // namespace pbat::sim::integration
461
462#endif // PBAT_SIM_INTEGRATION_BDF_H
(De)serializer
Compile-time for loops.
Modulo function.
Archive class for reading and writing data to HDF5 files.
Definition Archive.h:29
T ReadData(std::string const &path) const
Read data from the archive.
Definition Archive.h:179
void WriteMetaData(std::string const &key, T const &value)
Write metadata to the archive.
Definition Archive.h:158
void WriteData(std::string const &path, T const &data)
Write data to the archive.
Definition Archive.h:137
T ReadMetaData(std::string const &key) const
Read metadata from the archive.
Definition Archive.h:195
auto Order() const
Order of the ODE.
Definition Bdf.h:107
void SetInitialConditions(Eigen::DenseBase< TDerivedX > const &x0)
Set the initial conditions for the initial value problem.
Definition Bdf.h:384
auto State(int k, int o=0) const -> decltype(xt.col(0))
state derivative
Definition Bdf.h:259
auto Beta() const
Forcing term coefficient s.t. .
Definition Bdf.h:164
void SetTimeStep(ScalarType dt)
Set the time step size.
Definition Bdf.h:364
void SetInitialConditions(Eigen::DenseBase< TDerivedX > const &... x0)
Set the initial conditions for the initial value problem.
Definition Bdf.h:396
auto Step() const
Step s of the s-step BDF scheme.
Definition Bdf.h:112
auto BetaTilde() const
Time-step scaled forcing term coefficient .
Definition Bdf.h:169
auto CurrentState(int o=0) const -> decltype(xt.col(0))
Eigen::Matrix< ScalarType, Eigen::Dynamic, Eigen::Dynamic > xt
Definition Bdf.h:93
void Step(Eigen::DenseBase< TDerivedX > const &x)
Advance the BDF scheme by one time step.
Definition Bdf.h:414
void SetStep(int step)
Set the step of the BDF scheme.
Definition Bdf.h:311
void SetOrder(int order)
Set the order of the ODE system.
Definition Bdf.h:301
Eigen::Matrix< ScalarType, Eigen::Dynamic, Eigen::Dynamic > xtilde
Definition Bdf.h:97
void Serialize(io::Archive &archive) const
Serialize to HDF5 group.
Definition Bdf.h:433
void Deserialize(io::Archive const &archive)
Deserialize from HDF5 group.
Definition Bdf.h:447
auto Dimensions() const
Number of ODEs.
Definition Bdf.h:117
Bdf(int step=1, int order=2)
Construct a step-step BDF (backward differentiation formula) time integration scheme for a system of ...
Definition Bdf.h:251
void ConstructEquations()
Construct the BDF equations, i.e. compute for all .
Definition Bdf.h:374
void Tick()
Advance the BDF scheme by one time step.
Definition Bdf.h:229
auto Inertia(int o) const
Inertia of the BDF scheme for the state derivative.
Definition Bdf.h:128
auto Alpha() const
Definition Bdf.h:159
void Step(Eigen::DenseBase< TDerivedX > const &... xs)
Advance the BDF scheme by one time step.
Definition Bdf.h:423
auto TimeStep() const
Time step size.
Definition Bdf.h:122
Concepts for common types.
constexpr void ForRange(F &&f)
Compile-time for loop over a range of values.
Definition ConstexprFor.h:55
ODE integration schemes.
Definition Bdf.cpp:3
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic-size matrix type.
Definition Aliases.h:34
Eigen::Vector< Scalar, N > Vector
Fixed-size vector type.
Definition Aliases.h:24
std::ptrdiff_t Index
Index type.
Definition Aliases.h:17
double Scalar
Scalar type.
Definition Aliases.h:18