SPH
DerivativeHelpers.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "quantities/Quantity.h"
5 
7 
8 enum class DerivativeFlag {
13  CORRECTED = 1 << 0,
14 
17  SUM_ONLY_UNDAMAGED = 1 << 1,
18 };
19 
39 template <typename TDerived>
41 private:
45 
47 
48 public:
49  explicit DerivativeTemplate(const RunSettings& settings, const Flags<DerivativeFlag> flags = EMPTY_FLAGS)
50  : flags(flags) {
51  const bool useCorrectionTensor = settings.get<bool>(RunSettingsId::SPH_STRAIN_RATE_CORRECTION_TENSOR);
52  if (!useCorrectionTensor) {
53  // 'global' override for correction tensor
54  this->flags.unset(DerivativeFlag::CORRECTED);
55  }
56  const bool sumOnlyUndamaged = settings.get<bool>(RunSettingsId::SPH_SUM_ONLY_UNDAMAGED);
57  if (!sumOnlyUndamaged) {
58  // 'global' override - always sum all particles
60  }
61  }
62 
63  virtual void create(Accumulated& results) override final {
64  derived()->additionalCreate(results);
65  }
66 
67  virtual void initialize(const Storage& input, Accumulated& results) override final {
68  if (flags.has(DerivativeFlag::CORRECTED)) {
69  C = results.getBuffer<SymmetricTensor>(
71  } else {
72  C = nullptr;
73  }
75  idxs = input.getValue<Size>(QuantityId::FLAG);
76  reduce = input.getValue<Float>(QuantityId::STRESS_REDUCING);
77  } else {
78  idxs = nullptr;
79  reduce = nullptr;
80  }
81 
82  derived()->additionalInitialize(input, results);
83  }
84 
85  virtual bool equals(const IDerivative& other) const override final {
86  if (typeid(*this) != typeid(other)) {
87  return false;
88  }
89  const TDerived* actOther = assert_cast<const TDerived*>(&other);
90  return (flags == actOther->flags) && derived()->additionalEquals(*actOther);
91  }
92 
93  virtual void evalNeighs(const Size idx,
94  ArrayView<const Size> neighs,
95  ArrayView<const Vector> grads) override {
96  SPH_ASSERT(neighs.size() == grads.size());
97  if (C) {
98  sum(idx, neighs, grads, [this](Size i, Size j, const Vector& grad) INL {
100  derived()->template eval<false>(i, j, C[i] * grad);
101  });
102  } else {
103  sum(idx, neighs, grads, [this](Size i, Size j, const Vector& grad) INL {
104  derived()->template eval<false>(i, j, grad);
105  });
106  }
107  }
108 
109  virtual void evalSymmetric(const Size idx,
110  ArrayView<const Size> neighs,
111  ArrayView<const Vector> grads) override {
112  SPH_ASSERT(neighs.size() == grads.size());
114  sum(idx, neighs, grads, [this](Size i, Size j, const Vector& grad) INL {
115  derived()->template eval<true>(i, j, grad);
116  });
117  }
118 
119 private:
120  template <typename TFunctor>
121  INLINE void sum(const Size i,
122  ArrayView<const Size> neighs,
124  const TFunctor& functor) {
125  if (reduce) {
126  for (Size k = 0; k < neighs.size(); ++k) {
127  const Size j = neighs[k];
128  if (idxs[i] != idxs[j] || reduce[i] == 0._f || reduce[j] == 0._f) {
129  continue;
130  }
131  functor(i, j, grads[k]);
132  }
133  } else {
134  for (Size k = 0; k < neighs.size(); ++k) {
135  const Size j = neighs[k];
136  functor(i, j, grads[k]);
137  }
138  }
139  }
140 
141  TDerived* derived() {
142  return static_cast<TDerived*>(this);
143  }
144 
145  const TDerived* derived() const {
146  return static_cast<const TDerived*>(this);
147  }
148 };
149 
150 
158 template <typename TDerived>
160 private:
162  ArrayView<Float> du;
165  ArrayView<const Float> reduce;
166  bool sumOnlyUndamaged;
167 
168 public:
169  explicit AccelerationTemplate(const RunSettings& settings,
170  const Flags<DerivativeFlag> flags = EMPTY_FLAGS) {
171  SPH_ASSERT(!flags.has(DerivativeFlag::CORRECTED), "Forces should be never corrected");
172 
173  // sum only undamaged if specified by the flag and it is specified by the 'global' override
174  sumOnlyUndamaged = flags.has(DerivativeFlag::SUM_ONLY_UNDAMAGED) &&
176  }
177 
178  virtual void create(Accumulated& results) override final {
181 
182  derived()->additionalCreate(results);
183  }
184 
185  virtual void initialize(const Storage& input, Accumulated& results) override final {
186  dv = results.getBuffer<Vector>(QuantityId::POSITION, OrderEnum::SECOND);
187  du = results.getBuffer<Float>(QuantityId::ENERGY, OrderEnum::FIRST);
188 
189  m = input.getValue<Float>(QuantityId::MASS);
190  if (sumOnlyUndamaged && input.has(QuantityId::STRESS_REDUCING)) {
191  idxs = input.getValue<Size>(QuantityId::FLAG);
192  reduce = input.getValue<Float>(QuantityId::STRESS_REDUCING);
193  } else {
194  idxs = nullptr;
195  reduce = nullptr;
196  }
197 
198  derived()->additionalInitialize(input, results);
199  }
200 
201  virtual bool equals(const IDerivative& other) const override final {
202  if (typeid(*this) != typeid(other)) {
203  return false;
204  }
205  const TDerived* actOther = assert_cast<const TDerived*>(&other);
206  return (sumOnlyUndamaged == actOther->sumOnlyUndamaged) && derived()->additionalEquals(*actOther);
207  }
208 
209  virtual void evalNeighs(const Size idx,
210  ArrayView<const Size> neighs,
211  ArrayView<const Vector> grads) override {
212  SPH_ASSERT(neighs.size() == grads.size());
213  sum(idx, neighs, grads, [this](Size UNUSED(k), Size i, Size j, const Vector& grad) INL {
214  Vector f;
215  Float de;
216  tieToTuple(f, de) = derived()->template eval<false>(i, j, grad);
217  dv[i] += m[j] * f;
218  du[i] += m[j] * de;
219  });
220  }
221 
222  virtual void evalSymmetric(const Size idx,
223  ArrayView<const Size> neighs,
224  ArrayView<const Vector> grads) override {
225  SPH_ASSERT(neighs.size() == grads.size());
226  sum(idx, neighs, grads, [this](Size UNUSED(k), Size i, Size j, const Vector& grad) INL {
227  Vector f;
228  Float de;
229  tieToTuple(f, de) = derived()->template eval<true>(i, j, grad);
230  dv[i] += m[j] * f;
231  dv[j] -= m[i] * f;
232  du[i] += m[j] * de;
233  du[j] += m[i] * de;
234  });
235  }
236 
237  virtual void evalAcceleration(const Size idx,
238  ArrayView<const Size> neighs,
240  ArrayView<Vector> dv) override {
241  SPH_ASSERT(neighs.size() == grads.size() && neighs.size() == dv.size());
242  sum(idx, neighs, grads, [this, &dv](Size k, Size i, Size j, const Vector& grad) INL {
243  Vector f;
244  tieToTuple(f, IGNORE) = derived()->template eval<false>(i, j, grad);
245  dv[k] += m[j] * f;
246  });
247  }
248 
249 private:
250  template <typename TFunctor>
251  INLINE void sum(const Size i,
252  ArrayView<const Size> neighs,
254  const TFunctor& functor) {
255  if (reduce) {
256  for (Size k = 0; k < neighs.size(); ++k) {
257  const Size j = neighs[k];
258  if (idxs[i] != idxs[j] || reduce[i] == 0._f || reduce[j] == 0._f) {
259  continue;
260  }
261  functor(k, i, j, grads[k]);
262  }
263  } else {
264  for (Size k = 0; k < neighs.size(); ++k) {
265  const Size j = neighs[k];
266  functor(k, i, j, grads[k]);
267  }
268  }
269  }
270 
271  INLINE TDerived* derived() {
272  return static_cast<TDerived*>(this);
273  }
274 
275  INLINE const TDerived* derived() const {
276  return static_cast<const TDerived*>(this);
277  }
278 };
279 
286  ArrayView<const Float> rho, m;
287 
288 public:
289  void initialize(const Storage& input) {
291  }
292 
293  template <typename T>
294  INLINE T eval(const Size i, const Size j, const T& value) {
295  return m[j] / rho[i] * value;
296  }
297 };
298 
305  ArrayView<const Float> rho, m;
306 
307 public:
308  void initialize(const Storage& input) {
310  }
311 
312  template <typename T>
313  INLINE T eval(const Size UNUSED(i), const Size j, const T& value) {
314  return m[j] / rho[j] * value;
315  }
316 };
317 
318 
319 template <QuantityId Id, typename Discr, typename Traits>
320 class VelocityTemplate : public DerivativeTemplate<VelocityTemplate<Id, Discr, Traits>> {
321 private:
324 
326  Discr discr;
327 
330 
331 public:
333 
335  results.insert<typename Traits::Type>(Id, OrderEnum::ZERO, BufferSource::UNIQUE);
336  }
337 
338  INLINE void additionalInitialize(const Storage& input, Accumulated& results) {
339  v = input.getDt<Vector>(QuantityId::POSITION);
340  discr.initialize(input);
341  deriv = results.getBuffer<typename Traits::Type>(Id, OrderEnum::ZERO);
342  }
343 
344  INLINE bool additionalEquals(const VelocityTemplate& UNUSED(other)) const {
345  return true;
346  }
347 
348  template <bool Symmetrize>
349  INLINE void eval(const Size i, const Size j, const Vector& grad) {
350  const typename Traits::Type dv = Traits::eval(v[j] - v[i], grad);
351  deriv[i] += discr.eval(i, j, dv);
352  if (Symmetrize) {
353  deriv[j] += discr.eval(j, i, dv);
354  }
355  }
356 };
357 
359  using Type = Float;
360 
361  INLINE static Float eval(const Vector& v, const Vector& grad) {
362  return dot(v, grad);
363  }
364 };
365 
367  using Type = Vector;
368 
369  INLINE static Vector eval(const Vector& v, const Vector& grad) {
370  // nabla x v
371  return cross(grad, v);
372  }
373 };
374 
377 
378  INLINE static SymmetricTensor eval(const Vector& v, const Vector& grad) {
379  return symmetricOuter(v, grad);
380  }
381 };
382 
383 
384 template <typename Discr>
386 
387 template <typename Discr>
389 
390 template <typename Discr>
392 
393 
398 template <template <class> class TVelocityDerivative>
400  const DiscretizationEnum formulation =
402  switch (formulation) {
404  return makeAuto<TVelocityDerivative<CenterDensityDiscr>>(settings, flags);
406  return makeAuto<TVelocityDerivative<NeighbourDensityDiscr>>(settings, flags);
407  default:
409  }
410 }
411 
@ SHARED
Multiple derivatives may accumulate into the buffer.
@ UNIQUE
Only a single derivative accumulates to this buffer.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
Definition: Assert.h:100
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
AutoPtr< IDerivative > makeDerivative(const RunSettings &settings, Flags< DerivativeFlag > flags=EMPTY_FLAGS)
Creates a given velocity derivative, using discretization given by selected SPH formulation.
DerivativeFlag
@ SUM_ONLY_UNDAMAGED
Only undamaged particles (particles with damage > 0) from the same body (body with the same flag) wil...
@ CORRECTED
Use correction tensor on kernel gradient when evaluating the derivative.
Spatial derivatives to be computed by SPH discretization.
const EmptyFlags EMPTY_FLAGS
Definition: Flags.h:16
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
#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
#define INL
Definition: Object.h:32
@ FLAG
ID of original body, used to implement discontinuities between bodies in SPH.
@ STRAIN_RATE_CORRECTION_TENSOR
Correction tensor used to improve conservation of total angular momentum.
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ ENERGY
Specific internal energy, always a scalar quantity.
@ DENSITY
Density, always a scalar quantity.
@ MASS
Paricles masses, always a scalar quantity.
@ STRESS_REDUCING
Total stress reduction factor due to damage and yielding. Is always scalar.
Holder of quantity values and their temporal derivatives.
@ SECOND
Quantity with 1st and 2nd derivative.
@ FIRST
Quantity with 1st derivative.
@ ZERO
Quantity without derivatives, or "zero order" of quantity.
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
INLINE SymmetricTensor symmetricOuter(const Vector &v1, const Vector &v2)
SYMMETRIZED outer product of two vectors.
INLINE Tuple< TArgs &... > tieToTuple(TArgs &... args)
Creates a tuple of l-value references. Use IGNORE placeholder to omit one or more parameters.
Definition: Tuple.h:304
const struct Ignore IGNORE
INLINE BasicVector< float > cross(const BasicVector< float > &v1, const BasicVector< float > &v2)
Cross product between two vectors.
Definition: Vector.h:559
BasicVector< Float > Vector
Definition: Vector.h:539
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
Helper template specifically used to implement forces.
virtual bool equals(const IDerivative &other) const override final
Returns true if this derivative is equal to the given derivative.
virtual void evalAcceleration(const Size idx, ArrayView< const Size > neighs, ArrayView< const Vector > grads, ArrayView< Vector > dv) override
Computes the pair-wise accelerations of given particle and its neighbours.
virtual void initialize(const Storage &input, Accumulated &results) override final
Initialize derivative before iterating over neighbours.
virtual void evalNeighs(const Size idx, ArrayView< const Size > neighs, ArrayView< const Vector > grads) override
Compute derivatives of given particle.
virtual void evalSymmetric(const Size idx, ArrayView< const Size > neighs, ArrayView< const Vector > grads) override
Compute a part of derivatives from interaction of particle pairs.
virtual void create(Accumulated &results) override final
Emplace all needed buffers into shared storage.
AccelerationTemplate(const RunSettings &settings, const Flags< DerivativeFlag > flags=EMPTY_FLAGS)
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 insert(const QuantityId id, const OrderEnum order, const BufferSource source)
Creates a new storage with given ID.
INLINE TCounter size() const
Definition: ArrayView.h:101
Wrapper of pointer that deletes the resource from destructor.
Definition: AutoPtr.h:15
Discretization using the density of the center particle.
INLINE T eval(const Size i, const Size j, const T &value)
void initialize(const Storage &input)
Helper template for derivatives that define both the symmetrized and asymmetric variant.
virtual void create(Accumulated &results) override final
Emplace all needed buffers into shared storage.
virtual bool equals(const IDerivative &other) const override final
Returns true if this derivative is equal to the given derivative.
virtual void evalNeighs(const Size idx, ArrayView< const Size > neighs, ArrayView< const Vector > grads) override
Compute derivatives of given particle.
DerivativeTemplate(const RunSettings &settings, const Flags< DerivativeFlag > flags=EMPTY_FLAGS)
virtual void evalSymmetric(const Size idx, ArrayView< const Size > neighs, ArrayView< const Vector > grads) override
Compute a part of derivatives from interaction of particle pairs.
virtual void initialize(const Storage &input, Accumulated &results) override final
Initialize derivative before iterating over neighbours.
INLINE void unset(const TEnum flag)
Removed a single flag.
Definition: Flags.h:102
constexpr INLINE bool has(const TEnum flag) const
Checks if the object has a given flag.
Definition: Flags.h:77
Extension of derivative allowing to compute pair-wise acceleration for each neighbour.
Definition: Derivative.h:124
Derivative accumulated by summing up neighbouring particles.
Definition: Derivative.h:43
Extension of derivative, allowing a symmetrized evaluation.
Definition: Derivative.h:90
Discretization using the densities of summed particles.
void initialize(const Storage &input)
INLINE T eval(const Size UNUSED(i), const Size j, const T &value)
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.
Definition: Settings.h:326
Container storing all quantities used within the simulations.
Definition: Storage.h:230
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
Symmetric tensor of 2nd order.
static INLINE SymmetricTensor null()
Returns a tensor with all zeros.
INLINE void additionalCreate(Accumulated &results)
INLINE void eval(const Size i, const Size j, const Vector &grad)
INLINE void additionalInitialize(const Storage &input, Accumulated &results)
INLINE bool additionalEquals(const VelocityTemplate &UNUSED(other)) const
DiscretizationEnum
Definition: Settings.h:735
@ STANDARD
P_i / rho_i^2 + P_j / rho_j^2.
@ BENZ_ASPHAUG
(P_i + P_j) / (rho_i rho_j)
@ SPH_STRAIN_RATE_CORRECTION_TENSOR
@ SPH_DISCRETIZATION
Specifies a discretization of SPH equations; see DiscretizationEnum.
static INLINE Float eval(const Vector &v, const Vector &grad)
static INLINE SymmetricTensor eval(const Vector &v, const Vector &grad)
static INLINE Vector eval(const Vector &v, const Vector &grad)