3 #include <Caribou/config.h>
4 #include <Caribou/Geometry/BaseHexahedron.h>
5 #include <Caribou/Geometry/Quad.h>
8 namespace caribou::geometry {
10 template<UNSIGNED_INTEGER_TYPE Order = Linear>
15 static constexpr UNSIGNED_INTEGER_TYPE CanonicalDimension = 3;
16 static constexpr UNSIGNED_INTEGER_TYPE Dimension = 3;
17 static constexpr INTEGER_TYPE NumberOfNodesAtCompileTime = 8;
18 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = 8;
21 static constexpr INTEGER_TYPE NumberOfBoundaryElementsAtCompileTime = 6;
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] = {
79 this->p_nodes.row(0) = WorldCoordinates(canonical_nodes[0][0], canonical_nodes[0][1], canonical_nodes[0][2]);
80 this->p_nodes.row(1) = WorldCoordinates(canonical_nodes[1][0], canonical_nodes[1][1], canonical_nodes[1][2]);
81 this->p_nodes.row(2) = WorldCoordinates(canonical_nodes[2][0], canonical_nodes[2][1], canonical_nodes[2][2]);
82 this->p_nodes.row(3) = WorldCoordinates(canonical_nodes[3][0], canonical_nodes[3][1], canonical_nodes[3][2]);
83 this->p_nodes.row(4) = WorldCoordinates(canonical_nodes[4][0], canonical_nodes[4][1], canonical_nodes[4][2]);
84 this->p_nodes.row(5) = WorldCoordinates(canonical_nodes[5][0], canonical_nodes[5][1], canonical_nodes[5][2]);
85 this->p_nodes.row(6) = WorldCoordinates(canonical_nodes[6][0], canonical_nodes[6][1], canonical_nodes[6][2]);
86 this->p_nodes.row(7) = WorldCoordinates(canonical_nodes[7][0], canonical_nodes[7][1], canonical_nodes[7][2]);
95 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 2>, 12> indices = {{
117 inline auto get_L(
const LocalCoordinates & xi)
const {
118 const auto & u = xi[0];
119 const auto & v = xi[1];
120 const auto & w = xi[2];
122 Vector<NumberOfNodesAtCompileTime> m;
123 m << (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),
128 (1/8.) * (1 + u) * (1 - v) * (1 + w),
129 (1/8.) * (1 + u) * (1 + v) * (1 + w),
130 (1/8.) * (1 - u) * (1 + v) * (1 + w);
134 inline auto get_dL(
const LocalCoordinates & xi)
const {
135 const auto & u = xi[0];
136 const auto & v = xi[1];
137 const auto & w = xi[2];
139 Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> m;
141 m << -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),
146 +1/8. * (1 - v) * (1 + w), -1/8. * (1 + u) * (1 + w), +1/8. * (1 + u) * (1 - v),
147 +1/8. * (1 + v) * (1 + w), +1/8. * (1 + u) * (1 + w), +1/8. * (1 + u) * (1 + v),
148 -1/8. * (1 + v) * (1 + w), +1/8. * (1 - u) * (1 + w), +1/8. * (1 - u) * (1 + v);
152 inline auto get_gauss_nodes() const -> const auto & {
153 using Weight = FLOATING_POINT_TYPE;
154 static const std::vector<GaussNode> gauss_nodes {
155 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3), -1/sqrt(3)), Weight(1)},
156 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3), -1/sqrt(3)), Weight(1)},
157 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3), -1/sqrt(3)), Weight(1)},
158 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3), -1/sqrt(3)), Weight(1)},
159 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3), +1/sqrt(3)), Weight(1)},
160 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3), +1/sqrt(3)), Weight(1)},
161 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3), +1/sqrt(3)), Weight(1)},
162 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3), +1/sqrt(3)), Weight(1)}
167 inline auto get_boundary_elements_nodes() const -> const auto & {
168 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 4>, 6> indices = {{
183 static constexpr UNSIGNED_INTEGER_TYPE CanonicalDimension = 3;
184 static constexpr UNSIGNED_INTEGER_TYPE Dimension = 3;
185 static constexpr INTEGER_TYPE NumberOfNodesAtCompileTime = 20;
186 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = 4;
189 static constexpr INTEGER_TYPE NumberOfBoundaryElementsAtCompileTime = 6;
217 using LocalCoordinates =
typename Base::LocalCoordinates;
218 using WorldCoordinates =
typename Base::WorldCoordinates;
220 using GaussNode =
typename Base::GaussNode;
222 template <UNSIGNED_INTEGER_TYPE Dim>
223 using Vector =
typename Base::template Vector<Dim>;
225 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
226 using Matrix =
typename Base::template Matrix<Rows, Cols>;
229 static constexpr
auto CanonicalDimension = Base::CanonicalDimension;
230 static constexpr
auto Dimension = Base::Dimension;
231 static constexpr
auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
232 static constexpr
auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
234 static constexpr FLOATING_POINT_TYPE canonical_nodes [NumberOfNodesAtCompileTime][CanonicalDimension] = {
261 this->p_nodes.row(0) = WorldCoordinates(canonical_nodes[0][0], canonical_nodes[0][1], canonical_nodes[0][2]);
262 this->p_nodes.row(1) = WorldCoordinates(canonical_nodes[1][0], canonical_nodes[1][1], canonical_nodes[1][2]);
263 this->p_nodes.row(2) = WorldCoordinates(canonical_nodes[2][0], canonical_nodes[2][1], canonical_nodes[2][2]);
264 this->p_nodes.row(3) = WorldCoordinates(canonical_nodes[3][0], canonical_nodes[3][1], canonical_nodes[3][2]);
265 this->p_nodes.row(4) = WorldCoordinates(canonical_nodes[4][0], canonical_nodes[4][1], canonical_nodes[4][2]);
266 this->p_nodes.row(5) = WorldCoordinates(canonical_nodes[5][0], canonical_nodes[5][1], canonical_nodes[5][2]);
267 this->p_nodes.row(6) = WorldCoordinates(canonical_nodes[6][0], canonical_nodes[6][1], canonical_nodes[6][2]);
268 this->p_nodes.row(7) = WorldCoordinates(canonical_nodes[7][0], canonical_nodes[7][1], canonical_nodes[7][2]);
269 this->p_nodes.row(8) = WorldCoordinates(canonical_nodes[8][0], canonical_nodes[8][1], canonical_nodes[8][2]);
270 this->p_nodes.row(9) = WorldCoordinates(canonical_nodes[9][0], canonical_nodes[9][1], canonical_nodes[9][2]);
271 this->p_nodes.row(10) = WorldCoordinates(canonical_nodes[10][0], canonical_nodes[10][1], canonical_nodes[10][2]);
272 this->p_nodes.row(11) = WorldCoordinates(canonical_nodes[11][0], canonical_nodes[11][1], canonical_nodes[11][2]);
273 this->p_nodes.row(12) = WorldCoordinates(canonical_nodes[12][0], canonical_nodes[12][1], canonical_nodes[12][2]);
274 this->p_nodes.row(13) = WorldCoordinates(canonical_nodes[13][0], canonical_nodes[13][1], canonical_nodes[13][2]);
275 this->p_nodes.row(14) = WorldCoordinates(canonical_nodes[14][0], canonical_nodes[14][1], canonical_nodes[14][2]);
276 this->p_nodes.row(15) = WorldCoordinates(canonical_nodes[15][0], canonical_nodes[15][1], canonical_nodes[15][2]);
277 this->p_nodes.row(16) = WorldCoordinates(canonical_nodes[16][0], canonical_nodes[16][1], canonical_nodes[16][2]);
278 this->p_nodes.row(17) = WorldCoordinates(canonical_nodes[17][0], canonical_nodes[17][1], canonical_nodes[17][2]);
279 this->p_nodes.row(18) = WorldCoordinates(canonical_nodes[18][0], canonical_nodes[18][1], canonical_nodes[18][2]);
280 this->p_nodes.row(19) = WorldCoordinates(canonical_nodes[19][0], canonical_nodes[19][1], canonical_nodes[19][2]);
286 this->p_nodes.row(0) = linear_Hexahedron.
node(0);
287 this->p_nodes.row(1) = linear_Hexahedron.
node(1);
288 this->p_nodes.row(2) = linear_Hexahedron.
node(2);
289 this->p_nodes.row(3) = linear_Hexahedron.
node(3);
290 this->p_nodes.row(4) = linear_Hexahedron.
node(4);
291 this->p_nodes.row(5) = linear_Hexahedron.
node(5);
292 this->p_nodes.row(6) = linear_Hexahedron.
node(6);
293 this->p_nodes.row(7) = linear_Hexahedron.
node(7);
294 this->p_nodes.row(8) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[8][0], canonical_nodes[8][1], canonical_nodes[8][2]));
295 this->p_nodes.row(9) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[9][0], canonical_nodes[9][1], canonical_nodes[9][2]));
296 this->p_nodes.row(10) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[10][0], canonical_nodes[10][1], canonical_nodes[10][2]));
297 this->p_nodes.row(11) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[11][0], canonical_nodes[11][1], canonical_nodes[11][2]));
298 this->p_nodes.row(12) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[12][0], canonical_nodes[12][1], canonical_nodes[12][2]));
299 this->p_nodes.row(13) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[13][0], canonical_nodes[13][1], canonical_nodes[13][2]));
300 this->p_nodes.row(14) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[14][0], canonical_nodes[14][1], canonical_nodes[14][2]));
301 this->p_nodes.row(15) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[15][0], canonical_nodes[15][1], canonical_nodes[15][2]));
302 this->p_nodes.row(16) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[16][0], canonical_nodes[16][1], canonical_nodes[16][2]));
303 this->p_nodes.row(17) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[17][0], canonical_nodes[17][1], canonical_nodes[17][2]));
304 this->p_nodes.row(18) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[18][0], canonical_nodes[18][1], canonical_nodes[18][2]));
305 this->p_nodes.row(19) = linear_Hexahedron.
world_coordinates(LocalCoordinates(canonical_nodes[19][0], canonical_nodes[19][1], canonical_nodes[19][2]));
309 Hexahedron(WorldCoordinates & p0, WorldCoordinates & p1, WorldCoordinates & p2, WorldCoordinates & p3, WorldCoordinates & p4, WorldCoordinates & p5, WorldCoordinates & p6, WorldCoordinates & p7)
313 Hexahedron(
const WorldCoordinates & p0,
const WorldCoordinates & p1,
const WorldCoordinates & p2,
const WorldCoordinates & p3,
const WorldCoordinates & p4,
const WorldCoordinates & p5,
const WorldCoordinates & p6,
const WorldCoordinates & p7)
322 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 3>, 12> indices = {{
343 inline auto get_L(
const LocalCoordinates & xi)
const {
344 const auto & u = xi[0];
345 const auto & v = xi[1];
346 const auto & w = xi[2];
348 Vector<NumberOfNodesAtCompileTime> m;
349 m[ 8] = 1/4.*(1 - u*u)*(1 - v)*(1 - w);
350 m[ 9] = 1/4.*(1 - v*v)*(1 + u)*(1 - w);
351 m[10] = 1/4.*(1 - u*u)*(1 + v)*(1 - w);
352 m[11] = 1/4.*(1 - v*v)*(1 - u)*(1 - w);
353 m[12] = 1/4.*(1 - u*u)*(1 - v)*(1 + w);
354 m[13] = 1/4.*(1 - v*v)*(1 + u)*(1 + w);
355 m[14] = 1/4.*(1 - u*u)*(1 + v)*(1 + w);
356 m[15] = 1/4.*(1 - v*v)*(1 - u)*(1 + w);
357 m[16] = 1/4.*(1 - w*w)*(1 - u)*(1 - v);
358 m[17] = 1/4.*(1 - w*w)*(1 + u)*(1 - v);
359 m[18] = 1/4.*(1 - w*w)*(1 + u)*(1 + v);
360 m[19] = 1/4.*(1 - w*w)*(1 - u)*(1 + v);
362 m[0] = 1/8.*(1 - u)*(1 - v)*(1 - w) - 1/2.*(m[ 8] + m[11] + m[16]);
363 m[1] = 1/8.*(1 + u)*(1 - v)*(1 - w) - 1/2.*(m[ 8] + m[ 9] + m[17]);
364 m[2] = 1/8.*(1 + u)*(1 + v)*(1 - w) - 1/2.*(m[ 9] + m[10] + m[18]);
365 m[3] = 1/8.*(1 - u)*(1 + v)*(1 - w) - 1/2.*(m[10] + m[11] + m[19]);
366 m[4] = 1/8.*(1 - u)*(1 - v)*(1 + w) - 1/2.*(m[12] + m[15] + m[16]);
367 m[5] = 1/8.*(1 + u)*(1 - v)*(1 + w) - 1/2.*(m[12] + m[13] + m[17]);
368 m[6] = 1/8.*(1 + u)*(1 + v)*(1 + w) - 1/2.*(m[13] + m[14] + m[18]);
369 m[7] = 1/8.*(1 - u)*(1 + v)*(1 + w) - 1/2.*(m[14] + m[15] + m[19]);
373 inline auto get_dL(
const LocalCoordinates & xi)
const {
374 using ShapeDerivative = Vector<3>;
375 const auto & u = xi[0];
376 const auto & v = xi[1];
377 const auto & w = xi[2];
379 Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> m;
382 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)});
383 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)});
384 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)});
385 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)});
386 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)});
387 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)});
388 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)});
389 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)});
390 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)});
391 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)});
392 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)});
393 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)});
395 const auto du = m.col(0);
396 const auto dv = m.col(1);
397 const auto dw = m.col(2);
399 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])});
400 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])});
401 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])});
402 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])});
403 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])});
404 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])});
405 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])});
406 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])});
412 inline auto get_gauss_nodes() const -> const auto & {
413 using Weight = FLOATING_POINT_TYPE;
414 static const std::vector<GaussNode> gauss_nodes {
415 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3), -1/sqrt(3)), Weight(1)},
416 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3), -1/sqrt(3)), Weight(1)},
417 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3), -1/sqrt(3)), Weight(1)},
418 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3), -1/sqrt(3)), Weight(1)},
419 GaussNode {LocalCoordinates(-1/sqrt(3), -1/sqrt(3), +1/sqrt(3)), Weight(1)},
420 GaussNode {LocalCoordinates(+1/sqrt(3), -1/sqrt(3), +1/sqrt(3)), Weight(1)},
421 GaussNode {LocalCoordinates(-1/sqrt(3), +1/sqrt(3), +1/sqrt(3)), Weight(1)},
422 GaussNode {LocalCoordinates(+1/sqrt(3), +1/sqrt(3), +1/sqrt(3)), Weight(1)}
427 inline auto get_boundary_elements_nodes() const -> const auto & {
428 static const std::array<std::array<UNSIGNED_INTEGER_TYPE, 8>, 6> indices = {{
429 {0, 3, 2, 1, 11, 10, 9, 8},
430 {0, 4, 7, 3, 16, 15, 19, 11},
431 {1, 2, 6, 5, 9, 18, 13, 17},
432 {0, 1, 5, 4, 8, 17, 12, 16},
433 {2, 3, 7, 6, 10, 19, 14, 18},
434 {4, 5, 6, 7, 12, 13, 14, 15}