3 #include <Caribou/config.h>
4 #include <Caribou/Geometry/BaseQuad.h>
5 #include <Caribou/Geometry/Segment.h>
9 namespace caribou::geometry {
11 template<UNSIGNED_INTEGER_TYPE Dimension, UNSIGNED_INTEGER_TYPE Order = Linear>
14 template<UNSIGNED_INTEGER_TYPE _Dimension>
16 static constexpr UNSIGNED_INTEGER_TYPE CanonicalDimension = 2;
17 static constexpr UNSIGNED_INTEGER_TYPE Dimension = _Dimension;
18 static constexpr INTEGER_TYPE NumberOfNodesAtCompileTime = 4;
19 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = 4;
22 static constexpr INTEGER_TYPE NumberOfBoundaryElementsAtCompileTime = 4;
43 template<UNSIGNED_INTEGER_TYPE _Dimension>
44 struct Quad <_Dimension, Linear> :
public BaseQuad<Quad <_Dimension, Linear>> {
47 using LocalCoordinates =
typename Base::LocalCoordinates;
48 using WorldCoordinates =
typename Base::WorldCoordinates;
50 using GaussNode =
typename Base::GaussNode;
52 template <UNSIGNED_INTEGER_TYPE Dim>
53 using Vector =
typename Base::template Vector<Dim>;
55 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
56 using Matrix =
typename Base::template Matrix<Rows, Cols>;
59 static constexpr
auto CanonicalDimension = Base::CanonicalDimension;
60 static constexpr
auto Dimension = Base::Dimension;
61 static constexpr
auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
62 static constexpr
auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
64 static constexpr FLOATING_POINT_TYPE canonical_nodes [NumberOfNodesAtCompileTime][CanonicalDimension] = {
75 if constexpr (Dimension == 2) {
76 this->p_nodes.row(0) = WorldCoordinates(canonical_nodes[0][0], canonical_nodes[0][1]);
77 this->p_nodes.row(1) = WorldCoordinates(canonical_nodes[1][0], canonical_nodes[1][1]);
78 this->p_nodes.row(2) = WorldCoordinates(canonical_nodes[2][0], canonical_nodes[2][1]);
79 this->p_nodes.row(3) = WorldCoordinates(canonical_nodes[3][0], canonical_nodes[3][1]);
81 this->p_nodes.row(0) = WorldCoordinates(canonical_nodes[0][0], canonical_nodes[0][1], 0);
82 this->p_nodes.row(1) = WorldCoordinates(canonical_nodes[1][0], canonical_nodes[1][1], 0);
83 this->p_nodes.row(2) = WorldCoordinates(canonical_nodes[2][0], canonical_nodes[2][1], 0);
84 this->p_nodes.row(3) = WorldCoordinates(canonical_nodes[3][0], canonical_nodes[3][1], 0);
93 inline auto get_L(
const LocalCoordinates & xi)
const -> Vector<NumberOfNodesAtCompileTime> {
94 const auto & u = xi[0];
95 const auto & v = xi[1];
97 static_cast<FLOATING_POINT_TYPE
>(1 / 4. * (1 - u) * (1 - v)),
98 static_cast<FLOATING_POINT_TYPE
>(1 / 4. * (1 + u) * (1 - v)),
99 static_cast<FLOATING_POINT_TYPE
>(1 / 4. * (1 + u) * (1 + v)),
100 static_cast<FLOATING_POINT_TYPE
>(1 / 4. * (1 - u) * (1 + v))
104 inline auto get_dL(
const LocalCoordinates & xi)
const {
105 const auto & u = xi[0];
106 const auto & v = xi[1];
108 Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> m;
110 m << -1 / 4. * (1 - v), -1 / 4. * (1 - u),
111 +1 / 4. * (1 - v), -1 / 4. * (1 + u),
112 +1 / 4. * (1 + v), +1 / 4. * (1 + u),
113 -1 / 4. * (1 + v), +1 / 4. * (1 - u);
117 inline auto get_gauss_nodes()
const ->
const auto & {
118 using Weight = FLOATING_POINT_TYPE;
119 static const std::vector<GaussNode> gauss_nodes {
120 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3)), Weight(1)},
121 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3)), Weight(1)},
122 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3)), Weight(1)},
123 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3)), Weight(1)}
128 inline auto get_boundary_elements_nodes()
const ->
const auto & {
129 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 2>, 4> indices = {{
140 template<UNSIGNED_INTEGER_TYPE _Dimension>
142 static constexpr UNSIGNED_INTEGER_TYPE CanonicalDimension = 2;
143 static constexpr UNSIGNED_INTEGER_TYPE Dimension = _Dimension;
144 static constexpr INTEGER_TYPE NumberOfNodesAtCompileTime = 8;
145 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = 4;
148 static constexpr INTEGER_TYPE NumberOfBoundaryElementsAtCompileTime = 4;
169 template<UNSIGNED_INTEGER_TYPE _Dimension>
170 struct Quad <_Dimension, Quadratic> :
public BaseQuad<Quad <_Dimension, Quadratic>> {
173 using LocalCoordinates =
typename Base::LocalCoordinates;
174 using WorldCoordinates =
typename Base::WorldCoordinates;
176 using GaussNode =
typename Base::GaussNode;
178 template <UNSIGNED_INTEGER_TYPE Dim>
179 using Vector =
typename Base::template Vector<Dim>;
181 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
182 using Matrix =
typename Base::template Matrix<Rows, Cols>;
185 static constexpr
auto CanonicalDimension = Base::CanonicalDimension;
186 static constexpr
auto Dimension = Base::Dimension;
187 static constexpr
auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
188 static constexpr
auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
190 static constexpr FLOATING_POINT_TYPE canonical_nodes [NumberOfNodesAtCompileTime][CanonicalDimension] = {
205 if constexpr (Dimension == 2) {
206 this->p_nodes.row(0) = WorldCoordinates(canonical_nodes[0][0], canonical_nodes[0][1]);
207 this->p_nodes.row(1) = WorldCoordinates(canonical_nodes[1][0], canonical_nodes[1][1]);
208 this->p_nodes.row(2) = WorldCoordinates(canonical_nodes[2][0], canonical_nodes[2][1]);
209 this->p_nodes.row(3) = WorldCoordinates(canonical_nodes[3][0], canonical_nodes[3][1]);
210 this->p_nodes.row(4) = WorldCoordinates(canonical_nodes[4][0], canonical_nodes[4][1]);
211 this->p_nodes.row(5) = WorldCoordinates(canonical_nodes[5][0], canonical_nodes[5][1]);
212 this->p_nodes.row(6) = WorldCoordinates(canonical_nodes[6][0], canonical_nodes[6][1]);
213 this->p_nodes.row(7) = WorldCoordinates(canonical_nodes[7][0], canonical_nodes[7][1]);
215 this->p_nodes.row(0) = WorldCoordinates(canonical_nodes[0][0], canonical_nodes[0][1], 0);
216 this->p_nodes.row(1) = WorldCoordinates(canonical_nodes[1][0], canonical_nodes[1][1], 0);
217 this->p_nodes.row(2) = WorldCoordinates(canonical_nodes[2][0], canonical_nodes[2][1], 0);
218 this->p_nodes.row(3) = WorldCoordinates(canonical_nodes[3][0], canonical_nodes[3][1], 0);
219 this->p_nodes.row(4) = WorldCoordinates(canonical_nodes[4][0], canonical_nodes[4][1], 0);
220 this->p_nodes.row(5) = WorldCoordinates(canonical_nodes[5][0], canonical_nodes[5][1], 0);
221 this->p_nodes.row(6) = WorldCoordinates(canonical_nodes[6][0], canonical_nodes[6][1], 0);
222 this->p_nodes.row(7) = WorldCoordinates(canonical_nodes[7][0], canonical_nodes[7][1], 0);
228 this->p_nodes.row(0) = linear_Quad.node(0);
229 this->p_nodes.row(1) = linear_Quad.node(1);
230 this->p_nodes.row(2) = linear_Quad.node(2);
231 this->p_nodes.row(3) = linear_Quad.node(3);
232 this->p_nodes.row(4) = linear_Quad.world_coordinates(LocalCoordinates(canonical_nodes[4][0], canonical_nodes[4][1]));
233 this->p_nodes.row(5) = linear_Quad.world_coordinates(LocalCoordinates(canonical_nodes[5][0], canonical_nodes[5][1]));
234 this->p_nodes.row(6) = linear_Quad.world_coordinates(LocalCoordinates(canonical_nodes[6][0], canonical_nodes[6][1]));
235 this->p_nodes.row(7) = linear_Quad.world_coordinates(LocalCoordinates(canonical_nodes[7][0], canonical_nodes[7][1]));
239 Quad(WorldCoordinates & p0, WorldCoordinates & p1, WorldCoordinates & p2, WorldCoordinates & p3)
240 :
Quad(
Quad<Dimension, Linear>(p0, p1, p2, p3)) {}
243 Quad(
const WorldCoordinates & p0,
const WorldCoordinates & p1,
const WorldCoordinates & p2,
const WorldCoordinates & p3)
244 :
Quad(
Quad<Dimension, Linear>(p0, p1, p2, p3)) {}
249 friend struct Element<
Quad <_Dimension, Quadratic>>;
251 inline auto get_L(
const LocalCoordinates & xi)
const {
252 const auto & u = xi[0];
253 const auto & v = xi[1];
255 Vector<NumberOfNodesAtCompileTime> m;
256 m[4] = 1/2.*(1 - u*u)*(1 - v);
257 m[5] = 1/2.*(1 - v*v)*(1 + u);
258 m[6] = 1/2.*(1 - u*u)*(1 + v);
259 m[7] = 1/2.*(1 - v*v)*(1 - u);
261 m[0] = 1/4.*(1 - u)*(1 - v) - 1/2.*(m[4] + m[7]);
262 m[1] = 1/4.*(1 + u)*(1 - v) - 1/2.*(m[4] + m[5]);
263 m[2] = 1/4.*(1 + u)*(1 + v) - 1/2.*(m[5] + m[6]);
264 m[3] = 1/4.*(1 - u)*(1 + v) - 1/2.*(m[6] + m[7]);
269 inline auto get_dL(
const LocalCoordinates & xi)
const {
270 const auto & u = xi[0];
271 const auto & v = xi[1];
273 Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> m;
275 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)),
276 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)),
277 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)),
278 -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)),
279 -u*(1 - v) , -1/2.*(1 - u*u) ,
280 1/2.*(1 - v*v) , -v*(1 + u) ,
281 -u*(1 + v) , 1/2.*(1 - u*u) ,
282 -1/2.*(1 - v*v) , -v*(1 - u);
287 inline auto get_gauss_nodes() const -> const auto & {
288 using Weight = FLOATING_POINT_TYPE;
289 static const std::vector<GaussNode> gauss_nodes {
290 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3)), Weight(1)},
291 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3)), Weight(1)},
292 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3)), Weight(1)},
293 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3)), Weight(1)}
298 inline auto get_boundary_elements_nodes() const -> const auto & {
299 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 3>, 4> indices = {{