3 #include <Caribou/config.h>
4 #include <Caribou/Geometry/BaseRectangularQuad.h>
5 #include <Caribou/Geometry/Quad.h>
6 #include <Caribou/Geometry/Segment.h>
10 namespace caribou::geometry {
12 template<UNSIGNED_INTEGER_TYPE Dimension, UNSIGNED_INTEGER_TYPE Order = Linear>
16 template<UNSIGNED_INTEGER_TYPE _Dimension>
18 static constexpr UNSIGNED_INTEGER_TYPE CanonicalDimension = 2;
19 static constexpr UNSIGNED_INTEGER_TYPE Dimension = _Dimension;
20 static constexpr INTEGER_TYPE NumberOfNodesAtCompileTime = 4;
21 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = 4;
24 static constexpr INTEGER_TYPE NumberOfBoundaryElementsAtCompileTime = 4;
45 template<UNSIGNED_INTEGER_TYPE _Dimension>
49 using LocalCoordinates =
typename Base::LocalCoordinates;
50 using WorldCoordinates =
typename Base::WorldCoordinates;
52 using GaussNode =
typename Base::GaussNode;
54 template <UNSIGNED_INTEGER_TYPE Dim>
55 using Vector =
typename Base::template Vector<Dim>;
57 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
58 using Matrix =
typename Base::template Matrix<Rows, Cols>;
61 static constexpr
auto CanonicalDimension = Base::CanonicalDimension;
62 static constexpr
auto Dimension = Base::Dimension;
63 static constexpr
auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
64 static constexpr
auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
68 using Size =
typename Base::Size;
69 using Rotation =
typename Base::Rotation;
76 this->p_center = quad.center();
77 this->p_H = Size((quad.node(1)-quad.node(0)).norm(), (quad.node(3)-quad.node(0)).norm());
78 this->p_R = quad.frame({0, 0});
82 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
87 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
95 inline auto get_L(
const LocalCoordinates & xi)
const -> Vector<NumberOfNodesAtCompileTime> {
96 const auto & u = xi[0];
97 const auto & v = xi[1];
99 static_cast<FLOATING_POINT_TYPE
>(1 / 4. * (1 - u) * (1 - v)),
100 static_cast<FLOATING_POINT_TYPE
>(1 / 4. * (1 + u) * (1 - v)),
101 static_cast<FLOATING_POINT_TYPE
>(1 / 4. * (1 + u) * (1 + v)),
102 static_cast<FLOATING_POINT_TYPE
>(1 / 4. * (1 - u) * (1 + v))
106 inline auto get_dL(
const LocalCoordinates & xi)
const {
107 const auto & u = xi[0];
108 const auto & v = xi[1];
110 Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> m;
112 m << -1 / 4. * (1 - v), -1 / 4. * (1 - u),
113 +1 / 4. * (1 - v), -1 / 4. * (1 + u),
114 +1 / 4. * (1 + v), +1 / 4. * (1 + u),
115 -1 / 4. * (1 + v), +1 / 4. * (1 - u);
119 inline auto get_node(
const UNSIGNED_INTEGER_TYPE & index)
const -> WorldCoordinates {
120 caribou_assert(index < NumberOfNodesAtCompileTime and
"Trying to get a node from an invalid node index.");
121 return this->T(LocalCoordinates(canonical_nodes[index][0], canonical_nodes[index][1]));
124 inline auto get_nodes()
const {
125 Matrix<NumberOfNodesAtCompileTime, Dimension> nodes;
126 for (Eigen::Index node_id = 0; node_id < NumberOfNodesAtCompileTime; ++node_id) {
127 nodes.row(node_id) = get_node(node_id);
132 inline auto get_gauss_nodes() const -> const auto & {
133 using Weight = FLOATING_POINT_TYPE;
134 static const std::vector<GaussNode> gauss_nodes {
135 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3)), Weight(1)},
136 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3)), Weight(1)},
137 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3)), Weight(1)},
138 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3)), Weight(1)}
143 inline auto get_boundary_elements_nodes() const -> const auto & {
144 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 2>, 4> indices = {{
155 template<UNSIGNED_INTEGER_TYPE _Dimension>
157 static constexpr UNSIGNED_INTEGER_TYPE CanonicalDimension = 2;
158 static constexpr UNSIGNED_INTEGER_TYPE Dimension = _Dimension;
159 static constexpr INTEGER_TYPE NumberOfNodesAtCompileTime = 8;
160 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = 8;
163 static constexpr INTEGER_TYPE NumberOfBoundaryElementsAtCompileTime = 4;
184 template<UNSIGNED_INTEGER_TYPE _Dimension>
188 using LocalCoordinates =
typename Base::LocalCoordinates;
189 using WorldCoordinates =
typename Base::WorldCoordinates;
191 using GaussNode =
typename Base::GaussNode;
193 template <UNSIGNED_INTEGER_TYPE Dim>
194 using Vector =
typename Base::template Vector<Dim>;
196 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
197 using Matrix =
typename Base::template Matrix<Rows, Cols>;
200 static constexpr
auto CanonicalDimension = Base::CanonicalDimension;
201 static constexpr
auto Dimension = Base::Dimension;
202 static constexpr
auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
203 static constexpr
auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
207 using Size =
typename Base::Size;
208 using Rotation =
typename Base::Rotation;
214 template<UNSIGNED_INTEGER_TYPE Order>
216 this->p_center = quad.center();
217 this->p_H = Size((quad.node(1)-quad.node(0)).norm(), (quad.node(3)-quad.node(0)).norm());
218 this->p_R = quad.frame({0, 0});
222 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
227 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
235 inline auto get_L(
const LocalCoordinates & xi)
const {
236 const auto & u = xi[0];
237 const auto & v = xi[1];
239 Vector<NumberOfNodesAtCompileTime> m;
240 m[4] = 1/2.*(1 - u*u)*(1 - v);
241 m[5] = 1/2.*(1 - v*v)*(1 + u);
242 m[6] = 1/2.*(1 - u*u)*(1 + v);
243 m[7] = 1/2.*(1 - v*v)*(1 - u);
245 m[0] = 1/4.*(1 - u)*(1 - v) - 1/2.*(m[4] + m[7]);
246 m[1] = 1/4.*(1 + u)*(1 - v) - 1/2.*(m[4] + m[5]);
247 m[2] = 1/4.*(1 + u)*(1 + v) - 1/2.*(m[5] + m[6]);
248 m[3] = 1/4.*(1 - u)*(1 + v) - 1/2.*(m[6] + m[7]);
253 inline auto get_dL(
const LocalCoordinates & xi)
const {
254 const auto & u = xi[0];
255 const auto & v = xi[1];
257 Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> m;
259 m << -1/4.*(1 - v) - 1/2.*(-u*(1 - v) + -1/2.*(1 - v*v)) , -1/4.*(1 - u) - 1/2.*(-1/2.*(1 - u*u) + -v*(1 - u)),
260 1/4.*(1 - v) - 1/2.*(-u*(1 - v) + 1/2.*(1 - v*v)) , -1/4.*(1 + u) - 1/2.*(-1/2.*(1 - u*u) + -v*(1 + u)),
261 1/4.*(1 + v) - 1/2.*(-u*(1 + v) + 1/2.*(1 - v*v)) , 1/4.*(1 + u) - 1/2.*( 1/2.*(1 - u*u) + -v*(1 + u)),
262 -1/4.*(1 + v) - 1/2.*(-u*(1 + v) + -1/2.*(1 - v*v)) , 1/4.*(1 - u) - 1/2.*( 1/2.*(1 - u*u) + -v*(1 - u)),
263 -u*(1 - v) , -1/2.*(1 - u*u) ,
264 1/2.*(1 - v*v) , -v*(1 + u) ,
265 -u*(1 + v) , 1/2.*(1 - u*u) ,
266 -1/2.*(1 - v*v) , -v*(1 - u);
271 inline auto get_node(
const UNSIGNED_INTEGER_TYPE & index)
const -> WorldCoordinates {
272 caribou_assert(index < NumberOfNodesAtCompileTime and
"Trying to get a node from an invalid node index.");
273 return this->T(LocalCoordinates(canonical_nodes[index][0], canonical_nodes[index][1]));
276 inline auto get_nodes()
const {
277 Matrix<NumberOfNodesAtCompileTime, Dimension> nodes;
278 for (UNSIGNED_INTEGER_TYPE node_id = 0; node_id < NumberOfNodesAtCompileTime; ++node_id) {
279 nodes.row(node_id) = get_node(node_id);
284 inline auto get_gauss_nodes() const -> const auto & {
285 using Weight = FLOATING_POINT_TYPE;
286 static const std::vector<GaussNode> gauss_nodes {
287 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3)), Weight(1)},
288 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3)), Weight(1)},
289 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3)), Weight(1)},
290 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3)), Weight(1)}
295 inline auto get_boundary_elements_nodes() const -> const auto & {
296 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 3>, 4> indices = {{