In FEniCS the iterative procedure of solving a non-linear problem is
by default Newton's method. Here, the problem is linearized, the
Jacobian is computed and the corresponding linear systems solved.
You may take more control over this process either by implementing your
own solver or constructing your own variant of an approximate Jacobian.
The following example shows a Picard iteration:
"""
Program to solve x**4 - 4 with Picard
The solution x = pluss/minus sqrt(2)
We assume a problem on variational form:
F(u)vdx = (a(u)u - b)vdx = 0
Then, if up is the previous solution,
we find u as:
a(up)uvdx = b
and update:
u = alphau + (1-alpha)up
where alpha is the regularization parameter
"""
from dolfin import *
import math
mesh = UnitSquareMesh(1,1)
V = FunctionSpace(mesh, "DG", 0)
u = TrialFunction(V)
U = Function(V)
U.vector()[:] = 2.7
v = TestFunction(V)
a = U**3uvdx
L = 4v*dx
F = action(a, U) - L
picard_problem = NonlinearVariationalProblem(F, U, J=a)
solver = NonlinearVariationalSolver(picard_problem)
solver.parameters["newton_solver"]["relaxation_parameter"] = 0.4
solver.parameters["newton_solver"]["maximum_iterations"] = 40
solver.parameters["newton_solver"]["absolute_tolerance"] = 1.0e-6
solver.solve()
print "The true solution sqrt(2)=%e and the numerical solution is %e " % (math.sqrt(2), max(U.vector().array()[:]))