Solving a system of coupled PDEs in fenicsx

Hi dear fenicsx users.

I am trying to solve the following system of PDEs (in 2D) using fenicsx (dolfinx version 0.6.0).

\dfrac{\partial {m}}{\partial t} \ = \ a_m \ \Delta m + a_m \nu \ \Delta T
c \rho_{0} \dfrac{\partial {T}}{\partial t} \ = k \ \Delta T + R \epsilon \ \dfrac{\partial {m}}{\partial t}

with initial conditions
m(x, 0) = 0.30 and T(x, 0) = 10.

The boundary boundary conditions are:
m(x=1, y, t) = 0.12, m(x, y=1,t), T(x=1, y, t) = 60, and T(x, y=1, t) = 60.

I had a close look on the Cahn-Hilliard and Navier-Stockes equations and I have tried to implement this problem in fenicsx but I am encountering some issues with my code.
My code is as follow:

import os

import numpy as np

import ufl

from dolfinx.io import VTXWriter



from dolfinx.fem import (Constant, dirichletbc, Function, FunctionSpace, assemble_scalar,
                         form, locate_dofs_geometrical, locate_dofs_topological)

#from dolfinx.fem import (Constant, dirichletbc,
                         #extract_function_spaces, form,
                        # locate_dofs_topological)
from dolfinx import log, plot
#from dolfinx.plot import vtk_mesh
from dolfinx.fem import Function, FunctionSpace
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.io import XDMFFile
from dolfinx.mesh import CellType, create_rectangle, locate_entities_boundary
from dolfinx.nls.petsc import NewtonSolver
from ufl import dx, grad, inner
from dolfinx import fem, io, mesh, plot
from petsc4py.PETSc import ScalarType

from mpi4py import MPI
from petsc4py import PETSc

try:
    import pyvista as pv
    import pyvistaqt as pvqt
    have_pyvista = True
    if pv.OFF_SCREEN:
        pv.start_xvfb(wait=0.5)
except ModuleNotFoundError:
    print("pyvista and pyvistaqt are required to visualise the solution")
    have_pyvista = False

# Save all logging to file
log.set_output_file("log.txt")

import dolfinx
print(f"DOLFINx version: {dolfinx.__version__} based on GIT commit: {dolfinx.git_commit_hash} of https://github.com/FEniCS/dolfinx/")

lx = 1.0  #length of x-axis
Ly = 1.0  #length of y-axis
#nx, ny = 50, 50
nx = 8
ny = 8

t = 0
T = 10

# A rectangle mesh with 8 cells edges in each direction is created,
# and on this mesh a
# {py:class}`FunctionSpace<dolfinx.fem.FunctionSpace>` `ME` is built
# using a pair of linear Lagrange elements.

msh = mesh.create_rectangle(comm=MPI.COMM_WORLD,
                            points=((0.0, 0.0), (lx, Ly)), n=(nx, ny),
                            cell_type=mesh.CellType.triangle)

#msh = create_rectangle(MPI.COMM_WORLD, 96, 96, CellType.triangle)
m1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
T1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
ME = FunctionSpace(msh, m1 * T1)

Q = FunctionSpace(msh, m1)
V = FunctionSpace(msh, T1)

m = ufl.TrialFunction(Q)
q = ufl.TestFunction(Q)
T = ufl.TrialFunction(V)
v = ufl.TestFunction(V)

# Defining our problem
#p = fem.Constant(domain, ScalarType(1)) # SIMP penalty exponent
am = fem.Constant(msh, ScalarType(3.e-06 ))  
k = fem.Constant(msh, ScalarType(0.12))  
c = fem.Constant(msh, ScalarType(1284.))  
rho_0 = fem.Constant(msh, ScalarType(500.)) 
R = fem.Constant(msh, ScalarType(2400.))   

epsilon = fem.Constant(msh, ScalarType(0.1))  
nu = fem.Constant(msh, ScalarType(1.e-02))        
m_ini = fem.Constant(msh, ScalarType(0.5))  
m_lbou = fem.Constant(msh, ScalarType(0.12)) 
m_rbou = fem.Constant(msh, ScalarType(0.12))  
T_ini = fem.Constant(msh, ScalarType(10.))  
T_lbou = fem.Constant(msh, ScalarType(80.))  
T_rbou = fem.Constant(msh, ScalarType(80.))  

dt = 0.001  #0.02 #5.0e-06  # time step


#We create four python functions for determining the facets to apply boundary conditions to

def left(x):
    return np.isclose(x[0], 0)  #left (x = 0)


def right(x):
    return np.isclose(x[0], lx)  #right (x = 1)

def bottom(x):
    return np.isclose(x[1], 0)  #bottom (y = 0)


def top(x):
    return np.isclose(x[1], Ly)  #right (y = 1)


right_m_dofs = locate_dofs_geometrical(m1, right)
bc_m_right = dirichletbc(PETSc.ScalarType(0.12), right_m_dofs, m1)

top_m_dofs = locate_dofs_geometrical(m1, top)
bc_m_top = dirichletbc(PETSc.ScalarType(0.12), top_m_dofs, m1)

right_T_dofs = locate_dofs_geometrical(T1, right)
bc_T_right = dirichletbc(PETSc.ScalarType(60.), right_T_dofs, T1)

top_T_dofs = locate_dofs_geometrical(T1, top)
bc_T_top = dirichletbc(PETSc.ScalarType(60.), top_T_dofs, T1)

bcm = [bc_m_right, bc_m_top]
bcT = [bc_T_right, bc_T_top]






# +
u = Function(ME)  # current solution
u_n = Function(ME)  # solution from previous converged step

# Split mixed functions
m, T = ufl.split(u)
m_n, T_n = ufl.split(u_n)





# Weak statement of the equations
m_n = Function(Q)
m_n.name = "m_n"

T_n = Function(V)
T_n.name = "T_n"
F0 = inner(m, q) * dx - inner(m_n, q) * dx + dt*am * inner(grad(m), grad(q)) * dx + dt*am*nu * inner(grad(T), grad(q)) * dx
F1 = c*rho_0* inner(T, v) * dx - c*rho_0* inner(T_n, v) * dx + dt*k * inner(grad(T), grad(v)) * dx - R*epsilon * inner(m, v) * dx + R*epsilon * inner(m_n, v) * dx
F = F0 + F1


# Create nonlinear problem and Newton solver
problem = NonlinearProblem(F, u, bcs = [bcm, bcT])
solver = NewtonSolver(MPI.COMM_WORLD, problem)
solver.convergence_criterion = "incremental"
solver.rtol = 1e-6

# We can customize the linear solver used inside the NewtonSolver by
# modifying the PETSc options
ksp = solver.krylov_solver
opts = PETSc.Options()
option_prefix = ksp.getOptionsPrefix()
opts[f"{option_prefix}ksp_type"] = "preonly"
opts[f"{option_prefix}pc_type"] = "lu"
ksp.setFromOptions()
# -



# -

# The setting of `convergence_criterion` to `"incremental"` specifies
# that the Newton solver should compute a norm of the solution increment
# to check for convergence (the other possibility is to use
# `"residual"`, or to provide a user-defined check). The tolerance for
# convergence is specified by `rtol`.
#
# To run the solver and save the output to a VTK file for later
# visualization, the solver is advanced in time from $t_{n}$ to
# $t_{n+1}$ until a terminal time $T$ is reached:

# +
# Output file
file = XDMFFile(MPI.COMM_WORLD, "demo_ch/output.xdmf", "w")
file.write_mesh(msh)

from pathlib import Path
folder = Path("results")
folder.mkdir(exist_ok=True, parents=True)
vtx_u = VTXWriter(mesh.comm, folder / "poiseuille_m.bp", m0, engine="BP4")
vtx_p = VTXWriter(mesh.comm, folder / "poiseuille_T.bp", T0, engine="BP4")
vtx_u.write(t)
vtx_p.write(t)

When running the code, I got the following error:

DOLFINx version: 0.6.0 based on GIT commit: 30920d400ccb64d190de13509c43b1755d2606cc of https://github.com/FEniCS/dolfinx/
Traceback (most recent call last):
  File "/home/mamadou/Downloads/fawzoulazim2023_december2023_2.py", line 115, in <module>
    right_m_dofs = locate_dofs_geometrical(m1, right)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/fem/bcs.py", line 56, in locate_dofs_geometrical
    raise TypeError
TypeError

Thanks for your time and attention.

1 Like

You need to use function spaces when locating degrees of freedom, as a Finite element had no concept of a mesh.
See for instance
https://jsdokken.com/dolfinx-tutorial/chapter3/component_bc.html
For further questions, i would strongly recommend simplifying the code to just contain definitions required to reproduce the error message.

Please also add the full error message next time

Thank you dear Dokken for your quick reply.
I will check it out!

Yes, I will.

Thank you in advance.

Hi dear Dokken,

Following this Component-wise Dirichlet BC — FEniCSx tutorial, I replace ‘‘VectorElement’’ by ‘‘FiniteElement’’.
For the definitions of my boundaries conditions, I used this tutorial Test problem 1: Channel flow (Poiseuille flow) — FEniCSx tutorial

import os

import numpy as np

import ufl

from dolfinx.io import VTXWriter



from dolfinx.fem import (Constant, dirichletbc, Function, FunctionSpace, assemble_scalar,
                         form, locate_dofs_geometrical, locate_dofs_topological)

#from dolfinx.fem import (Constant, dirichletbc,
                         #extract_function_spaces, form,
                        # locate_dofs_topological)
from dolfinx import log, plot
#from dolfinx.plot import vtk_mesh
from dolfinx.fem import Function, FunctionSpace
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.io import XDMFFile
from dolfinx.mesh import CellType, create_rectangle, locate_entities_boundary
from dolfinx.nls.petsc import NewtonSolver
from ufl import dx, grad, inner
from dolfinx import fem, io, mesh, plot
from petsc4py.PETSc import ScalarType

from mpi4py import MPI
from petsc4py import PETSc

try:
    import pyvista as pv
    import pyvistaqt as pvqt
    have_pyvista = True
    if pv.OFF_SCREEN:
        pv.start_xvfb(wait=0.5)
except ModuleNotFoundError:
    print("pyvista and pyvistaqt are required to visualise the solution")
    have_pyvista = False

# Save all logging to file
log.set_output_file("log.txt")

import dolfinx
print(f"DOLFINx version: {dolfinx.__version__} based on GIT commit: {dolfinx.git_commit_hash} of https://github.com/FEniCS/dolfinx/")

lx = 1.0  #length of x-axis
Ly = 1.0  #length of y-axis
#nx, ny = 50, 50
nx = 8
ny = 8

t = 0
T = 10

# A rectangle mesh with 8 cells edges in each direction is created,
# and on this mesh a
# {py:class}`FunctionSpace<dolfinx.fem.FunctionSpace>` `ME` is built
# using a pair of linear Lagrange elements.

msh = mesh.create_rectangle(comm=MPI.COMM_WORLD,
                            points=((0.0, 0.0), (lx, Ly)), n=(nx, ny),
                            cell_type=mesh.CellType.triangle)

#msh = create_rectangle(MPI.COMM_WORLD, 96, 96, CellType.triangle)
#m1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
m1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
T1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
ME = FunctionSpace(msh, m1 * T1)

Q = FunctionSpace(msh, m1)
V = FunctionSpace(msh, T1)

m = ufl.TrialFunction(Q)
q = ufl.TestFunction(Q)
T = ufl.TrialFunction(V)
v = ufl.TestFunction(V)

# Defining our problem
#p = fem.Constant(domain, ScalarType(1)) # SIMP penalty exponent
am = fem.Constant(msh, ScalarType(3.e-06 ))  
k = fem.Constant(msh, ScalarType(0.12))  
c = fem.Constant(msh, ScalarType(1284.))  
rho_0 = fem.Constant(msh, ScalarType(500.)) 
R = fem.Constant(msh, ScalarType(2400.))   

epsilon = fem.Constant(msh, ScalarType(0.1))  
nu = fem.Constant(msh, ScalarType(1.e-02))        


dt = 0.001  #0.02 #5.0e-06  # time step


#We create four python functions for determining the facets to apply boundary conditions to

def left(x):
    return np.isclose(x[0], 0)  #left (x = 0)


def right(x):
    return np.isclose(x[0], lx)  #right (x = 1)

def bottom(x):
    return np.isclose(x[1], 0)  #bottom (y = 0)


def top(x):
    return np.isclose(x[1], Ly)  #right (y = 1)


right_m_dofs = locate_dofs_geometrical(m1, right)
bc_m_right = dirichletbc(PETSc.ScalarType(0.12), right_m_dofs, m1)

top_m_dofs = locate_dofs_geometrical(m1, top)
bc_m_top = dirichletbc(PETSc.ScalarType(0.12), top_m_dofs, m1)

right_T_dofs = locate_dofs_geometrical(T1, right)
bc_T_right = dirichletbc(PETSc.ScalarType(60.), right_T_dofs, T1)

top_T_dofs = locate_dofs_geometrical(T1, top)
bc_T_top = dirichletbc(PETSc.ScalarType(60.), top_T_dofs, T1)

bcm = [bc_m_right, bc_m_top]
bcT = [bc_T_right, bc_T_top]







But I got the following error message:

Traceback (most recent call last):
  File "/home/mamadou/Downloads/fawzoulazim2023_december2023_3.py", line 111, in <module>
    right_m_dofs = locate_dofs_geometrical(m1, right)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/fem/bcs.py", line 56, in locate_dofs_geometrical
    raise TypeError
TypeError

Thanks for your time and attention.

Sorry dear Dokken, I understand now (i.e. You need to use function spaces when locating degrees of freedom, as a Finite element had no concept of a mesh.).

Thank you.

Hi dear Dokken,

I am trying to implement the system using a mixed finite element method based on the demo code provided here: https://fenicsproject.org/olddocs/dolfin/latest/python/demos/cahn-hilliard/demo_cahn-hilliard.py.htm.

Next, I would like to :

a) Incorporate the initial conditions for the system (i.e. m(x, 0) = 0.30 and T(x, 0) = 60) and,
b) Visualize each the two unknown solutions (i.e. m, T in my case).

The MWE is as follows:

import os

import numpy as np

import ufl

from dolfinx.io import VTXWriter



from dolfinx.fem import (Constant, dirichletbc, Function, FunctionSpace, assemble_scalar,
                         form, locate_dofs_geometrical, locate_dofs_topological)

#from dolfinx.fem import (Constant, dirichletbc,
                         #extract_function_spaces, form,
                        # locate_dofs_topological)
from dolfinx import log, plot
#from dolfinx.plot import vtk_mesh
from dolfinx.fem import Function, FunctionSpace
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.io import XDMFFile
from dolfinx.mesh import CellType, create_rectangle, locate_entities_boundary
from dolfinx.nls.petsc import NewtonSolver
from ufl import dx, grad, inner
from dolfinx import fem, io, mesh, plot
from petsc4py.PETSc import ScalarType

from mpi4py import MPI
from petsc4py import PETSc

try:
    import pyvista as pv
    import pyvistaqt as pvqt
    have_pyvista = True
    if pv.OFF_SCREEN:
        pv.start_xvfb(wait=0.5)
except ModuleNotFoundError:
    print("pyvista and pyvistaqt are required to visualise the solution")
    have_pyvista = False

# Save all logging to file
log.set_output_file("log.txt")

import dolfinx
print(f"DOLFINx version: {dolfinx.__version__} based on GIT commit: {dolfinx.git_commit_hash} of https://github.com/FEniCS/dolfinx/")

lx = 1.0  #length of x-axis
Ly = 1.0  #length of y-axis
#nx, ny = 50, 50
nx = 8
ny = 8

t = 0
T = 10

# A rectangle mesh with 8 cells edges in each direction is created,
# and on this mesh a
# {py:class}`FunctionSpace<dolfinx.fem.FunctionSpace>` `ME` is built
# using a pair of linear Lagrange elements.

msh = mesh.create_rectangle(comm=MPI.COMM_WORLD,
                            points=((0.0, 0.0), (lx, Ly)), n=(nx, ny),
                            cell_type=mesh.CellType.triangle)

#msh = create_rectangle(MPI.COMM_WORLD, 96, 96, CellType.triangle)
#m1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
m1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
T1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
ME = FunctionSpace(msh, m1 * T1)

Q = FunctionSpace(msh, m1)
V = FunctionSpace(msh, T1)



# Defining our problem
#p = fem.Constant(domain, ScalarType(1)) # SIMP penalty exponent
am = fem.Constant(msh, ScalarType(3.e-06 ))  
k = fem.Constant(msh, ScalarType(0.12))  
c = fem.Constant(msh, ScalarType(1284.))  
rho_0 = fem.Constant(msh, ScalarType(500.)) 
R = fem.Constant(msh, ScalarType(2400.))   

epsilon = fem.Constant(msh, ScalarType(0.1))  
nu = fem.Constant(msh, ScalarType(1.e-02))        


dt = 0.001  #0.02 #5.0e-06  # time step


#We create four python functions for determining the facets to apply boundary conditions to

def left(x):
    return np.isclose(x[0], 0)  #left (x = 0)


def right(x):
    return np.isclose(x[0], lx)  #right (x = 1)

def bottom(x):
    return np.isclose(x[1], 0)  #bottom (y = 0)


def top(x):
    return np.isclose(x[1], Ly)  #top (y = 1)


right_m_dofs = locate_dofs_geometrical(Q, right)
bc_m_right = dirichletbc(PETSc.ScalarType(0.12), right_m_dofs, Q)



top_m_dofs = locate_dofs_geometrical(Q, top)
bc_m_top = dirichletbc(PETSc.ScalarType(0.12), top_m_dofs, Q)

right_T_dofs = locate_dofs_geometrical(V, right)
bc_T_right = dirichletbc(PETSc.ScalarType(60.), right_T_dofs, V)

top_T_dofs = locate_dofs_geometrical(V, top)
bc_T_top = dirichletbc(PETSc.ScalarType(60.), top_T_dofs, V)

#Creation of dirichlet conditions
bcm = [bc_m_right, bc_m_top]     #bc for unknown m
bcT = [bc_T_right, bc_T_top]     #bc for unknown T


#m = ufl.TrialFunction(Q)
#q = ufl.TestFunction(Q)
#T = ufl.TrialFunction(V)
#v = ufl.TestFunction(V)


#Test Functions (q, v)
q, v = ufl.TestFunctions(ME)

u = Function(ME)  # current solution
u_n = Function(ME)  # solution from previous converged step

# Split mixed functions
m, T = ufl.split(u)
m_n, T_n = ufl.split(u_n)

# Weak statement of the equations
m_n = Function(Q)
m_n.name = "m_n"
T_n = Function(V)
T_n.name = "T_n"

# The initial conditions are interpolated into a finite element space:


# Zero u
u.x.array[:] = 0.0

# Interpolate initial condition
u.sub(0).interpolate(lambda x: 0.30)  #Initial condition for m
#u.x.scatter_forward()
u.sub(1).interpolate(lambda x: 60.)   #Initial condition for T
u.x.scatter_forward()

I had the following error message:

DOLFINx version: 0.6.0 based on GIT commit: 30920d400ccb64d190de13509c43b1755d2606cc of https://github.com/FEniCS/dolfinx/
Traceback (most recent call last):
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/fem/function.py", line 370, in interpolate
    _interpolate(u, cells)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/functools.py", line 889, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/fem/function.py", line 346, in _interpolate
    self._cpp_object.interpolate(u, cells)
TypeError: interpolate(): incompatible function arguments. The following argument types are supported:
    1. (self: dolfinx.cpp.fem.Function_float64, f: numpy.ndarray[numpy.float64], cells: numpy.ndarray[numpy.int32]) -> None
    2. (self: dolfinx.cpp.fem.Function_float64, u: dolfinx.cpp.fem.Function_float64, cells: numpy.ndarray[numpy.int32]) -> None
    3. (self: dolfinx.cpp.fem.Function_float64, expr: dolfinx::fem::Expression<double>, cells: numpy.ndarray[numpy.int32]) -> None

Invoked with: <dolfinx.cpp.fem.Function_float64 object at 0x7f132459ca30>, <function <lambda> at 0x7f132456a4d0>, array([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
        13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
        26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
        39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
        52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
        65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
        78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
        91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103,
       104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
       117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127], dtype=int32)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/mamadou/Downloads/fawzoulazim2023_december2023_3.py", line 156, in <module>
    u.sub(0).interpolate(lambda x: 0.30)  #Initial condition for m
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/fem/function.py", line 376, in interpolate
    self._cpp_object.interpolate(
IndexError: invalid axis: 0 (ndim = 0)

Please let me know if this is correct. If not, I would appreciate any help.

Thanks for your time and attention.

The expected function should return an array with the same second dimension as x, so I would try:
u.sub(0).interpolate(lambda x: np.full(x.shape[1], 0.30, dtype=np.float64)) #Initial condition for m

Thank you, dear Dokken,

It works now.

Hi dear Dokken,
Thank you in advance.
Finally, I try to visualize the unknown function m based on the demo code provided here: https://fenicsproject.org/olddocs/dolfin/latest/python/demos/cahn-hilliard/demo_cahn-hilliard.py.html.

The complete code is as follows:

import os

import numpy as np

import ufl

from dolfinx.io import VTXWriter



from dolfinx.fem import (Constant, dirichletbc, Function, FunctionSpace, assemble_scalar,
                         form, locate_dofs_geometrical, locate_dofs_topological)

#from dolfinx.fem import (Constant, dirichletbc,
                         #extract_function_spaces, form,
                        # locate_dofs_topological)
from dolfinx import log, plot
#from dolfinx.plot import vtk_mesh
from dolfinx.fem import Function, FunctionSpace
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.io import XDMFFile
from dolfinx.mesh import CellType, create_rectangle, locate_entities_boundary
from dolfinx.nls.petsc import NewtonSolver
from ufl import dx, grad, inner
from dolfinx import fem, io, mesh, plot
from petsc4py.PETSc import ScalarType

from mpi4py import MPI
from petsc4py import PETSc

try:
    import pyvista as pv
    import pyvistaqt as pvqt
    have_pyvista = True
    if pv.OFF_SCREEN:
        pv.start_xvfb(wait=0.5)
except ModuleNotFoundError:
    print("pyvista and pyvistaqt are required to visualise the solution")
    have_pyvista = False

# Save all logging to file
log.set_output_file("log.txt")

import dolfinx
print(f"DOLFINx version: {dolfinx.__version__} based on GIT commit: {dolfinx.git_commit_hash} of https://github.com/FEniCS/dolfinx/")

lx = 1.0  #length of x-axis
Ly = 1.0  #length of y-axis
#nx, ny = 50, 50
nx = 8
ny = 8

t = 0
T = 10

# A rectangle mesh with 8 cells edges in each direction is created,
# and on this mesh a
# {py:class}`FunctionSpace<dolfinx.fem.FunctionSpace>` `ME` is built
# using a pair of linear Lagrange elements.

msh = mesh.create_rectangle(comm=MPI.COMM_WORLD,
                            points=((0.0, 0.0), (lx, Ly)), n=(nx, ny),
                            cell_type=mesh.CellType.triangle)

#msh = create_rectangle(MPI.COMM_WORLD, 96, 96, CellType.triangle)
#m1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
m1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
T1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
ME = FunctionSpace(msh, m1 * T1)

Q = FunctionSpace(msh, m1)
V = FunctionSpace(msh, T1)



# Defining our problem
#p = fem.Constant(domain, ScalarType(1)) # SIMP penalty exponent
am = fem.Constant(msh, ScalarType(3.e-06 ))  
k = fem.Constant(msh, ScalarType(0.12))  
c = fem.Constant(msh, ScalarType(1284.))  
rho_0 = fem.Constant(msh, ScalarType(500.)) 
R = fem.Constant(msh, ScalarType(2400.))   

epsilon = fem.Constant(msh, ScalarType(0.1))  
nu = fem.Constant(msh, ScalarType(1.e-02))        


dt = 0.001  #0.02 #5.0e-06  # time step


#We create four python functions for determining the facets to apply boundary conditions to

def left(x):
    return np.isclose(x[0], 0)  #left (x = 0)


def right(x):
    return np.isclose(x[0], lx)  #right (x = 1)

def bottom(x):
    return np.isclose(x[1], 0)  #bottom (y = 0)


def top(x):
    return np.isclose(x[1], Ly)  #top (y = 1)


right_m_dofs = locate_dofs_geometrical(Q, right)
bc_m_right = dirichletbc(PETSc.ScalarType(0.12), right_m_dofs, Q)



top_m_dofs = locate_dofs_geometrical(Q, top)
bc_m_top = dirichletbc(PETSc.ScalarType(0.12), top_m_dofs, Q)

right_T_dofs = locate_dofs_geometrical(V, right)
bc_T_right = dirichletbc(PETSc.ScalarType(60.), right_T_dofs, V)

top_T_dofs = locate_dofs_geometrical(V, top)
bc_T_top = dirichletbc(PETSc.ScalarType(60.), top_T_dofs, V)

#Creation of dirichlet conditions
bcm = [bc_m_right, bc_m_top]     #bc for unknown m
bcT = [bc_T_right, bc_T_top]     #bc for unknown T


#m = ufl.TrialFunction(Q)
#q = ufl.TestFunction(Q)
#T = ufl.TrialFunction(V)
#v = ufl.TestFunction(V)


#Test Functions (q, v)
q, v = ufl.TestFunctions(ME)

u = Function(ME)  # current solution
u_n = Function(ME)  # solution from previous converged step

# Split mixed functions
m, T = ufl.split(u)
m_n, T_n = ufl.split(u_n)

# Weak statement of the equations
m_n = Function(Q)
m_n.name = "m_n"
T_n = Function(V)
T_n.name = "T_n"

# The initial conditions are interpolated into a finite element space:


# Zero u
u.x.array[:] = 0.0

# Interpolate initial condition
#u.sub(0).interpolate(PETSc.ScalarType(0.30))  
u.sub(0).interpolate(lambda x: np.full(x.shape[1], 0.30, dtype=np.float64)) #Initial condition for m
u.sub(1).interpolate(lambda x: np.full(x.shape[1], 10., dtype=np.float64)) #Initial condition for T
u.x.scatter_forward()



#Variational formulation of the system
F0 = inner(m, q) * dx - inner(m_n, q) * dx + dt*am * inner(grad(m), grad(q)) * dx + dt*am*nu * inner(grad(T), grad(q)) * dx
F1 = c*rho_0* inner(T, v) * dx - c*rho_0* inner(T_n, v) * dx + dt*k * inner(grad(T), grad(v)) * dx - R*epsilon * inner(m, v) * dx + R*epsilon * inner(m_n, v) * dx
F = F0 + F1

#Solve variational problem
# Create nonlinear problem and Newton solver
problem = NonlinearProblem(F, u, bcs = [bcm, bcT])
solver = NewtonSolver(MPI.COMM_WORLD, problem)
solver.convergence_criterion = "incremental"
solver.rtol = 1e-6


# We can customize the linear solver used inside the NewtonSolver by
# modifying the PETSc options
ksp = solver.krylov_solver
opts = PETSc.Options()
option_prefix = ksp.getOptionsPrefix()
opts[f"{option_prefix}ksp_type"] = "preonly"
opts[f"{option_prefix}pc_type"] = "lu"
opts[f"{option_prefix}pc_factor_mat_solver_type"] = "mumps"
ksp.setFromOptions()



# Output file
file = XDMFFile(MPI.COMM_WORLD, "demo_fawzoulazim/output.xdmf", "w")
file.write_mesh(msh)

# Step in time
t = 0.0

#  Reduce run time if on test (CI) server
if "CI" in os.environ.keys() or "GITHUB_ACTIONS" in os.environ.keys():
    T = 3 * dt
else:
    T = 50 * dt

# Get the sub-space for m and the corresponding dofs in the mixed space
# vector
V0, dofs = ME.sub(0).collapse()

# Prepare viewer for plotting the solution during the computation
if have_pyvista:
    # Create a VTK 'mesh' with 'nodes' at the function dofs
    topology, cell_types, x = plot.create_vtk_mesh(V0)
    grid = pv.UnstructuredGrid(topology, cell_types, x)

    # Set output data
    grid.point_data["m"] = u.x.array[dofs].real
    grid.set_active_scalars("m")

    p = pvqt.BackgroundPlotter(title="concentration", auto_update=True)
    p.add_mesh(grid, clim=[0, 1])
    p.view_xy(True)
    p.add_text(f"time: {t}", font_size=12, name="timelabel")

m = u.sub(0)
u_n.x.array[:] = u.x.array
while (t < T):
    t += dt
    r = solver.solve(u)
    print(f"Step {int(t/dt)}: num iterations: {r[0]}")
    u_n.x.array[:] = u.x.array
    file.write_function(m, t)

    # Update the plot window
    if have_pyvista:
        p.add_text(f"time: {t:.2e}", font_size=12, name="timelabel")
        grid.point_data["m"] = u.x.array[dofs].real
        p.app.processEvents()

file.close()

# Update ghost entries and plot
if have_pyvista:
    u.x.scatter_forward()
    grid.point_data["m"] = u.x.array[dofs].real
    screenshot = None
    if pv.OFF_SCREEN:
        screenshot = "m.png"
    pv.plot(grid, show_edges=True, screenshot=screenshot)

But it did not work and the full error message is here:

DOLFINx version: 0.6.0 based on GIT commit: 30920d400ccb64d190de13509c43b1755d2606cc of https://github.com/FEniCS/dolfinx/
Traceback (most recent call last):
  File "/home/mamadou/Downloads/fawzoulazim2023_december2023_3.py", line 224, in <module>
    r = solver.solve(u)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/nls/petsc.py", line 41, in solve
    n, converged = super().solve(u.vector)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/fem/petsc.py", line 730, in F
    apply_lifting(b, [self._a], bcs=[self.bcs], x0=[x], scale=-1.0)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/fem/petsc.py", line 494, in apply_lifting
    assemble.apply_lifting(b_local.array_w, a, bcs, x0_r, scale, constants, coeffs)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/fem/assemble.py", line 307, in apply_lifting
    _cpp.fem.apply_lifting(b, a, constants, coeffs, bcs, x0, scale)
TypeError: apply_lifting(): incompatible function arguments. The following argument types are supported:
    1. (b: numpy.ndarray[numpy.float32], a: List[dolfinx::fem::Form<float>], constants: List[numpy.ndarray[numpy.float32]], coeffs: List[Dict[Tuple[dolfinx::fem::IntegralType, int], numpy.ndarray[numpy.float32]]], bcs1: List[List[dolfinx::fem::DirichletBC<float>]], x0: List[numpy.ndarray[numpy.float32]], scale: float) -> None
    2. (b: numpy.ndarray[numpy.float64], a: List[dolfinx::fem::Form<double>], constants: List[numpy.ndarray[numpy.float64]], coeffs: List[Dict[Tuple[dolfinx::fem::IntegralType, int], numpy.ndarray[numpy.float64]]], bcs1: List[List[dolfinx::fem::DirichletBC<double>]], x0: List[numpy.ndarray[numpy.float64]], scale: float) -> None
    3. (b: numpy.ndarray[numpy.complex64], a: List[dolfinx::fem::Form<std::complex<float> >], constants: List[numpy.ndarray[numpy.complex64]], coeffs: List[Dict[Tuple[dolfinx::fem::IntegralType, int], numpy.ndarray[numpy.complex64]]], bcs1: List[List[dolfinx::fem::DirichletBC<std::complex<float> >]], x0: List[numpy.ndarray[numpy.complex64]], scale: float) -> None
    4. (b: numpy.ndarray[numpy.complex128], a: List[dolfinx::fem::Form<std::complex<double> >], constants: List[numpy.ndarray[numpy.complex128]], coeffs: List[Dict[Tuple[dolfinx::fem::IntegralType, int], numpy.ndarray[numpy.complex128]]], bcs1: List[List[dolfinx::fem::DirichletBC<std::complex<double> >]], x0: List[numpy.ndarray[numpy.complex128]], scale: float) -> None

Invoked with: array([2.34375000e-03, 7.81250000e-04, 2.34375000e-03, 5.01556875e+04,
       1.67185625e+04, 5.01556875e+04, 4.68750000e-03, 1.00311375e+05,
       2.34375000e-03, 5.01556875e+04, 2.34375000e-03, 5.01556875e+04,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       2.34375000e-03, 5.01556875e+04, 2.34375000e-03, 5.01556875e+04,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 2.34375000e-03, 5.01556875e+04,
       2.34375000e-03, 5.01556875e+04, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 2.34375000e-03, 5.01556875e+04,
       2.34375000e-03, 5.01556875e+04, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       2.34375000e-03, 5.01556875e+04, 2.34375000e-03, 5.01556875e+04,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       2.34375000e-03, 5.01556875e+04, 2.34375000e-03, 5.01556875e+04,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 1.56250000e-03, 3.34371250e+04,
       1.56250000e-03, 3.34371250e+04, 2.34375000e-03, 5.01556875e+04,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       2.34375000e-03, 5.01556875e+04, 2.34375000e-03, 5.01556875e+04,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 2.34375000e-03, 5.01556875e+04,
       2.34375000e-03, 5.01556875e+04, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 2.34375000e-03, 5.01556875e+04,
       2.34375000e-03, 5.01556875e+04, 4.68750000e-03, 1.00311375e+05,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       2.34375000e-03, 5.01556875e+04, 2.34375000e-03, 5.01556875e+04,
       4.68750000e-03, 1.00311375e+05, 4.68750000e-03, 1.00311375e+05,
       2.34375000e-03, 5.01556875e+04, 2.34375000e-03, 5.01556875e+04,
       4.68750000e-03, 1.00311375e+05, 2.34375000e-03, 5.01556875e+04,
       2.34375000e-03, 5.01556875e+04, 2.34375000e-03, 5.01556875e+04,
       7.81250000e-04, 1.67185625e+04]), [<dolfinx.fem.forms.Form object at 0x7f4dd45ba3e0>], [array([3.000e-06, 1.200e-01, 1.284e+03, 5.000e+02, 2.400e+03, 1.000e-01,
       1.000e-02])], [{(<IntegralType.cell: 0>, -1): array([], shape=(0, 0), dtype=float64)}], [[[<dolfinx.fem.bcs.DirichletBC object at 0x7f4dd84fb8d0>, <dolfinx.fem.bcs.DirichletBC object at 0x7f4dd45a7510>], [<dolfinx.fem.bcs.DirichletBC object at 0x7f4dd45a75b0>, <dolfinx.fem.bcs.DirichletBC object at 0x7f4dd45a7740>]]], [array([ 0.3,  0.3,  0.3, 10. , 10. , 10. ,  0.3, 10. ,  0.3, 10. ,  0.3,
       10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,
        0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3,
       10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,
        0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3,
       10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,
        0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3,
       10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,
        0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3,
       10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,
        0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3,
       10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,
        0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3,
       10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ,
        0.3, 10. ,  0.3, 10. ,  0.3, 10. ,  0.3, 10. ])], -1.0

Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,
<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic
conversions are optional and require extra headers to be included
when compiling your pybind11 module.

Thanks for your time and attention.

Your bcs should be a single list, not a list of lists, as you have here, as

See for instance: Merge Two Lists in Python - GeeksforGeeks

Thank you for your quick reply,

Here you mean I will write my bcs as follows:

bcs = [bc_m_right, bc_m_top, bc_T_right, bc_T_top] 

Yes, that is what I mean.

Yes, I did.

Now, when I run it again, I get the following error message:

DOLFINx version: 0.6.0 based on GIT commit: 30920d400ccb64d190de13509c43b1755d2606cc of https://github.com/FEniCS/dolfinx/
Traceback (most recent call last):
  File "/home/mamadou/Downloads/fawzoulazim2023_december2023_3.py", line 225, in <module>
    r = solver.solve(u)
  File "/home/mamadou/anaconda3/envs/fenicsx/lib/python3.10/site-packages/dolfinx/nls/petsc.py", line 41, in solve
    n, converged = super().solve(u.vector)
RuntimeError: Newton solver did not converge because maximum number of iterations reached

which comes from this:

r = solver.solve(u)

I would suggest you have a look at: Default absolute tolerance and relative tolerance - #4 by nate

Hi dear Dokken, thanks for pointing this out, it’s very helpful!
Reading the documentation and some older questions, I learned that this is a common problem when solving nonlinear PDEs. Following Nate’s advice (‘some tips and tricks for nonlinear problems with a Newton solver’), I tried increasing the relative tolerance (i.e. 10^{-14} and 0.0) and also the number of cells (from 8 \times 8 to 96 \times 96).

However, the same error is displayed, i.e. ‘Newton solver did not converge because maximum number of iterations reached’.

According to Solution nonconvergence - #6 by violetus and Default absolute tolerance and relative tolerance - #4 by nate, the error could be due to a malformed Jacobian.

Can you help me further?

Thanks in advance.

Please make a minimal reproducible example, that means an example with as little code as possible that illustrates your problem.

First of all, I don’t see what makes your problem non-linear.
From your description above the equations look linear, and should therefore converge within one iteration.

The above system of equations is coupled and nonlinear PDEs. The unknowns are m and T.

Below is my implementation:

import os

import numpy as np

import ufl

from dolfinx.io import VTXWriter



from dolfinx.fem import (Constant, dirichletbc, Function, FunctionSpace, assemble_scalar,
                         form, locate_dofs_geometrical, locate_dofs_topological)

#from dolfinx.fem import (Constant, dirichletbc,
                         #extract_function_spaces, form,
                        # locate_dofs_topological)
from dolfinx import log, plot
#from dolfinx.plot import vtk_mesh
from dolfinx.fem import Function, FunctionSpace
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.io import XDMFFile
from dolfinx.mesh import CellType, create_rectangle, locate_entities_boundary
from dolfinx.nls.petsc import NewtonSolver
from ufl import dx, grad, inner
from dolfinx import fem, io, mesh, plot
from petsc4py.PETSc import ScalarType

from mpi4py import MPI
from petsc4py import PETSc

try:
    import pyvista as pv
    import pyvistaqt as pvqt
    have_pyvista = True
    if pv.OFF_SCREEN:
        pv.start_xvfb(wait=0.5)
except ModuleNotFoundError:
    print("pyvista and pyvistaqt are required to visualise the solution")
    have_pyvista = False

# Save all logging to file
log.set_output_file("log.txt")

import dolfinx
print(f"DOLFINx version: {dolfinx.__version__} based on GIT commit: {dolfinx.git_commit_hash} of https://github.com/FEniCS/dolfinx/")

lx = 1.0  #length of x-axis
Ly = 1.0  #length of y-axis
#nx, ny = 8, 8, 50, 50, 96, 96 
nx = 96
ny = 96

#t = 0
#T = 10

# A rectangle mesh with 8 cells edges in each direction is created,
# and on this mesh a
# {py:class}`FunctionSpace<dolfinx.fem.FunctionSpace>` `ME` is built
# using a pair of linear Lagrange elements.

msh = mesh.create_rectangle(comm=MPI.COMM_WORLD,
                            points=((0.0, 0.0), (lx, Ly)), n=(nx, ny),
                            cell_type=mesh.CellType.triangle)

#msh = create_rectangle(MPI.COMM_WORLD, 96, 96, CellType.triangle)
#m1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
m1 = ufl.FiniteElement("DG", msh.ufl_cell(), 4)
T1 = ufl.FiniteElement("DG", msh.ufl_cell(), 4)
ME = FunctionSpace(msh, m1 * T1)

Q = FunctionSpace(msh, m1)
V = FunctionSpace(msh, T1)



# Defining our problem
#p = fem.Constant(domain, ScalarType(1)) # SIMP penalty exponent
am = fem.Constant(msh, ScalarType(3.e-06 ))  
k = fem.Constant(msh, ScalarType(0.12))  
c = fem.Constant(msh, ScalarType(1284.))  
rho_0 = fem.Constant(msh, ScalarType(500.)) 
R = fem.Constant(msh, ScalarType(2400.))   

epsilon = fem.Constant(msh, ScalarType(0.1))  
nu = fem.Constant(msh, ScalarType(1.e-02))        


dt = 5.0e-06  # 0.001  #0.02 #5.0e-06  # time step


#We create four python functions for determining the facets to apply boundary conditions to

def left(x):
    return np.isclose(x[0], 0)  #left (x = 0)


def right(x):
    return np.isclose(x[0], lx)  #right (x = 1)

def bottom(x):
    return np.isclose(x[1], 0)  #bottom (y = 0)


def top(x):
    return np.isclose(x[1], Ly)  #top (y = 1)


right_m_dofs = locate_dofs_geometrical(Q, right)
bc_m_right = dirichletbc(PETSc.ScalarType(0.12), right_m_dofs, Q)



top_m_dofs = locate_dofs_geometrical(Q, top)
bc_m_top = dirichletbc(PETSc.ScalarType(0.12), top_m_dofs, Q)

right_T_dofs = locate_dofs_geometrical(V, right)
bc_T_right = dirichletbc(PETSc.ScalarType(80.), right_T_dofs, V)

top_T_dofs = locate_dofs_geometrical(V, top)
bc_T_top = dirichletbc(PETSc.ScalarType(80.), top_T_dofs, V)

#Creation of dirichlet conditions
#bcm = [bc_m_right, bc_m_top]     #bc for unknown m
#bcT = [bc_T_right, bc_T_top]     #bc for unknown T

bcs = [bc_m_right, bc_m_top, bc_T_right, bc_T_top]  #dirichlet boundary conditions

#m = ufl.TrialFunction(Q)
#q = ufl.TestFunction(Q)
#T = ufl.TrialFunction(V)
#v = ufl.TestFunction(V)


#Test Functions (q, v)
q, v = ufl.TestFunctions(ME)

u = Function(ME)  # current solution
u_n = Function(ME)  # solution from previous converged step

# Split mixed functions
m, T = ufl.split(u)
m_n, T_n = ufl.split(u_n)

# Weak statement of the equations
m_n = Function(Q)
m_n.name = "m_n"
T_n = Function(V)
T_n.name = "T_n"

# The initial conditions are interpolated into a finite element space:


# Zero u
u.x.array[:] = 0.0

# Interpolate initial condition
#u.sub(0).interpolate(PETSc.ScalarType(0.30))  
u.sub(0).interpolate(lambda x: np.full(x.shape[1], 0.50, dtype=np.float64)) #Initial condition for m
u.sub(1).interpolate(lambda x: np.full(x.shape[1], 10., dtype=np.float64)) #Initial condition for T
u.x.scatter_forward()



#Variational formulation of the system
F0 = inner(m, q) * dx - inner(m_n, q) * dx + dt*am * inner(grad(m), grad(q)) * dx + dt*am*nu * inner(grad(T), grad(q)) * dx
F1 = c*rho_0* inner(T, v) * dx - c*rho_0* inner(T_n, v) * dx + dt*k * inner(grad(T), grad(v)) * dx - R*epsilon * inner(m, v) * dx + R*epsilon * inner(m_n, v) * dx
F = F0 + F1

#Solve variational problem
# Create nonlinear problem and Newton solver
problem = NonlinearProblem(F, u, bcs = bcs)
solver = NewtonSolver(MPI.COMM_WORLD, problem)
solver.convergence_criterion = "residual"          #incremental
solver.rtol = 1e-14 #0.0 #1e-12


# We can customize the linear solver used inside the NewtonSolver by
# modifying the PETSc options
ksp = solver.krylov_solver
opts = PETSc.Options()
option_prefix = ksp.getOptionsPrefix()
opts[f"{option_prefix}ksp_type"] = "preonly"
opts[f"{option_prefix}pc_type"] = "lu"
opts[f"{option_prefix}pc_factor_mat_solver_type"] = "mumps"
ksp.setFromOptions()




# Output file
file = XDMFFile(MPI.COMM_WORLD, "demo_fawzoulazim/output.xdmf", "w")
file.write_mesh(msh)

# Step in time
t = 0.0

#  Reduce run time if on test (CI) server
if "CI" in os.environ.keys() or "GITHUB_ACTIONS" in os.environ.keys():
    T = 3 * dt
else:
    T = 50 * dt

# Get the sub-space for m and the corresponding dofs in the mixed space
# vector
V0, dofs = ME.sub(0).collapse()

# Prepare viewer for plotting the solution during the computation
if have_pyvista:
    # Create a VTK 'mesh' with 'nodes' at the function dofs
    topology, cell_types, x = plot.create_vtk_mesh(V0)
    grid = pv.UnstructuredGrid(topology, cell_types, x)

    # Set output data
    grid.point_data["m"] = u.x.array[dofs].real
    grid.set_active_scalars("m")

    p = pvqt.BackgroundPlotter(title="concentration", auto_update=True)
    p.add_mesh(grid, clim=[0, 0.50])
    p.view_xy(True)
    p.add_text(f"time: {t}", font_size=12, name="timelabel")

m = u.sub(0)
u_n.x.array[:] = u.x.array
while (t < T):
    t += dt
    r = solver.solve(u)   #Issue from here
    print(f"Step {int(t/dt)}: num iterations: {r[0]}")
    u_n.x.array[:] = u.x.array
    file.write_function(m, t)

    # Update the plot window
    if have_pyvista:
        p.add_text(f"time: {t:.2e}", font_size=12, name="timelabel")
        grid.point_data["m"] = u.x.array[dofs].real
        p.app.processEvents()

file.close()

# Update ghost entries and plot
if have_pyvista:
    u.x.scatter_forward()
    grid.point_data["m"] = u.x.array[dofs].real
    screenshot = None
    if pv.OFF_SCREEN:
        screenshot = "m.png"
    pv.plot(grid, show_edges=True, screenshot=screenshot)

Could you please point me to the non-linear term in your equations, as I cannot spot them.

The a_m \nu \Delta T term for the first PDE nonlinear and the $R \epsilon \frac{\partial m}{t} term for the second PDE.

The a_m \nu ΔT term for the first PDE and the R \epsilon \frac{\partial m}{t} term for the second PDE.