Error while using NewtonSolver in conjunction with NonlinearProblem

Dear. Researchers
I have successfully programmed nonlinear time-dependent problem using fenics. To leverage the capability of fenicsx for applying multipoint constraint on the model, I have trasnsferred the code into fenicsx format. uppon runnig the code I have received the following message in the output:
solver_problem = NewtonSolver(MPI.COMM_WORLD,problem)
File “/home/mohammad-jalili/anaconda3/envs/fenicsx/lib/python3.14/site-packages/dolfinx/nls/petsc.py”, line 60, in init
self._A = create_matrix(problem.a)
^^^^^^^^^
AttributeError: ‘NonlinearProblem’ object has no attribute ‘a’. Did you mean: ‘A’?
Exception ignored while calling deallocator <function NewtonSolver.del at 0x794181b16a30>:
Traceback (most recent call last):
File “/home/mohammad-jalili/anaconda3/envs/fenicsx/lib/python3.14/site-packages/dolfinx/nls/petsc.py”, line 67, in del
for obj in filter(lambda obj: obj is not None, (self._A, self._b)):
AttributeError: ‘NewtonSolver’ object has no attribute ‘_A’

The solver part of the code is as follows:
‘’'python
= ufl.Measure(“dx”, domain = refined_domain)
Form_c = ((c_new - c_old)/dt_barv_cdx
+ beta*ufl.inner(ufl.grad(c_new),ufl.grad(v_c))*dx
+ ((1-n_new)*c_new)v_cdx)

zeta = c_characteristic/Molarity

Form_n = ((n_new - n_old)/dt_bar * v_n * dx
- zetac_new(1 - n_new)v_ndx)

Form_total = Form_c + Form_n

Gain = ufl.derivative(Form_total, w,dw)

# -----------------------------

problem = NonlinearProblem(Form_total, w,petsc_options_prefix= “reaction-diffusion” ,bcs = bcs_problem, J = Gain)
solver_problem = NewtonSolver(MPI.COMM_WORLD,problem)
solver_problem.convergence_criterion = “residual”
solver_problem.atol = 1e-9
solver_problem.rtol = 1e-7
solver_problem.max_it = 10
solver_problem.report = True
solver_problem.error_on_nonconvergence = False

print(type(problem))

w_old.x.array[:] = w.x.array

for step in range(num_steps_bar):
t += dt_bar

solver_problem.solve(w)

w_old.x.array[:] = w.x.array

‘’’
I will be really appreciated for any assistance to resolve the issue.

You seem to be mixing the new and old implementation of NonlInearProblem, see:

and

for a usage example.

I am so grateful for your response. I have modified the solver and now it runs but the convergence is largely deteriorated compared with the Fenics-version of the code. please note that I do not change the specification and structure of Fenics counterpart while transferring the code into Fenicsx. Besides, the types of linear solver and line search method is MUMPS and “bt” for both cases. However, after running the code I have received converged_reason equal -8 which implies convergence to local minimum of weak form. During the debugging process, I have recognized that Dirichlet boundary conditions are not properly enforced. I applied the procedure described in the forum but it was unsuccessful. I will put the selected part of the code. Any assistance will be appreciated.

‘’'python

from mpi4py import MPI

import dolfinx

from dolfinx.mesh import create_rectangle

import ufl

import basix.ufl

from dolfinx.mesh import meshtags, locate_entities_boundary

from dolfinx.fem import functionspace, Function, locate_dofs_topological, Constant, locate_dofs_geometrical

from dolfinx.mesh import compute_midpoints

from dolfinx import geometry

import numpy as np

from dolfinx.io import XDMFFile

from dolfinx.cpp.mesh import CellType

from petsc4py import PETSc

from ufl.classes import *

from ufl.algorithms import *

from ufl import Measure

from dolfinx.fem.petsc import NonlinearProblem

from dolfinx.nls.petsc import NewtonSolver

import os

from pathlib import Path

from mpi4py import MPI

from dolfinx import default_real_type, log, plot

from petsc4py.PETSc import ScalarType

-----------------------------

Time parameters

-----------------------------

num_steps = 72000

t = 0.0

t_end = 3600

dt = t_end/num_steps

BC_thickness = 100e-6

Oxide_thickness = 1e-6

Lx = 60e-6

Ly = BC_thickness + Oxide_thickness

refine_length = BC_thickness - 10e-6

-----------------------------

Parameters

-----------------------------

x_bar = Ly

BC_bar = BC_thickness/x_bar

Oxide_bar = Oxide_thickness/x_bar

Lx_bar = Lx/x_bar

Ly_bar = Ly/x_bar

refine_length_bar = refine_length/x_bar

print(refine_length_bar)

c_characteristic = 0.32e6

-----------------------------

Geometry

-----------------------------

nx, ny = 300,1000

domain = create_rectangle(MPI.COMM_WORLD, [np.array([0,0]), np.array([Lx_bar,Ly_bar])], [nx,ny])

tdim = domain.topology.dim

def refine_cells(x, tol=1e-16):

return x[1] >= refine_length_bar + tol

cells2 = dolfinx.mesh.locate_entities(domain,tdim,refine_cells)

print(“cells shape”,np.shape(cells2))

domain.topology.create_connectivity(tdim,tdim-1)

domain_topo = domain.topology

associated_edges = dolfinx.mesh.compute_incident_entities(domain_topo,cells2,2,1)

refined_domain,,= dolfinx.mesh.refine(domain,associated_edges)

with XDMFFile(MPI.COMM_WORLD,“refined_domain_scaled.xdmf”,“w”) as xdmf:

xdmf.write_mesh(refined_domain)

element_degree = 1

variant = basix.LagrangeVariant.equispaced

c_el = basix.ufl.element(“Lagrange”, refined_domain.topology.cell_name(), element_degree, variant, dtype = default_real_type)

n_el = basix.ufl.element(“Lagrange”, refined_domain.topology.cell_name(), element_degree, variant, dtype = default_real_type)

total_elements = basix.ufl.mixed_element([c_el,n_el])

ME = dolfinx.fem.functionspace(refined_domain, total_elements)

w = dolfinx.fem.Function(ME)

w.name = “WW”

w_old = dolfinx.fem.Function(ME)

dw = ufl.TrialFunction(ME)

c_new,n_new = ufl.split(w)

c_old,n_old = ufl.split(w_old)

w.sub(0).x.array[:] = 0.0

w.sub(1).x.array[:] = 0.0

x= ufl.SpatialCoordinate(refined_domain)

w.sub(1).interpolate(lambda x: np.where(x[1] >= BC_bar, 1.0, 0.0))

def top(x):

return np.isclose(x[1], Ly_bar)

def bottom(x):

return np.isclose(x[1], 0.0)

c_space, _ = ME.sub(0).collapse()

c_bc_top = dolfinx.fem.Function(c_space)

c_bc_top.x.array[:] = 1.55

top_facets = dolfinx.mesh.locate_entities_boundary(refined_domain, tdim-1, top)

top_dofs = dolfinx.fem.locate_dofs_topological((ME.sub(0), c_space), tdim-1, top_facets)

c_space_bot, _ = ME.sub(0).collapse()

c_bc_bot = dolfinx.fem.Function(c_space)

c_bc_bot.x.array[:] = 0.0

bottom_facets = dolfinx.mesh.locate_entities_boundary(refined_domain, tdim-1, bottom)

bot_dofs = dolfinx.fem.locate_dofs_topological((ME.sub(0), c_space), tdim-1, bottom_facets)

bc_c_top = dolfinx.fem.dirichletbc(c_bc_top, top_dofs,c_space)

bc_c_bot = dolfinx.fem.dirichletbc(c_bc_bot,bot_dofs,c_space)

bcs_problem = [bc_c_top, bc_c_bot]

‘’’

Please format the code with 3x`,
i.e.

```python
# Add code here
```
from mpi4py import MPI
import dolfinx 
from dolfinx.mesh import create_rectangle
import ufl
import basix.ufl
from dolfinx.mesh import meshtags, locate_entities_boundary
from dolfinx.fem import functionspace, Function, locate_dofs_topological, Constant, locate_dofs_geometrical
from dolfinx.mesh import compute_midpoints
from dolfinx import geometry
import numpy as np
from dolfinx.io import XDMFFile
from dolfinx.cpp.mesh import CellType
from petsc4py import PETSc
from ufl.classes import *
from ufl.algorithms import *
from ufl import Measure
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.nls.petsc import NewtonSolver
import os
from pathlib import Path

from mpi4py import MPI
from dolfinx import default_real_type, log, plot
from petsc4py.PETSc import ScalarType

# -----------------------------
# Time parameters
# -----------------------------
num_steps = 72000
t = 0.0
t_end = 3600

dt = t_end/num_steps


BC_thickness = 100e-6
Oxide_thickness = 1e-6
Lx = 60e-6
Ly = BC_thickness + Oxide_thickness
refine_length = BC_thickness - 10e-6

x_bar = Ly

BC_bar = BC_thickness/x_bar
Oxide_bar = Oxide_thickness/x_bar
Lx_bar = Lx/x_bar
Ly_bar = Ly/x_bar
refine_length_bar = refine_length/x_bar

print(refine_length_bar)
c_characteristic = 0.32e6
nx, ny = 300,1000


domain = create_rectangle(MPI.COMM_WORLD, [np.array([0,0]), np.array([Lx_bar,Ly_bar])], [nx,ny])

tdim = domain.topology.dim
def refine_cells(x, tol=1e-16):
    return x[1] >= refine_length_bar + tol


cells2 = dolfinx.mesh.locate_entities(domain,tdim,refine_cells)


print("cells shape",np.shape(cells2))

domain.topology.create_connectivity(tdim,tdim-1)

domain_topo = domain.topology

associated_edges = dolfinx.mesh.compute_incident_entities(domain_topo,cells2,2,1)


refined_domain,_,_= dolfinx.mesh.refine(domain,associated_edges)


with XDMFFile(MPI.COMM_WORLD,"refined_domain_scaled.xdmf","w") as xdmf:
    xdmf.write_mesh(refined_domain)

element_degree = 1
variant = basix.LagrangeVariant.equispaced
c_el = basix.ufl.element("Lagrange", refined_domain.topology.cell_name(), element_degree, variant, dtype = default_real_type)
n_el = basix.ufl.element("Lagrange", refined_domain.topology.cell_name(), element_degree, variant, dtype = default_real_type)

total_elements = basix.ufl.mixed_element([c_el,n_el])


ME = dolfinx.fem.functionspace(refined_domain, total_elements)

w = dolfinx.fem.Function(ME)
w_old = dolfinx.fem.Function(ME)
dw = ufl.TrialFunction(ME)


c_new,n_new = ufl.split(w)
c_old,n_old = ufl.split(w_old)
v_c,v_n = ufl.TestFunctions(ME)
dc,dn = ufl.TrialFunctions(ME)


w.sub(0).x.array[:] = 0.0
w.sub(1).x.array[:] = 0.0


x= ufl.SpatialCoordinate(refined_domain)


w.sub(1).interpolate(lambda x: np.where(x[1] >= BC_bar, 1.0, 0.0))


with XDMFFile(refined_domain.comm, "phase_sub.xdmf", "w") as xdmf: 
    xdmf.write_mesh(refined_domain)
    xdmf.write_function(w.sub(1))


def top(x):
    return np.isclose(x[1], Ly_bar)


def bottom(x):
    return np.isclose(x[1], 0.0)

c_space, _ = ME.sub(0).collapse()
c_bc_top = dolfinx.fem.Function(c_space)
c_bc_top.x.array[:] = 1.55
top_facets = dolfinx.mesh.locate_entities_boundary(refined_domain, tdim-1, top)
top_dofs = dolfinx.fem.locate_dofs_topological((ME.sub(0), c_space), tdim-1, top_facets)


c_space_bot, _ = ME.sub(0).collapse()
c_bc_bot = dolfinx.fem.Function(c_space)
c_bc_bot.x.array[:] = 0.0
bottom_facets = dolfinx.mesh.locate_entities_boundary(refined_domain, tdim-1, bottom)
bot_dofs = dolfinx.fem.locate_dofs_topological((ME.sub(0), c_space_bot), tdim-1, bottom_facets)


bc_c_top = dolfinx.fem.dirichletbc(c_bc_top, top_dofs,ME.sub(0))
bc_c_bot = dolfinx.fem.dirichletbc(c_bc_bot,bot_dofs,ME.sub(0))

bcs_problem = [bc_c_top, bc_c_bot]



D = dolfinx.fem.Constant(refined_domain,2e-13)
eta = dolfinx.fem.Constant(refined_domain,1e-5)
Molarity = dolfinx.fem.Constant(refined_domain,1.11e5)

t_characteristic = 1/(Molarity*eta)

t_bar = t_end/t_characteristic
dt_bar = dt/t_characteristic
num_steps_bar = 72000
beta = D/(Molarity*eta*x_bar**2)


dx = ufl.Measure("dx", domain = refined_domain)
Form_c = ((c_new - c_old)/dt_bar*v_c*dx
         + beta*ufl.inner(ufl.grad(c_new),ufl.grad(v_c))*dx
           + ((1-n_new)*c_new)*v_c*dx)
zeta = c_characteristic/Molarity

Form_n = ((n_new - n_old)/dt_bar * v_n * dx
           - zeta*c_new*(1 - n_new)*v_n*dx)
Form_total = Form_c + Form_n
Gain = ufl.derivative(Form_total, w,dw)
problem = NonlinearProblem(Form_total, w,petsc_options_prefix= "reaction-diffusion" ,bcs = bcs_problem, J = Gain)


use_superlu = PETSc.IntType == np.int64  # or PETSc.ScalarType == np.complex64
sys = PETSc.Sys()  # type: ignore
if sys.hasExternalPackage("mumps") and not use_superlu:
    linear_solver = "mumps"
elif sys.hasExternalPackage("superlu_dist"):
    linear_solver = "superlu_dist"
else:
    linear_solver = "petsc"
petsc_options = {
    "snes_type": "newtonls",
    "snes_linesearch_type": "bt",
    "snes_atol": 1e-5,
    "snes_rtol": 1e-6,
    "ksp_type": "preonly",
    "pc_type": "lu",
    "pc_factor_mat_solver_type":linear_solver,
    "snes_monitor": None,
    "snes_max_it": 1000
}
problem = NonlinearProblem(
    Form_total, w, petsc_options_prefix="reaction-diffusion", petsc_options=petsc_options, J = Gain, bcs = bcs_problem
)


c_new_c = w.sub(0).collapse()

n_new_c = w.sub(1).collapse()

w_old.x.array[:] = w.x.array

with XDMFFile(MPI.COMM_WORLD, "results2D-fenicsx/solution.xdmf", "w") as xdmfout:
    xdmfout.write_mesh(refined_domain)

for step in range(num_steps_bar):
    t += dt_bar
    
    _ = problem.solve()
    converged_reason = problem.solver.getConvergedReason()
    num_iterations = problem.solver.getIterationNumber()
    print(f"Step {step}: {converged_reason=} {num_iterations=}")

    w_old.x.array[:] = w.x.array
    xdmfout.write_function(c_new_c,t)
    xdmfout.write_function(n_new_c,t)
xdmfout.close()