Hello, now everything works without errors, but I get zero solution. Can it be because of mistake in stating boundary conditions or in weak formulation of my problem? Because for me everything looks fine:
import dolfinx
import gmsh
!pip install meshio
import meshio
!pip install pygmsh
import pygmsh
!pip install h5py
import h5py
from mpi4py import MPI
import numpy as np
print(f"DOLFINx version: {dolfinx.__version__} based on GIT commit: {dolfinx.git_commit_hash} of https://github.com/FEniCS/dolfinx/")
# Radius of the inner and outer boubdary of the domain
resolution = 0.04
r_in = 0.5
r_out = 1.5
c = [ 0, 0, 0 ]
gmsh.initialize()
model_rank = 0
mesh_comm = MPI.COMM_WORLD
# Define geometry for iron cylinder
circ_inner = gmsh.model.occ.addDisk(0, 0, 0, r_in,r_in)
circ_outer = gmsh.model.occ.addDisk(0, 0, 0, r_out,r_out)
gmsh.model.occ.synchronize()
# Resolve all boundaries of the different wires in the background domain
all_surfaces = [(2, circ_inner)]
whole_domain = gmsh.model.occ.fragment([(2, circ_outer)], all_surfaces)
gmsh.model.occ.synchronize()
# Create physical markers for the different wires.
# We use the following markers:
# - Inner: 0
# - Domain: 1
background_surfaces = []
other_surfaces = []
for domain in whole_domain[0]:
com = gmsh.model.occ.getCenterOfMass(domain[0], domain[1])
mass = gmsh.model.occ.getMass(domain[0], domain[1])
# Identify iron circle by its mass
if np.isclose(mass, np.pi*(r_in**2)):
gmsh.model.addPhysicalGroup(domain[0], [domain[1]], tag=103)
other_surfaces.append(domain)
# Identify the domain circle by its center of mass
elif np.allclose(com, [0, 0, 0]):
background_surfaces.append(domain[1])
# Add marker for the vacuum
gmsh.model.addPhysicalGroup(2, background_surfaces, tag=104)
gmsh.model.mesh.field.add("Distance", 1)
edges = gmsh.model.getBoundary(other_surfaces, oriented=False)
gmsh.model.mesh.field.setNumbers(1, "EdgesList", [e[1] for e in edges])
gmsh.model.mesh.field.add("Threshold", 2)
gmsh.model.mesh.field.setNumber(2, "IField", r_out)
gmsh.model.mesh.field.setNumber(2, "LcMin", 0.04)
gmsh.model.mesh.field.setNumber(2, "LcMax", 0.04)
gmsh.model.mesh.field.setNumber(2, "DistMin", r_in)
gmsh.model.mesh.field.setNumber(2, "DistMax", r_out)
gmsh.model.mesh.field.setAsBackgroundMesh(2)
# Generate mesh
gmsh.model.mesh.generate(2)
from dolfinx.io.gmshio import model_to_mesh
mesh, ct, _ = model_to_mesh(gmsh.model, mesh_comm, model_rank, gdim=2)
gmsh.finalize()
import pyvista
pyvista.set_jupyter_backend("pythreejs")
from dolfinx.plot import create_vtk_mesh
plotter = pyvista.Plotter()
grid = pyvista.UnstructuredGrid(*create_vtk_mesh(mesh, mesh.topology.dim))
num_local_cells = mesh.topology.index_map(mesh.topology.dim).size_local
grid.cell_data["Marker"] = ct.values[ct.indices<num_local_cells]
grid.set_active_scalars("Marker")
actor = plotter.add_mesh(grid, show_edges=True)
plotter.view_xy()
if not pyvista.OFF_SCREEN:
plotter.show()
else:
pyvista.start_xvfb()
cell_tag_fig = plotter.screenshot("cell_tags.png")
from dolfinx.fem import (dirichletbc, Expression, Function, FunctionSpace,
VectorFunctionSpace, locate_dofs_topological)
from dolfinx.fem.petsc import LinearProblem
from dolfinx.mesh import locate_entities_boundary
from ufl import TestFunction, TrialFunction, as_vector, dot, dx, grad, inner, ds, lhs, rhs, SpatialCoordinate, sqrt, FacetNormal
from petsc4py.PETSc import ScalarType
if not np.issubdtype(ScalarType, np.complexfloating):
print("Demo should only be executed with DOLFINx complex mode")
exit(0)
class BackgroundElectricField:
def __init__(self, n, k0):
self.k0 = k0
self.n = n
def eval(self, x):
return (np.exp(-1j * self.k0*self.n*x[0]))
def radial_distance(x):
"""Returns the radial distance from the origin"""
return sqrt(x[0]**2 + x[1]**2)
n = FacetNormal(mesh)
V = FunctionSpace(mesh, ("CG", 2))
tdim = mesh.topology.dim
facets = locate_entities_boundary(mesh, tdim-1, lambda x: np.full(x.shape[1], True))
dofs = locate_dofs_topological(V, tdim-1, facets)
bc = dirichletbc(ScalarType(0), dofs, V)
x = SpatialCoordinate(mesh)
f = BackgroundElectricField(n=1, k0=2*np.pi)
Einc = dolfinx.fem.Function(V)
Einc.interpolate(f.eval)
k = 2*np.pi
eps = 1
mu = 1
beta = eps*mu*k**2
u = TrialFunction(V)
v = TestFunction(V)
F = (beta*inner(u,v)-inner(grad(u),grad(v)))*dx + (1j * k + 1 / (2 * r_out))*(inner(Einc,v)-inner(u,v))*ds + inner(inner(grad(Einc),n),v)*ds
# Splitting in left-hand side and right-hand side
a, L = lhs(F), rhs(F)
Esc = Function(V)
problem = LinearProblem(a, L, u=Esc, bcs=[bc])
problem.solve()
plotter = pyvista.Plotter()
Esc_grid = pyvista.UnstructuredGrid(*create_vtk_mesh(V))
Esc_grid.point_data["Esc"] = Esc.x.array
Esc_grid.set_active_scalars("Esc")
warp = Esc_grid.warp_by_scalar("Esc", factor=1e7)
actor = plotter.add_mesh(warp, show_edges=True)
if not pyvista.OFF_SCREEN:
plotter.show()
else:
pyvista.start_xvfb()
Esc_fig = plotter.screenshot("Esc.png")
I expected getting something like this one:
and after that to plot angular dependence.