Hi everyone,
I am trying to convert a code written in Fenics to FenicsX. Here we use a fully incompressible formulation, solving for the displacement and the hydrostatic pressure simultaneously. However, it doesn’t work (aka, doesn’t converge), and I’m not able to see why.
I’ve tried to adapt this code, which runs fine as it is, to my case: Hyperelasticity — FEniCSx tutorial
The code reads as follows:
import numpy as np
import ufl
from petsc4py import PETSc
from mpi4py import MPI
from dolfinx import fem, mesh, plot, io, nls, log, cpp
domain = mesh.create_box(MPI.COMM_WORLD,[[0.0,0.0,0.0], [1, 1, 1]], [2, 2, 2], mesh.CellType.hexahedron)
P2 = ufl.VectorElement("Lagrange", domain.ufl_cell(), 2)
P1 = ufl.FiniteElement("Lagrange", domain.ufl_cell(), 1)
state_space = fem.FunctionSpace(domain, P2 * P1)
V, _ = state_space.sub(0).collapse()
def left(x):
return np.isclose(x[0], 0)
def right(x):
return np.isclose(x[0], 1)
fdim = domain.topology.dim -1
left_facets = mesh.locate_entities_boundary(domain, fdim, left)
right_facets = mesh.locate_entities_boundary(domain, fdim, right)
# Concatenate and sort the arrays based on facet indices. Left facets marked with 1, right facets with two
marked_facets = np.hstack([left_facets, right_facets])
marked_values = np.hstack([np.full_like(left_facets, 1), np.full_like(right_facets, 2)])
sorted_facets = np.argsort(marked_facets)
facet_tag = mesh.meshtags(domain, fdim, marked_facets[sorted_facets], marked_values[sorted_facets])
u_bc = np.array((0,) * domain.geometry.dim, dtype=PETSc.ScalarType)
left_dofs = fem.locate_dofs_topological(V, facet_tag.dim, facet_tag.find(1))
bcs = [fem.dirichletbc(u_bc, left_dofs, V)]
T = fem.Constant(domain, PETSc.ScalarType((0, 0, -1.5)))
state = fem.Function(state_space, name="state")
test_state = ufl.TestFunctions(state_space)
u, p = state.split()
v, q = test_state
# Kinematics
d = len(u)
I = ufl.variable(ufl.Identity(d))
F = ufl.variable(I + ufl.grad(u))
C = ufl.variable(F.T * F)
Ic = ufl.variable(ufl.tr(C))
J = ufl.variable(ufl.det(F))
# Elasticity parameters
E = PETSc.ScalarType(1.0e4)
nu = PETSc.ScalarType(0.5)
mu = fem.Constant(domain, E/(2*(1 + nu)))
# Stored strain energy density (fully incompressible neo-Hookean model)
psi = (mu / 2) * (Ic - 3) - mu * ufl.ln(J)
# Hyper-elasticity
P = ufl.diff(psi, F) + p * J * ufl.inv(F.T)
metadata = {"quadrature_degree": 4}
ds = ufl.Measure('ds', domain=domain, subdomain_data=facet_tag, metadata=metadata)
dx = ufl.Measure("dx", domain=domain, metadata=metadata)
R = ufl.inner(ufl.grad(v), P)*dx - ufl.inner(v, T)*ds(2) + q * (J - 1) * dx
problem = fem.petsc.NonlinearProblem(R, state, bcs)
solver = nls.petsc.NewtonSolver(domain.comm, problem)
# Set Newton solver options
solver.atol = 1e-8
solver.rtol = 1e-8
solver.convergence_criterion = "incremental"
solver.solve(state)
If I implement the same in Fenics it does run nicely, so I think my error is in the FenicsX syntax. Is anyone able to see what could cause the non-convergent behavior?