Hi all,
I am modifying the this example to a geometry with an extra subdomain on the upper half. The subdomain definitions are
Omega = {
0 : lambda x: x[1] <= 0.5, # lower half of the mesh
# a block at the middle on the upper half of the mesh
1 : lambda x : np.logical_and(
np.logical_and(x[0] >= 1/3, x[0] <= 2/3),
x[1] >= 0.75
),
}
# the remaining part in the upper mesh
Omega[2] = lambda x : np.logical_and(x[1] >= 0.5, np.logical_not(Omega[1](x)))
I assigned the same \kappa value to subdomain 1
and 2
so that the expect solution should be the same as if there are only 2 subdomains. However, the solution is Nan. I have tried chopping the upper mesh into half and solution is valid. So, what is the best practice to implement subdomains to make sure they are connected? I appreciate for the help. Below if the script to reproduce the issue.
import numpy as np
import ufl
from mpi4py import MPI
from dolfinx import mesh, fem
from dolfinx.fem import FunctionSpace
from petsc4py.PETSc import ScalarType
domain = mesh.create_unit_square(MPI.COMM_WORLD, 30, 30)
Q = FunctionSpace(domain, ('DG', 0))
Omega = {
0 : lambda x: x[1] <= 0.5,
# this division works
# 1 : lambda x : np.logical_and(x[1] >= 0.5, x[0] <= 0.5),
# 2 : lambda x : np.logical_and(x[1] >= 0.5, x[0] >= 0.5),
1 : lambda x : np.logical_and(
np.logical_and(x[0] >= 1/3, x[0] <= 2/3),
x[1] >= 0.75
),
}
Omega[2] = lambda x : np.logical_and(x[1] >= 0.5, np.logical_not(Omega[1](x)))
cells = {
tag : mesh.locate_entities(domain, domain.topology.dim, omega) for tag, omega in Omega.items()
}
domain_indices = [cell for _, cell in cells.items()]
domain_markers = [np.full_like(cell, tag) for tag, cell in cells.items()]
domain_indices = np.hstack(domain_indices).astype(np.int32)
domain_markers = np.hstack(domain_markers).astype(np.int32)
sorted_domain = np.argsort(domain_indices)
subdomain_tag = mesh.meshtags(domain, domain.topology.dim, domain_indices[sorted_domain], domain_markers[sorted_domain])
dx = ufl.Measure('dx', domain=domain, subdomain_data=subdomain_tag)
Q = FunctionSpace(domain, ('DG',0))
kappa = fem.Function(Q)
kappa_values = {
0 : 1,
1 : 0.1,
2 : 0.1,
}
for tag, value in kappa_values.items():
cell = cells[tag]
kappa.x.array[cell] = np.full_like(cell, value, dtype=ScalarType)
V = FunctionSpace(domain, ('CG', 1))
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
x = ufl.SpatialCoordinate(domain)
s = fem.Constant(domain, ScalarType(1.))
a = kappa * ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
L = ufl.inner(s, v) * dx
dofs = fem.locate_dofs_geometrical(V, lambda x : np.isclose(x[0], 0))
bcs = [fem.dirichletbc(ScalarType(1.), dofs, V)]
problem = fem.petsc.LinearProblem(a, L, bcs=bcs, petsc_options={'ksp_type': 'preonly', 'pc_type': 'lu'})
uh = problem.solve()
import pyvista
from dolfinx.plot import create_vtk_mesh
pyvista.start_xvfb()
print(pyvista.global_theme.jupyter_backend)
num_cells_local = domain.topology.index_map(domain.topology.dim).size_local
marker = np.zeros(num_cells_local, dtype=np.int32)
for tag, cell in cells.items():
cell = cell[cell < num_cells_local]
marker[cell] = tag
topology, cell_types, geometry = create_vtk_mesh(domain, domain.topology.dim, np.arange(num_cells_local, dtype=np.int32))
grid = pyvista.UnstructuredGrid(topology, cell_types, geometry)
grid.cell_data['Marker'] = marker
grid.set_active_scalars('Marker')
plotter = pyvista.Plotter()
plotter.add_mesh(grid, show_edges=True)
plotter.view_xy()
if not pyvista.OFF_SCREEN:
plotter.show()
u_topology, u_cell_types, u_geometry = create_vtk_mesh(V)
u_grid = pyvista.UnstructuredGrid(u_topology, u_cell_types, u_geometry)
u_grid.point_data['u'] = uh.x.array
u_grid.set_active_scalars('u')
u_plotter = pyvista.Plotter()
u_plotter.add_mesh(u_grid, show_edges=True)
u_plotter.view_xy()
if not pyvista.OFF_SCREEN:
u_plotter.show()