The nonlinear-poisson demo gives an example of using an iterative Newton solver to solve a nonlinear Poisson equation with Dirichlet boundary conditions. I want to use the the solver with Neumann conditions, since the iterative solver solves for Function u rather than TrialFunction, which seems to make it easier to setup a nonlinear source function.
I can get a Neumann solution using direct solvers (via TrialFunction). But when I try Neumann conditions with a Newton solver, it immediately diverges:
No Jacobian form specified for nonlinear variational problem.
Differentiating residual form F to obtain Jacobian J = F'.
Solving nonlinear variational problem.
Newton iteration 0: r (abs) = 9.896e-01 (tol = 1.000e-10) r (rel) = 1.000e+00 (tol = 1.000e-06)
Newton iteration 1: r (abs) = -nan (tol = 1.000e-10) r (rel) = -nan (tol = 1.000e-06)
Newton iteration 2: r (abs) = -nan (tol = 1.000e-10) r (rel) = -nan (tol = 1.000e-06)
I've tried variations such as solving the Dirichlet problem first, then using that solution as an initial guess for the Neumann problem. But that gives the same kind of divergence, even if I set the Neumann condition using the gradient from the Dirichlet solution.
The simplest test case, reduced to 1D, is
from dolfin import *
# Sub domain for Dirichlet boundary condition
class BoundaryRight(SubDomain):
def inside(self, x, on_boundary):
return abs(x[0] - 1.0) < DOLFIN_EPS and on_boundary
# Create mesh and define function space
mesh = UnitIntervalMesh(32)
V = FunctionSpace(mesh, "CG", 1)
boundaries = FacetFunction("size_t", mesh)
boundaries.set_all(0)
boundaryRight = BoundaryRight()
boundaryRight.mark(boundaries, 1)
ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
g = Constant(1.0)
# Define variational problem
u = Function(V)
v = TestFunction(V)
f = Expression("x[0]", degree=2)
F = inner(grad(u), grad(v))*dx - f*v*dx + g*v*ds(1)
# Compute solution
solve(F == 0, u, [], solver_parameters={"newton_solver": {"relative_tolerance": 1e-6}})
plot(u, title="Solution Neumann")
plot(grad(u), title="Solution Neumann gradient")
interactive()
Would you expect this code to converge?