Input for mesh refinement with refine_plaza

Dear FEniCS community.

I’m trying to use the refine_plaza function in order to consider a criterium for refinement.

I have followed Mesh refinement in dolfinx - #2 by dokken and considered the following MWE.

import dolfinx
from mpi4py import MPI
import numpy as np


def cell_criterion(x):
    """Given mesh coordinates, return if each point 
    satisfies x[0]<0.3 or x[1]>0.4

    :param x: Input coordinates, shape (num_points, 3)
    :returns: Boolean array of shape (num_points, )
    """
    return (x[0] < 0.3) | (x[1] > 0.4)


mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 4, 4)

# Compute midpoints for all cells on process
cells_local = np.arange(mesh.topology.index_map(
    mesh.topology.dim).size_local, dtype=np.int32)
midpoints = dolfinx.mesh.compute_midpoints(
    mesh, mesh.topology.dim, cells_local).T

# Check midpoint criterion and find edges connected to cells
should_refine = np.flatnonzero(cell_criterion(midpoints)).astype(np.int32)
mesh.topology.create_entities(1)
local_edges = dolfinx.mesh.compute_incident_entities(
    mesh.topology, should_refine, mesh.topology.dim, 1)
fine_mesh, parent_cell, parent_facet = dolfinx.mesh.refine_plaza(
    mesh, local_edges, False, dolfinx.mesh.RefinementOption.parent_cell_and_facet)

But I get the error on the refine_plaza function

TypeError: refine_plaza(): incompatible function arguments. The following argument types are supported:
    1. (mesh: dolfinx.cpp.mesh.Mesh_float32, redistribute: bool, option: dolfinx.cpp.refinement.RefinementOption) -> Tuple[dolfinx.cpp.mesh.Mesh_float32, numpy.ndarray[numpy.int32], numpy.ndarray[numpy.int8]]
    2. (mesh: dolfinx.cpp.mesh.Mesh_float64, redistribute: bool, option: dolfinx.cpp.refinement.RefinementOption) -> Tuple[dolfinx.cpp.mesh.Mesh_float64, numpy.ndarray[numpy.int32], numpy.ndarray[numpy.int8]]
    3. (mesh: dolfinx.cpp.mesh.Mesh_float32, edges: numpy.ndarray[numpy.int32], redistribute: bool, option: dolfinx.cpp.refinement.RefinementOption) -> Tuple[dolfinx.cpp.mesh.Mesh_float32, numpy.ndarray[numpy.int32], numpy.ndarray[numpy.int8]]
    4. (mesh: dolfinx.cpp.mesh.Mesh_float64, edges: numpy.ndarray[numpy.int32], redistribute: bool, option: dolfinx.cpp.refinement.RefinementOption) -> Tuple[dolfinx.cpp.mesh.Mesh_float64, numpy.ndarray[numpy.int32], numpy.ndarray[numpy.int8]]

Invoked with: <dolfinx.cpp.mesh.Mesh_float64 object at 0x7fa3de0b5df0>, array([ 8, 10, 13, 14, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
       30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
       47, 48, 49, 50, 51, 52, 53, 54, 55], dtype=int32), False

If I remove local_edges the code runs but using uniform refinements.

Any help is appreciated.

1 Like

I don’t have the scope to run your code, but perhaps the following could help elucidate the arguments to the function: leopart-x/demo/demo_rayleigh-taylor-instability/demo_adaptive-mesh.py at main · LEoPart-project/leopart-x · GitHub

Quickly scanning your code vs mine, your issue could be as simple as needing to pass mesh._cpp_object rather than the python wrapped mesh.

Thanks Nate.

I tried your suggestion and got the error:

File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/mesh.py", line 322, in refine_plaza
    mesh1, cells, facets = _cpp.refinement.refine_plaza(mesh._cpp_object, edges, redistribute)
AttributeError: 'dolfinx.cpp.mesh.Mesh_float64' object has no attribute '_cpp_object'

BTW I’m using the dolfinx docker image v.0.7.3

Try manually applying the fix that you see in Fix input arguments to dolfinx.mesh.refine_plaza by francesco-ballarin · Pull Request #3018 · FEniCS/dolfinx · GitHub to your docker image by editing python/dolfinx/mesh.py in your installation. It seems to me that there is a mistake in the wrappers of the C++ interface.

1 Like

Thanks Francesco.

Manually applying the fix solves the problem.

Same error message encountered with the calling of refined_mesh = mesh.refine(old_mesh, edges, redistribute=False). Guess the same issue with it. Not sure how to correct it with the suggested pull request. Any help?

Please provide what version of DOLFINx you are running. Can you make a 5 line example (trying to refine a unit square) that reproduces the issue?

DOLFINx version 0.7.3

I found that is due to I messed up dolfinx.mesh.Mesh and dolfinx.cpp.mesh.Mesh_float64, where I should use dolfinx.mesh.Mesh mesh1 to do mesh.refine rather than dolfinx.cpp.mesh.Mesh_float64 mesh2. In my implementation, I load once a coarse background mesh mesh0 and then copy it to mesh1 as active mesh for refinement. But mesh0 is changed accordingly as mesh1 changes.

MWE:

from mpi4py import MPI
from dolfinx import mesh, cpp
import numpy as np
mesh0 = mesh.create_unit_square(MPI.COMM_WORLD, 2, 2)                      # 'dolfinx.mesh.Mesh'
mesh1 = mesh.Mesh(mesh0._cpp_object, mesh0.ufl_domain())                   # 'dolfinx.mesh.Mesh'
mesh2 = cpp.mesh.Mesh_float64(mesh0.comm, mesh0.topology, mesh0.geometry)  # 'dolfinx.cpp.mesh.Mesh_float64'
mesh1.geometry.x[:, :] *= 2                      # change mesh1
print("mesh0:\n", mesh0.geometry.x, "\n")        # but mesh0 is also changed
print("mesh1:\n", mesh1.geometry.x, "\n")
print("mesh2:\n", mesh2.geometry.x, "\n")

mesh1.topology.create_entities(1)
new_mesh1 = mesh.refine(mesh1, np.array([1,2,3], dtype=np.int32), redistribute=False)
# mesh2.topology.create_entities(1)
# new_mesh2 = mesh.refine(mesh2, np.array([1,2,3], dtype=np.int32))
# AttributeError: 'dolfinx.cpp.mesh.Mesh_float64' object has no attribute '_cpp_object'

So is the issue resolved?
Are you trying to copy a mesh?

Yes, resolved. It leads to copy mesh question. What is difference between mesh1 and mesh2? And I thought mesh.Mesh is a copy constructor.

The mesh takes in pointers: dolfinx/python/dolfinx/wrappers/mesh.cpp at main · FEniCS/dolfinx · GitHub