UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
NewtonElasticFEM.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "Chaos/Core.h"
10#include "Chaos/VelocityField.h"
11
12namespace Chaos::Softs
13{
14
15
16template <typename T, typename ParticleType>
18{
19public:
23 TArray<TVector<T, 3>> ElementForces; // extra storage in case of parallel force and force differential computation
24 int32 Np;// the total number of particles in the arrays that mesh is indexing
27
29 const ParticleType& InParticles,
32 )
34 {
35
36 Np = InParticles.Size();
37 DmInverse.Init((T)0., 9 * Mesh.Num());
38 Measure.Init((T)0., Mesh.Num());
39 for (int e = 0; e < Mesh.Num(); e++)
40 {
42 PMatrix<T, 3, 3> DmInv = Dm.Inverse();
43 for (int r = 0; r < 3; r++) {
44 for (int c = 0; c < 3; c++) {
45 DmInverse[(3 * 3) * e + 3 * r + c] = DmInv.GetAt(r, c);
46 }
47 }
48
49 Measure[e] = Dm.Determinant() / (T)6.;
50
51 //part of preprocessing: if inverted element is found,
52 //invert it so that the measure is positive
53 if (Measure[e] < (T)0.)
54 {
55
56 Measure[e] = -Measure[e];
57 }
58 }
59 }
60
62 {
63 MNodalMass.Init((T)0., Np);
64 for (int32 e = 0; e < Mesh.Num(); e++)
65 {
66 T NodeMassContribution = Density * Measure[e] / (T)4.;
67 for (int32 i = 0; i < 4; i++)
68 {
70 }
71 }
72 }
73
74 PMatrix<T, 3, 3> DsInit(const int e, const ParticleType& InParticles) const
75 {
76 PMatrix<T, 3, 3> Result((T)0.);
77 for (int i = 0; i < 3; i++) {
78 for (int c = 0; c < 3; c++) {
79 Result.SetAt(c, i, InParticles.GetX(Mesh[e][i + 1])[c] - InParticles.GetX(Mesh[e][0])[c]);
80 }
81 }
82 return Result;
83 }
84
85
86 PMatrix<T, 3, 3> Ds(const int e, const ParticleType& InParticles) const
87 {
88 PMatrix<T, 3, 3> Result((T)0.);
89 for (int i = 0; i < 3; i++) {
90 for (int c = 0; c < 3; c++) {
91 Result.SetAt(c, i, InParticles.P(Mesh[e][i + 1])[c] - InParticles.P(Mesh[e][0])[c]);
92 }
93 }
94 return Result;
95 }
96
97 PMatrix<T, 3, 3> Ds(const int e, const TArray<TVector<T, 3>>& InParticles) const
98 {
99 PMatrix<T, 3, 3> Result((T)0.);
100 for (int i = 0; i < 3; i++) {
101 for (int c = 0; c < 3; c++) {
102 Result.SetAt(c, i, InParticles[Mesh[e][i + 1]][c] - InParticles[Mesh[e][0]][c]);
103 }
104 }
105 return Result;
106 }
107
108
109 PMatrix<T, 3, 3> F(const int e, const ParticleType& InParticles) const {
110 return ElementDmInv(e) * Ds(e, InParticles);
111 }
112
113 PMatrix<T, 3, 3> F(const int e, const TArray<TVector<T, 3>>& InParticles) const {
114 return ElementDmInv(e) * Ds(e, InParticles);
115 }
116
117 PMatrix<T, 3, 3> ElementDmInv(const int e) const
118 {
119 PMatrix<T, 3, 3> DmInv((T)0.);
120 for (int r = 0; r < 3; r++) {
121 for (int c = 0; c < 3; c++) {
122 DmInv.SetAt(r, c, DmInverse[(3 * 3) * e + 3 * r + c]);
123 }
124 }
125 return DmInv;
126 }
127
128 template <typename Func>
129 void AddInternalElasticForce(const ParticleType& InParticles, Func P, TArray<TVector<T, 3>>& Force, const TArray<TArray<TVector<int32, 2>>>* IncidentElements = nullptr, T Scale = (T)1., const TArray<T>* NodalMass = 0)
130 {
131 //compute the force per node from the mesh, DmInv and P
132 //incident elements optionally used for parallelism
133 //scale and nodal mass can be used to multiply/divide the force entries so that this can be used with time stepping
134
135 Force.Init(TVector<T, 3>((T)0.), Force.Num());
136
137 if (NodalMass)
138 ensureMsgf(NodalMass->Num() == InParticles.Size(), TEXT("NewtonEvolution::AddInternalElasticForce: mass and position sized inconistently."));
139
140 if (!IncidentElements) {
141 for (int32 e = 0; e < Mesh.Num() ; e++) {
143 PMatrix<T, 3, 3> Pe(0.f);
144 P(Fe, Pe, e);
145 PMatrix<T, 3, 3> g = -Measure[e] * (ElementDmInv(e).GetTransposed()) * Pe;
146 for (int32 ie = 0; ie < 3; ie++) {
147 T InverseMass = 1.f;
148 if (NodalMass)
149 InverseMass = 1.f / NodalMass -> operator[](Mesh[e][ie+1]);
150 for (int32 c = 0; c < 3; c++) {
151 Force[Mesh[e][ie+1]][c] += Scale * InverseMass * g.GetAt(c, ie);
152 }
153 }
154 T InverseMass = 1.f;
155 if (NodalMass)
156 InverseMass = 1.f / NodalMass->operator[](Mesh[e][0]);
157 for (int32 c = 0; c < 3; c++) {
158 for (int32 h = 0; h < 3; h++) {
159 Force[Mesh[e][0]][c] -= Scale * InverseMass * g.GetAt(c, h);
160 }
161 }
162 }
163 }
164 else {
165 ElementForces.Init(TVector<T, 3>(0.f), 4 * Mesh.Num());
166 PhysicsParallelFor(Mesh.Num(), [&](const int32 e)
167 {
168 PMatrix<T, 3, 3> Fe = F(e, InParticles);
169 PMatrix<T, 3, 3> Pe(0.f);
170 P(Fe, Pe, e);
171 PMatrix<T, 3, 3> g = -Measure[e] * (ElementDmInv(e).GetTransposed()) * Pe;
172 for (int32 ie = 0; ie < 3; ie++) {
173 for (int32 c = 0; c < 3; c++) {
174 ElementForces[4 * e + ie + 1][c] += g.GetAt(c, ie);
175 }
176 }
177 for (int32 c = 0; c < 3; c++) {
178 for (int32 h = 0; h < 3; h++) {
179 ElementForces[4 * e][c] -= g.GetAt(c, h);
180 }
181 }
182 });
183
184
185 if (!NodalMass) {
186 //#pragma omp parallel for
187 PhysicsParallelFor(IncidentElements->Num(), [&](const int32 i)
188 {
189 for (int32 e = 0; e < (*IncidentElements)[i].Num(); e++) {
190 for (int32 c = 0; c < 3; c++) {
191 Force[Mesh[(*IncidentElements)[i][e][0]][(*IncidentElements)[i][e][1]]][c] += Scale * ElementForces[4* (*IncidentElements)[i][e][0]+ (*IncidentElements)[i][e][1]][c];
192 }
193 }
194 });
195 }
196 else {
197 //#pragma omp parallel for
198 PhysicsParallelFor(IncidentElements->Num(), [&](const int32 i)
199 {
200 for (int32 e = 0; e < (*IncidentElements)[i].Num(); e++) {
201 for (int32 c = 0; c < 3; c++) {
202 Force[Mesh[(*IncidentElements)[i][e][0]][(*IncidentElements)[i][e][1]]][c] += Scale * ElementForces[4 * (*IncidentElements)[i][e][0] + (*IncidentElements)[i][e][1]][c] / (*NodalMass)[Mesh[(*IncidentElements)[i][e][0]][(*IncidentElements)[i][e][1]]];
203 }
204 }
205 });
206 }
207 }
208 }
209
210 template <typename Func>
212 {
213 //matrix free elastic potential energy Hessian based differentials
214 //compute the force differential per node from the mesh, DmInv and dP
215 //incident elements optionally used for parallelism
216
217 ndf.Init(TVector<T, 3>(0.f), ndf.Num());
218
219 if (!IncidentElements) {
220 for (int32 e = 0; e < Mesh.Num() ; e++) {
223 dP(Fe, dFe, dPe, e);
224 PMatrix<T, 3, 3> dg = Measure[e] * (ElementDmInv(e).GetTransposed()) * dPe;
225 for (int32 ie = 0; ie < 3; ie++) {
226 for (int32 c = 0; c < 3; c++) {
227 ndf[Mesh[e][ie+1]][c] += dg.GetAt(c, ie);
228 }
229 }
230 for (int32 c = 0; c < 3; c++) {
231 for (int32 h = 0; h < 3; h++) {
232 ndf[Mesh[e][0]][c] -= dg.GetAt(c, h);
233 }
234 }
235 }
236 }
237 else {
238 ElementForces.Init(TVector<T, 3>(0.f), Mesh.Num() * 4);
239 PhysicsParallelFor(Mesh.Num(), [&](const int32 e) {
240 //for (int32 e = 0; e < int32(Mesh.Num() ); ++e) {
241 PMatrix<T, 3, 3> Fe = F(e, InParticles), dFe = F(e, DeltaParticles);
242 PMatrix<T, 3, 3> dPe;
243 dP(Fe, dFe, dPe, e);
244 PMatrix<T, 3, 3> dg = Measure[e] * (ElementDmInv(e).GetTransposed()) * dPe;
245 for (int32 ie = 0; ie < 3; ie++)
246 {
247 for (int32 c = 0; c < 3; c++)
248 {
249 ElementForces[4 * e + ie + 1][c] += dg.GetAt(c, ie);
250 }
251 }
252 for (int32 c = 0; c < 3; c++) {
253 for (int32 h = 0; h < 3; h++) {
254 ElementForces[4 * e][c] -= dg.GetAt(c, h);
255 }
256 }
257 });
258
259 //#pragma omp parallel for
260 for (int32 i = 0; i < int32(IncidentElements->Num()); ++i) {
261 for (int32 e = 0; e < (*IncidentElements)[i].Num(); e++) {
262 for (int32 c = 0; c < 3; c++) {
263 ndf[Mesh[(*IncidentElements)[i][e][0]][(*IncidentElements)[i][e][1]]][c] += ElementForces[4 * (*IncidentElements)[i][e][0] + (*IncidentElements)[i][e][1]][c];
264 }
265 }
266 }
267 }
268 }
269
270
271
272};
273
274}
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
for(;InputBuffer< InputBufferEnd;BlockIndex++)
Definition binka_ue_decode_test.cpp:39
Definition Matrix.h:21
Definition NewtonElasticFEM.h:18
TArray< T > DmInverse
Definition NewtonElasticFEM.h:21
ElasticFEM(const ParticleType &InParticles, const TArray< TVector< int32, 4 > > &InMesh, const TArray< TArray< TVector< int32, 2 > > > &IncidentElementsIn)
Definition NewtonElasticFEM.h:28
TArray< TVector< T, 3 > > ElementForces
Definition NewtonElasticFEM.h:23
TArray< T > MNodalMass
Definition NewtonElasticFEM.h:25
TArray< T > Measure
Definition NewtonElasticFEM.h:22
PMatrix< T, 3, 3 > F(const int e, const TArray< TVector< T, 3 > > &InParticles) const
Definition NewtonElasticFEM.h:113
void AddNegativeInternalElasticForceDifferential(const ParticleType &InParticles, Func dP, const TArray< TVector< T, 3 > > &DeltaParticles, TArray< TVector< T, 3 > > &ndf, const TArray< TArray< TVector< int32, 2 > > > *IncidentElements=nullptr)
Definition NewtonElasticFEM.h:211
TArray< TArray< TVector< int32, 2 > > > MIncidentElements
Definition NewtonElasticFEM.h:26
const TArray< TVector< int32, 4 > > & Mesh
Definition NewtonElasticFEM.h:20
int32 Np
Definition NewtonElasticFEM.h:24
PMatrix< T, 3, 3 > Ds(const int e, const ParticleType &InParticles) const
Definition NewtonElasticFEM.h:86
PMatrix< T, 3, 3 > Ds(const int e, const TArray< TVector< T, 3 > > &InParticles) const
Definition NewtonElasticFEM.h:97
PMatrix< T, 3, 3 > ElementDmInv(const int e) const
Definition NewtonElasticFEM.h:117
PMatrix< T, 3, 3 > DsInit(const int e, const ParticleType &InParticles) const
Definition NewtonElasticFEM.h:74
void AddInternalElasticForce(const ParticleType &InParticles, Func P, TArray< TVector< T, 3 > > &Force, const TArray< TArray< TVector< int32, 2 > > > *IncidentElements=nullptr, T Scale=(T) 1., const TArray< T > *NodalMass=0)
Definition NewtonElasticFEM.h:129
PMatrix< T, 3, 3 > F(const int e, const ParticleType &InParticles) const
Definition NewtonElasticFEM.h:109
void ComputeNodalMass(const T Density)
Definition NewtonElasticFEM.h:61
Definition Vector.h:41
int32 Num() const
Definition Vector.h:150
Definition Array.h:670
void Init(const ElementType &Element, SizeType Number)
Definition Array.h:3043
Definition CollectionEmbeddedSpringConstraintFacade.cpp:6
void CHAOS_API PhysicsParallelFor(int32 InNum, TFunctionRef< void(int32)> InCallable, bool bForceSingleThreaded=false)
Definition Parallel.cpp:55