I’m trying to solve Euler’s elastica equation (see this link) for a loop in the plane:
u: \mathbb{R} / \mathbb{Z} \to \mathbb{R}^2
with the bending energy:
E[u] = \int_0^1 (|u''|^2 + p(|u'|^2 - 1))dx
and p a Lagrange multiplier enforcing the inextensibility constraint |u'| = 1. I have expressed it in the weak form:
\int_0^1[u'' \cdot v'' + p u' \cdot v' - q(u'\cdot u' - 1)]dx = 0
Finally, here is my code implementing this:
import numpy as np
import pdb
from mpi4py import MPI
import dolfinx
import dolfinx_mpc
import ufl
from fenics_tools import *
# Create mesh & solution space
n_elem = 50
comm = MPI.COMM_WORLD
domain = dolfinx.mesh.create_unit_interval(comm=comm, nx=n_elem)
P1 = ufl.VectorElement('Lagrange', cell=domain.ufl_cell(), degree=2, dim=2)
P2 = ufl.FiniteElement('Lagrange', cell=domain.ufl_cell(), degree=1)
V = dolfinx.fem.FunctionSpace(domain, ufl.MixedElement([P1, P2]))
# Set periodic boundary conditions
mpc = apply_periodic_bcs(domain, V, 1)
# Create problem
state = dolfinx.fem.Function(V)
twopi = 2 * np.pi
state.sub(0).interpolate(lambda x: np.stack((np.sin(twopi * x[0]), np.cos(twopi * x[0]))) / twopi)
(u, p) = ufl.split(state)
(v, q) = ufl.TestFunctions(V)
dx = ufl.Measure('dx', domain=domain, metadata={'quadrature_degree': 4})
F = (
ufl.inner(ufl.grad(ufl.grad(u)), ufl.grad(ufl.grad(v)))
+ p * ufl.inner(ufl.grad(u), ufl.grad(v))
- q * (ufl.inner(ufl.grad(u), ufl.grad(u)) - 1)
) * dx
problem = dolfinx.fem.petsc.NonlinearProblem(F, state, bcs=[])
# Solve problem
solver = dolfinx.nls.petsc.NewtonSolver(comm, problem)
solver.atol = 1e-6
solver.rtol = 1e-6
solver.convergence_criterion = 'incremental'
solver.report = True
solver.solve(state)
u_sol, p_sol = state.split()
ux_sol, uy_sol = u_sol.split()
ux_sol, uy_sol, p_sol = ux_sol.x.array, uy_sol.x.array, p_sol.x.array
where apply_periodic_bcs
is more or less exactly from the MPC example here.
However, it always returns:
RuntimeError: Newton solver did not converge because maximum number of iterations reached
I then tried interpolating an analytical solution, which should be a circle of circumference 1:
u(x) = (\sin(2\pi x)/2\pi, \cos(2\pi x)/2\pi)
But still obtain the same result. I’m new to the nonlinear solver and am wondering if I’m doing something incorrect in setting up this problem. Especially with the analytical solution interpolated, very few to no steps should be required in principle. Could I have some help with this?