17 , criterion(
std::move(criterion)) {
29 this->
stepImpl(scheduler, solver, stats);
35 criterionId = result.
id;
46 template <
typename TFunc>
47 static void stepFirstOrder(
Storage& storage,
IScheduler& scheduler,
const TFunc& stepper) {
50 auto process = [&](
const QuantityId id,
auto& x,
auto& dx) {
54 stepper(x[i], asConst(dx[i]));
55 const Interval range = storage.getMaterialOfParticle(i)->range(id);
56 if (range != Interval::unbounded()) {
57 tie(x[i], dx[i]) = clampWithDerivative(x[i], dx[i], range);
62 iterate<VisitorEnum::FIRST_ORDER>(storage, process);
65 template <
typename TFunc>
66 static void stepSecondOrder(
Storage& storage,
IScheduler& scheduler,
const TFunc& stepper) {
68 auto process = [&](
const QuantityId id,
auto& r,
auto& v,
const auto& dv) {
69 SPH_ASSERT(r.size() == v.size() && r.size() == dv.size());
72 stepper(r[i], v[i], dv[i]);
74 const Interval range = storage.getMaterialOfParticle(i)->range(id);
75 if (range != Interval::unbounded()) {
76 tie(r[i], v[i]) = clampWithDerivative(r[i], v[i], range);
81 iterate<VisitorEnum::SECOND_ORDER>(storage, process);
84 template <
typename TFunc>
85 static void stepFirstOrder(
Storage& storage1,
88 const TFunc& stepper) {
90 auto processPair = [&](
QuantityId id,
auto& px,
auto& pdx,
const auto& cx,
const auto& cdx) {
96 stepper(px[i], pdx[i], cdx[i]);
98 const Interval range = storage1.getMaterialOfParticle(i)->range(id);
99 if (range != Interval::unbounded()) {
100 tie(px[i], pdx[i]) = clampWithDerivative(px[i], pdx[i], range);
105 iteratePair<VisitorEnum::FIRST_ORDER>(storage1, storage2, processPair);
109 template <
typename TFunc>
110 static void stepPairFirstOrder(
Storage& storage1,
113 const TFunc& stepper) {
115 auto processPair = [&](
QuantityId id,
auto& px,
auto& pdx,
const auto& cx,
const auto& cdx) {
121 stepper(px[i], pdx[i], cx[i], cdx[i]);
123 const Interval range = storage1.getMaterialOfParticle(i)->range(id);
124 if (range != Interval::unbounded()) {
125 tie(px[i], pdx[i]) = clampWithDerivative(px[i], pdx[i], range);
130 iteratePair<VisitorEnum::FIRST_ORDER>(storage1, storage2, processPair);
133 template <
typename TFunc>
134 static void stepSecondOrder(
Storage& storage1,
137 const TFunc& stepper) {
146 SPH_ASSERT(pr.size() == pv.size() && pr.size() == pdv.size());
152 stepper(pr[i], pv[i], pdv[i], cdv[i]);
154 const Interval range = storage1.getMaterialOfParticle(i)->range(id);
155 if (range != Interval::unbounded()) {
156 tie(pr[i], pv[i]) = clampWithDerivative(pr[i], pv[i], range);
161 iteratePair<VisitorEnum::SECOND_ORDER>(storage1, storage2, processPair);
164 template <
typename TFunc>
165 static void stepPairSecondOrder(
Storage& storage1,
168 const TFunc& stepper) {
177 SPH_ASSERT(pr.size() == pv.size() && pr.size() == pdv.size());
183 stepper(pr[i], pv[i], pdv[i], cr[i], cv[i], cdv[i]);
185 const Interval range = storage1.getMaterialOfParticle(i)->range(id);
186 if (range != Interval::unbounded()) {
187 tie(pr[i], pv[i]) = clampWithDerivative(pr[i], pv[i], range);
192 iteratePair<VisitorEnum::SECOND_ORDER>(storage1, storage2, processPair);
212 stepSecondOrder(*
storage, scheduler, [dt](
auto&
UNUSED(r),
auto& v,
const auto& dv)
INL {
213 using Type =
typename std::decay_t<decltype(v)>;
219 stepSecondOrder(*
storage, scheduler, [dt](
auto& r,
auto& v,
const auto&
UNUSED(dv))
INL {
220 using Type =
typename std::decay_t<decltype(v)>;
225 stepFirstOrder(*
storage, scheduler, [dt](
auto& x,
const auto& dx)
INL {
226 using Type =
typename std::decay_t<decltype(x)>;
256 stepSecondOrder(*
storage, scheduler, [dt, dt2](
auto& r,
auto& v,
const auto& dv)
INL {
257 using Type =
typename std::decay_t<decltype(v)>;
258 r += Type(v * dt + dv * dt2);
261 stepFirstOrder(*
storage, scheduler, [dt](
auto& x,
const auto& dx)
INL {
262 using Type =
typename std::decay_t<decltype(x)>;
271 constexpr
Float a = 1._f / 3._f;
272 constexpr
Float b = 0.5_f;
277 [a, b, dt, dt2](
auto& pr,
auto& pv,
const auto& pdv,
const auto& cdv) {
278 using Type =
typename std::decay_t<decltype(pr)>;
279 pr -= Type(a * (cdv - pdv) * dt2);
280 pv -= Type(b * (cdv - pdv) * dt);
283 stepFirstOrder(*
storage, *predictions, scheduler, [dt](
auto& px,
const auto& pdx,
const auto& cdx) {
284 using Type =
typename std::decay_t<decltype(px)>;
285 px -= Type(0.5_f * (cdx - pdx) * dt);
323 stepSecondOrder(*
storage, scheduler, [dt](
auto& r,
const auto& v,
const auto&
UNUSED(dv))
INL {
324 using Type =
typename std::decay_t<decltype(v)>;
325 r += Type(v * 0.5_f * dt);
334 stepFirstOrder(*
storage, scheduler, [dt](
auto& x,
const auto& dx)
INL {
335 using Type =
typename std::decay_t<decltype(x)>;
341 stepSecondOrder(*
storage, scheduler, [dt](
auto&
UNUSED(r),
auto& v,
const auto& dv)
INL {
342 using Type =
typename std::decay_t<decltype(v)>;
350 stepSecondOrder(*
storage, scheduler, [dt](
auto& r,
auto& v,
const auto&
UNUSED(dv))
INL {
351 using Type =
typename std::decay_t<decltype(v)>;
352 r += Type(v * 0.5_f * dt);
388 iteratePair<VisitorEnum::FIRST_ORDER>(
390 using Type =
typename std::decay_t<decltype(kv)>::Type;
391 for (
Size i = 0; i < v.size(); ++i) {
392 kv[i] += Type(kdv[i] * m * this->
timeStep);
393 v[i] += Type(kdv[i] * n * this->timeStep);
396 iteratePair<VisitorEnum::SECOND_ORDER>(k,
398 [&](
const QuantityId UNUSED(
id),
auto& kv,
auto& kdv,
auto& kd2v,
auto& v,
auto& dv,
auto&) {
399 using Type =
typename std::decay_t<decltype(kv)>::Type;
400 for (
Size i = 0; i < v.size(); ++i) {
401 kv[i] += Type(kdv[i] * m * this->
timeStep);
402 kdv[i] += Type(kd2v[i] * m * this->timeStep);
403 v[i] += Type(kdv[i] * n * this->timeStep);
404 dv[i] += Type(kd2v[i] * n * this->timeStep);
433 iteratePair<VisitorEnum::FIRST_ORDER>(
435 using Type =
typename std::decay_t<decltype(v)>::Type;
436 for (
Size i = 0; i < v.size(); ++i) {
437 v[i] += Type(this->
timeStep / 6._f * kdv[i]);
440 iteratePair<VisitorEnum::SECOND_ORDER>(*
storage,
442 [
this](
const QuantityId UNUSED(
id),
auto& v,
auto& dv,
auto&,
auto&,
auto& kdv,
auto& kd2v) {
443 using Type =
typename std::decay_t<decltype(v)>::Type;
444 for (
Size i = 0; i < v.size(); ++i) {
445 dv[i] += Type(this->
timeStep / 6._f * kd2v[i]);
446 v[i] += Type(this->
timeStep / 6._f * kdv[i]);
469 stepPairSecondOrder(*mid,
472 [h](
auto& pr,
auto& pv,
const auto&,
const auto& cr,
const auto& cv,
const auto& cdv)
INL {
473 using Type =
typename std::decay_t<decltype(cv)>;
474 pv = Type(cv + h * cdv);
475 pr = Type(cr + h * cv);
478 stepPairFirstOrder(*mid,
481 [h](
auto& px,
const auto&
UNUSED(pdx),
const auto& cx,
const auto& cdx)
INL {
482 using Type =
typename std::decay_t<decltype(cx)>;
483 px = Type(cx + h * cdx);
494 for (
Size iter = 0; iter < n - 1; ++iter) {
504 const auto& cdv)
INL {
505 using Type =
typename std::decay_t<decltype(pr)>;
506 pv += Type(2._f * h * cdv);
507 pr += Type(2._f * h * cv);
513 [h](
auto& px,
const auto&
UNUSED(pdx),
const auto&
UNUSED(cx),
const auto& cdx)
INL {
514 using Type =
typename std::decay_t<decltype(px)>;
515 px += Type(2._f * h * cdx);
528 [h](
auto& pr,
auto& pv,
const auto&
UNUSED(pdv),
auto& cr,
const auto& cv,
const auto& cdv)
INL {
529 using Type =
typename std::decay_t<decltype(pr)>;
530 pv = Type(0.5_f * (pv + cv + h * cdv));
531 pr = Type(0.5_f * (pr + cr + h * cv));
537 [h](
auto& px,
const auto&
UNUSED(pdx),
const auto& cx,
const auto& cdx)
INL {
538 using Type =
typename std::decay_t<decltype(px)>;
539 px = Type(0.5_f * (px + cx + h * cdx));
551 template <
typename T, Size Dim1, Size Dim2>
572 for (
auto& row : alpha) {
580 for (
Size k = 0; k < q; ++k) {
581 alpha[k][q] = (A[k + 1] - A[q + 1]) /
std::pow(eps, (2 * k + 1) * (A[q + 1] - A[0] + 1));
590 if (A[i + 1] > A[i] * alpha[i - 1][i]) {
INLINE bool isReal(const AntisymmetricTensor &t)
#define SPH_ASSERT(x,...)
uint32_t Size
Integral type used to index arrays (by default).
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Base class for all particle materials.
Base interface for all solvers.
Functions for iterating over individual quantities in Storage.
#define VERBOSE_LOG
Helper macro, creating.
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
constexpr INLINE Float pow(const Float v)
Power for floats.
#define NAMESPACE_SPH_END
Tool to measure time spent in functions and profile the code.
#define PROFILE_SCOPE(name)
QuantityId
Unique IDs of basic quantities of SPH particles.
Interface for executing tasks (potentially) asynchronously.
INLINE void parallelFor(IScheduler &scheduler, const Size from, const Size to, TFunctor &&functor)
Executes a functor concurrently from all available threads.
Statistics gathered and periodically displayed during the run.
@ TIMESTEP_VALUE
Current value of timestep.
@ TIMESTEP_CRITERION
Criterion that currently limits the timestep.
@ TIMESTEP_ELAPSED
Wallclock time spend on computing last timestep.
Criteria for computing the time step.
@ INITIAL_VALUE
Timestep is not computed, using given initial value.
const StaticArray< Size, BS_SIZE > BS_STEPS
Algorithms for temporal evolution of the physical model.
virtual void stepImpl(IScheduler &scheduler, ISolver &solver, Statistics &stats) override
BulirschStoer(const SharedPtr< Storage > &storage, const RunSettings &settings)
virtual void stepImpl(IScheduler &scheduler, ISolver &solver, Statistics &stats) override
Interface that allows unified implementation of sequential and parallelized versions of algorithms.
Base class for all solvers.
virtual void integrate(Storage &storage, Statistics &stats)=0
Computes derivatives of all time-dependent quantities.
virtual void collide(Storage &UNUSED(storage), Statistics &UNUSED(stats), const Float UNUSED(dt))
Detects the collisions and computes new positions of particles.
virtual TimeStep compute(IScheduler &scheduler, Storage &storage, Float maxStep, Statistics &stats)=0
Computes the value of the time step.
Base object providing integration in time for all quantities.
Float timeStep
Current time step.
SharedPtr< Storage > storage
Main storage holding all the particles in the run.
virtual void stepImpl(IScheduler &scheduler, ISolver &solver, Statistics &stats)=0
AutoPtr< ITimeStepCriterion > criterion
Criterion used to compute the time step.
~ITimeStepping() override
Float maxTimeStep
Maximal allowed time step.
void step(IScheduler &scheduler, ISolver &solver, Statistics &stats)
ITimeStepping(const SharedPtr< Storage > &storage, const RunSettings &settings)
Constructs the timestepping, using timestep criteria from parameters in settings.
virtual void stepImpl(IScheduler &scheduler, ISolver &solver, Statistics &stats) override
ModifiedMidpointMethod(const SharedPtr< Storage > &storage, const RunSettings &settings)
virtual void stepImpl(IScheduler &scheduler, ISolver &solver, Statistics &stats) override
virtual void stepImpl(IScheduler &scheduler, ISolver &solver, Statistics &stats) override
void makePredictions(IScheduler &scheduler)
void makeCorrections(IScheduler &scheduler)
PredictorCorrector(const SharedPtr< Storage > &storage, const RunSettings &settings)
~PredictorCorrector() override
virtual void stepImpl(IScheduler &scheduler, ISolver &solver, Statistics &stats) override
void integrateAndAdvance(ISolver &solver, Statistics &stats, Storage &k, const Float m, const Float n)
RungeKutta(const SharedPtr< Storage > &storage, const RunSettings &settings)
TValue get(const TEnum idx, std::enable_if_t<!std::is_enum< std::decay_t< TValue >>::value, int >=0) const
Returns a value of given type from the settings.
Array with fixed number of allocated elements.
void fill(const T &value)
Assigns a value to all constructed elements of the array.
Object holding various statistics about current run.
Statistics & set(const StatisticsId idx, TValue &&value)
Sets new values of a statistic.
Container storing all quantities used within the simulations.
Outcome isValid(const Flags< ValidFlag > flags=ValidFlag::COMPLETE) const
Checks whether the storage is in valid state.
void addDependent(const WeakPtr< Storage > &other)
Registers a dependent storage.
void swap(Storage &other, const Flags< VisitorEnum > flags)
Swap quantities or given subset of quantities between two storages.
Size getParticleCnt() const
Returns the number of particles.
Size getQuantityCnt() const
Returns the number of stored quantities.
void zeroHighestDerivatives()
Sets all highest-level derivatives of quantities to zero.
Storage clone(const Flags< VisitorEnum > buffers) const
Clones specified buffers of the storage.
Basic time-measuring tool. Starts automatically when constructed.
int64_t elapsed(const TimerUnit unit) const
Returns elapsed time in timer units. Does not reset the timer.
Creating code components based on values from settings.
@ TIMESTEPPING_MAX_TIMESTEP
@ TIMESTEPPING_INITIAL_TIMESTEP
@ TIMESTEPPING_MIDPOINT_COUNT
Number of sub-steps in the modified midpoint method.
@ TIMESTEPPING_BS_ACCURACY
Required relative accuracy of the Bulirsch-Stoer integrator.
Provides a convenient way to construct objects from settings.
AutoPtr< ITimeStepCriterion > getTimeStepCriterion(const RunSettings &settings)
Overload of std::swap for Sph::Array.
Float value
Value of the time step in code units (currently SI).
CriterionId id
Criterion applied to compute the time step;.