From 3b5acc651abb9148a52e6fd9015ccc334894b35f Mon Sep 17 00:00:00 2001 From: nate-sime <> Date: Thu, 8 Feb 2024 15:08:20 -0700 Subject: [PATCH] update with pointcloud plotting and v0.8.0.0 --- .github/workflows/run_tests.yml | 2 +- examples/demo_bad_fe_problem.py | 2 +- examples/demo_debug_plotting.py | 6 +++--- examples/demo_ksp_monitors.py | 2 +- examples/demo_plotting.py | 12 ++++++------ febug/__init__.py | 3 ++- febug/plot.py | 21 +++++++++++++++++--- setup.py | 4 ++-- test/test_fem.py | 2 +- test/test_nls.py | 2 +- test/test_plot.py | 34 ++++++++++++++++++++++----------- 11 files changed, 59 insertions(+), 31 deletions(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index ee551b3..e5705c8 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -8,7 +8,7 @@ on: jobs: Run-Tests: runs-on: ubuntu-latest - container: dolfinx/dolfinx:v0.7.3 + container: dolfinx/dolfinx:nightly steps: - uses: actions/checkout@v3 diff --git a/examples/demo_bad_fe_problem.py b/examples/demo_bad_fe_problem.py index aae3f72..6c7c508 100644 --- a/examples/demo_bad_fe_problem.py +++ b/examples/demo_bad_fe_problem.py @@ -10,7 +10,7 @@ mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 4, 4) -V = dolfinx.fem.FunctionSpace(mesh, ("CG", 1)) +V = dolfinx.fem.functionspace(mesh, ("CG", 1)) v = ufl.TestFunction(V) u = dolfinx.fem.Function(V) diff --git a/examples/demo_debug_plotting.py b/examples/demo_debug_plotting.py index 6f48dbf..93a6f51 100644 --- a/examples/demo_debug_plotting.py +++ b/examples/demo_debug_plotting.py @@ -17,13 +17,13 @@ febug.plot_mesh(mesh, plotter=subplotter) # -- CG1 dofmap and ordering -V = dolfinx.fem.FunctionSpace(mesh, ("CG", 1)) +V = dolfinx.fem.functionspace(mesh, ("CG", 1)) subplotter.subplot(0, 1) subplotter.add_title("CG1 dofmap") febug.plot_dofmap(V, plotter=subplotter) # -- CG2 dofmap and ordering -V = dolfinx.fem.FunctionSpace(mesh, ("CG", 2)) +V = dolfinx.fem.functionspace(mesh, ("CG", 2)) subplotter.subplot(0, 2) subplotter.add_title("CG2 dofmap") febug.plot_dofmap(V, plotter=subplotter) @@ -40,7 +40,7 @@ for e_i, e in enumerate(eles): subplotter.subplot(2, e_i) subplotter.add_title(f"{e[0]}{e[1]} space DoFs") - V = dolfinx.fem.FunctionSpace(mesh, e) + V = dolfinx.fem.functionspace(mesh, e) u = dolfinx.fem.Function(V) u.interpolate(lambda x: x[0]*x[1]) febug.plot_function(u, plotter=subplotter) diff --git a/examples/demo_ksp_monitors.py b/examples/demo_ksp_monitors.py index b9623b7..e0bbf8d 100644 --- a/examples/demo_ksp_monitors.py +++ b/examples/demo_ksp_monitors.py @@ -23,7 +23,7 @@ x = ufl.SpatialCoordinate(mesh) f = ufl.sin(ufl.pi*x[0])*ufl.sin(ufl.pi*x[1])*ufl.sin(ufl.pi*x[2]) -V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 2)) +V = dolfinx.fem.functionspace(mesh, ("Lagrange", 2)) u = ufl.TrialFunction(V) v = ufl.TestFunction(V) a = dolfinx.fem.form(inner(grad(u), grad(v)) * dx) diff --git a/examples/demo_plotting.py b/examples/demo_plotting.py index 13e2b18..28f6ae1 100644 --- a/examples/demo_plotting.py +++ b/examples/demo_plotting.py @@ -20,7 +20,7 @@ # -- function subplotter.subplot(0, 1) subplotter.add_title("CG1") -V = dolfinx.fem.FunctionSpace(mesh, ("CG", 1)) +V = dolfinx.fem.functionspace(mesh, ("CG", 1)) u = dolfinx.fem.Function(V) u.interpolate(lambda x: np.sin(np.pi*x[0])*np.sin(np.pi*x[1])) febug.plot_function(u, plotter=subplotter) @@ -28,7 +28,7 @@ # -- high order function subplotter.subplot(0, 2) subplotter.add_title("CG2") -V = dolfinx.fem.FunctionSpace(mesh, ("CG", 2)) +V = dolfinx.fem.functionspace(mesh, ("CG", 2)) u = dolfinx.fem.Function(V) u.interpolate(lambda x: np.sin(np.pi*x[0])*np.sin(np.pi*x[1])) febug.plot_function(u, plotter=subplotter) @@ -36,10 +36,10 @@ # -- vector function magnitude subplotter.subplot(1, 0) subplotter.add_title("magnitude") -V = dolfinx.fem.VectorFunctionSpace(mesh, ("CG", 1)) +V = dolfinx.fem.functionspace(mesh, ("CG", 1, (2,))) u = dolfinx.fem.Function(V, dtype=np.float64) u.interpolate(lambda x: np.stack((-x[1], x[0]))) -u_scalar = dolfinx.fem.Function(dolfinx.fem.FunctionSpace(mesh, ("CG", 1))) +u_scalar = dolfinx.fem.Function(dolfinx.fem.functionspace(mesh, ("CG", 1))) u_scalar.interpolate(dolfinx.fem.Expression(ufl.inner(u, u), u_scalar.function_space.element.interpolation_points())) febug.plot_function(u_scalar, plotter=subplotter) @@ -47,7 +47,7 @@ # -- vector function subplotter.subplot(1, 1) subplotter.add_title("quiver") -V = dolfinx.fem.VectorFunctionSpace(mesh, ("CG", 1)) +V = dolfinx.fem.functionspace(mesh, ("CG", 1, (2,))) u = dolfinx.fem.Function(V) u.interpolate(lambda x: np.stack((-x[1], x[0]))) febug.plot_quiver(u, plotter=subplotter) @@ -55,7 +55,7 @@ # -- warp subplotter.subplot(1, 2) subplotter.add_title("warp") -V = dolfinx.fem.VectorFunctionSpace(mesh, ("CG", 1)) +V = dolfinx.fem.functionspace(mesh, ("CG", 1, (2,))) u = dolfinx.fem.Function(V) u.interpolate(lambda x: np.stack((-x[1], x[0]))) febug.plot_warp(u, plotter=subplotter) diff --git a/febug/__init__.py b/febug/__init__.py index 82e504e..0b3c3f9 100644 --- a/febug/__init__.py +++ b/febug/__init__.py @@ -4,7 +4,8 @@ plot_streamlines_evenly_spaced_2D, plot_streamlines_from_source, plot_entity_indices, - plot_mesh_quality, plot_function_dofs) + plot_mesh_quality, plot_function_dofs, + plot_point_cloud) def overload_dolfinx(): diff --git a/febug/plot.py b/febug/plot.py index 76d2d85..c1dbd86 100644 --- a/febug/plot.py +++ b/febug/plot.py @@ -19,7 +19,7 @@ def _to_pyvista_grid(mesh: dolfinx.mesh.Mesh, tdim: int, @_to_pyvista_grid.register -def _(V: dolfinx.fem.FunctionSpaceBase): +def _(V: dolfinx.fem.FunctionSpace): return pyvista.UnstructuredGrid(*dolfinx.plot.vtk_mesh(V)) @@ -40,7 +40,7 @@ def _(u: dolfinx.fem.Function): if np.iscomplexobj(dof_values): dof_values = dof_values.real - if V.ufl_element().degree() == 0: + if V.ufl_element().degree == 0: grid = _to_pyvista_grid(mesh, mesh.topology.dim) num_dofs_local = V.dofmap.index_map.size_local grid.cell_data[u.name] = dof_values[:num_dofs_local] @@ -242,7 +242,7 @@ def plot_streamlines_from_source( return plotter -def plot_dofmap(V: dolfinx.fem.FunctionSpaceBase, plotter: pyvista.Plotter=None): +def plot_dofmap(V: dolfinx.fem.FunctionSpace, plotter: pyvista.Plotter=None): if plotter is None: plotter = pyvista.Plotter() mesh = V.mesh @@ -354,6 +354,21 @@ def plot_entity_indices(mesh: dolfinx.mesh.Mesh, tdim: int, return plotter +def plot_point_cloud(xp: np.ndarray[float], + plotter: pyvista.Plotter=None): + if plotter is None: + plotter = pyvista.Plotter() + + pv_point_cloud = pyvista.PolyData(xp) + plotter.add_mesh(pv_point_cloud) + + if np.all(np.isclose(xp[:,2], 0.0)): + plotter.enable_parallel_projection() + plotter.view_xy() + + return plotter + + def plot_mesh_quality(mesh: dolfinx.mesh.Mesh, tdim: int, plotter: pyvista.Plotter=None, quality_measure: str="scaled_jacobian", diff --git a/setup.py b/setup.py index 34ea541..ca555ab 100644 --- a/setup.py +++ b/setup.py @@ -13,9 +13,9 @@ print("Python 3.10 or higher required, please upgrade.") sys.exit(1) -VERSION = "2024.0.1" +VERSION = "0.8.0" -REQUIREMENTS = ["pyvista", "fenics-dolfinx>0.7.0.dev0"] +REQUIREMENTS = ["pyvista", "fenics-dolfinx>0.8.0"] class CMakeExtension(Extension): diff --git a/test/test_fem.py b/test/test_fem.py index 169cc6a..6958c00 100644 --- a/test/test_fem.py +++ b/test/test_fem.py @@ -9,7 +9,7 @@ def test_petsc_object_count_limit(): mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 4, 4) - V = dolfinx.fem.FunctionSpace(mesh, ("CG", 1)) + V = dolfinx.fem.functionspace(mesh, ("CG", 1)) v = ufl.TestFunction(V) u = dolfinx.fem.Function(V) diff --git a/test/test_nls.py b/test/test_nls.py index 86e907c..940e9c9 100644 --- a/test/test_nls.py +++ b/test/test_nls.py @@ -11,7 +11,7 @@ (lambda x: x[0]+1, False))) def test_singularity_finder_residual(u_lmbda_has_zero): mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 4, 4) - V = dolfinx.fem.FunctionSpace(mesh, ("CG", 1)) + V = dolfinx.fem.functionspace(mesh, ("CG", 1)) v = ufl.TestFunction(V) u_lmbda, has_zero = u_lmbda_has_zero diff --git a/test/test_plot.py b/test/test_plot.py index 6e2f4d9..5cc4880 100644 --- a/test/test_plot.py +++ b/test/test_plot.py @@ -20,14 +20,14 @@ @pytest.mark.parametrize("mesh", meshes1D + meshes2D + meshes3D) @pytest.mark.parametrize("p", [1, 2]) def test_plot_function_cg(p, mesh): - u = dolfinx.fem.Function(dolfinx.fem.FunctionSpace(mesh, ("CG", p))) + u = dolfinx.fem.Function(dolfinx.fem.functionspace(mesh, ("CG", p))) febug.plot_function(u) @pytest.mark.parametrize("mesh", meshes1D + meshes2D + meshes3D) @pytest.mark.parametrize("p", [0, 1, 2]) def test_plot_function_dg(p, mesh): - u = dolfinx.fem.Function(dolfinx.fem.FunctionSpace(mesh, ("DG", p))) + u = dolfinx.fem.Function(dolfinx.fem.functionspace(mesh, ("DG", p))) febug.plot_function(u) @@ -38,7 +38,7 @@ def test_plot_function_dg(p, mesh): for msh in meshes1D + meshes2D + meshes3D]) @pytest.mark.parametrize("p", [1, 2]) def test_plot_warp(p, mesh): - u = dolfinx.fem.Function(dolfinx.fem.VectorFunctionSpace(mesh, ("CG", p))) + u = dolfinx.fem.Function(dolfinx.fem.functionspace(mesh, ("CG", p, (mesh.geometry.dim,)))) febug.plot_warp(u) @@ -49,7 +49,7 @@ def test_plot_warp(p, mesh): for msh in meshes1D + meshes2D + meshes3D]) @pytest.mark.parametrize("p", [1, 2]) def test_plot_quiver(p, mesh): - u = dolfinx.fem.Function(dolfinx.fem.VectorFunctionSpace(mesh, ("CG", p))) + u = dolfinx.fem.Function(dolfinx.fem.functionspace(mesh, ("CG", p, (mesh.geometry.dim,)))) febug.plot_quiver(u) @@ -60,7 +60,7 @@ def test_plot_quiver(p, mesh): for msh in meshes1D + meshes2D + meshes3D]) @pytest.mark.parametrize("p", [1, 2]) def test_plot_streamlines_evenly_spaced_2D(p, mesh): - u = dolfinx.fem.Function(dolfinx.fem.VectorFunctionSpace(mesh, ("CG", p))) + u = dolfinx.fem.Function(dolfinx.fem.functionspace(mesh, ("CG", p, (mesh.geometry.dim,)))) febug.plot_streamlines_evenly_spaced_2D(u, start_position=(0.5, 0.5, 0.0)) @@ -71,7 +71,7 @@ def test_plot_streamlines_evenly_spaced_2D(p, mesh): for msh in meshes1D + meshes2D + meshes3D]) @pytest.mark.parametrize("p", [1, 2]) def test_plot_streamlines_from_source(p, mesh): - u = dolfinx.fem.Function(dolfinx.fem.VectorFunctionSpace(mesh, ("CG", p))) + u = dolfinx.fem.Function(dolfinx.fem.functionspace(mesh, ("CG", p, (mesh.geometry.dim,)))) pt_cloud_source = pyvista.PolyData(mesh.geometry.x) febug.plot_streamlines_from_source(u, pt_cloud_source, max_time=1.0) @@ -89,16 +89,16 @@ def test_plot_mesh(mesh): @pytest.mark.parametrize("mesh", meshes1D + meshes2D + meshes3D) @pytest.mark.parametrize("p", [1, 2]) def test_plot_dofmap(p, mesh): - V = dolfinx.fem.FunctionSpace(mesh, ("CG", p)) + V = dolfinx.fem.functionspace(mesh, ("CG", p)) febug.plot_dofmap(V) -_plot_elements = [("CG", 1), ("CG", 2), ("DG", 0), ("DG", 1)] +_plot_elements = (("CG", 1), ("CG", 2), ("DG", 0), ("DG", 1)) @pytest.mark.parametrize("mesh", meshes1D + meshes2D + meshes3D) @pytest.mark.parametrize("e", _plot_elements) def test_plot_function_dofs(e, mesh): - V = dolfinx.fem.FunctionSpace(mesh, e) + V = dolfinx.fem.functionspace(mesh, e) u = dolfinx.fem.Function(V) febug.plot_function_dofs(u, fmt=".3e") @@ -107,7 +107,7 @@ def test_plot_function_dofs(e, mesh): @pytest.mark.parametrize("mesh", meshes1D + meshes2D + meshes3D) @pytest.mark.parametrize("e", _plot_elements) def test_plot_vector_function_dofs(e, mesh, vec_dim): - V = dolfinx.fem.VectorFunctionSpace(mesh, e, dim=vec_dim) + V = dolfinx.fem.functionspace(mesh, (*e, (vec_dim,))) u = dolfinx.fem.Function(V) febug.plot_function_dofs(u, fmt=".3e") @@ -125,7 +125,10 @@ def test_plot_meshtags(mesh): @pytest.mark.parametrize("mesh", meshes1D + meshes2D + meshes3D) def test_plot_mesh_quality(mesh): for d in range(1, mesh.topology.dim+1): - febug.plot_mesh_quality(mesh, d) + mesh.topology.create_entities(d) + febug.plot_mesh_quality( + mesh, d, + entities=np.arange(mesh.topology.index_map(d).size_local)) @pytest.mark.parametrize("mesh", meshes1D + meshes2D + meshes3D) @@ -133,3 +136,12 @@ def test_plot_entity_indices(mesh): for d in range(mesh.topology.dim+1): mesh.topology.create_entities(d) febug.plot_entity_indices(mesh, d) + + +@pytest.mark.parametrize("dim", [1, 2, 3]) +def test_plot_point_cloud(dim): + np.random.seed(1) + pc = np.random.rand(10, 3) + if dim < 3: + pc[:,(3-dim):] = 0.0 + febug.plot_point_cloud(pc)