Hello dear FEniCSX users,
I wanted to solve the following PDE:
\dfrac{\partial T}{\partial t} = \Delta T ,
T(x=1, y, t) = 1 ,
T(x, y=1, t) = 1 ,
T(x, y, 0) = 0 .
I have used the tutorials available in the FEniCS discourse when writing my code.
Here is my code:
#Below are my references
#https://fenicsproject.discourse.group/t/upadate-solutions-in-time-dependent-non-linear-problem/15719/4
#https://fenicsproject.discourse.group/t/upadate-solutions-in-time-dependent-non-linear-problem/15719
#https://fenicsproject.discourse.group/t/time-dependent-diffusion-constant-in-dolfinx/8137/5
#code to solve 2D Heat Transfer
from mpi4py import MPI
import dolfinx
from dolfinx import default_scalar_type as dst
from dolfinx import mesh, fem, io, log
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.nls.petsc import NewtonSolver
import ufl
import basix
import numpy as np
import pathlib
cache_dir = pathlib.Path('cache_2HeatTransfer2024')
Tf = 67. #Final time
num_step = 100
dt = Tf/num_step
T_r = 1.0 #boundary value for the dimensionless temperature at right boundary
T_t = 1.0 #boundary value for the dimensionless temperature at top boundary
T_init = 0.0 ##initial condition for dimensionless temperature
L = 1.0 #total length
# Create domain and element
# Define mesh
nx, ny = 100, 100
domain = mesh.create_rectangle(MPI.COMM_WORLD, [np.array([0.0, 0.0]), np.array([L, L])],
[nx, ny], mesh.CellType.triangle)
# Function space
V = fem.functionspace(domain, ("Lagrange", 1))
# Get boundary dofs
tdim = domain.topology.dim
fdim = tdim - 1
def right_boundary(x):
return np.isclose(x[0], L)
right_boundary_facets = mesh.locate_entities_boundary(domain, fdim,
right_boundary)
right_boundary_dofs = fem.locate_dofs_topological(V, fdim,
right_boundary_facets)
def top_boundary(x):
return np.isclose(x[1], L)
top_boundary_facets = mesh.locate_entities_boundary(domain, fdim,
top_boundary)
top_boundary_dofs = fem.locate_dofs_topological(V, fdim,
top_boundary_facets)
# Create functions
T = fem.Function(V) # current solution
v = ufl.TestFunction(V)
T_n = fem.Function(V) # previous solution
# Initial condition
T_init_expr = fem.Expression(fem.Constant(domain,
dst(T_init)),
V.element.interpolation_points(),
jit_options={'cache_dir': cache_dir})
T_n.interpolate(T_init_expr)
T_n.x.scatter_forward()
dt = fem.Constant(domain, dst(dt))
A = ufl.dot(ufl.grad(T), ufl.grad(v)) * ufl.dx
lf = ((T - T_n) / dt) * v * ufl.dx
# BC
bc_0 = fem.dirichletbc(dst(T_r), right_boundary_dofs, V)
bc_L = fem.dirichletbc(dst(T_t), top_boundary_dofs, V)
# Problem
F = A + lf
problem = NonlinearProblem(F, T, [bc_0, bc_L],
jit_options={'cache_dir': cache_dir})
# Solver
solver = NewtonSolver(MPI.COMM_WORLD, problem)
info = solver.solve(T)
print(info)
solver.convergence_criterion = "incremental"
solver.rtol = 1e-6
solver.max_it = 100
solver.report = True
'''
with dolfinx.io.VTXWriter(domain.comm, "C_moisture.bp", V, engine="BP4") as vtx:
vtx.write(0.0)
'''
# Output
T_out = io.XDMFFile(domain.comm,
'2DHeatTransfer_Dec2024.xdmf',
'w')
T_out.write_mesh(domain)
# Time loop
t = 0
while t < Tf:
if t == 0:
T_out.write_function(T, t)
t += dst(dt)
print(f'Time {t}')
n, converged = solver.solve(T)
print(f'converged: {converged}, n_iter: {n}')
T_n.interpolate(T) # update prev. sol
T_n.x.scatter_forward()
# Save
T_out.write_function(T, t)
T_out.close()
The code works well and converges in two iterations. But when I visualize the results in Paraview, the results at timesteps 0 and 1 are the same.
I am not sure if my initial condition is well implemented. I am a quite loss with this problem, and any suggestions would be appreciated.
Thank you very much in advance!