SPH
DensityIndependentSolver.cpp
Go to the documentation of this file.
2 #include "objects/Exceptions.h"
4 #include "sph/Materials.h"
6 #include "system/Factory.h"
7 #include "system/Statistics.h"
8 
10 
12 class DensityIndependentPressureGradient : public DerivativeTemplate<DensityIndependentPressureGradient> {
13 private:
18 
21 
22 public:
25 
29  }
30 
31  INLINE void additionalInitialize(const Storage& input, Accumulated& results) {
32  tie(m, y, Y) = input.getValues<Float>(
34  v = input.getDt<Vector>(QuantityId::POSITION);
35 
38  }
39 
41  return true;
42  }
43 
44  template <bool Symmetrize>
45  INLINE void eval(const Size i, const Size j, const Vector& grad) {
46  SPH_ASSERT(!Symmetrize);
47 
48  dv[i] += Y[i] * Y[j] / m[i] * (1._f / y[i] + 1._f / y[j]) * grad;
49  SPH_ASSERT(getSqrLength(dv[i]) < LARGE, dv[i]);
50 
51  du[i] += Y[i] * Y[j] / m[i] / y[i] * dot(v[i] - v[j], grad);
52  SPH_ASSERT(abs(du[i]) < LARGE, du[i]);
53  }
54 };
55 
57 public:
58  virtual void setDerivatives(DerivativeHolder& derivatives, const RunSettings& settings) override {
59  derivatives.require(makeAuto<DensityIndependentPressureGradient>(settings));
60  }
61 
62  virtual void initialize(IScheduler& UNUSED(scheduler), Storage& storage, const Float UNUSED(t)) override {
63  // EoS can return negative pressure, which is not allowed in DISPH, so we have to clamp it
65  for (Size i = 0; i < p.size(); ++i) {
66  SPH_ASSERT(p[i] >= 100._f);
67  p[i] = max(p[i], 100._f);
68  }
69  }
70 
71  virtual void finalize(IScheduler& UNUSED(scheduler),
72  Storage& UNUSED(storage),
73  const Float UNUSED(t)) override {}
74 
75  virtual void create(Storage& storage, IMaterial& material) const override {
76  if (!dynamic_cast<EosMaterial*>(&material)) {
77  throw InvalidSetup("DISPH requires EosMaterial or derived");
78  }
79  const Float u0 = material.getParam<Float>(BodySettingsId::ENERGY);
82  }
83 };
84 
86  : scheduler(scheduler)
87  , threadData(scheduler) {
88  finder = Factory::getFinder(settings);
89  kernel = Factory::getKernel<3>(settings);
90 
91  // config.alpha = settings.get<Float>(RunSettingsId::SPH_DI_ALPHA);
92 
93  equations += makeTerm<DensityIndependentPressureForce>();
94  equations += makeTerm<SolidStressForce>(settings);
95  equations += makeTerm<StandardAV>();
96 
97  equations.setDerivatives(derivatives, settings);
98 }
99 
101 
104  finder->build(scheduler, r);
105 
106  // step 1: compute density from the current y and Y
112  for (Size i = 0; i < r.size(); ++i) {
113  rho[i] = m[i] * y[i] / Y[i];
114  SPH_ASSERT(rho[i] > 1._f && rho[i] < 1.e4_f, rho[i]);
115  }
116 
117  // step 2: using computed density, get the non-smoothed pressure from equation of state
118  for (Size matId = 0; matId < storage.getMaterialCnt(); ++matId) {
119  MaterialView material = storage.getMaterial(matId);
120  material->initialize(scheduler, storage, material.sequence());
121  }
122 
123  const Float t = stats.get<Float>(StatisticsId::RUN_TIME);
124  equations.initialize(scheduler, storage, t);
125  derivatives.initialize(storage);
126 
127  // step 3: update Y from the pressure
128 
129  for (Size i = 0; i < r.size(); ++i) {
130  Y[i] = m[i] * /*pow(p[i], config.alpha) */ p[i] / rho[i];
131  SPH_ASSERT(Y[i] > EPS && Y[i] < LARGE, Y[i]);
132  }
133 
134  const Float radius = kernel.radius() * r[0][H];
135 
136  // step 4: compute y by summing up neighbours
137  auto pressureFunc = [this, Y, r, p, &y, radius](const Size i, ThreadData& data) {
138  // find neighbours
139  finder->findAll(i, radius, data.neighs);
140 
141  y[i] = 0._f;
142  for (NeighbourRecord& n : data.neighs) {
143  const Size j = n.index;
144  y[i] += Y[j] * kernel.value(r[i], r[j]);
145  }
146  SPH_ASSERT(y[i] > 0._f);
147 
148  // y[i] = pow(y[i], 1._f / config.alpha - 2._f);
149  SPH_ASSERT(y[i] > EPS && y[i] < LARGE, y[i]);
150  };
151  parallelFor(scheduler, threadData, 0, r.size(), pressureFunc);
152 
153  // step 5: using computed y, evaluate equation of motion and energy equation
154  auto equationFunc = [this, Y, r, radius](const Size i, ThreadData& data) {
155  // find neighbours
156  finder->findAll(i, radius, data.neighs);
157 
158  // compute kernels and value p^alpha using direct summation
159  data.idxs.clear();
160  data.grads.clear();
161  for (NeighbourRecord& n : data.neighs) {
162  const Size j = n.index;
163  const Float hbar = 0.5_f * (r[i][H] + r[j][H]);
164  SPH_ASSERT(hbar > EPS, hbar);
165  if (i == j || n.distanceSqr >= sqr(kernel.radius() * hbar)) {
166  // aren't actual neighbours
167  continue;
168  }
169 
170  const Vector gr = kernel.grad(r[i], r[j]);
171  SPH_ASSERT(isReal(gr) && dot(gr, r[i] - r[j]) <= 0._f, gr, r[i] - r[j]);
172  data.grads.emplaceBack(gr);
173  data.idxs.emplaceBack(j);
174  }
175 
176  derivatives.eval(i, data.idxs, data.grads);
177  };
178  parallelFor(scheduler, threadData, 0, r.size(), equationFunc);
179 
180  derivatives.getAccumulated().store(storage);
181  equations.finalize(scheduler, storage, t);
182 
183  // step 6: get an estimate of Y for next time step by computing its derivative
184  // dY/dt must be computed after all equations are finalized, as it depends on du/dt
188  for (Size i = 0; i < r.size(); ++i) {
189  const Float gamma = rho[i] / p[i] * sqr(cs[i]);
190  SPH_ASSERT(gamma > 0._f);
191  // y[i] = pow(y[i], 1._f / (1._f / config.alpha - 2._f)); /// \todo
192  // const Float y1 = pow(y[i], 1._f - 1._f / config.alpha);
193  dY[i] = 0._f * (/*config.alpha * */ gamma - 1._f) * m[i] * du[i];
194  SPH_ASSERT(isReal(dY[i]) && abs(dY[i]) < LARGE);
195  }
196 
197  for (Size matId = 0; matId < storage.getMaterialCnt(); ++matId) {
198  MaterialView material = storage.getMaterial(matId);
199  material->finalize(scheduler, storage, material.sequence());
200  }
201 }
202 
203 void DensityIndependentSolver::create(Storage& storage, IMaterial& material) const {
204  const Float rho0 = material.getParam<Float>(BodySettingsId::DENSITY);
206 
207  // set up to something which equals y/Y = m/rho
208  const Float m0 = storage.getValue<Float>(QuantityId::MASS)[0];
212  equations.create(storage, material);
213 }
214 
@ SHARED
Multiple derivatives may accumulate into the buffer.
INLINE bool isReal(const AntisymmetricTensor &t)
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
const float radius
Definition: CurveDialog.cpp:18
Density-independent formulation of SPH.
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
SPH-specific implementation of particle materials.
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
constexpr Float EPS
Definition: MathUtils.h:30
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
Definition: MathUtils.h:67
constexpr Float INFTY
Definition: MathUtils.h:38
INLINE auto abs(const T &f)
Definition: MathUtils.h:276
constexpr Float LARGE
Definition: MathUtils.h:34
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
@ PRESSURE
Pressure, affected by yielding and fragmentation model, always a scalar quantity.
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ ENERGY
Specific internal energy, always a scalar quantity.
@ GENERALIZED_PRESSURE
@ DENSITY
Density, always a scalar quantity.
@ MASS
Paricles masses, always a scalar quantity.
@ SOUND_SPEED
Sound speed, always a scalar quantity.
@ GENERALIZED_ENERGY
The "Y" quantity defined by , used to compute equation of motion and energy in DISPH.
@ SECOND
Quantity with 1st and 2nd derivative.
@ FIRST
Quantity with 1st derivative.
@ ZERO
Quantity without derivatives, or "zero order" of quantity.
INLINE void parallelFor(IScheduler &scheduler, const Size from, const Size to, TFunctor &&functor)
Executes a functor concurrently from all available threads.
Definition: Scheduler.h:98
Standard SPH artificial viscosity.
StaticArray< T0 &, sizeof...(TArgs)+1 > tie(T0 &t0, TArgs &... rest)
Creates a static array from a list of l-value references.
Definition: StaticArray.h:281
Statistics gathered and periodically displayed during the run.
@ RUN_TIME
Current time of the simulation in code units. Does not necessarily have to be 0 when run starts.
INLINE Float getSqrLength(const Vector &v)
Definition: Vector.h:574
INLINE float dot(const BasicVector< float > &v1, const BasicVector< float > &v2)
Make sure the vector is trivially constructible and destructible, needed for fast initialization of a...
Definition: Vector.h:548
@ H
Definition: Vector.h:25
@ Y
Definition: Vector.h:23
Storage for accumulating derivatives.
Definition: Accumulated.h:30
Array< TValue > & getBuffer(const QuantityId id, const OrderEnum order)
Returns the buffer of given quantity and given order.
Definition: Accumulated.cpp:53
void store(Storage &storage)
Stores accumulated values to corresponding quantities.
Definition: Accumulated.cpp:86
void insert(const QuantityId id, const OrderEnum order, const BufferSource source)
Creates a new storage with given ID.
Object providing safe access to continuous memory of data.
Definition: ArrayView.h:17
INLINE TCounter size() const
Definition: ArrayView.h:101
virtual void finalize(IScheduler &UNUSED(scheduler), Storage &UNUSED(storage), const Float UNUSED(t)) override
virtual void initialize(IScheduler &UNUSED(scheduler), Storage &storage, const Float UNUSED(t)) override
virtual void create(Storage &storage, IMaterial &material) const override
Creates all quantities needed by the term using given material.
virtual void setDerivatives(DerivativeHolder &derivatives, const RunSettings &settings) override
Sets derivatives required by this term.
INLINE void additionalCreate(Accumulated &results)
INLINE void additionalInitialize(const Storage &input, Accumulated &results)
DensityIndependentPressureGradient(const RunSettings &settings)
INLINE bool additionalEquals(const DensityIndependentPressureGradient &UNUSED(other)) const
INLINE void eval(const Size i, const Size j, const Vector &grad)
DensityIndependentSolver(IScheduler &scheduler, const RunSettings &settings)
virtual void integrate(Storage &storage, Statistics &stats) override
Computes derivatives of all time-dependent quantities.
virtual void create(Storage &storage, IMaterial &material) const override
Initializes all quantities needed by the solver in the storage.
Container holding derivatives and the storage they accumulate to.
Definition: Derivative.h:173
virtual void require(AutoPtr< IDerivative > &&derivative)
Adds derivative if not already present.
Definition: Derivative.cpp:77
void eval(const Size idx, ArrayView< const Size > neighs, ArrayView< const Vector > grads)
Evaluates all held derivatives for given particle.
Definition: Derivative.cpp:113
INLINE Accumulated & getAccumulated()
Definition: Derivative.h:226
virtual void initialize(const Storage &input)
Initialize derivatives before loop.
Definition: Derivative.cpp:96
Helper template for derivatives that define both the symmetrized and asymmetric variant.
Material holding equation of state.
Definition: Materials.h:21
void setDerivatives(DerivativeHolder &derivatives, const RunSettings &settings) const
Calls EquationTerm::setDerivatives for all stored equation terms.
Definition: EquationTerm.h:277
void create(Storage &storage, IMaterial &material) const
Calls EquationTerm::create for all stored equation terms.
Definition: EquationTerm.h:300
void initialize(IScheduler &scheduler, Storage &storage, const Float t)
Calls EquationTerm::initialize for all stored equation terms.
Definition: EquationTerm.h:284
void finalize(IScheduler &scheduler, Storage &storage, const Float t)
Calls EquationTerm::finalize for all stored equation terms.
Definition: EquationTerm.h:293
void build(IScheduler &scheduler, ArrayView< const Vector > points)
Constructs the struct with an array of vectors.
virtual Size findAll(const Size index, const Float radius, Array< NeighbourRecord > &neighbours) const =0
Finds all neighbours within given radius from the point given by index.
Represents a term or terms appearing in evolutionary equations.
Definition: EquationTerm.h:22
Material settings and functions specific for one material.
Definition: IMaterial.h:110
INLINE TValue getParam(const BodySettingsId paramIdx) const
Returns a parameter associated with given particle.
Definition: IMaterial.h:137
void setRange(const QuantityId id, const Interval &range, const Float minimal)
Sets the timestepping parameters of given quantity.
Definition: IMaterial.cpp:17
Interface that allows unified implementation of sequential and parallelized versions of algorithms.
Definition: Scheduler.h:27
Object representing a 1D interval of real numbers.
Definition: Interval.h:17
Thrown when components of the run are mutually incompatible.
Definition: Exceptions.h:24
Non-owning wrapper of a material and particles with this material.
Definition: IMaterial.h:30
INLINE IndexSequence sequence()
Returns iterable index sequence.
Definition: IMaterial.h:75
Object holding various statistics about current run.
Definition: Statistics.h:22
TValue get(const StatisticsId idx) const
Returns value of a statistic.
Definition: Statistics.h:88
Container storing all quantities used within the simulations.
Definition: Storage.h:230
Size getMaterialCnt() const
Return the number of materials in the storage.
Definition: Storage.cpp:437
Quantity & insert(const QuantityId key, const OrderEnum order, const TValue &defaultValue)
Creates a quantity in the storage, given its key, value type and order.
Definition: Storage.cpp:270
Array< TValue > & getDt(const QuantityId key)
Retrieves a quantity derivative from the storage, given its key and value type.
Definition: Storage.cpp:217
auto getValues(const QuantityId first, const QuantityId second, const TArgs... others)
Retrieves an array of quantities from the key.
Definition: Storage.h:359
MaterialView getMaterial(const Size matIdx) const
Returns an object containing a reference to given material.
Definition: Storage.cpp:366
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Definition: Storage.cpp:191
INLINE Float value(const Vector &r1, const Vector &r2) const
Definition: Kernel.h:573
INLINE Float radius() const
Definition: Kernel.h:583
INLINE Vector grad(const Vector &r1, const Vector &r2) const
Definition: Kernel.h:578
Creating code components based on values from settings.
@ ENERGY_MIN
Estimated minimal value of energy used to determine timestepping error.
@ ENERGY
Initial specific internal energy.
@ DENSITY
Density at zero pressure.
@ ENERGY_RANGE
Allowed range of specific internal energy.
AutoPtr< ISymmetricFinder > getFinder(const RunSettings &settings)
Definition: Factory.cpp:156
Holds information about a neighbour particles.
Size index
Index of particle in the storage.
Float distanceSqr
Squared distance of the particle from the queried particle / position.