This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Initial guess in NonLinearVariationalProblem

0 votes

Hi,

Does anyone know how NonlinearVariationalProblem sets the initial guess for the newton iteration at each load step when the the Dirichlet B.C. is changed?

I can reproduce the first load step in my own implementation of the newton method and the initial guess appears to be from solving the linearized problem with the first initial guess. However, in subsequent changes of Dirichlet B.C. (u_R and u_up), the initial guess doesn't seems to come from the solution of the previous load step. It also appear that the first iteration (of the 2nd load step) in NonlinearVariationalProblem is twice of that from my own implementation. Any idea?

Thanks!

from dolfin import *
import numpy as np

parameters["form_compiler"]["representation"] ="uflacs"
parameters["form_compiler"]["quadrature_degree"]= 2


def Fmat(u):

    d = u.ufl_domain().geometric_dimension()
    I = Identity(d)
    F = I + grad(u)
    return F

#boundary conditions
class Left(SubDomain):
      def inside(self, x, on_boundary):
          tol = 1E-14
          return on_boundary and abs(x[0]) < tol

class Right(SubDomain):
      def inside(self, x, on_boundary):
          tol = 1E-14
          return on_boundary and abs(x[0]-10.0) < tol

class Lower(SubDomain):
      def inside(self, x, on_boundary):
          tol = 1E-14
          return on_boundary and abs(x[1]) < tol

class Upper(SubDomain):
      def inside(self, x, on_boundary):
          tol = 1E-14
          return on_boundary and abs(x[1]-10.0) < tol

class Bottom(SubDomain):
      def inside(self, x, on_boundary):
          tol = 1E-14
          return on_boundary and abs(x[2]) < tol

class Top(SubDomain):
      def inside(self, x, on_boundary):
          tol = 1E-14
          return on_boundary and abs(x[2]-1.0) < tol

nx = 1
ny = 1
nz = 1
mesh = BoxMesh(Point(0.0, 0.0, 0.0), Point(10.0, 10.0, 1.0), nx, ny, nz)
V = VectorFunctionSpace(mesh, 'CG', 2)
TF = TensorFunctionSpace(mesh,'CG',1)
Q = FunctionSpace(mesh,'CG',1)
W = MixedFunctionSpace([V,Q])

boundaries = MeshFunction('size_t', mesh, mesh.topology().dim()-1)
boundaries.set_all(0)
left = Left()
right = Right()
bottom = Bottom()
top = Top()
lower = Lower()
upper = Upper()

left.mark(boundaries, 1)
right.mark(boundaries, 2)
lower.mark(boundaries, 3)
upper.mark(boundaries, 4)
bottom.mark(boundaries, 5)
top.mark(boundaries, 6)

c = Constant(0.0)
u_R = Expression('x[0]*(lmbda - 1.0)', lmbda = 1.0)
u_up = Expression('x[1]*(lmbda - 1.0)', lmbda = 1.0)

bcleft0 = DirichletBC(W.sub(0).sub(0), c, boundaries, 1)
bcright0 = DirichletBC(W.sub(0).sub(0), u_R, boundaries, 2)
dbcright0 = DirichletBC(W.sub(0).sub(0), c, boundaries, 2)
bclower1 = DirichletBC(W.sub(0).sub(1), c, boundaries, 3)
bcupper1 = DirichletBC(W.sub(0).sub(1), u_up, boundaries, 4)
dbcupper1 = DirichletBC(W.sub(0).sub(1), c, boundaries, 4)
bcbottom2 = DirichletBC(W.sub(0).sub(2), c, boundaries, 5)

bcs = [bcleft0, bcright0, bclower1, bcupper1, bcbottom2]
bcs_dw = [bcleft0, dbcright0, bclower1, dbcupper1, bcbottom2]

dw = TrialFunction(W)
du,dq = TrialFunctions(W)
v,q = TestFunctions(W)
wtest = TestFunction(W)
w = Function(W)
u,p = split(w)


J = det(Fmat(u))
I1 = tr(Fmat(u).T*Fmat(u))
Wsimple = ((I1**2 - 9.0) - p*(J - 1.0))*dx

F1 = derivative(Wsimple,w,wtest)

Jac = derivative(F1, w, dw)
############################ Using Own Newton Method ############################################
abs_tol = 1.0E-10
rel_tol = 1.0E-9
maxiter = 25
omega = 1.0
sigma_real = []
lmbda = 1.0
dxx = 1.0

w_k = Function(W)
for lmbda_value in range(1, 3):

    it = 0
        print "lmbda value = ", lmbda_value

        u_R.lmbda = 1.0 + lmbda_value * 0.5
        u_up.lmbda = 1.0 + lmbda_value * 0.5


            A0, b0 = assemble_system(Jac, -F1, bcs)
            solve(A0, w.vector(), b0, "mumps")
    resid0 = b0.norm("l2")
    rel_res = b0.norm("l2")/resid0
    res = resid0
    print "Residual: %.3e, Relative residual: %.3e" %(res, rel_res)


    dww = Function(W)

    while (rel_res > rel_tol and res > abs_tol) and it < maxiter:
                    it += 1

                    A, b = assemble_system(Jac, -F1, bcs_dw)
                    solve(A, dww.vector(), b, "mumps")

            B = assemble(F1)
            for bc in bcs_dw:
                    bc.apply(B)

            rel_res = B.norm("l2")/resid0
            res = B.norm("l2")
            w.vector().axpy(1.0, dww.vector())

            print "Residual: %.3e, Relative residual: %.3e" %(res, rel_res)



############################ Using Nonlinearvariationalproblem ############################################
w.vector()[:] = 0
problem = NonlinearVariationalProblem(F1, w, bcs, Jac)
solver = NonlinearVariationalSolver(problem)

displacementfile = File("displacement.pvd")
stressfile = File("stress.pvd")

for lmbda_value in range(1, 3):

        print "lmbda value = ", lmbda_value

        u_R.lmbda = 1.0 + lmbda_value * 0.5
        u_up.lmbda = 1.0 + lmbda_value * 0.5

        solver.solve()
asked Nov 9, 2016 by lee FEniCS User (1,170 points)

Can you post a minimal working example? Your snippet is very verbose. At a quick glance, you're not applying the correct boundary conditions correctly in your iterative update. You should ensure your initial guess satisfies your boundary conditions. Thereby prescribe that the update should yield no change for those boundaries as your initial guess has already satisfied this condition.

...