I’ll post the code in case someone needs it
import numpy as np
from time import process_time
import ufl
from dolfinx import plot
import pyvista
from dolfinx.fem import Function, FunctionSpace, assemble_scalar, form, locate_dofs_geometrical, dirichletbc, Expression
from dolfinx.fem.petsc import LinearProblem
from dolfinx.io import XDMFFile
from dolfinx.mesh import create_rectangle, CellType
from ufl import dx, grad, inner, div, conj, real, imag, Index, Dx
from mpi4py import MPI
from petsc4py import PETSc
if np.issubdtype(PETSc.ScalarType, np.complexfloating):
imaginaryUnit = PETSc.ScalarType(0 + 1j)
else:
error('Complex Treatment is needed')
# Parameters
dt = 1/50;
hbar = 0.03;
inlet_velocity = np.array([1.0, 0.0]);
T = 50;
numsteps = 50/dt
# Mesh Discretization
dimensions = np.array([10,4]);
nx = 250;
ny = 100;
domain = create_rectangle(MPI.COMM_WORLD, [np.array([0, 0]), dimensions],
[nx, ny], CellType.triangle)
tdim = domain.topology.dim;
# Definition of the functional space
deg = 1; # linear = 1, parabolic = 2 Lagrangian FE are used
V = FunctionSpace(domain, ("Lagrange", deg))
psi1 = Function(V)
psi2 = Function(V)
psi1.name = "psi1"
psi2.name = "psi2"
tmpPsi1 = Function(V)
tmpPsi2 = Function(V)
psi1old = Function(V)
psi2old = Function(V)
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
# Defining the inlet boundary condition
dofs_inlet = locate_dofs_geometrical(V, lambda x: np.isclose(x[0],0))
inletPlaneWave = Function(V)
kvec = inlet_velocity/hbar
inletPlaneWave.interpolate(lambda x: np.exp(imaginaryUnit * (kvec[0]*x[0] + kvec[1]*x[1])))
bc_Inlet = dirichletbc(inletPlaneWave, dofs_inlet)
# Initialization
def initial_condition1(x):
return 1 + 0j + 0 * x[0] + 1 * x[1]
def initial_condition2(x, c = 0.01 ):
return c + 0j + 0 * x[0] + 1 * x[1]
psi1old.interpolate(initial_condition1)
psi2old.interpolate(initial_condition2)
# Definition of the variational formulation
theta = 0.5 # Crank-Nicolson is used - theta method is implemented
a = inner(u, v) * dx - imaginaryUnit * dt * hbar / 2 * (1-theta) * inner(grad(u), grad(v)) * dx
L1 = inner(psi1old, v) * dx + imaginaryUnit * dt * hbar / 2 * theta * inner(grad(psi1old), grad(v)) * dx
L2 = inner(psi2old, v) * dx + imaginaryUnit * dt * hbar / 2 * theta * inner(grad(psi2old), grad(v)) * dx
problem1 = LinearProblem(a, L1, u = tmpPsi1, bcs = [bc_Inlet], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
problem2 = LinearProblem(a, L2, u = tmpPsi2, bcs = [bc_Inlet], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
cputime_start = process_time()
n = 0;
for n in range (0,int(numsteps)):
t = float(n+1)*dt
print("Time = %.2f" % t)
# Schrodinger Evolution
problem1.solve()
problem2.solve()
psi1old.interpolate(psi1)
psi2old.interpolate(psi2)