A question about Function numerical setting

Hi yonggangli,

As @francesco-ballarin points out, the marker functions you use here will be problematic if the cells don’t align with the split coordinate. A good first step when dealing with problems where things are marked is plotting the mesh with the meshtags of the markings. Here is what I get when using your code:

I have tagged volume0 with 2 and volume1 with 3, leaving any untagged cells with the tag 1. As you can see, the middle cells of the mesh are not tagged.

If you instead compute the midpoints of each cell and use these in the locator function, you would get this:

Note that this still won’t produce a split that is a horizontal line, since the cell midpoints are not aligned with the split coordinate. To achieve an even split, you would have to address this issue while meshing, as pointed out by @francesco-ballarin.

In case it is of interest, here is your code with the changes I made to mark all the cells using their midpoints as reference:

import numpy as np
from dolfinx.io import XDMFFile, gmshio
from mpi4py import MPI
from dolfinx.mesh import locate_entities, meshtags, compute_midpoints
from dolfinx import fem, default_scalar_type


len_side = 50
lc = 8
split = len_side / 2


def get_device():
    # Initialize Gmsh
    gmsh.initialize()

    model = gmsh.model()

    # Create a new model
    model.add("Device")

    p1 = model.occ.addPoint(0, 0, 0, lc, 1)
    p2 = model.occ.addPoint(len_side, 0, 0, lc, 2)
    p3 = model.occ.addPoint(len_side, len_side, 0, lc, 3)
    p4 = model.occ.addPoint(0, len_side, 0, lc, 4)

    line1 = model.occ.addLine(p1, p2, 1)
    line2 = model.occ.addLine(p2, p3, 2)
    line3 = model.occ.addLine(p3, p4, 3)
    line4 = model.occ.addLine(p4, p1, 4)

    loop = model.occ.addCurveLoop([line1, line2, line3, line4], 5)
    surface = model.occ.addPlaneSurface([loop], 1)

    model.occ.synchronize()

    model.add_physical_group(dim=2, tags=[surface])

    # Generate the 3D mesh
    model.mesh.generate(2)
    return model


def volume0(x):
    return x[1] >= split


def volume1(x):
    return x[1] <= split


model = get_device()
gdim  = 2

# Interfacing with dolfinx
mesh, cell_markers, facet_markers = gmshio.model_to_mesh(model, MPI.COMM_WORLD, 0, gdim=gdim)

Q = fem.functionspace(mesh, ("DG", 0))
epsilon = fem.Function(Q)

cells0 = locate_entities(mesh, mesh.topology.dim, volume0)
print('cells1', len(cells0), MPI.COMM_WORLD.rank)
cells1 = locate_entities(mesh, mesh.topology.dim, volume1)
print('cells2', len(cells1), MPI.COMM_WORLD.rank)

num_cells = mesh.topology.index_map(gdim).size_local +  + mesh.topology.index_map(gdim).num_ghosts
mids = compute_midpoints(mesh, mesh.topology.dim, np.arange(num_cells, dtype=np.int32))
locator0 = volume0(mids.T)
locator1 = volume1(mids.T)
cell_tags = np.full(num_cells, 1, dtype=np.int32)
cell_tags[locator0] = 2
cell_tags[locator1] = 3
tags = meshtags(mesh, gdim, np.arange(num_cells), cell_tags)

with XDMFFile(MPI.COMM_WORLD, "tags.xdmf", "w") as xdmf:
    xdmf.write_mesh(mesh)
    xdmf.write_meshtags(tags, mesh.geometry)

print('length of array', len(epsilon.x.array), MPI.COMM_WORLD.rank)
print('total', np.sum(locator0) + np.sum(locator1), MPI.COMM_WORLD.rank)

if np.sum(locator0) + np.sum(locator1) == len(epsilon.x.array):
    print("All cells are included.")
else:
    print("Some cells are missing or duplicated.")

dofs0 = fem.locate_dofs_topological(Q, gdim, np.where(cell_tags==2)[0])
dofs1 = fem.locate_dofs_topological(Q, gdim, np.where(cell_tags==3)[0])

epsilon.x.array[dofs0] = np.full(np.sum(locator0), 1, dtype=default_scalar_type)
epsilon.x.array[dofs1] = np.full(np.sum(locator1), 2, dtype=default_scalar_type)

if np.any(epsilon.x.array == 0):
    print("Warning: Some cells have not been assigned values.")```

Cheers
1 Like