SPH
Damage.cpp
Go to the documentation of this file.
1 #include "physics/Damage.h"
2 #include "io/Logger.h"
3 #include "math/rng/Rng.h"
4 #include "quantities/IMaterial.h"
5 #include "quantities/Quantity.h"
6 #include "quantities/Storage.h"
7 #include "sph/kernel/Kernel.h"
8 #include "system/Factory.h"
9 #include "thread/Scheduler.h"
10 
12 
13 //-----------------------------------------------------------------------------------------------------------
14 // ScalarGradyKippModel implementation
15 //-----------------------------------------------------------------------------------------------------------
16 
18  IMaterial& material,
19  const MaterialInitialContext& context) const {
21 
22  SPH_ASSERT(storage.getMaterialCnt() == 1);
23  storage.insert<Float>(
26 
27  SPH_ASSERT(!storage.has(QuantityId::EPS_MIN) && !storage.has(QuantityId::M_ZERO) &&
29  "Recreating flaws");
34  ArrayView<Float> rho, m, eps_min, m_zero, growth;
35  tie(rho, m, eps_min, m_zero, growth) = storage.getValues<Float>(QuantityId::DENSITY,
42 
43  const Float mu = material.getParam<Float>(BodySettingsId::SHEAR_MODULUS);
44  const Float A = material.getParam<Float>(BodySettingsId::BULK_MODULUS);
45  // here all particles have the same material
47  const Float youngModulus = mu * 9._f * A / (3._f * A + mu);
48  material.setParam(BodySettingsId::YOUNG_MODULUS, youngModulus);
49 
50  const Float cgFactor = material.getParam<Float>(BodySettingsId::RAYLEIGH_SOUND_SPEED);
51  const Float rho0 = material.getParam<Float>(BodySettingsId::DENSITY);
52  const Float cg = cgFactor * sqrt((A + 4._f / 3._f * mu) / rho0);
53 
54  const Size size = storage.getParticleCnt();
55  // compute explicit growth
56  for (Size i = 0; i < size; ++i) {
57  growth[i] = cg / (context.kernelRadius * r[i][H]);
58  }
59  // find volume used to normalize fracture model
60  Float V = 0._f;
61  for (Size i = 0; i < size; ++i) {
62  V += m[i] / rho[i];
63  }
64  SPH_ASSERT(V > 0._f);
65  const Float k_weibull = material.getParam<Float>(BodySettingsId::WEIBULL_COEFFICIENT);
66  const Float m_weibull = material.getParam<Float>(BodySettingsId::WEIBULL_EXPONENT);
68 
69  // cannot use pow on k_weibull*V, leads to float overflow for larger V
70  const Float denom = 1._f / (std::pow(k_weibull, 1._f / m_weibull) * std::pow(V, 1._f / m_weibull));
71  SPH_ASSERT(isReal(denom) && denom > 0._f);
72  Array<Float> eps_max(size);
73 
74  if (sampleDistribution) {
75  // estimate of the highest iteration
76  const Float p_max = size * log(size);
77  const Float mult = exp(p_max / size) - 1._f;
78  for (Size i = 0; i < size; ++i) {
79  const Float x = context.rng();
80 
81  // sample with exponential distribution
82  const Float p1 = -Float(size) * log(1._f - x);
83  const Float p2 = Float(size) * log(1._f + x * mult);
84 
85  eps_min[i] = denom * std::pow(p1, 1._f / m_weibull);
86  eps_max[i] = denom * std::pow(max(p1, p2), 1._f / m_weibull);
87  SPH_ASSERT(eps_min[i] > 0 && eps_min[i] <= eps_max[i], eps_min[i], eps_max[i]);
88 
89  // sample with Poisson distribution
90  const Float mu = log(size);
91  n_flaws[i] = max<int>(1, samplePoissonDistribution(*context.rng, mu));
92 
93  // ensure that m_zero >= 1
94  // n_flaws[i] = max(n_flaws[i], Size(ceil(eps_max[i] / eps_min[i])));
95  eps_max[i] = min(eps_max[i], n_flaws[i] * eps_min[i]);
96  SPH_ASSERT(n_flaws[i] >= eps_max[i] / eps_min[i]);
97  }
98  } else {
99  Size flawedCnt = 0, p = 1;
100  while (flawedCnt < size) {
101  const Size i = Size(context.rng() * size);
102  const Float eps = denom * std::pow(Float(p), 1._f / m_weibull);
103  SPH_ASSERT(isReal(eps) && eps > 0._f);
104  if (n_flaws[i] == 0) {
105  flawedCnt++;
106  eps_min[i] = eps;
107  }
108  eps_max[i] = eps;
109  SPH_ASSERT(eps_max[i] >= eps_min[i]);
110  p++;
111  n_flaws[i]++;
112  }
113  }
114  for (Size i = 0; i < size; ++i) {
115  if (n_flaws[i] == 1) {
116  // special case to avoid division by zero below
117  m_zero[i] = 1._f;
118  } else {
119  const Float ratio = eps_max[i] / eps_min[i];
120  SPH_ASSERT(ratio >= 1._f, eps_min[i], eps_max[i]);
121 
122  m_zero[i] = log(n_flaws[i]) / log(ratio);
123  SPH_ASSERT(m_zero[i] >= 0.95_f, m_zero[i], n_flaws[i], eps_min[i], eps_max[i]);
124  }
125  }
126 }
127 
128 void ScalarGradyKippModel::integrate(IScheduler& scheduler, Storage& storage, const MaterialView material) {
130 
134  ArrayView<Float> p, eps_min, m_zero, growth;
135  tie(eps_min, m_zero, growth) =
137  p = storage.getValue<Float>(QuantityId::PRESSURE);
138  ArrayView<Size> n_flaws = storage.getValue<Size>(QuantityId::N_FLAWS);
139  ArrayView<Float> damage, ddamage;
140  tie(damage, ddamage) = storage.getAll<Float>(QuantityId::DAMAGE);
141 
142  IndexSequence seq = material.sequence();
143  parallelFor(scheduler, *seq.begin(), *seq.end(), [&](const Size i) {
144  const Interval range = material->range(QuantityId::DAMAGE);
145 
146  if (damage[i] >= range.upper()) {
147  // We CANNOT set derivative of damage to zero, it would break predictor-corrector integrator!
148  // Instead, we set damage derivative to large value, so that it is larger than the derivative from
149  // prediction, therefore damage will INCREASE in corrections, but will be immediately clamped
150  // to 1 TOGETHER WITH DERIVATIVES, time step is computed afterwards, so it should be ok.
151  ddamage[i] = LARGE;
152  return;
153  }
154  const SymmetricTensor sigma = SymmetricTensor(s[i]) - p[i] * SymmetricTensor::identity();
155  Float sig1, sig2, sig3;
156  tie(sig1, sig2, sig3) = findEigenvalues(sigma);
157  const Float sigMax = max(sig1, sig2, sig3);
158  const Float young = material->getParam<Float>(BodySettingsId::YOUNG_MODULUS);
159  // we need to assume reduces Young modulus here, hence 1-D factor
160  const Float young_red = max((1._f - pow<3>(damage[i])) * young, 1.e-20_f);
161  const Float strain = sigMax / young_red;
162  const Float ratio = strain / eps_min[i];
163  SPH_ASSERT(isReal(ratio));
164  if (ratio <= 1._f) {
165  return;
166  }
167  ddamage[i] = growth[i] * root<3>(min(std::pow(ratio, m_zero[i]), Float(n_flaws[i])));
168  SPH_ASSERT(ddamage[i] >= 0._f);
169  });
170 }
171 
172 //-----------------------------------------------------------------------------------------------------------
173 // TensorGradyKippModel implementation
174 //-----------------------------------------------------------------------------------------------------------
175 
177  IMaterial& UNUSED(material),
178  const MaterialInitialContext& UNUSED(context)) const {
180 }
181 
182 /*void TensorGradyKippModel::reduce(IScheduler& scheduler,
183  Storage& storage,
184  const Flags<DamageFlag> flags,
185  const MaterialView material) {
186  ArrayView<SymmetricTensor> damage = storage.getValue<SymmetricTensor>(QuantityId::DAMAGE);
187  // we can reduce pressure in place as the original value can be computed from equation of state
188  ArrayView<Float> p = storage.getValue<Float>(QuantityId::PRESSURE);
189  ArrayView<Float> reduce = storage.getValue<Float>(QuantityId::STRESS_REDUCING);
190  // stress tensor is evolved in time, so we need to keep unchanged value; create modified value
191  ArrayView<TracelessTensor> s, s_dmg;
192  tie(s, s_dmg) = storage.modify<TracelessTensor>(QuantityId::DEVIATORIC_STRESS);
193 
194  IndexSequence seq = material.sequence();
195  parallelFor(scheduler, *seq.begin(), *seq.end(), [&](const Size i) INL {
196  // const Float d = pow<3>(damage[i]);
197  const SymmetricTensor d = damage[i]; /// \todo should we have third root here?
198 
199  const SymmetricTensor f = SymmetricTensor::identity() - d;
200 
201  SymmetricTensor sigmaD;
202  if (p[i] < 0._f) {
203  const SymmetricTensor sigma = SymmetricTensor(s[i]) - p[i] * SymmetricTensor::identity();
204  sigmaD = f * sigma * f;
205  } else {
206  sigmaD = f * SymmetricTensor(s[i]) * f - p[i] * SymmetricTensor::identity();
207  }
208  const Float pD = -sigmaD.trace() / 3._f;
209  const TracelessTensor sD = TracelessTensor(sigmaD + pD * SymmetricTensor::identity());
210 
211  // pressure is reduced only for negative values
212  if (flags.has(DamageFlag::PRESSURE)) {
213  p[i] = pD;
214  }
215  // stress is reduced for both positive and negative values
216  if (flags.has(DamageFlag::STRESS_TENSOR)) {
217  s_dmg[i] = sD;
218  }
219  if (flags.has(DamageFlag::REDUCTION_FACTOR)) {
220  reduce[i] = (1._f - d.trace()) * reduce[i];
221  }
222  });
223 }*/
224 
226  Storage& UNUSED(storage),
227  const MaterialView UNUSED(material)) {
229 }
230 
232  IMaterial& UNUSED(material),
233  const MaterialInitialContext& UNUSED(context)) const {}
234 
236  Storage& UNUSED(storage),
237  const MaterialView UNUSED(material)) {}
238 
INLINE bool isReal(const AntisymmetricTensor &t)
#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
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
Base class for all particle materials.
SPH kernels.
Logging routines of the run.
#define VERBOSE_LOG
Helper macro, creating.
Definition: Logger.h:242
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
NAMESPACE_SPH_BEGIN constexpr INLINE T min(const T &f1, const T &f2)
Minimum & Maximum value.
Definition: MathBasic.h:15
INLINE T sqrt(const T f)
Return a squared root of a value.
Definition: MathUtils.h:78
constexpr INLINE Float pow< 3 >(const Float v)
Definition: MathUtils.h:132
constexpr INLINE Float pow(const Float v)
Power for floats.
INLINE T exp(const T f)
Definition: MathUtils.h:269
INLINE Float root< 3 >(const Float f)
Definition: MathUtils.h:105
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
@ M_ZERO
Coefficient M_0 of the stretched Weibull distribution.
@ EXPLICIT_GROWTH
Explicit growth of fractures.
@ DEVIATORIC_STRESS
Deviatoric stress tensor, always a traceless tensor.
@ PRESSURE
Pressure, affected by yielding and fragmentation model, always a scalar quantity.
@ DAMAGE
Damage.
@ N_FLAWS
Number of explicit flaws per particle.
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ DENSITY
Density, always a scalar quantity.
@ MASS
Paricles masses, always a scalar quantity.
@ EPS_MIN
Activation strait rate.
Holder of quantity values and their temporal derivatives.
@ FIRST
Quantity with 1st derivative.
@ ZERO
Quantity without derivatives, or "zero order" of quantity.
Random number generators.
INLINE Size samplePoissonDistribution(TRng &rng, const Float lambda)
Generates a random integer from Poisson distribution.
Definition: Rng.h:152
INLINE Float sampleDistribution(TRng &rng, const Interval &range, const Float upperBound, const TFunc &func)
Generates a random number from a generic distribution, using rejection sampling.
Definition: Rng.h:184
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.
Definition: Scheduler.h:98
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
Container for storing particle quantities and materials.
INLINE StaticArray< Float, 3 > findEigenvalues(const SymmetricTensor &t)
Returns three eigenvalue of symmetric matrix.
@ H
Definition: Vector.h:25
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
INLINE IMaterial & setParam(const BodySettingsId paramIdx, TValue &&value)
Definition: IMaterial.h:130
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
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
virtual void setFlaws(Storage &storage, IMaterial &material, const MaterialInitialContext &context) const override
Sets up all the necessary quantities in the storage given material settings.
Definition: Damage.cpp:231
virtual void integrate(IScheduler &scheduler, Storage &storage, const MaterialView material) override
Compute damage derivatives.
Definition: Damage.cpp:235
virtual void integrate(IScheduler &scheduler, Storage &storage, const MaterialView material) override
Compute damage derivatives.
Definition: Damage.cpp:128
virtual void setFlaws(Storage &storage, IMaterial &material, const MaterialInitialContext &context) const override
Sets up all the necessary quantities in the storage given material settings.
Definition: Damage.cpp:17
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
StaticArray< Array< TValue > &, 3 > getAll(const QuantityId key)
Retrieves quantity buffers from the storage, given its key and value type.
Definition: Storage.cpp:163
Array< TValue > & getDt(const QuantityId key)
Retrieves a quantity derivative from the storage, given its key and value type.
Definition: Storage.cpp:217
Size getParticleCnt() const
Returns the number of particles.
Definition: Storage.cpp:445
auto getValues(const QuantityId first, const QuantityId second, const TArgs... others)
Retrieves an array of quantities from the key.
Definition: Storage.h:359
bool has(const QuantityId key) const
Checks if the storage contains quantity with given key.
Definition: Storage.cpp:130
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Definition: Storage.cpp:191
Symmetric tensor of 2nd order.
static INLINE SymmetricTensor identity()
Returns an identity tensor.
virtual void setFlaws(Storage &storage, IMaterial &material, const MaterialInitialContext &context) const override
Sets up all the necessary quantities in the storage given material settings.
Definition: Damage.cpp:176
virtual void integrate(IScheduler &scheduler, Storage &storage, const MaterialView material) override
Compute damage derivatives.
Definition: Damage.cpp:225
Symmetric traceless 2nd order tensor.
Creating code components based on values from settings.
@ WEIBULL_EXPONENT
Exponent of the Weibull distribution of flaws.
@ DAMAGE_MIN
Estimate minimal value of damage used to determine timestepping error.
@ DAMAGE
Initial damage of the body.
@ SHEAR_MODULUS
Shear modulus mu (a.k.a Lame's second parameter) of the material.
@ YOUNG_MODULUS
Young modulus of the material.
@ BULK_MODULUS
Bulk modulus of the material.
@ DENSITY
Density at zero pressure.
@ WEIBULL_COEFFICIENT
Coefficient (multiplier) of the Weibull distribution of flaws.
@ RAYLEIGH_SOUND_SPEED
Speed of crack growth, in units of local sound speed.
@ DAMAGE_RANGE
Allowed range of damage.
@ WEIBULL_SAMPLE_DISTRIBUTIONS
Shared data used when creating all bodies in the simulation.
Definition: IMaterial.h:89
Float kernelRadius
Kernel radius in units of smoothing length.
Definition: IMaterial.h:96
AutoPtr< IRng > rng
Random number generator.
Definition: IMaterial.h:91