Loading...
Searching...
No Matches
SnowConstitutiveModel-Impl.hpp
Go to the documentation of this file.
1// This code is based on Jet framework.
2// Copyright (c) 2018 Doyub Kim
3// CubbyFlow is voxel-based fluid simulation engine for computer games.
4// Copyright (c) 2020 CubbyFlow Team
5// Core Part: Chris Ohk, Junwoo Hwang, Jihong Sin, Seungwoo Yoo
6// AI Part: Dongheon Cho, Minseo Kim
7// We are making my contributions/submissions to this project solely in our
8// personal capacity and are not conveying any rights to any intellectual
9// property of any third parties.
10
11#ifndef CUBBYFLOW_SNOW_CONSTITUTIVE_MODEL_IMPL_HPP
12#define CUBBYFLOW_SNOW_CONSTITUTIVE_MODEL_IMPL_HPP
13
14#include <Core/Math/SVD.hpp>
15
16#include <algorithm>
17#include <array>
18#include <cmath>
19#include <stdexcept>
20
21namespace CubbyFlow
22{
23template <size_t N>
25 double poissonRatio,
27 double criticalStretch,
29 : m_criticalCompression(criticalCompression),
30 m_criticalStretch(criticalStretch),
31 m_hardeningCoefficient(hardeningCoefficient)
32{
33 if (const std::array parameterChecks = { std::isfinite(youngsModulus),
34 youngsModulus > 0.0,
35 std::isfinite(poissonRatio),
36 poissonRatio > -1.0,
37 poissonRatio < 0.5,
38 std::isfinite(criticalCompression),
41 std::isfinite(criticalStretch),
42 criticalStretch >= 0.0,
43 std::isfinite(
45 hardeningCoefficient >= 0.0 };
46 !std::ranges::all_of(parameterChecks,
47 [](bool isValid) { return isValid; }))
48 {
49 throw std::invalid_argument{ "Invalid snow material parameters." };
50 }
51
52 m_mu0 = youngsModulus / (2.0 * (1.0 + poissonRatio));
53 m_lambda0 = youngsModulus * poissonRatio /
54 ((1.0 + poissonRatio) * (1.0 - 2.0 * poissonRatio));
55
56 if (!std::isfinite(m_mu0) || !std::isfinite(m_lambda0))
57 {
58 throw std::invalid_argument{ "Invalid snow material parameters." };
59 }
60}
61
62template <size_t N>
65{
66 ValidateDeformation(deformationGradientIncrement);
67 ValidateDeformation(state.elastic);
68 ValidateDeformation(state.plastic);
69
72 const MatrixType trialTotal = trialElastic * state.plastic;
73
74 ValidateDeformation(trialElastic);
75 ValidateDeformation(trialTotal);
76
80
82
83 for (size_t i = 0; i < N; ++i)
84 {
86 std::clamp(singularValues[i], 1.0 - m_criticalCompression,
87 1.0 + m_criticalStretch);
88 }
89
91 result.elastic =
92 u * MatrixType::MakeScaleMatrix(singularValues) * v.Transposed();
93 result.plastic = result.elastic.Inverse() * trialTotal;
94
95 ValidateDeformation(result.elastic);
96 ValidateDeformation(result.plastic);
97
98 return result;
99}
100
101template <size_t N>
104{
105 ValidateDeformation(state.elastic);
106 ValidateDeformation(state.plastic);
107
111
112 SVD(state.elastic, u, singularValues, v);
113
114 const MatrixType rotation = u * v.Transposed();
115 const double elasticDeterminant = state.elastic.Determinant();
116 const double hardening = ComputeHardening(state);
117
118 const double mu = m_mu0 * hardening;
119 const double lambda = m_lambda0 * hardening;
120 const MatrixType stress =
121 2.0 * mu * (state.elastic - rotation) * state.elastic.Transposed() +
123 MatrixType::MakeIdentity();
124
125 if (!IsFinite(stress))
126 {
127 throw std::invalid_argument{ "Non-finite snow stress." };
128 }
129
130 return stress;
131}
132
133template <size_t N>
136 const State& state, const MatrixType& differential) const
137{
138 ValidateDeformation(state.elastic);
139 ValidateDeformation(state.plastic);
140
141 if (!IsFinite(differential))
142 {
143 throw std::invalid_argument{ "Invalid snow deformation differential." };
144 }
145
149
150 SVD(state.elastic, u, singularValues, v);
151
154
155 for (size_t i = 0; i < N; ++i)
156 {
157 for (size_t j = i + 1; j < N; ++j)
158 {
159 const double value =
162 omega(i, j) = value;
163 omega(j, i) = -value;
164 }
165 }
167 const MatrixType& f = state.elastic;
168 const double determinant = f.Determinant();
171 double determinantDifferential = 0.0;
172
173 for (size_t row = 0; row < N; ++row)
174 {
175 for (size_t column = 0; column < N; ++column)
176 {
179 }
180 }
181
186 const double hardening = ComputeHardening(state);
187 const double mu = m_mu0 * hardening;
188 const double lambda = m_lambda0 * hardening;
189 const MatrixType result =
193
194 if (!IsFinite(result))
195 {
196 throw std::invalid_argument{ "Non-finite snow stress differential." };
197 }
198
199 return result;
200}
201
202template <size_t N>
204 double referenceDensity) const
205{
206 ValidateDeformation(state.elastic);
207 ValidateDeformation(state.plastic);
208
209 if (!std::isfinite(referenceDensity) || referenceDensity <= 0.0)
210 {
211 throw std::invalid_argument{ "Invalid snow reference density." };
212 }
213
217 SVD(state.elastic, u, singularValues, v);
218
219 const double elasticDeterminant = state.elastic.Determinant();
220 const double totalDeterminant =
223 const double hardening = ComputeHardening(state);
224 const double mu = m_mu0 * hardening;
225 const double lambda = m_lambda0 * hardening;
226 double maxCandidate = 0.0;
227
228 for (size_t a = 0; a < N; ++a)
229 {
230 const double sigmaA = singularValues[a];
231 maxCandidate = std::max(
232 maxCandidate, 2.0 * mu * sigmaA * sigmaA +
234
235 for (size_t b = 0; b < N; ++b)
236 {
237 if (a == b)
238 {
239 continue;
240 }
241
242 const double sigmaB = singularValues[b];
243 maxCandidate = std::max(maxCandidate, 2.0 * mu * sigmaB * sigmaB *
244 (sigmaA + sigmaB - 1.0) /
245 (sigmaA + sigmaB));
246 }
247 }
248
249 const double kappa = maxCandidate / totalDeterminant;
250 const double waveSpeed = std::sqrt(kappa / currentDensity);
251
252 if (!std::isfinite(totalDeterminant) || totalDeterminant <= 0.0 ||
253 !std::isfinite(currentDensity) || currentDensity <= 0.0 ||
254 !std::isfinite(kappa) || kappa <= 0.0 || !std::isfinite(waveSpeed))
255 {
256 throw std::invalid_argument{ "Invalid snow wave speed." };
257 }
258
259 return waveSpeed;
260}
261
262template <size_t N>
263double SnowConstitutiveModel<N>::ComputeHardening(const State& state) const
264{
265 const double hardening =
266 std::exp(m_hardeningCoefficient * (1.0 - state.plastic.Determinant()));
267
268 if (!std::isfinite(hardening))
269 {
270 throw std::invalid_argument{ "Non-finite snow hardening." };
271 }
272
273 return hardening;
274}
275
276template <size_t N>
277bool SnowConstitutiveModel<N>::IsFinite(const MatrixType& matrix)
278{
279 return std::ranges::all_of(
280 matrix, [](double value) { return std::isfinite(value); });
281}
282
283template <size_t N>
284void SnowConstitutiveModel<N>::ValidateDeformation(const MatrixType& matrix)
285{
286 const double determinant = matrix.Determinant();
287
288 if (!IsFinite(matrix) || !std::isfinite(determinant) || determinant <= 0.0)
289 {
290 throw std::invalid_argument{ "Invalid snow deformation gradient." };
291 }
292}
293} // namespace CubbyFlow
294
295#endif
ValueType Determinant() const
Definition MatrixExpression-Impl.hpp:198
Matrix< T, Rows, Cols > Inverse() const
Returns inverse matrix.
Definition MatrixExpression-Impl.hpp:371
MatrixTranspose< T, Rows, Cols, const Derived & > Transposed() const
Definition MatrixExpression-Impl.hpp:365
Definition Matrix.hpp:30
Snow-specific elastoplastic constitutive model.
Definition SnowConstitutiveModel.hpp:42
double ComputeWaveSpeed(const State &state, double referenceDensity) const
Estimates the fastest elastic wave speed for the state.
Definition SnowConstitutiveModel-Impl.hpp:203
MatrixType ComputeFirstPiolaStressDifferential(const State &state, const MatrixType &differential) const
Computes the first Piola stress differential.
Definition SnowConstitutiveModel-Impl.hpp:135
State Update(const MatrixType &deformationGradientIncrement, const State &state) const
Projects a deformation increment into elastic and plastic parts.
Definition SnowConstitutiveModel-Impl.hpp:63
SnowConstitutiveModel(double youngsModulus=1.4e5, double poissonRatio=0.2, double criticalCompression=2.5e-2, double criticalStretch=7.5e-3, double hardeningCoefficient=10.0)
Constructs a snow constitutive model.
Definition SnowConstitutiveModel-Impl.hpp:24
MatrixType ComputeKirchhoffStress(const State &state) const
Computes the fixed-corotated Kirchhoff stress for the state.
Definition SnowConstitutiveModel-Impl.hpp:103
Definition pybind11Utils.hpp:22
void SVD(const MatrixMxN< T > &a, MatrixMxN< T > &u, VectorN< T > &w, MatrixMxN< T > &v)
Singular value decomposition (SVD).
Definition SVD-Impl.hpp:54
Matrix< T, Rows, 1 > Vector
Definition Matrix.hpp:648
Per-particle multiplicative deformation state for snow.
Definition SnowConstitutiveModel.hpp:26