Skip to content

Commit

Permalink
Simplify init of base-class element.Element (#924)
Browse files Browse the repository at this point in the history
* Simplify `Element`

and add `element.Element` to the top-level namespace

* Update _lagrange.py

* Don't use `Element.shape` in `"tetra10"` and `"triangle6"`
  • Loading branch information
adtzlr authored Jan 3, 2025
1 parent 4aaf105 commit 2ab6697
Show file tree
Hide file tree
Showing 10 changed files with 16 additions and 65 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. The format
- Add `BoundaryDict` as a subclassed dict with methods to `plot()`, `screenshot()` and `imshow()`.
- Add a new argument to apply a callable on the assembled vector/matrix of a solid body, `SolidBody(..., apply=None)`. This may be used to sum the list of sub-blocks instead of stacking them together, `SolidBody(..., block=False, apply=None)`. This is useful for mixed formulations where both the deformation gradient and the displacement values are required.
- Add support for non-symmetric bilinear mixed forms in `IntegralForm`.
- Add `element.Element` to the top-level package namespace.

### Changed
- The first Piola-Kirchhoff stress tensor is evaluated if `ViewSolid(stress_type=None)`.
Expand All @@ -25,6 +26,9 @@ All notable changes to this project will be documented in this file. The format
### Fixed
- Fix `Boundary(..., mode="and")` by ignoring any undefined axis.

### Removed
- Remove the unused `shape`-argument in `element.Element(shape)`. Adopt the arbitrary-lagrange element to use its own `dim`-argument. This simplifies the creation of custom finite element formulations.

## [9.1.0] - 2024-11-23

### Added
Expand Down
2 changes: 2 additions & 0 deletions src/felupe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
BiQuadraticQuad,
ConstantHexahedron,
ConstantQuad,
Element,
Hexahedron,
Line,
Quad,
Expand Down Expand Up @@ -173,6 +174,7 @@
"BiQuadraticQuad",
"ConstantHexahedron",
"ConstantQuad",
"Element",
"Hexahedron",
"Line",
"Quad",
Expand Down
13 changes: 5 additions & 8 deletions src/felupe/element/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@


class Element:
def __init__(self, shape):
self.shape = shape
self.dim = self.shape[1]

def view(self, point_data=None, cell_data=None, cell_type=None):
"""View the element with optional given dicts of point- and cell-data items.
Expand Down Expand Up @@ -91,7 +88,7 @@ def plot(
)
if add_point_labels:
plotter.add_point_labels(
points=np.pad(self.points, ((0, 0), (0, 3 - self.shape[1]))),
points=np.pad(self.points, ((0, 0), (0, 3 - self.points.shape[1]))),
labels=[f"{a}" for a in np.arange(len(self.points))],
font_size=font_size,
show_points=show_points,
Expand All @@ -108,19 +105,19 @@ def plot(
actor.SetNormalizedShaftLength((0.9, 0.9, 0.9))
actor.SetNormalizedTipLength((0.1, 0.1, 0.1))

if self.shape[1] == 3:
if self.points.shape[1] == 3:
actor.SetTotalLength([1.3, 1.3, 1.3])
elif self.shape[1] == 2:
elif self.points.shape[1] == 2:
actor.SetZAxisLabelText("")
actor.SetTotalLength([1.3, 1.3, 0])
elif self.shape[1] == 1:
elif self.points.shape[1] == 1:
actor.SetYAxisLabelText("")
actor.SetZAxisLabelText("")
actor.SetTotalLength([1.3, 0, 0])

plotter.camera.zoom(0.7)

if self.shape[1] == 3:
if self.points.shape[1] == 3:
plotter.camera.azimuth = -17

return plotter
Expand Down
5 changes: 0 additions & 5 deletions src/felupe/element/_hexahedron.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ def __init__(self):
)
self.cells = np.arange(len(self.points)).reshape(1, -1)
self.cell_type = "hexahedron"
super().__init__(shape=(1, 3))

def function(self, rst):
"Return the shape functions at given coordinates (r, s, t)."
Expand Down Expand Up @@ -140,7 +139,6 @@ def __init__(self):
)
self.cells = np.arange(len(self.points)).reshape(1, -1)
self.cell_type = "hexahedron"
super().__init__(shape=(8, 3))

def function(self, rst):
"Return the shape functions at given coordinates (r, s, t)."
Expand Down Expand Up @@ -263,7 +261,6 @@ def __init__(self):
)
self.cells = np.arange(len(self.points)).reshape(1, -1)
self.cell_type = "hexahedron20"
super().__init__(shape=(20, 3))

def function(self, rst):
"Return the shape functions at given coordinates (r, s, t)."
Expand Down Expand Up @@ -471,8 +468,6 @@ class TriQuadraticHexahedron(Element):
"""

def __init__(self):
super().__init__(shape=(27, 3))

self.points = np.array(
[
[-1, -1, -1],
Expand Down
6 changes: 3 additions & 3 deletions src/felupe/element/_lagrange.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,14 @@ def __init__(self, order, dim, interval=(-1, 1), permute=True):
self._nbasis = self._npoints
self._interval = interval

self.dim = dim

self.permute = None
if permute:
self.permute = [None, lagrange_line, lagrange_quad, lagrange_hexahedron][
dim
](order)

super().__init__(shape=(self._npoints, dim))

# init curve-parameter matrix
n = self._nshape
self._AT = np.linalg.inv(
Expand All @@ -278,7 +278,7 @@ def __init__(self, order, dim, interval=(-1, 1), permute=True):
# indices for outer product in einstein notation
# idx = ["a", "b", "c", ...][:dim]
# subscripts = "a,b,c -> abc"
self._idx = [letter for letter in alphabet][: self.dim]
self._idx = [letter for letter in alphabet][:dim]
self._subscripts = ",".join(self._idx) + "->" + "".join(self._idx)

# init points
Expand Down
1 change: 0 additions & 1 deletion src/felupe/element/_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class Line(Element):
"""

def __init__(self):
super().__init__(shape=(2, 1))
self.points = np.array([-1, 1], dtype=float).reshape(-1, 1)
self.cells = np.arange(len(self.points)).reshape(1, -1)
self.cell_type = "line"
Expand Down
5 changes: 0 additions & 5 deletions src/felupe/element/_quad.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ class ConstantQuad(Element):
"""

def __init__(self):
super().__init__(shape=(1, 2))
self.points = np.array([[-1, -1], [1, -1], [1, 1], [-1, 1]], dtype=float)
self.cells = np.arange(len(self.points)).reshape(1, -1)
self.cell_type = "quad"
Expand Down Expand Up @@ -106,7 +105,6 @@ class Quad(Element):
"""

def __init__(self):
super().__init__(shape=(4, 2))
self.points = np.array([[-1, -1], [1, -1], [1, 1], [-1, 1]], dtype=float)
self.cells = np.arange(len(self.points)).reshape(1, -1)
self.cell_type = "quad"
Expand Down Expand Up @@ -188,7 +186,6 @@ class QuadraticQuad(Element):
"""

def __init__(self):
super().__init__(shape=(8, 2))
self.points = np.array(
[
[-1, -1],
Expand Down Expand Up @@ -289,8 +286,6 @@ class BiQuadraticQuad(Element):
"""

def __init__(self):
super().__init__(shape=(9, 2))

self._lagrange = ArbitraryOrderLagrange(order=2, dim=2, permute=False)

self._vertices = np.array([0, 2, 8, 6])
Expand Down
5 changes: 1 addition & 4 deletions src/felupe/element/_tetra.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class Tetra(Element):
"""

def __init__(self):
super().__init__(shape=(4, 3))
self.points = np.array(
[[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=float
)
Expand Down Expand Up @@ -117,7 +116,6 @@ class TetraMINI(Element):
"""

def __init__(self, bubble_multiplier=1.0):
super().__init__(shape=(5, 3))
self.points = np.array(
[[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [1 / 3, 1 / 3, 1 / 3]],
dtype=float,
Expand Down Expand Up @@ -237,8 +235,7 @@ class QuadraticTetra(Element):
"""

def __init__(self):
super().__init__(shape=(10, 3))
self.points = np.zeros(self.shape)
self.points = np.zeros((10, 3))
self.points[:4] = np.array(
[[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=float
)
Expand Down
5 changes: 1 addition & 4 deletions src/felupe/element/_triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ class Triangle(Element):
"""

def __init__(self):
super().__init__(shape=(3, 2))
self.points = np.array([[0, 0], [1, 0], [0, 1]], dtype=float)
self.cells = np.arange(len(self.points)).reshape(1, -1)
self.cell_type = "triangle"
Expand Down Expand Up @@ -115,7 +114,6 @@ class TriangleMINI(Element):
"""

def __init__(self, bubble_multiplier=1.0):
super().__init__(shape=(4, 2))
self.points = np.array([[0, 0], [1, 0], [0, 1], [1 / 3, 1 / 3]], dtype=float)
self.cells = np.arange(len(self.points) - 1).reshape(1, -1)
self.cell_type = "triangle"
Expand Down Expand Up @@ -198,8 +196,7 @@ class QuadraticTriangle(Element):
"""

def __init__(self):
super().__init__(shape=(6, 2))
self.points = np.zeros(self.shape)
self.points = np.zeros((6, 2))
self.points[:3] = np.array([[0, 0], [1, 0], [0, 1]], dtype=float)
self.points[3] = np.mean(self.points[[0, 1]], axis=0)
self.points[4] = np.mean(self.points[[1, 2]], axis=0)
Expand Down
35 changes: 0 additions & 35 deletions tests/test_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ def test_line2():
assert np.all(dhdr[0] == -0.5)
assert np.all(d2hdrdr == 0.0)

assert line2.shape == dhdr.shape

line2.plot(off_screen=True)


Expand All @@ -59,8 +57,6 @@ def test_line_lagrange():
assert np.isclose(h[0], 1)
assert np.isclose(dhdr[0, 0], -5.70833333)

assert line6.shape == dhdr.shape

line6.plot(off_screen=True)


Expand All @@ -77,8 +73,6 @@ def test_quad0():
assert np.all(dhdr[0] == 0)
assert np.all(d2hdrdr == 0.0)

assert quad0.shape == dhdr.shape


def test_quad4():
quad4 = fem.element.Quad()
Expand All @@ -93,8 +87,6 @@ def test_quad4():
assert np.all(dhdr[0] == -0.5)
assert d2hdrdr.shape == (4, 2, 2)

assert quad4.shape == dhdr.shape

quad4.plot(off_screen=True)


Expand All @@ -111,8 +103,6 @@ def test_quad8():
assert np.all(dhdr[0] == -1.5)
assert d2hdrdr.shape == (8, 2, 2)

assert quad8.shape == dhdr.shape


def test_quad9():
quad9 = fem.element.BiQuadraticQuad()
Expand All @@ -125,8 +115,6 @@ def test_quad9():
assert h[0] == 1
assert np.all(dhdr[0] == -1.5)

assert quad9.shape == dhdr.shape


def test_hex0():
hex0 = fem.element.ConstantHexahedron()
Expand All @@ -141,8 +129,6 @@ def test_hex0():
assert np.all(dhdr[0] == 0)
assert np.all(d2hdrdr == 0)

assert hex0.shape == dhdr.shape


def test_hex8():
hex8 = fem.element.Hexahedron()
Expand All @@ -157,8 +143,6 @@ def test_hex8():
assert np.all(dhdr[0] == -0.5)
assert d2hdrdr.shape == (8, 3, 3)

assert hex8.shape == dhdr.shape


def test_hex20():
hex20 = fem.element.QuadraticHexahedron()
Expand All @@ -171,8 +155,6 @@ def test_hex20():
assert h[0] == 1
assert np.all(dhdr[0] == -1.5)

assert hex20.shape == dhdr.shape

hex20.plot(off_screen=True)


Expand All @@ -187,8 +169,6 @@ def test_hex27():
assert h[0] == 1
assert np.all(dhdr[0] == -1.5)

assert hex27.shape == dhdr.shape

hex27.plot(off_screen=True)


Expand All @@ -205,9 +185,6 @@ def test_tri3():
assert np.all(dhdr[0] == -1)
assert np.all(d2hdrdr == 0)

assert tri3.shape == dhdr.shape


def test_tri6():
tri6 = fem.element.QuadraticTriangle()

Expand All @@ -219,8 +196,6 @@ def test_tri6():
assert h[0] == 1
assert np.all(dhdr[0] == -3)

assert tri6.shape == dhdr.shape


def test_tri_mini():
trim = fem.element.TriangleMINI()
Expand All @@ -236,8 +211,6 @@ def test_tri_mini():
assert np.all(dhdr[0] == -1)
assert d2hdrdr.shape == (4, 2, 2)

assert trim.shape == dhdr.shape


def test_tet4():
tet4 = fem.element.Tetra()
Expand All @@ -252,8 +225,6 @@ def test_tet4():
assert np.all(dhdr[0] == -1)
assert np.all(d2hdrdr == 0)

assert tet4.shape == dhdr.shape


def test_tet10():
tet10 = fem.element.QuadraticTetra()
Expand All @@ -266,8 +237,6 @@ def test_tet10():
assert h[0] == 1
assert np.all(dhdr[0] == -3)

assert tet10.shape == dhdr.shape


def test_tet_mini():
tetm = fem.element.TetraMINI()
Expand All @@ -283,8 +252,6 @@ def test_tet_mini():
assert np.all(dhdr[0] == -1)
assert d2hdrdr.shape == (5, 3, 3)

assert tetm.shape == dhdr.shape


def test_aol():
aol32 = fem.element.ArbitraryOrderLagrange(order=3, dim=2)
Expand All @@ -296,15 +263,13 @@ def test_aol():
dhdr = aol32.gradient(r)

assert h[0] == 1
assert aol32.shape == dhdr.shape

r = [-1, -1, -1]

h = aol23.function(r)
dhdr = aol23.gradient(r)

assert h[0] == 1
assert aol23.shape == dhdr.shape


if __name__ == "__main__":
Expand Down

0 comments on commit 2ab6697

Please sign in to comment.