Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use mesh tangling checker #103

Merged
merged 8 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions movement/laplacian_smoothing.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,6 @@ def move(self, time, update_boundary_velocity=None, boundary_conditions=None):
self.displacement[:] = self.v.dat.data_with_halos * self.dt
self.x.dat.data_with_halos[:] += self.displacement
self.mesh.coordinates.assign(self.x)

if hasattr(self, "tangling_checker"):
self.tangling_checker.check()
3 changes: 3 additions & 0 deletions movement/monge_ampere.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ def _update_coordinates(self):
self.x.assign(self.xi + self.grad_phi)
self.mesh.coordinates.assign(self.x)

if hasattr(self, "tangling_checker"):
self.tangling_checker.check()

@property
@PETSc.Log.EventDecorator()
def l2_projector(self):
Expand Down
22 changes: 20 additions & 2 deletions movement/mover.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from firedrake.cython.dmcommon import create_section
from firedrake.petsc import PETSc

from movement.tangling import MeshTanglingChecker

__all__ = ["PrimeMover"]


Expand All @@ -15,7 +17,12 @@ class PrimeMover:
"""

def __init__(
self, mesh, monitor_function=None, raise_convergence_errors=True, **kwargs
self,
mesh,
monitor_function=None,
raise_convergence_errors=True,
tangling_check=None,
**kwargs,
):
r"""
:arg mesh: the physical mesh
Expand All @@ -25,7 +32,10 @@ def __init__(
:kwarg raise_convergence_errors: convergence error handling behaviour: if `True`
then :class:`~.ConvergenceError`\s are raised, else warnings are raised and
the program is allowed to continue
:kwarg raise_convergence_errors: :class:`bool`
:type raise_convergence_errors: :class:`bool`
:kwarg tangling_check: check whether the mesh has tangled elements (by default
on in the 2D case and off otherwise)
:type tangling_check: :class:`bool`
"""
self.mesh = firedrake.Mesh(mesh.coordinates.copy(deepcopy=True))
self.monitor_function = monitor_function
Expand Down Expand Up @@ -55,6 +65,14 @@ def __init__(
)
self.v = firedrake.Function(self.coord_space, name="Mesh velocity")

# Utilities
if tangling_check is None:
tangling_check = self.dim == 2
if tangling_check:
self.tangling_checker = MeshTanglingChecker(
self.mesh, raise_error=raise_convergence_errors
)

def _convergence_message(self, iterations=None):
"""
Report solver convergence.
Expand Down
3 changes: 3 additions & 0 deletions movement/spring.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ def move(self, time, update_boundary_displacement=None, boundary_conditions=None
self.mesh.coordinates.dat.data_with_halos[:] += self.displacement.reshape(shape)
self._update_plex_coordinates()

if hasattr(self, "tangling_checker"):
self.tangling_checker.check()


class SpringMover_Torsional(SpringMover_Lineal):
"""
Expand Down
6 changes: 3 additions & 3 deletions movement/tangling.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import firedrake
import ufl
from firedrake.__future__ import interpolate

__all__ = ["MeshTanglingChecker"]

Expand All @@ -28,12 +29,11 @@ def __init__(self, mesh, raise_error=True):
# Store initial signs of Jacobian determinant
P0 = firedrake.FunctionSpace(mesh, "DG", 0)
detJ = ufl.JacobianDeterminant(mesh)
s = firedrake.Function(P0)
s.interpolate(ufl.sign(detJ))
s = firedrake.assemble(interpolate(ufl.sign(detJ), P0))

# Get scaled Jacobian expression
P0_ten = firedrake.TensorFunctionSpace(mesh, "DG", 0)
J = firedrake.interpolate(ufl.Jacobian(mesh), P0_ten)
J = firedrake.assemble(interpolate(ufl.Jacobian(mesh), P0_ten))
edge1 = ufl.as_vector([J[0, 0], J[1, 0]])
edge2 = ufl.as_vector([J[0, 1], J[1, 1]])
edge3 = edge1 - edge2
Expand Down
7 changes: 7 additions & 0 deletions test/test_monge_ampere.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ def test_no_monitor_valueerror(self):
MongeAmpereMover(self.dummy_mesh, None)
self.assertEqual(str(cm.exception), "Please supply a monitor function.")

def test_tangling_valueerror(self):
mover = MongeAmpereMover(self.mesh(2, n=3), ring_monitor)
mover.xi.dat.data[3] += 0.2
with self.assertRaises(ValueError) as cm:
mover.move()
self.assertEqual(str(cm.exception), "Mesh has 1 tangled element.")

@parameterized.expand(
[(2, "relaxation"), (2, "quasi_newton"), (3, "relaxation"), (3, "quasi_newton")]
)
Expand Down
11 changes: 10 additions & 1 deletion test/test_spring.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ def test_convergence_error(self):
mover.move(0)
self.assertEqual(str(cm.exception), "Solver failed to converge.")

def test_tangling_valueerror(self):
mover = SpringMover(UnitSquareMesh(3, 3), 1.0)
mover.mesh.coordinates.dat.data[3] += 0.2
with self.assertRaises(ValueError) as cm:
mover.move(0)
self.assertEqual(str(cm.exception), "Mesh has 1 tangled element.")


class TestStiffness(unittest.TestCase):
"""
Expand Down Expand Up @@ -191,7 +198,9 @@ def test_force_right_free(self):
def test_force_right_fixed(self):
mesh = UnitSquareMesh(10, 10)
coord_array = mesh.coordinates.dat.data
new_mesh = self.move(mesh, moving_boundary_tags=1, fixed_boundary_tags=2)
new_mesh = self.move(
mesh, moving_boundary_tags=1, fixed_boundary_tags=2, vector=[0.1, 0]
)
new_coord_array = new_mesh.coordinates.dat.data
self.assertFalse(np.allclose(coord_array, new_coord_array))
# # TODO: Implement no-slip BCs for segments 3 and 4 (#99)
Expand Down
Loading