# Copyright (C) 2021-2025 Université Gustave Eiffel.
# This file is part of the EasyFEA project.
# EasyFEA is distributed under the terms of the GNU General Public License v3, see LICENSE.txt and CREDITS.md for more information.
"""Tetra element module."""
import numpy as np
from .._group_elems import _GroupElem
from ...utilities import _types
[docs]
class TETRA4(_GroupElem):
# v
# .
# ,/
# /
# 2
# ,/|`\
# ,/ | `\
# ,/ '. `\
# ,/ | `\
# ,/ | `\
# 0-----------'.--------1 --> u
# `\. | ,/
# `\. | ,/
# `\. '. ,/
# `\. |/
# `3
# `\.
# ` w
def __init__(
self, gmshId: int, connect: _types.IntArray, coordGlob: _types.FloatArray
):
super().__init__(gmshId, connect, coordGlob)
@property
def origin(self) -> list[int]:
return super().origin
@property
def triangles(self) -> list[int]:
return super().triangles
@property
def surfaces(self) -> _types.IntArray:
return np.array(
[
[0, 1, 2],
[0, 2, 3],
[0, 3, 1],
[1, 3, 2],
],
dtype=int,
)
@property
def faces(self) -> _types.IntArray:
return self.surfaces
[docs]
def Get_Local_Coords(self):
list_x = [0, 1, 0, 0]
list_y = [0, 0, 1, 0]
list_z = [0, 0, 0, 1]
local_coords = np.array([list_x, list_y, list_z]).T
return local_coords
@property
def segments(self) -> _types.IntArray:
return np.array(
[[0, 1], [2, 1], [2, 0], [0, 3], [2, 3], [3, 1]],
dtype=int,
)
[docs]
def _N(self) -> _types.FloatArray:
N1 = lambda r, s, t: -r - s - t + 1
N2 = lambda r, s, t: r
N3 = lambda r, s, t: s
N4 = lambda r, s, t: t
N = np.array([N1, N2, N3, N4]).reshape(-1, 1)
return N
[docs]
def _dN(self) -> _types.FloatArray:
dN1 = [lambda r, s, t: -1, lambda r, s, t: -1, lambda r, s, t: -1]
dN2 = [lambda r, s, t: 1, lambda r, s, t: 0, lambda r, s, t: 0]
dN3 = [lambda r, s, t: 0, lambda r, s, t: 1, lambda r, s, t: 0]
dN4 = [lambda r, s, t: 0, lambda r, s, t: 0, lambda r, s, t: 1]
dN = np.array([dN1, dN2, dN3, dN4])
return dN
[docs]
def _ddN(self) -> _types.FloatArray:
return super()._ddN()
[docs]
def _dddN(self) -> _types.FloatArray:
return super()._dddN()
[docs]
def _ddddN(self) -> _types.FloatArray:
return super()._ddddN()
[docs]
class TETRA10(_GroupElem):
# v
# .
# ,/
# /
# 2
# ,/|`\
# ,/ | `\
# ,6 '. `5
# ,/ 8 `\
# ,/ | `\
# 0--------4--'.--------1 --> u
# `\. | ,/
# `\. | ,9
# `7. '. ,/
# `\. |/
# `3
# `\.
# ` w
def __init__(
self, gmshId: int, connect: _types.IntArray, coordGlob: _types.FloatArray
):
super().__init__(gmshId, connect, coordGlob)
@property
def origin(self) -> list[int]:
return super().origin
@property
def triangles(self) -> list[int]:
return super().triangles
@property
def surfaces(self) -> _types.IntArray:
return np.array(
[
[0, 4, 1, 5, 2, 6],
[0, 6, 2, 8, 3, 7],
[0, 7, 3, 9, 1, 4],
[1, 9, 3, 8, 2, 5],
],
dtype=int,
)
@property
def faces(self) -> _types.IntArray:
return np.array(
[
[0, 1, 2, 4, 5, 6],
[0, 2, 3, 6, 8, 7],
[0, 3, 1, 7, 9, 4],
[1, 3, 2, 9, 8, 5],
],
dtype=int,
)
[docs]
def Get_Local_Coords(self):
list_x = [0, 1, 0, 0, 0.5, 0.5, 0, 0, 0, 0.5]
list_y = [0, 0, 1, 0, 0, 0.5, 0.5, 0, 0.5, 0]
list_z = [0, 0, 0, 1, 0, 0, 0, 0.5, 0.5, 0.5]
local_coords = np.array([list_x, list_y, list_z]).T
return local_coords
@property
def segments(self) -> _types.IntArray:
return np.array(
[[0, 4, 1], [2, 5, 1], [2, 6, 0], [0, 7, 3], [2, 8, 3], [3, 9, 1]],
dtype=int,
)
[docs]
def _N(self) -> _types.FloatArray:
N1 = lambda r, s, t: (r + s + t - 1) * (2 * r + 2 * s + 2 * t - 1)
N2 = lambda r, s, t: r * (2 * r - 1)
N3 = lambda r, s, t: s * (2 * s - 1)
N4 = lambda r, s, t: t * (2 * t - 1)
N5 = lambda r, s, t: -4 * r * (r + s + t - 1)
N6 = lambda r, s, t: 4 * r * s
N7 = lambda r, s, t: -4 * s * (r + s + t - 1)
N8 = lambda r, s, t: -4 * t * (r + s + t - 1)
N9 = lambda r, s, t: 4 * s * t
N10 = lambda r, s, t: 4 * r * t
N = np.array([N1, N2, N3, N4, N5, N6, N7, N8, N9, N10]).reshape(-1, 1)
return N
[docs]
def _dN(self) -> _types.FloatArray:
dN1 = [
lambda r, s, t: 4 * r + 4 * s + 4 * t - 3,
lambda r, s, t: 4 * r + 4 * s + 4 * t - 3,
lambda r, s, t: 4 * r + 4 * s + 4 * t - 3,
]
dN2 = [lambda r, s, t: 4 * r - 1, lambda r, s, t: 0, lambda r, s, t: 0]
dN3 = [lambda r, s, t: 0, lambda r, s, t: 4 * s - 1, lambda r, s, t: 0]
dN4 = [lambda r, s, t: 0, lambda r, s, t: 0, lambda r, s, t: 4 * t - 1]
dN5 = [
lambda r, s, t: -8 * r - 4 * s - 4 * t + 4,
lambda r, s, t: -4 * r,
lambda r, s, t: -4 * r,
]
dN6 = [lambda r, s, t: 4 * s, lambda r, s, t: 4 * r, lambda r, s, t: 0]
dN7 = [
lambda r, s, t: -4 * s,
lambda r, s, t: -4 * r - 8 * s - 4 * t + 4,
lambda r, s, t: -4 * s,
]
dN8 = [
lambda r, s, t: -4 * t,
lambda r, s, t: -4 * t,
lambda r, s, t: -4 * r - 4 * s - 8 * t + 4,
]
dN9 = [lambda r, s, t: 0, lambda r, s, t: 4 * t, lambda r, s, t: 4 * s]
dN10 = [lambda r, s, t: 4 * t, lambda r, s, t: 0, lambda r, s, t: 4 * r]
dN = np.array([dN1, dN2, dN3, dN4, dN5, dN6, dN7, dN8, dN9, dN10])
return dN
[docs]
def _ddN(self) -> _types.FloatArray:
ddN1 = [lambda r, s, t: 4, lambda r, s, t: 4, lambda r, s, t: 4]
ddN2 = [lambda r, s, t: 4, lambda r, s, t: 0, lambda r, s, t: 0]
ddN3 = [lambda r, s, t: 0, lambda r, s, t: 4, lambda r, s, t: 0]
ddN4 = [lambda r, s, t: 0, lambda r, s, t: 0, lambda r, s, t: 4]
ddN5 = [lambda r, s, t: -8, lambda r, s, t: 0, lambda r, s, t: 0]
ddN6 = [lambda r, s, t: 0, lambda r, s, t: 0, lambda r, s, t: 0]
ddN7 = [lambda r, s, t: 0, lambda r, s, t: -8, lambda r, s, t: 0]
ddN8 = [lambda r, s, t: 0, lambda r, s, t: 0, lambda r, s, t: -8]
ddN9 = [lambda r, s, t: 0, lambda r, s, t: 0, lambda r, s, t: 0]
ddN10 = [lambda r, s, t: 0, lambda r, s, t: 0, lambda r, s, t: 0]
ddN = np.array([ddN1, ddN2, ddN3, ddN4, ddN5, ddN6, ddN7, ddN8, ddN9, ddN10])
return ddN
[docs]
def _dddN(self) -> _types.FloatArray:
return super()._dddN()
[docs]
def _ddddN(self) -> _types.FloatArray:
return super()._ddddN()