3 #include <Caribou/config.h>
4 #include <Caribou/Geometry/BaseRectangularHexahedron.h>
5 #include <Caribou/Geometry/Hexahedron.h>
6 #include <Caribou/Geometry/RectangularQuad.h>
9 namespace caribou::geometry {
11 template<UNSIGNED_INTEGER_TYPE Order = Linear>
16 static constexpr UNSIGNED_INTEGER_TYPE CanonicalDimension = 3;
17 static constexpr UNSIGNED_INTEGER_TYPE Dimension = 3;
18 static constexpr INTEGER_TYPE NumberOfNodesAtCompileTime = 8;
19 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = 8;
22 static constexpr INTEGER_TYPE NumberOfBoundaryElementsAtCompileTime = 6;
48 using LocalCoordinates =
typename Base::LocalCoordinates;
49 using WorldCoordinates =
typename Base::WorldCoordinates;
51 using GaussNode =
typename Base::GaussNode;
53 template <UNSIGNED_INTEGER_TYPE Dim>
54 using Vector =
typename Base::template Vector<Dim>;
56 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
57 using Matrix =
typename Base::template Matrix<Rows, Cols>;
60 static constexpr
auto CanonicalDimension = Base::CanonicalDimension;
61 static constexpr
auto Dimension = Base::Dimension;
62 static constexpr
auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
63 static constexpr
auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
72 this->p_center = hexa.
center();
73 this->p_H = Size((hexa.
node(1)-hexa.
node(0)).norm(), (hexa.
node(3)-hexa.
node(0)).norm(), (hexa.
node(4)-hexa.
node(0)).norm());
74 this->p_R = hexa.
frame({0, 0, 0});
78 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
83 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
93 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 2>, 12> indices = {{
114 inline auto get_L(
const LocalCoordinates & xi)
const {
115 const auto & u = xi[0];
116 const auto & v = xi[1];
117 const auto & w = xi[2];
119 Vector<NumberOfNodesAtCompileTime> m;
120 m << (1/8.) * (1 - u) * (1 - v) * (1 - w),
121 (1/8.) * (1 + u) * (1 - v) * (1 - w),
122 (1/8.) * (1 + u) * (1 + v) * (1 - w),
123 (1/8.) * (1 - u) * (1 + v) * (1 - w),
124 (1/8.) * (1 - u) * (1 - v) * (1 + w),
125 (1/8.) * (1 + u) * (1 - v) * (1 + w),
126 (1/8.) * (1 + u) * (1 + v) * (1 + w),
127 (1/8.) * (1 - u) * (1 + v) * (1 + w);
131 inline auto get_dL(
const LocalCoordinates & xi)
const {
132 const auto & u = xi[0];
133 const auto & v = xi[1];
134 const auto & w = xi[2];
136 Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> m;
138 m << -1/8. * (1 - v) * (1 - w), -1/8. * (1 - u) * (1 - w), -1/8. * (1 - u) * (1 - v),
139 +1/8. * (1 - v) * (1 - w), -1/8. * (1 + u) * (1 - w), -1/8. * (1 + u) * (1 - v),
140 +1/8. * (1 + v) * (1 - w), +1/8. * (1 + u) * (1 - w), -1/8. * (1 + u) * (1 + v),
141 -1/8. * (1 + v) * (1 - w), +1/8. * (1 - u) * (1 - w), -1/8. * (1 - u) * (1 + v),
142 -1/8. * (1 - v) * (1 + w), -1/8. * (1 - u) * (1 + w), +1/8. * (1 - u) * (1 - v),
143 +1/8. * (1 - v) * (1 + w), -1/8. * (1 + u) * (1 + w), +1/8. * (1 + u) * (1 - v),
144 +1/8. * (1 + v) * (1 + w), +1/8. * (1 + u) * (1 + w), +1/8. * (1 + u) * (1 + v),
145 -1/8. * (1 + v) * (1 + w), +1/8. * (1 - u) * (1 + w), +1/8. * (1 - u) * (1 + v);
149 inline auto get_node(
const UNSIGNED_INTEGER_TYPE & index)
const -> WorldCoordinates {
150 caribou_assert(index < NumberOfNodesAtCompileTime and
"Trying to get a node from an invalid node index.");
151 return this->world_coordinates(LocalCoordinates(canonical_nodes[index][0], canonical_nodes[index][1], canonical_nodes[index][2]));
154 inline auto get_nodes()
const {
155 Matrix<NumberOfNodesAtCompileTime, Dimension> nodes;
156 for (UNSIGNED_INTEGER_TYPE node_id = 0; node_id < NumberOfNodesAtCompileTime; ++node_id) {
157 nodes.row(node_id) = get_node(node_id);
162 inline auto get_gauss_nodes() const -> const auto & {
163 using Weight = FLOATING_POINT_TYPE;
164 static const std::vector<GaussNode> gauss_nodes {
165 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3), -1/sqrt(3)), Weight(1)},
166 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3), -1/sqrt(3)), Weight(1)},
167 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3), -1/sqrt(3)), Weight(1)},
168 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3), -1/sqrt(3)), Weight(1)},
169 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3), +1/sqrt(3)), Weight(1)},
170 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3), +1/sqrt(3)), Weight(1)},
171 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3), +1/sqrt(3)), Weight(1)},
172 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3), +1/sqrt(3)), Weight(1)}
177 inline auto get_boundary_elements_nodes() const -> const auto & {
178 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 4>, 6> indices = {{
193 static constexpr UNSIGNED_INTEGER_TYPE CanonicalDimension = 3;
194 static constexpr UNSIGNED_INTEGER_TYPE Dimension = 3;
195 static constexpr INTEGER_TYPE NumberOfNodesAtCompileTime = 20;
196 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = 4;
199 static constexpr INTEGER_TYPE NumberOfBoundaryElementsAtCompileTime = 6;
227 using LocalCoordinates =
typename Base::LocalCoordinates;
228 using WorldCoordinates =
typename Base::WorldCoordinates;
230 using GaussNode =
typename Base::GaussNode;
232 template <UNSIGNED_INTEGER_TYPE Dim>
233 using Vector =
typename Base::template Vector<Dim>;
235 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
236 using Matrix =
typename Base::template Matrix<Rows, Cols>;
239 static constexpr
auto CanonicalDimension = Base::CanonicalDimension;
240 static constexpr
auto Dimension = Base::Dimension;
241 static constexpr
auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
242 static constexpr
auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
250 template<UNSIGNED_INTEGER_TYPE Order>
252 this->p_center = hexa.center();
253 this->p_H = Size((hexa.node(1)-hexa.node(0)).norm(), (hexa.node(3)-hexa.node(0)).norm(), (hexa.node(4)-hexa.node(0)).norm());
254 this->p_R = hexa.frame({0, 0, 0});
258 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
263 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
268 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == 8)>
273 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == 8)>
283 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 3>, 12> indices = {{
304 inline auto get_L(
const LocalCoordinates & xi)
const {
305 const auto & u = xi[0];
306 const auto & v = xi[1];
307 const auto & w = xi[2];
309 Vector<NumberOfNodesAtCompileTime> m;
310 m[ 8] = 1/4.*(1 - u*u)*(1 - v)*(1 - w);
311 m[ 9] = 1/4.*(1 - v*v)*(1 + u)*(1 - w);
312 m[10] = 1/4.*(1 - u*u)*(1 + v)*(1 - w);
313 m[11] = 1/4.*(1 - v*v)*(1 - u)*(1 - w);
314 m[12] = 1/4.*(1 - u*u)*(1 - v)*(1 + w);
315 m[13] = 1/4.*(1 - v*v)*(1 + u)*(1 + w);
316 m[14] = 1/4.*(1 - u*u)*(1 + v)*(1 + w);
317 m[15] = 1/4.*(1 - v*v)*(1 - u)*(1 + w);
318 m[16] = 1/4.*(1 - w*w)*(1 - u)*(1 - v);
319 m[17] = 1/4.*(1 - w*w)*(1 + u)*(1 - v);
320 m[18] = 1/4.*(1 - w*w)*(1 + u)*(1 + v);
321 m[19] = 1/4.*(1 - w*w)*(1 - u)*(1 + v);
323 m[0] = 1/8.*(1 - u)*(1 - v)*(1 - w) - 1/2.*(m[ 8] + m[11] + m[16]);
324 m[1] = 1/8.*(1 + u)*(1 - v)*(1 - w) - 1/2.*(m[ 8] + m[ 9] + m[17]);
325 m[2] = 1/8.*(1 + u)*(1 + v)*(1 - w) - 1/2.*(m[ 9] + m[10] + m[18]);
326 m[3] = 1/8.*(1 - u)*(1 + v)*(1 - w) - 1/2.*(m[10] + m[11] + m[19]);
327 m[4] = 1/8.*(1 - u)*(1 - v)*(1 + w) - 1/2.*(m[12] + m[15] + m[16]);
328 m[5] = 1/8.*(1 + u)*(1 - v)*(1 + w) - 1/2.*(m[12] + m[13] + m[17]);
329 m[6] = 1/8.*(1 + u)*(1 + v)*(1 + w) - 1/2.*(m[13] + m[14] + m[18]);
330 m[7] = 1/8.*(1 - u)*(1 + v)*(1 + w) - 1/2.*(m[14] + m[15] + m[19]);
334 inline auto get_dL(
const LocalCoordinates & xi)
const {
335 using ShapeDerivative = Vector<3>;
336 const auto & u = xi[0];
337 const auto & v = xi[1];
338 const auto & w = xi[2];
340 Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> m;
343 m.row( 8) = ShapeDerivative({-1/2.*u*(1 - v)*(1 - w), -1/4.*(1 - u*u)*(1 - w), -1/4.*(1 - u*u)*(1 - v)});
344 m.row( 9) = ShapeDerivative({ 1/4.*(1 - v*v)*(1 - w), -1/2.*v*(1 + u)*(1 - w), -1/4.*(1 - v*v)*(1 + u)});
345 m.row(10) = ShapeDerivative({-1/2.*u*(1 + v)*(1 - w), 1/4.*(1 - u*u)*(1 - w), -1/4.*(1 - u*u)*(1 + v)});
346 m.row(11) = ShapeDerivative({-1/4.*(1 - v*v)*(1 - w), -1/2.*v*(1 - u)*(1 - w), -1/4.*(1 - v*v)*(1 - u)});
347 m.row(12) = ShapeDerivative({-1/2.*u*(1 - v)*(1 + w), -1/4.*(1 - u*u)*(1 + w), 1/4.*(1 - u*u)*(1 - v)});
348 m.row(13) = ShapeDerivative({ 1/4.*(1 - v*v)*(1 + w), -1/2.*v*(1 + u)*(1 + w), 1/4.*(1 - v*v)*(1 + u)});
349 m.row(14) = ShapeDerivative({-1/2.*u*(1 + v)*(1 + w), 1/4.*(1 - u*u)*(1 + w), 1/4.*(1 - u*u)*(1 + v)});
350 m.row(15) = ShapeDerivative({-1/4.*(1 - v*v)*(1 + w), -1/2.*v*(1 - u)*(1 + w), 1/4.*(1 - v*v)*(1 - u)});
351 m.row(16) = ShapeDerivative({-1/4.*(1 - w*w)*(1 - v), -1/4.*(1 - w*w)*(1 - u), -1/2.*w*(1 - u)*(1 - v)});
352 m.row(17) = ShapeDerivative({ 1/4.*(1 - w*w)*(1 - v), -1/4.*(1 - w*w)*(1 + u), -1/2.*w*(1 + u)*(1 - v)});
353 m.row(18) = ShapeDerivative({ 1/4.*(1 - w*w)*(1 + v), 1/4.*(1 - w*w)*(1 + u), -1/2.*w*(1 + u)*(1 + v)});
354 m.row(19) = ShapeDerivative({-1/4.*(1 - w*w)*(1 + v), 1/4.*(1 - w*w)*(1 - u), -1/2.*w*(1 - u)*(1 + v)});
356 const auto du = m.col(0);
357 const auto dv = m.col(1);
358 const auto dw = m.col(2);
360 m.row(0) = ShapeDerivative({-1/8.*(1 - v)*(1 - w) - 1/2.*(du[8 ] + du[11] + du[16]), -1/8.*(1 - u)*(1 - w) - 1/2.*(dv[ 8] + dv[11] + dv[16]), -1/8.*(1 - u)*(1 - v) - 1/2.*(dw[ 8] + dw[11] + dw[16])});
361 m.row(1) = ShapeDerivative({ 1/8.*(1 - v)*(1 - w) - 1/2.*(du[8 ] + du[ 9] + du[17]), -1/8.*(1 + u)*(1 - w) - 1/2.*(dv[ 8] + dv[ 9] + dv[17]), -1/8.*(1 + u)*(1 - v) - 1/2.*(dw[ 8] + dw[ 9] + dw[17])});
362 m.row(2) = ShapeDerivative({ 1/8.*(1 + v)*(1 - w) - 1/2.*(du[9 ] + du[10] + du[18]), 1/8.*(1 + u)*(1 - w) - 1/2.*(dv[ 9] + dv[10] + dv[18]), -1/8.*(1 + u)*(1 + v) - 1/2.*(dw[ 9] + dw[10] + dw[18])});
363 m.row(3) = ShapeDerivative({-1/8.*(1 + v)*(1 - w) - 1/2.*(du[10] + du[11] + du[19]), 1/8.*(1 - u)*(1 - w) - 1/2.*(dv[10] + dv[11] + dv[19]), -1/8.*(1 - u)*(1 + v) - 1/2.*(dw[10] + dw[11] + dw[19])});
364 m.row(4) = ShapeDerivative({-1/8.*(1 - v)*(1 + w) - 1/2.*(du[12] + du[15] + du[16]), -1/8.*(1 - u)*(1 + w) - 1/2.*(dv[12] + dv[15] + dv[16]), 1/8.*(1 - u)*(1 - v) - 1/2.*(dw[12] + dw[15] + dw[16])});
365 m.row(5) = ShapeDerivative({ 1/8.*(1 - v)*(1 + w) - 1/2.*(du[12] + du[13] + du[17]), -1/8.*(1 + u)*(1 + w) - 1/2.*(dv[12] + dv[13] + dv[17]), 1/8.*(1 + u)*(1 - v) - 1/2.*(dw[12] + dw[13] + dw[17])});
366 m.row(6) = ShapeDerivative({ 1/8.*(1 + v)*(1 + w) - 1/2.*(du[13] + du[14] + du[18]), 1/8.*(1 + u)*(1 + w) - 1/2.*(dv[13] + dv[14] + dv[18]), 1/8.*(1 + u)*(1 + v) - 1/2.*(dw[13] + dw[14] + dw[18])});
367 m.row(7) = ShapeDerivative({-1/8.*(1 + v)*(1 + w) - 1/2.*(du[14] + du[15] + du[19]), 1/8.*(1 - u)*(1 + w) - 1/2.*(dv[14] + dv[15] + dv[19]), 1/8.*(1 - u)*(1 + v) - 1/2.*(dw[14] + dw[15] + dw[19])});
373 inline auto get_node(
const UNSIGNED_INTEGER_TYPE & index)
const -> WorldCoordinates {
374 caribou_assert(index < NumberOfNodesAtCompileTime and
"Trying to get a node from an invalid node index.");
375 return this->world_coordinates(LocalCoordinates(canonical_nodes[index][0], canonical_nodes[index][1], canonical_nodes[index][2]));
378 inline auto get_nodes()
const {
379 Matrix<NumberOfNodesAtCompileTime, Dimension> nodes;
380 for (UNSIGNED_INTEGER_TYPE node_id = 0; node_id < NumberOfNodesAtCompileTime; ++node_id) {
381 nodes.row(node_id) = get_node(node_id);
386 inline auto get_gauss_nodes() const -> const auto & {
387 using Weight = FLOATING_POINT_TYPE;
388 static const std::vector<GaussNode> gauss_nodes {
389 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3), -1/sqrt(3)), Weight(1)},
390 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3), -1/sqrt(3)), Weight(1)},
391 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3), -1/sqrt(3)), Weight(1)},
392 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3), -1/sqrt(3)), Weight(1)},
393 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3), +1/sqrt(3)), Weight(1)},
394 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3), +1/sqrt(3)), Weight(1)},
395 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3), +1/sqrt(3)), Weight(1)},
396 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3), +1/sqrt(3)), Weight(1)}
401 inline auto get_boundary_elements_nodes() const -> const auto & {
402 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 8>, 6> indices = {{
403 {0, 3, 2, 1, 9, 13, 11, 8},
404 {0, 4, 7, 3, 10, 17, 15, 9},
405 {1, 2, 6, 5, 11, 14, 18, 12},
406 {0, 1, 5, 4, 8, 12, 16, 10},
407 {2, 3, 7, 6, 13, 15, 19, 14},
408 {4, 5, 6, 7, 16, 18, 19, 17}