I am trying to write a manual newton iteration code in FEniCS for some problem, i.e., I want to supply my own Jacobian and residual information instead of using the derivative command. To test my algorithm in this context I am considering a simple linear poisson problem with homogeneous boundary data on a unit square domain. Then, writing u = u^0 + \delta u, I obtain the following to be solved:
In order to do this I have written the following minimal code:
from dolfin import *
# Data
N = 8; deg = 1; nr = 4
uex = Expression('sin(pi*x[0])*sin(pi*x[1])', degree = deg + 3)
f = Expression('2*pow(pi, 2)*sin(pi*x[0])*sin(pi*x[1])', degree = deg + 3)
u0 = Constant(0)
# Domain
mesh = UnitSquareMesh(4)
# Function space
V = FunctionSpace(mesh, 'CG', 1)
# Boundary
def boundary(x, on_boundary):
return on_boundary
bc = DirichletBC(V, u0, boundary)
u = TrialFunction(V)
v = TestFunction(V)
Eq1 = dot(grad(u), grad(v))*dx
Eq2 = f*v*dx
u0 = interpolate(Constant(0), V)
iter = 0; R = 1; tol = 1e-5
while (R > tol):
J = Eq1 # Jacobian
res = - action(Eq1, u0) + Eq2 # residual
deltau = Function(V)
solve(J == res, deltau, bc)
error = (u0 - deltau)**2*dx
R = sqrt(abs(assemble(error)))
iter += 1
u0 += deltau
print('|res| = %e, iteration %d \n' % (R, iter))
Error: 'Sum' object has no attribute 'ufl_function_space' File "/Users/jaitushar/Documents/myFEniCS/mySolvers/mySSNStAdSolver.py", line 33, in <module> res = - action(Eq1, u0) + Eq2
After looking at the algorithm, I realised that I was not performing the following update $$u0 += \deltau$$. But now, after this update u0 becomes a variable of type <class \;\; 'ufl.algebra.Sum'>. and thus produces an error 'Sum' object has no attribute 'ufl_function_space' on the residual calculation step, specifically the part action(Eq1, u0). How to bypass this error
Thank you, dockken!. It is updating now. I ran the code, but the residual remains stable i.e., the res that I am printing in my code remains |res| = 4.301287e-01, iteration 1 for all iterations and never crosses the tolerance value 1e-5, with u0