PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
Quadrilateral.h
Go to the documentation of this file.
1
11#ifndef PBAT_FEM_QUADRILATERAL_H
12#define PBAT_FEM_QUADRILATERAL_H
13
14#include "pbat/Aliases.h"
16#include "QuadratureRules.h"
17
18#include <array>
19
20namespace pbat {
21namespace fem {
22
23namespace detail {
24
25template <int Order>
26struct Quadrilateral;
27
28} // namespace detail
29
37template <int Order>
38using Quadrilateral = typename detail::Quadrilateral<Order>;
39
40namespace detail {
41
42template <>
43struct Quadrilateral<1>
44{
45 using AffineBaseType = Quadrilateral<1>;
46
47 static int constexpr kOrder = 1;
48 static int constexpr kDims = 2;
49 static int constexpr kNodes = 4;
50 static std::array<int, kNodes * kDims> constexpr Coordinates =
51 {0,0,1,0,0,1,1,1};
52 static std::array<int, AffineBaseType::kNodes> constexpr Vertices = {0,1,2,3};
53 static bool constexpr bHasConstantJacobian = false;
54
55 template <int PolynomialOrder, common::CFloatingPoint TScalar = Scalar>
57
58 template <class TDerived, class TScalar = typename TDerived::Scalar>
59 [[maybe_unused]] static Eigen::Vector<TScalar, kNodes> N([[maybe_unused]] Eigen::DenseBase<TDerived> const& X_)
60 {
61#include "pbat/warning/Push.h"
62#include "pbat/warning/SignConversion.h"
63 using namespace pbat::math;
64 Eigen::Vector<TScalar, kNodes> Nm;
65 auto const X = X_.reshaped();
66 auto const a0 = X[0] - 1;
67 auto const a1 = X[1] - 1;
68 Nm[0] = a0*a1;
69 Nm[1] = -a1*X[0];
70 Nm[2] = -a0*X[1];
71 Nm[3] = X[0]*X[1];
72 return Nm;
73#include "pbat/warning/Pop.h"
74 }
75
76 template <class TDerived, class TScalar = typename TDerived::Scalar>
77 [[maybe_unused]] static Eigen::Matrix<TScalar, kNodes, kDims> GradN([[maybe_unused]] Eigen::DenseBase<TDerived> const& X_)
78 {
79#include "pbat/warning/Push.h"
80#include "pbat/warning/SignConversion.h"
81 Eigen::Matrix<TScalar, kNodes, kDims> GNm;
82 TScalar* GNp = GNm.data();
83 [[maybe_unused]] auto const X = X_.reshaped();
84 auto const a0 = X[1] - 1;
85 auto const a1 = X[0] - 1;
86 GNp[0] = a0;
87 GNp[1] = -a0;
88 GNp[2] = -X[1];
89 GNp[3] = X[1];
90 GNp[4] = a1;
91 GNp[5] = -X[0];
92 GNp[6] = -a1;
93 GNp[7] = X[0];
94 return GNm;
95#include "pbat/warning/Pop.h"
96 }
97};
98
99template <>
100struct Quadrilateral<2>
101{
102 using AffineBaseType = Quadrilateral<1>;
103
104 static int constexpr kOrder = 2;
105 static int constexpr kDims = 2;
106 static int constexpr kNodes = 9;
107 static std::array<int, kNodes * kDims> constexpr Coordinates =
108 {0,0,1,0,2,0,0,1,1,1,2,1,0,2,1,2,2,2};
109 static std::array<int, AffineBaseType::kNodes> constexpr Vertices = {0,2,6,8};
110 static bool constexpr bHasConstantJacobian = false;
111
112 template <int PolynomialOrder, common::CFloatingPoint TScalar = Scalar>
114
115 template <class TDerived, class TScalar = typename TDerived::Scalar>
116 [[maybe_unused]] static Eigen::Vector<TScalar, kNodes> N([[maybe_unused]] Eigen::DenseBase<TDerived> const& X_)
117 {
118#include "pbat/warning/Push.h"
119#include "pbat/warning/SignConversion.h"
120 using namespace pbat::math;
121 Eigen::Vector<TScalar, kNodes> Nm;
122 auto const X = X_.reshaped();
123 auto const a0 = 2*X[0] - 1;
124 auto const a1 = 2*X[1] - 1;
125 auto const a2 = a0*a1;
126 auto const a3 = X[0] - 1;
127 auto const a4 = X[1] - 1;
128 auto const a5 = a3*a4;
129 auto const a6 = 4*a5;
130 auto const a7 = a1*X[0];
131 auto const a8 = a2*X[0];
132 auto const a9 = a0*X[1];
133 auto const a10 = a3*X[1];
134 Nm[0] = a2*a5;
135 Nm[1] = -a6*a7;
136 Nm[2] = a4*a8;
137 Nm[3] = -a6*a9;
138 Nm[4] = 16*a5*X[0]*X[1];
139 Nm[5] = -4*a4*a9*X[0];
140 Nm[6] = a10*a2;
141 Nm[7] = -4*a10*a7;
142 Nm[8] = a8*X[1];
143 return Nm;
144#include "pbat/warning/Pop.h"
145 }
146
147 template <class TDerived, class TScalar = typename TDerived::Scalar>
148 [[maybe_unused]] static Eigen::Matrix<TScalar, kNodes, kDims> GradN([[maybe_unused]] Eigen::DenseBase<TDerived> const& X_)
149 {
150#include "pbat/warning/Push.h"
151#include "pbat/warning/SignConversion.h"
152 Eigen::Matrix<TScalar, kNodes, kDims> GNm;
153 TScalar* GNp = GNm.data();
154 [[maybe_unused]] auto const X = X_.reshaped();
155 auto const a0 = 4*X[1] - 2;
156 auto const a1 = X[1] - 1;
157 auto const a2 = X[0] - 1;
158 auto const a3 = a1*a2;
159 auto const a4 = (2*X[0] - 1)*(2*X[1] - 1);
160 auto const a5 = a1*a4;
161 auto const a6 = 8*X[1];
162 auto const a7 = 4 - a6;
163 auto const a8 = a1*X[0];
164 auto const a9 = 8*X[0];
165 auto const a10 = 4 - a9;
166 auto const a11 = a1*X[1];
167 auto const a12 = a10*a11;
168 auto const a13 = 8 - a9;
169 auto const a14 = X[0]*X[1];
170 auto const a15 = 16*X[0] - 16;
171 auto const a16 = a2*X[1];
172 auto const a17 = a4*X[1];
173 auto const a18 = 4*X[0] - 2;
174 auto const a19 = a2*a4;
175 auto const a20 = a2*a7*X[0];
176 auto const a21 = a4*X[0];
177 GNp[0] = a0*a3 + a5;
178 GNp[1] = a3*a7 + a7*a8;
179 GNp[2] = a0*a8 + a5;
180 GNp[3] = a11*a13 + a12;
181 GNp[4] = a11*a15 + a14*(16*X[1] - 16);
182 GNp[5] = a12 + a14*(8 - a6);
183 GNp[6] = a0*a16 + a17;
184 GNp[7] = a14*a7 + a16*a7;
185 GNp[8] = a0*a14 + a17;
186 GNp[9] = a18*a3 + a19;
187 GNp[10] = a13*a8 + a20;
188 GNp[11] = a18*a8 + a21;
189 GNp[12] = a10*a16 + a10*a3;
190 GNp[13] = a14*a15 + a15*a8;
191 GNp[14] = a10*a14 + a10*a8;
192 GNp[15] = a16*a18 + a19;
193 GNp[16] = a13*a14 + a20;
194 GNp[17] = a14*a18 + a21;
195 return GNm;
196#include "pbat/warning/Pop.h"
197 }
198};
199
200template <>
201struct Quadrilateral<3>
202{
203 using AffineBaseType = Quadrilateral<1>;
204
205 static int constexpr kOrder = 3;
206 static int constexpr kDims = 2;
207 static int constexpr kNodes = 16;
208 static std::array<int, kNodes * kDims> constexpr Coordinates =
209 {0,0,1,0,2,0,3,0,0,1,1,1,2,1,3,1,0,2,1,2,2,2,3,2,0,3,1,3,2,3,3,3};
210 static std::array<int, AffineBaseType::kNodes> constexpr Vertices = {0,3,12,15};
211 static bool constexpr bHasConstantJacobian = false;
212
213 template <int PolynomialOrder, common::CFloatingPoint TScalar = Scalar>
215
216 template <class TDerived, class TScalar = typename TDerived::Scalar>
217 [[maybe_unused]] static Eigen::Vector<TScalar, kNodes> N([[maybe_unused]] Eigen::DenseBase<TDerived> const& X_)
218 {
219#include "pbat/warning/Push.h"
220#include "pbat/warning/SignConversion.h"
221 using namespace pbat::math;
222 Eigen::Vector<TScalar, kNodes> Nm;
223 auto const X = X_.reshaped();
224 auto const a0 = X[0] - 1;
225 auto const a1 = X[1] - 1;
226 auto const a2 = 3*X[0];
227 auto const a3 = a2 - 2;
228 auto const a4 = 3*X[1];
229 auto const a5 = a4 - 2;
230 auto const a6 = a0*a1*a3*a5;
231 auto const a7 = a2 - 1;
232 auto const a8 = a4 - 1;
233 auto const a9 = a7*a8;
234 auto const a10 = (1.0/4.0)*a9;
235 auto const a11 = (9.0/4.0)*X[0];
236 auto const a12 = a11*a8;
237 auto const a13 = a1*a5;
238 auto const a14 = a0*a13;
239 auto const a15 = a11*a9;
240 auto const a16 = a13*a3;
241 auto const a17 = a10*X[0];
242 auto const a18 = a6*X[1];
243 auto const a19 = (81.0/4.0)*X[0];
244 auto const a20 = a7*X[1];
245 auto const a21 = a0*X[1];
246 auto const a22 = a1*a3;
247 auto const a23 = a21*a22;
248 auto const a24 = a21*a5;
249 auto const a25 = a24*a3;
250 Nm[0] = a10*a6;
251 Nm[1] = -a12*a6;
252 Nm[2] = a14*a15;
253 Nm[3] = -a16*a17;
254 Nm[4] = -9.0/4.0*a18*a7;
255 Nm[5] = a18*a19;
256 Nm[6] = -a14*a19*a20;
257 Nm[7] = a11*a16*a20;
258 Nm[8] = (9.0/4.0)*a23*a9;
259 Nm[9] = -a19*a23*a8;
260 Nm[10] = a1*a19*a21*a9;
261 Nm[11] = -a15*a22*X[1];
262 Nm[12] = -a10*a25;
263 Nm[13] = a12*a25;
264 Nm[14] = -a15*a24;
265 Nm[15] = a17*a3*a5*X[1];
266 return Nm;
267#include "pbat/warning/Pop.h"
268 }
269
270 template <class TDerived, class TScalar = typename TDerived::Scalar>
271 [[maybe_unused]] static Eigen::Matrix<TScalar, kNodes, kDims> GradN([[maybe_unused]] Eigen::DenseBase<TDerived> const& X_)
272 {
273#include "pbat/warning/Push.h"
274#include "pbat/warning/SignConversion.h"
275 Eigen::Matrix<TScalar, kNodes, kDims> GNm;
276 TScalar* GNp = GNm.data();
277 [[maybe_unused]] auto const X = X_.reshaped();
278 auto const a0 = (9.0/4.0)*X[1] - 3.0/4.0;
279 auto const a1 = X[0] - 1;
280 auto const a2 = 3*X[0];
281 auto const a3 = a2 - 2;
282 auto const a4 = X[1] - 1;
283 auto const a5 = 3*X[1];
284 auto const a6 = a5 - 2;
285 auto const a7 = a4*a6;
286 auto const a8 = a3*a7;
287 auto const a9 = a1*a8;
288 auto const a10 = a1*a7;
289 auto const a11 = a5 - 1;
290 auto const a12 = (3.0/4.0)*X[0] - 1.0/4.0;
291 auto const a13 = a11*a12;
292 auto const a14 = a11*a3;
293 auto const a15 = a12*a14;
294 auto const a16 = (27.0/4.0)*X[1];
295 auto const a17 = a16 - 9.0/4.0;
296 auto const a18 = -a17;
297 auto const a19 = a18*a2;
298 auto const a20 = a8*X[0];
299 auto const a21 = (81.0/4.0)*X[1];
300 auto const a22 = a21 - 27.0/4.0;
301 auto const a23 = a10*X[0];
302 auto const a24 = (27.0/4.0)*X[0];
303 auto const a25 = a24 - 9.0/4.0;
304 auto const a26 = a11*a25;
305 auto const a27 = a7*X[0];
306 auto const a28 = -a0;
307 auto const a29 = -a12;
308 auto const a30 = a11*a29;
309 auto const a31 = a14*a29;
310 auto const a32 = -a25;
311 auto const a33 = a32*a5;
312 auto const a34 = a8*X[1];
313 auto const a35 = a24 - 27.0/4.0;
314 auto const a36 = -a35;
315 auto const a37 = (81.0/4.0)*X[0];
316 auto const a38 = a37 - 81.0/4.0;
317 auto const a39 = a27*a5;
318 auto const a40 = a3*X[1];
319 auto const a41 = a6*X[0];
320 auto const a42 = a40*a41;
321 auto const a43 = (243.0/4.0)*X[0];
322 auto const a44 = a43 - 81.0/4.0;
323 auto const a45 = -a44;
324 auto const a46 = a45*X[1];
325 auto const a47 = 243.0/4.0 - a43;
326 auto const a48 = a4*a40;
327 auto const a49 = a1*a48;
328 auto const a50 = a1*a4;
329 auto const a51 = a5*a50;
330 auto const a52 = a4*X[1];
331 auto const a53 = a14*a52;
332 auto const a54 = 81.0/4.0 - 243.0/4.0*X[1];
333 auto const a55 = a54*X[0];
334 auto const a56 = a48*X[0];
335 auto const a57 = a1*a52;
336 auto const a58 = a57*X[0];
337 auto const a59 = a11*a44;
338 auto const a60 = a59*X[0];
339 auto const a61 = -a22;
340 auto const a62 = a11*a32;
341 auto const a63 = a4*X[0];
342 auto const a64 = a5*a63;
343 auto const a65 = a1*a6;
344 auto const a66 = a40*a65;
345 auto const a67 = a6*X[1];
346 auto const a68 = a1*a41;
347 auto const a69 = a17*a5;
348 auto const a70 = a41*X[1];
349 auto const a71 = a1*a70;
350 auto const a72 = a1*a62;
351 auto const a73 = (9.0/4.0)*X[0] - 3.0/4.0;
352 auto const a74 = a3*a50;
353 auto const a75 = a3*a68;
354 auto const a76 = a37 - 27.0/4.0;
355 auto const a77 = -a73;
356 auto const a78 = a3*a64;
357 auto const a79 = a14*a25;
358 auto const a80 = a1*X[1];
359 auto const a81 = -a76;
360 auto const a82 = a14*a32;
361 auto const a83 = a5*X[0];
362 GNp[0] = a0*a9 + 3*a10*a13 + a15*a7;
363 GNp[1] = a10*a19 + a18*a20 + a18*a9;
364 GNp[2] = a10*a26 + a22*a23 + a26*a27;
365 GNp[3] = a2*a30*a7 + a20*a28 + a31*a7;
366 GNp[4] = a10*a33 + a32*a34 + a34*a36;
367 GNp[5] = a34*a38 + a38*a39 + a42*(a21 - 81.0/4.0);
368 GNp[6] = a10*a46 + a27*a46 + a27*a47*X[1];
369 GNp[7] = a25*a34 + a25*a39 + a42*(a16 - 27.0/4.0);
370 GNp[8] = a22*a49 + a25*a53 + a26*a51;
371 GNp[9] = a49*a54 + a51*a55 + a54*a56;
372 GNp[10] = a52*a60 + a57*a59 + a58*((729.0/4.0)*X[1] - 243.0/4.0);
373 GNp[11] = a32*a53 + a56*a61 + a62*a64;
374 GNp[12] = a28*a66 + a30*a5*a65 + a31*a67;
375 GNp[13] = a17*a42 + a17*a66 + a68*a69;
376 GNp[14] = a61*a71 + a62*a70 + a67*a72;
377 GNp[15] = a0*a42 + a13*a41*a5 + a15*a67;
378 GNp[16] = 3*a15*a50 + a15*a65 + a73*a9;
379 GNp[17] = a18*a75 + a19*a74 + a20*a36;
380 GNp[18] = a2*a26*a50 + a23*a76 + a26*a68;
381 GNp[19] = a2*a31*a4 + a20*a77 + a31*a41;
382 GNp[20] = a32*a66 + a32*a9 + a33*a74;
383 GNp[21] = a20*a38 + a38*a42 + a38*a78;
384 GNp[22] = a23*a45 + a45*a51*X[0] + a46*a68;
385 GNp[23] = a20*a25 + a25*a42 + a25*a78;
386 GNp[24] = a49*a76 + a50*a79 + a79*a80;
387 GNp[25] = a1*a40*a55 + a47*a56 + a55*a74;
388 GNp[26] = a50*a60 + a58*((729.0/4.0)*X[0] - 243.0/4.0) + a60*a80;
389 GNp[27] = a56*a81 + a63*a82 + a82*X[0]*X[1];
390 GNp[28] = a1*a31*a5 + a31*a65 + a66*a77;
391 GNp[29] = a1*a3*a69*X[0] + a17*a75 + a35*a42;
392 GNp[30] = a41*a72 + a71*a81 + a72*a83;
393 GNp[31] = a15*a41 + a15*a83 + a42*a73;
394 return GNm;
395#include "pbat/warning/Pop.h"
396 }
397};
398
399} // namespace detail
400} // namespace fem
401} // namespace pbat
402
403#endif // PBAT_FEM_QUADRILATERAL_H
Concepts for common types.
Finite Element Method (FEM)
Definition Concepts.h:19
typename detail::Quadrilateral< Order > Quadrilateral
Quadrilateral finite element.
Definition Quadrilateral.h:38
Math related functionality.
Definition Concepts.h:19
typename detail::GaussLegendreQuadrature< Dims, Order, TScalar > GaussLegendreQuadrature
Shifted Gauss-Legendre quadrature scheme over the unit box in dimensions .
Definition GaussQuadrature.h:66
The main namespace of the library.
Definition Aliases.h:15