SPH
src
core
sph
equations
Rotation.cpp
Go to the documentation of this file.
1
#include "
sph/equations/Rotation.h
"
2
3
NAMESPACE_SPH_BEGIN
4
9
/*INLINE bool interacts(Size i, Size j, ArrayView<const Size> flag, ArrayView<const Float> reduce) {
10
return flag[i] == flag[j] && reduce[i] > 0._f && reduce[j] > 0._f;
11
}
12
14
template <typename Term>
15
class RotationStressDivergence : public DerivativeTemplate<RotationStressDivergence<Term>> {
16
private:
17
ArrayView<const Float> rho, m, I;
18
ArrayView<const TracelessTensor> s;
19
ArrayView<const Float> reduce;
20
ArrayView<const Size> flag;
21
ArrayView<const Vector> r;
22
ArrayView<Vector> domega;
23
24
public:
25
virtual void create(Accumulated& results) override {
26
results.insert<Vector>(QuantityId::ANGULAR_VELOCITY, OrderEnum::FIRST);
27
}
28
29
virtual void initialize(const Storage& input, Accumulated& results) override {
30
tie(rho, m, I) =
31
input.getValues<Float>(QuantityId::DENSITY, QuantityId::MASS, QuantityId::MOMENT_OF_INERTIA);
32
s = input.getPhysicalValue<TracelessTensor>(QuantityId::DEVIATORIC_STRESS);
33
reduce = input.getValue<Float>(QuantityId::STRESS_REDUCING);
34
flag = input.getValue<Size>(QuantityId::FLAG);
35
r = input.getValue<Vector>(QuantityId::POSITION);
36
domega = results.getBuffer<Vector>(QuantityId::ANGULAR_VELOCITY, OrderEnum::FIRST);
37
}
38
39
40
template <bool Symmetrize>
41
INLINE void eval(const Size i, const Size j, const Vector& grad) {
42
if (!interacts(i, j, flag, reduce)) {
43
return;
44
}
45
const TracelessTensor t = Term::term(s, rho, i, j);
46
const Vector force = t * grad;
47
const Vector torque = 0.5_f * cross(r[j] - r[i], force);
48
SPH_ASSERT(isReal(force) && isReal(torque));
49
domega[i] += m[i] / I[i] * m[j] * torque;
50
SPH_ASSERT(isReal(domega[i]));
51
52
if (Symmetrize) {
53
domega[j] += m[j] / I[j] * m[i] * torque;
54
SPH_ASSERT(isReal(domega[j]));
55
}
56
}
57
};
58
59
template <QuantityId Id, typename TDerived>
60
class RotationStrengthVelocityTemplate : public SymmetricDerivative {
61
protected:
62
ArrayView<const Float> rho, m;
63
ArrayView<const Vector> r, omega;
64
ArrayView<const Size> flag;
65
ArrayView<const Float> reduce;
66
ArrayView<SymmetricTensor> gradv;
67
68
bool useCorrectionTensor;
69
ArrayView<const SymmetricTensor> C;
70
71
public:
72
explicit RotationStrengthVelocityTemplate(const RunSettings& settings) {
73
useCorrectionTensor = settings.get<bool>(RunSettingsId::SPH_STRAIN_RATE_CORRECTION_TENSOR);
74
}
75
76
virtual void create(Accumulated& results) override {
77
results.insert<SymmetricTensor>(Id, OrderEnum::ZERO);
78
}
79
80
virtual void initialize(const Storage& input, Accumulated& results) override {
81
tie(rho, m) = input.getValues<Float>(QuantityId::DENSITY, QuantityId::MASS);
82
tie(r, omega) = input.getValues<Vector>(QuantityId::POSITION, QuantityId::ANGULAR_VELOCITY);
83
flag = input.getValue<Size>(QuantityId::FLAG);
84
reduce = input.getValue<Float>(QuantityId::STRESS_REDUCING);
85
86
gradv = results.getBuffer<SymmetricTensor>(Id, OrderEnum::ZERO);
87
if (useCorrectionTensor) {
88
// RotationStrengthVelocityGradient can only be used with StrengthVelocityGradient, that computes
89
// the correction tensor and saves it to the accumulated buffer. We don't compute it here, it must
90
// be already computed.
91
C = results.getBuffer<SymmetricTensor>(
92
QuantityId::STRAIN_RATE_CORRECTION_TENSOR, OrderEnum::ZERO);
93
}
94
}
95
96
virtual void evalNeighs(const Size idx,
97
ArrayView<const Size> neighs,
98
ArrayView<const Vector> grads) override {
99
SPH_ASSERT(neighs.size() == grads.size());
100
if (useCorrectionTensor) {
101
for (Size k = 0; k < neighs.size(); ++k) {
102
SPH_ASSERT(C[idx] != SymmetricTensor::null()); // check that it has been computed
103
static_cast<TDerived*>(this)->template eval<false>(idx, neighs[k], C[idx] * grads[k]);
104
}
105
} else {
106
for (Size k = 0; k < neighs.size(); ++k) {
107
static_cast<TDerived*>(this)->template eval<false>(idx, neighs[k], grads[k]);
108
}
109
}
110
}
111
112
virtual void evalSymmetric(const Size idx,
113
ArrayView<const Size> neighs,
114
ArrayView<const Vector> grads) override {
115
SPH_ASSERT(neighs.size() == grads.size());
116
SPH_ASSERT(!useCorrectionTensor);
117
for (Size k = 0; k < neighs.size(); ++k) {
118
static_cast<TDerived*>(this)->template eval<true>(idx, neighs[k], grads[k]);
119
}
120
}
121
};
122
123
class RotationStrengthVelocityGradient
124
: public RotationStrengthVelocityTemplate<QuantityId::STRENGTH_VELOCITY_GRADIENT,
125
RotationStrengthVelocityGradient> {
126
public:
127
using RotationStrengthVelocityTemplate<QuantityId::STRENGTH_VELOCITY_GRADIENT,
128
RotationStrengthVelocityGradient>::RotationStrengthVelocityTemplate;
129
130
template <bool Symmetrize>
131
INLINE void eval(const Size i, const Size j, const Vector& grad) {
132
// Here we modify the velocity gradient ONLY if particles interact. Equation using the velocity
133
// gradient shall use it only if the particles have nonzero reduction factor, otherwise use simple
134
// velocity divergence (see ContinuityEquation for example).
135
if (!interacts(i, j, flag, reduce)) {
136
return;
137
}
138
const Vector dr = r[j] - r[i];
139
const Vector dvj = cross(omega[j], dr);
140
const SymmetricTensor tj = outer(dvj, grad);
141
SPH_ASSERT(isReal(tj));
142
gradv[i] -= m[j] / rho[j] * tj;
143
if (Symmetrize) {
144
const Vector dvi = cross(omega[i], dr);
145
const SymmetricTensor ti = outer(dvi, grad);
146
gradv[j] -= m[i] / rho[i] * ti;
147
}
148
}
149
};
150
151
class RotationVelocityGradient : public RotationTemplate<QuantityId::STRENGTH_DENSITY_VELOCITY_GRADIENT,
152
RotationStrengthDensityVelocityGradient> {
153
public:
154
using RotationStrengthVelocityTemplate<QuantityId::STRENGTH_DENSITY_VELOCITY_GRADIENT,
155
RotationStrengthDensityVelocityGradient>::RotationStrengthVelocityTemplate;
156
157
template <bool Symmetrize>
158
INLINE void eval(const Size i, const Size j, const Vector& grad) {
159
if (flag[i] != flag[j] || reduce[i] == 0._f || reduce[j] == 0._f) {
160
return;
161
}
162
const Vector dr = r[j] - r[i];
163
const Vector dvj = cross(omega[j], dr);
164
const SymmetricTensor tj = outer(dvj, grad);
165
SPH_ASSERT(isReal(tj));
166
gradv[i] -= m[j] * tj;
167
if (Symmetrize) {
168
const Vector dvi = cross(omega[i], dr);
169
const SymmetricTensor ti = outer(dvi, grad);
170
gradv[j] -= m[i] * ti;
171
}
172
}
173
};
174
175
BenzAsphaugSph::SolidStressTorque::SolidStressTorque(const RunSettings& settings) {
176
const KernelEnum kernel = settings.get<KernelEnum>(RunSettingsId::SPH_KERNEL);
177
switch (kernel) {
178
case KernelEnum::CUBIC_SPLINE:
179
inertia = 0.6_f;
180
break;
181
default:
182
NOT_IMPLEMENTED;
183
}
184
185
evolveAngle = settings.get<bool>(RunSettingsId::SPH_PHASE_ANGLE);
186
}
187
188
void BenzAsphaugSph::SolidStressTorque::setDerivatives(DerivativeHolder& derivatives,
189
const RunSettings& settings) {
190
struct Term {
191
INLINE static TracelessTensor term(ArrayView<const TracelessTensor> s,
192
ArrayView<const Float> rho,
193
const Size i,
194
const Size j) {
195
return BenzAsphaugSph::SolidStressForce::forceTerm(s, rho, i, j);
196
}
197
};
198
derivatives.require<RotationStressDivergence<Term>>(settings);
199
200
// this derivative is never actually used by the equation term, but it accumulates additional
201
// values to the velocity gradient, used by other terms in the SPH formulation.
202
derivatives.require<RotationStrengthVelocityGradient>(settings);
203
}
204
205
void BenzAsphaugSph::SolidStressTorque::initialize(Storage& storage) {
206
ArrayView<const Vector> r = storage.getValue<Vector>(QuantityId::POSITION);
207
ArrayView<const Float> m = storage.getValue<Float>(QuantityId::MASS);
208
ArrayView<Float> I = storage.getValue<Float>(QuantityId::MOMENT_OF_INERTIA);
209
for (Size i = 0; i < r.size(); ++i) {
210
I[i] = inertia * m[i] * sqr(r[i][H]);
211
SPH_ASSERT(isReal(I[i]) && I[i] > EPS);
212
}
213
}
214
215
void BenzAsphaugSph::SolidStressTorque::finalize(Storage& storage) {
216
if (evolveAngle) {
217
// copy angular velocity into the phase angle derivative (they are separate quantities)
218
ArrayView<Vector> dphi = storage.getDt<Vector>(QuantityId::PHASE_ANGLE);
219
ArrayView<Vector> omega = storage.getValue<Vector>(QuantityId::ANGULAR_VELOCITY);
220
for (Size i = 0; i < omega.size(); ++i) {
221
dphi[i] = omega[i];
222
SPH_ASSERT(maxElement(abs(omega[i])) < 1.e6_f, omega[i]);
223
}
224
}
225
}
226
227
void BenzAsphaugSph::SolidStressTorque::create(Storage& storage, IMaterial& material) const {
228
// although we should evolve phase angle as second-order quantity rather than angular velocity, the
229
// SPH particles are spherically symmetric, so there is no point of doing that
230
storage.insert<Vector>(QuantityId::ANGULAR_VELOCITY, OrderEnum::FIRST, Vector(0._f));
231
232
// let the angular velocity be unbounded and not affecting timestepping
233
material.setRange(QuantityId::ANGULAR_VELOCITY, Interval::unbounded(), LARGE);
234
235
// if needed (for testing purposes), evolve phase angle as a separate first order quantity; this is a
236
// waste of one buffer as we need to copy angular velocities between quantities, but it makes no sense
237
// to use in final runs anyway.
238
if (evolveAngle) {
239
storage.insert<Vector>(QuantityId::PHASE_ANGLE, OrderEnum::FIRST, Vector(0._f));
240
material.setRange(QuantityId::PHASE_ANGLE, Interval::unbounded(), LARGE);
241
}
242
243
// we can set it to zero here, it will be overwritten in \ref initialize anyway
244
storage.insert<Float>(QuantityId::MOMENT_OF_INERTIA, OrderEnum::ZERO, 0._f);
245
}
246
247
void StandardSph::SolidStressTorque::setDerivatives(DerivativeHolder& derivatives,
248
const RunSettings& settings) {
249
struct Term {
250
INLINE static TracelessTensor term(ArrayView<const TracelessTensor> s,
251
ArrayView<const Float> rho,
252
const Size i,
253
const Size j) {
254
// namespace specified for clarity
255
return StandardSph::SolidStressForce::forceTerm(s, rho, i, j);
256
}
257
};
258
derivatives.require<RotationStressDivergence<Term>>(settings);
259
derivatives.require<RotationStrengthDensityVelocityGradient>(settings);
260
}*/
261
262
NAMESPACE_SPH_END
NAMESPACE_SPH_BEGIN
NAMESPACE_SPH_BEGIN
Definition:
BarnesHut.cpp:13
NAMESPACE_SPH_END
#define NAMESPACE_SPH_END
Definition:
Object.h:12
Rotation.h
Generated by
1.9.1