Hi all, This is probably a simple thing but I've been hitting my head against it. I need to program the newton method manually, and want to compare it to the nonlinearvariationalsolver. Both converge but I can't seem to match my residual norms. Here is my code:
from dolfin import *
import numpy as np
mesh = IntervalMesh(100, 0,1)
V = FunctionSpace(mesh, "Lagrange",1) # Order 1 function space
dU = TrialFunction(V)
test_U = TestFunction(V)
U = Function(V)
left, right = compile_subdomains([
"(std::abs( x[0] ) < DOLFIN_EPS) && on_boundary",
"(std::abs( x[0]-1.0 ) < DOLFIN_EPS) && on_boundary"])
bcs = [
DirichletBC(V, 1, left),
DirichletBC(V, 0 , right),
]
k = 1.0*U+1.0
F = inner(k*grad(U), grad(test_U))*dx
Jac = derivative(F, U, dU)
U_init = Expression("1-x[0]")
U.interpolate(U_init)
if False:
problem = NonlinearVariationalProblem(F, U, bcs, Jac) #,form_compiler_parameters=ffc_options
solver = NonlinearVariationalSolver(problem)
solver.solve()
else:
a_tol, r_tol = 1e-7, 1e-10
bcs_du = homogenize(bcs)
U_inc = Function(V)
nIter = 0
eps = 1
while eps > 1e-10 and nIter < 10: # Newton iterations
nIter += 1
A, b = assemble_system(Jac, -F, bcs_du)
solve(A, U_inc.vector(), b) # Determine step direction
eps = np.linalg.norm(U_inc.vector().array(), ord = 2)
a = assemble(F)
fnorm = np.linalg.norm(a.array(), ord = 2)
lmbda = 1.0 # step size, initially 1
U.vector()[:] += lmbda*U_inc.vector() # New u vector
print ' {0:2d} {1:3.2E} {2:5e}'.format(nIter, eps, fnorm)
plot(U)
interactive()
Change the True / False above to switch methods. With the nonlinearvariationalsolver I get the output:
Solving nonlinear variational problem.
Newton iteration 1: r (abs) = 5.898e-03 (tol = 1.000e-10) r (rel) = 5.927e-02 (tol = 1.000e-09)
Newton iteration 2: r (abs) = 6.381e-06 (tol = 1.000e-10) r (rel) = 6.413e-05 (tol = 1.000e-09)
Newton iteration 3: r (abs) = 7.288e-12 (tol = 1.000e-10) r (rel) = 7.325e-11 (tol = 1.000e-09)
Newton solver finished in 3 iterations and 3 linear solver iterations.
With my code I get:
1 6.24E-01 2.236057e+00
2 1.56E-02 2.121959e+00
3 1.14E-05 2.121320e+00
4 7.20E-12 2.121320e+00
Can anyone point out my error?
Thanks,
Mike