Skip to content

Commit 1008665

Browse files
authored
Merge pull request #88 from finsberg/remove-utils
Remove utils.py in test folder and use scifem more
2 parents 021cf3b + 9fc7195 commit 1008665

7 files changed

Lines changed: 52 additions & 140 deletions

File tree

src/pulse/kinematics.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ def IsochoricDeformationGradient(F: ufl.core.expr.Expr) -> ufl.core.expr.Expr:
8181
return pow(J, -1.0 / float(dim)) * F
8282

8383

84+
def IsochoricDeformationGradient_from_u(u) -> ufl.core.expr.Expr:
85+
return IsochoricDeformationGradient(DeformationGradient(u))
86+
87+
8488
def Jacobian(F: ufl.core.expr.Expr) -> ufl.core.expr.Expr:
8589
r"""Determinant of the deformation gradient
8690

src/pulse/utils.py

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,8 @@
11
import dolfinx
22
import numpy as np
33
import numpy.typing as npt
4-
5-
6-
def vertex_to_dofmap(V: dolfinx.fem.FunctionSpace) -> npt.NDArray[np.int32]:
7-
"""Compute a mapping from vertices to dofs in a function space
8-
9-
Parameters
10-
----------
11-
V : dolfinx.fem.FunctionSpace
12-
The function space
13-
14-
Returns
15-
-------
16-
npt.NDArray[np.int32]
17-
The mapping from vertices to dofs
18-
"""
19-
mesh = V.mesh
20-
num_vertices_per_cell = dolfinx.cpp.mesh.cell_num_entities(mesh.topology.cell_type, 0)
21-
22-
dof_layout = np.empty((num_vertices_per_cell,), dtype=np.int32)
23-
for i in range(num_vertices_per_cell):
24-
var = V.dofmap.dof_layout.entity_dofs(0, i)
25-
assert len(var) == 1
26-
dof_layout[i] = var[0]
27-
28-
num_vertices = mesh.topology.index_map(0).size_local + mesh.topology.index_map(0).num_ghosts
29-
30-
c_to_v = mesh.topology.connectivity(mesh.topology.dim, 0)
31-
assert (c_to_v.offsets[1:] - c_to_v.offsets[:-1] == c_to_v.offsets[1]).all(), (
32-
"Single cell type supported"
33-
)
34-
35-
vertex_to_dof_map = np.empty(num_vertices, dtype=np.int32)
36-
vertex_to_dof_map[c_to_v.array] = V.dofmap.list[:, dof_layout].reshape(-1)
37-
return vertex_to_dof_map
38-
39-
40-
def unroll_dofmap(dofs: npt.NDArray[np.int32], bs: int) -> npt.NDArray[np.int32]:
41-
"""
42-
Given a two-dimensional dofmap of size `(num_cells, num_dofs_per_cell)`
43-
Expand the dofmap by its block size such that the resulting array
44-
is of size `(num_cells, bs*num_dofs_per_cell)`
45-
"""
46-
num_cells, num_dofs_per_cell = dofs.shape
47-
unrolled_dofmap = np.repeat(dofs, bs).reshape(num_cells, num_dofs_per_cell * bs) * bs
48-
unrolled_dofmap += np.tile(np.arange(bs), num_dofs_per_cell)
49-
return unrolled_dofmap
4+
import scifem
5+
import ufl
506

517

528
def evaluate_at_vertex_tag(
@@ -72,9 +28,9 @@ def evaluate_at_vertex_tag(
7228
npt.NDArray[np.int32]
7329
The values of `u` at the vertices tagged with `tag`
7430
"""
75-
v2d = vertex_to_dofmap(u.function_space)
31+
v2d = scifem.vertex_to_dofmap(u.function_space)
7632
block_index = v2d[vt.find(tag)]
77-
dofs = unroll_dofmap(block_index.reshape(-1, 1), u.function_space.dofmap.bs)
33+
dofs = scifem.utils.unroll_dofmap(block_index.reshape(-1, 1), u.function_space.dofmap.bs)
7834
return u.x.array[dofs]
7935

8036

@@ -115,3 +71,32 @@ def gather_broadcast_array(comm, local_array):
11571
else:
11672
global_array = np.array([])
11773
return comm.bcast(global_array, root=0)
74+
75+
76+
def matrix_is_zero(A: ufl.core.expr.Expr) -> bool:
77+
n = ufl.domain.find_geometric_dimension(A)
78+
for i in range(n):
79+
for j in range(n):
80+
value = dolfinx.fem.assemble_scalar(dolfinx.fem.form(A[i, j] * ufl.dx))
81+
print(i, j, value)
82+
is_zero = np.isclose(value, 0)
83+
if not is_zero:
84+
return False
85+
return True
86+
87+
88+
def float2object(
89+
f: float,
90+
obj_str: str,
91+
mesh: dolfinx.mesh.Mesh,
92+
V: dolfinx.fem.FunctionSpace,
93+
):
94+
if obj_str == "float":
95+
return f
96+
if obj_str == "Constant":
97+
return dolfinx.fem.Constant(mesh, f)
98+
if obj_str == "Function":
99+
v = dolfinx.fem.Function(V)
100+
v.x.array[:] = f
101+
return v
102+
raise ValueError(f"Invalid object string {obj_str!r}")

tests/test_invariants.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import numpy as np
33
import pytest
44
import ufl
5-
import utils
65

76
from pulse import invariants, kinematics
87

@@ -11,7 +10,7 @@
1110
"cls, expected",
1211
(
1312
(kinematics.DeformationGradient, 4 * 3),
14-
(utils.IsochoricDeformationGradient, pow(8, -2 / 3) * 4 * 3),
13+
(kinematics.IsochoricDeformationGradient_from_u, pow(8, -2 / 3) * 4 * 3),
1514
),
1615
)
1716
def test_I1(cls, expected, u) -> None:
@@ -30,7 +29,7 @@ def test_I1(cls, expected, u) -> None:
3029
(
3130
(kinematics.DeformationGradient, 0.5 * ((4 * 3) ** 2 - (4**2) * 3)),
3231
(
33-
utils.IsochoricDeformationGradient,
32+
kinematics.IsochoricDeformationGradient_from_u,
3433
0.5 * (((pow(8, -2 / 3) * 4 * 3) ** 2) - ((pow(8, -2 / 3) * 4) ** 2) * 3),
3534
),
3635
),
@@ -49,7 +48,7 @@ def test_I2(cls, expected, u) -> None:
4948
"cls, expected",
5049
(
5150
(kinematics.DeformationGradient, 4**3),
52-
(utils.IsochoricDeformationGradient, (pow(8, -2 / 3) * 4) ** 3),
51+
(kinematics.IsochoricDeformationGradient_from_u, (pow(8, -2 / 3) * 4) ** 3),
5352
),
5453
)
5554
def test_I3(cls, expected, u) -> None:
@@ -67,7 +66,7 @@ def test_I3(cls, expected, u) -> None:
6766
"cls, expected",
6867
(
6968
(kinematics.DeformationGradient, 4),
70-
(utils.IsochoricDeformationGradient, pow(8, -2 / 3) * 4),
69+
(kinematics.IsochoricDeformationGradient_from_u, pow(8, -2 / 3) * 4),
7170
),
7271
)
7372
def test_I4(cls, expected, u, mesh) -> None:
@@ -86,7 +85,7 @@ def test_I4(cls, expected, u, mesh) -> None:
8685
"cls, expected",
8786
(
8887
(kinematics.DeformationGradient, 4**2),
89-
(utils.IsochoricDeformationGradient, (pow(8, -2 / 3) * 4) ** 2),
88+
(kinematics.IsochoricDeformationGradient_from_u, (pow(8, -2 / 3) * 4) ** 2),
9089
),
9190
)
9291
def test_I5(cls, expected, u, mesh) -> None:
@@ -103,7 +102,7 @@ def test_I5(cls, expected, u, mesh) -> None:
103102

104103
@pytest.mark.parametrize(
105104
"cls, expected",
106-
((kinematics.DeformationGradient, 0), (utils.IsochoricDeformationGradient, 0)),
105+
((kinematics.DeformationGradient, 0), (kinematics.IsochoricDeformationGradient_from_u, 0)),
107106
)
108107
def test_I8(cls, expected, u, mesh) -> None:
109108
u.interpolate(lambda x: x)

tests/test_kinematics.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import pytest
22
import ufl
3-
import utils
43

5-
from pulse import kinematics
4+
from pulse import kinematics, utils
65

76

87
def test_SecondOrderIdentity(u) -> None:
@@ -13,7 +12,7 @@ def test_SecondOrderIdentity(u) -> None:
1312
"cls, factor",
1413
(
1514
(kinematics.DeformationGradient, 2),
16-
(utils.IsochoricDeformationGradient, pow(8, -1 / 3) * 2),
15+
(kinematics.IsochoricDeformationGradient_from_u, pow(8, -1 / 3) * 2),
1716
),
1817
)
1918
def test_DeformationGradient(cls, factor, u) -> None:
@@ -47,7 +46,7 @@ def test_DeformationGradient(cls, factor, u) -> None:
4746
"cls, factor",
4847
(
4948
(kinematics.DeformationGradient, 4),
50-
(utils.IsochoricDeformationGradient, pow(8, -2 / 3) * 4),
49+
(kinematics.IsochoricDeformationGradient_from_u, pow(8, -2 / 3) * 4),
5150
),
5251
)
5352
def test_RightCauchyGreen(cls, factor, u) -> None:
@@ -63,7 +62,7 @@ def test_RightCauchyGreen(cls, factor, u) -> None:
6362
"cls, factor",
6463
(
6564
(kinematics.DeformationGradient, 4),
66-
(utils.IsochoricDeformationGradient, pow(8, -2 / 3) * 4),
65+
(kinematics.IsochoricDeformationGradient_from_u, pow(8, -2 / 3) * 4),
6766
),
6867
)
6968
def test_LeftCauchyGreen(cls, factor, u) -> None:
@@ -79,7 +78,7 @@ def test_LeftCauchyGreen(cls, factor, u) -> None:
7978
"cls, factor",
8079
(
8180
(kinematics.DeformationGradient, 1),
82-
(utils.IsochoricDeformationGradient, pow(8, -1 / 3) * 2 - 1),
81+
(kinematics.IsochoricDeformationGradient_from_u, pow(8, -1 / 3) * 2 - 1),
8382
),
8483
)
8584
def test_EngineeringStrain(cls, factor, u) -> None:
@@ -95,7 +94,7 @@ def test_EngineeringStrain(cls, factor, u) -> None:
9594
"cls, factor",
9695
(
9796
(kinematics.DeformationGradient, 1.5),
98-
(utils.IsochoricDeformationGradient, 0.5 * (pow(8, -2 / 3) * 4 - 1)),
97+
(kinematics.IsochoricDeformationGradient_from_u, 0.5 * (pow(8, -2 / 3) * 4 - 1)),
9998
),
10099
)
101100
def test_GreenLagrangeStrain(cls, factor, u) -> None:

tests/test_material_models.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import dolfinx
44
import pytest
55
import ufl
6-
import utils
76

87
import pulse
98

@@ -12,7 +11,7 @@
1211
def test_linear_elastic_model(obj_str, mesh, P1, u) -> None:
1312
E = 2.0
1413
_nu = 0.2
15-
nu = utils.float2object(f=_nu, obj_str=obj_str, mesh=mesh, V=P1)
14+
nu = pulse.utils.float2object(f=_nu, obj_str=obj_str, mesh=mesh, V=P1)
1615
model = pulse.LinearElastic(E=pulse.Variable(E, "Pa"), nu=nu)
1716

1817
u.interpolate(lambda x: x)
@@ -23,14 +22,14 @@ def test_linear_elastic_model(obj_str, mesh, P1, u) -> None:
2322
sigma = model.sigma(F)
2423
I = ufl.Identity(3)
2524
zero = sigma - (E / (1 + _nu)) * (1 + (_nu / (1 - 2 * _nu)) * 3) * I
26-
assert utils.matrix_is_zero(zero)
25+
assert pulse.utils.matrix_is_zero(zero)
2726

2827

2928
@pytest.mark.parametrize("obj_str", ("float", "Constant", "Function"))
3029
def test_linear_elastic_model_with_invalid_range(obj_str, mesh, P1) -> None:
3130
E = pulse.Variable(2.0, "kPa")
3231
_nu = 0.5
33-
nu = utils.float2object(f=_nu, obj_str=obj_str, mesh=mesh, V=P1)
32+
nu = pulse.utils.float2object(f=_nu, obj_str=obj_str, mesh=mesh, V=P1)
3433

3534
with pytest.raises(pulse.exceptions.InvalidRangeError):
3635
pulse.LinearElastic(E=E, nu=nu)

tests/test_utils.py

Lines changed: 0 additions & 36 deletions
This file was deleted.

tests/utils.py

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)