Hi all,
I adapted a code from a previous forum post to the latest version of fenicsx. the simulation runs smoothly for 2nd order continuous galerkin elements, but fails to converge for first order elements, how is that so? this was done using
dolfinx version 0.8
import numpy as np
import ufl
from petsc4py import PETSc
from mpi4py import MPI
from dolfinx import fem, mesh, plot, io, nls, log, cpp
import basix
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.nls.petsc import NewtonSolver
domain = mesh.create_box(MPI.COMM_WORLD,[[0.0,0.0,0.0], [1, 1, 1]], [2, 2, 2], mesh.CellType.hexahedron)
P2 = basix.ufl.element(
"CG",
domain.topology.cell_name(),
1,
shape=(domain.geometry.dim, )
)
P1 = basix.ufl.element(
"CG",
domain.topology.cell_name(),
1,
)
# combine and define our mixed element
mixed = basix.ufl.mixed_element([P2, P1])
state_space = fem.functionspace(domain, mixed)
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])
u0_bc = fem.Function(V)
u0 = lambda x: np.zeros_like(x, dtype=PETSc.ScalarType)
u0_bc.interpolate(u0)
left_dofs = fem.locate_dofs_topological((state_space.sub(0), V), facet_tag.dim, facet_tag.find(1))
bcs = [fem.dirichletbc(u0_bc, left_dofs, state_space.sub(0))]
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 = ufl.split(state)
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 = NonlinearProblem(R, state, bcs)
solver = NewtonSolver(domain.comm, problem)
# Set Newton solver options
solver.atol = 1e-8
solver.rtol = 1e-8
solver.convergence_criterion = "incremental"
solver.solve(state)
u_sol, p_sol = state.split()
in particular, changing the displacement element to first order:
P2 = basix.ufl.element(
"CG",
domain.topology.cell_name(),
1,
shape=(domain.geometry.dim, )
)
then fails the simulation, as such:
RuntimeError: Newton solver did not converge because maximum number of iterations reached
thanks in advance.