Dear dokken,
I have attempted to rebuild the code, and it seems to be running correctly now.
However, I am not certain if the usage of many APIs is correct, especially in the mixed function space.
Therefore, I have tried my best to extract MWE, as shown below.
I really hope to receive your confirmation so that I can make further settings and carry out the next simulation work.
from dolfinx import mesh, fem, plot
from dolfinx.fem.petsc import LinearProblem
import ufl
from ufl import (dot, dx, lhs, grad, rhs, sqrt, exp)
import numpy
from petsc4py import PETSc
from mpi4py import MPI
import pyvista
domain = mesh.create_rectangle(MPI.COMM_WORLD, [numpy.array([-1, 0]), numpy.array([1, 5])],
[20, 50], mesh.CellType.triangle)
# Defining FunctionSpace
## Voltage
V = fem.FunctionSpace(domain, ("Lagrange", 1))
## Particle density
P1 = ufl.FiniteElement("Lagrange", domain.ufl_cell(), 1)
element = ufl.MixedElement([P1, P1, P1])
N = fem.FunctionSpace(domain, element)
## Particle velocity
v_cg = ufl.VectorElement("Lagrange", domain.ufl_cell(), 2)
element = ufl.MixedElement([v_cg, v_cg, v_cg])
W = fem.FunctionSpace(domain, element)
# Define trailfunction and testfunction
## Voltage
u_voltage = ufl.TrialFunction(V)
v_voltage = ufl.TestFunction(V)
## Particle density
v_1, v_2, v_3 = ufl.TestFunctions(N)
u_1, u_2, u_3 = ufl.TrialFunctions(N)
u_n = fem.Function(N)
u_n1, u_n2, u_n3 = ufl.split(u_n)
## Particle velocity
velocity = fem.Function(W)
ve1, ve2, ve3 = ufl.split(velocity)
# Create boundary condition
## anode_marker
def anode_marker(x):
return numpy.isclose(x[1], 5)
anode_boundary_entity = mesh.locate_entities_boundary(domain, 1, anode_marker)
anode_boundary_dof = fem.locate_dofs_topological(V, 1, anode_boundary_entity)
bc1 = fem.dirichletbc(PETSc.ScalarType(9000), anode_boundary_dof, V)
## cathode_marker
def cathode_marker(x):
return numpy.isclose(x[1], 0)
cathode_boundary_entity = mesh.locate_entities_boundary(domain, 1, cathode_marker)
cathode_boundary_dof = fem.locate_dofs_topological(V, 1, cathode_boundary_entity)
bc2 = fem.dirichletbc(PETSc.ScalarType(0), cathode_boundary_dof, V)
# Create initial condition of partical density
# compute electric field intensity at the initial moment
def gaussian_distribution(x, y, x0, y0, sigma_x, sigma_y, amplitude):
return amplitude * numpy.exp(-((x - x0)**2 / (2 * sigma_x**2) + (y - y0)**2 / (2 * sigma_y**2)))
def electron_initial_condition(x):
return gaussian_distribution(x[0], x[1], 0, 4, 0.1, 0.1, 10**30)
u_n.sub(0).interpolate(electron_initial_condition)
u_n.sub(1).interpolate(electron_initial_condition)
# Create variational formulation
air_dielectric = fem.Constant(domain, PETSc.ScalarType(1))
elementary_charge = fem.Constant(domain, PETSc.ScalarType(1.6 * 10**(-19)))
a = dot(grad(u_voltage), grad(v_voltage)) * dx
L = elementary_charge / air_dielectric * (u_n2-u_n1-u_n3) * v_voltage * dx
problem = LinearProblem(a, L, bcs=[bc1, bc2], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
u_voltage = problem.solve()
# set simulation time, step size, and some parameters
T = 5e-6 # final time
num_steps = 500 # number of time steps
dt = T / num_steps # time step size
D1 = 0.18 # diffusion coefficient
D2 = 0.028e-4 # diffusion coefficient
D3 = 0.043e-4 # diffusion coefficient
t = 0
import tqdm.autonotebook
progress = tqdm.autonotebook.tqdm(desc="Solving PDE", total=num_steps)
for i in range(num_steps):
t += dt
progress.update(1)
# compute electric field intensity
E = -grad(u_voltage)
# compute particle mobility
μ_e = 1.9163 * sqrt(dot(E, E)) ** (-0.25)
μ_p = 2.43 * 1e-4
μ_n = 2.7 * 1e-4
# compute particle velocity
v_e = - E * μ_e
v_p = E * μ_p
v_n = - E * μ_n
# compute ionization and attachment coefficient
alpha = 3.5 * 1e5 * exp(-1.65 * 1e7 / sqrt(dot(E, E)))
eta = 1.5 * 1e3 * exp(-2.5 * 1e6 / sqrt(dot(E, E)))
# create variational formulation
def diffusion_advection(u, u_n, ve, v, D):
return ((u - u_n) / dt)*v*dx + dot(ve, grad(u))*v*dx - D*dot(grad(u), grad(v))*dx
## redefine trialfunctions
u_1, u_2, u_3 = ufl.TrialFunctions(N)
F1 = diffusion_advection(u_1, u_n1, v_e, v_1, D1) - (alpha - eta) * u_1 * sqrt(dot(μ_e, μ_e)) * v_1 *dx
F2 = diffusion_advection(u_2, u_n2, v_p, v_2, D2) - alpha * u_1 * sqrt(dot(μ_p, μ_p)) * v_1 *dx
F3 = diffusion_advection(u_3, u_n3, v_n, v_3, D3) + eta * u_1 * sqrt(dot(v_n, v_n)) * v_1 *dx
F = F1 + F2 + F3
a = lhs(F)
L = rhs(F)
problem = LinearProblem(a, L, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
u = problem.solve()
u_n1, u_n2, u_n3 = ufl.split(u)
u_voltage = ufl.TrialFunction(V)
a = ufl.dot(ufl.grad(u_voltage), ufl.grad(v_voltage)) * ufl.dx
L = elementary_charge / air_dielectric * (u_n2-u_n1-u_n3) * v_voltage * ufl.dx
problem = LinearProblem(a, L, bcs=[bc1, bc2], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
u_voltage = problem.solve()