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

Is there a way to set the inital guess in the Krylov solver?

+4 votes

I'm using a Krylov solver as in the stokes-iterative demo. However, it runs extremely slow. Is there a way to set the initial guess so as to speed the process up?

Thanks,

Amanda

asked Sep 6, 2013 by adiegel FEniCS Novice (290 points)

1 Answer

+6 votes
 
Best answer

Yes, just set

parameters['krylov_solver']['nonzero_initial_guess'] = True

The solver will then use whatever you have put in your solution Function as initial guess. The parameter above defaults to False.

answered Sep 7, 2013 by mikael-mortensen FEniCS Expert (29,340 points)
selected Sep 8, 2013 by Garth N. Wells

Mikael,

Thank you for your quick response. I have implemented the line of code above, but would you mind elaborating on the meaning of "the solver will then use whatever you have put in your solution Function as initial guess"? Specifically, if I were to put a time stepping loop on the stokes-iterative demo and use the code above, would the Krylov solver use the solution from the first time step as the initial guess for the second time step?

Furthermore, is there a way to determine what initial guess the Krylov solver is using?

Thanks for the help!

Amanda

Hi,

If you put this at the start of the stokes-iterative demo:

parameters['krylov_solver']['nonzero_initial_guess'] = True
parameters['krylov_solver']['monitor_convergence'] = True

then you'll see the progression of the solver. It should take 59 iterations to converge. Now after finishing the solution will be in your U Function object. So if you now were to restart your solver once more with

solver.solve(U.vector(), bb)

then the solver will start from the converged solution and use just one iteration. If you do

U.vector()[:] = 0.
solver.solve(U.vector(), bb)

then you'll start from initial guess = 0 and you will again use 59 iterations. If

parameters['krylov_solver']['nonzero_initial_guess'] = False

then you'll always use 59 iterations.

So if you put the stokes-iterative demo in a time stepping loop you'll start from the previous solution. See the Navier-Stokes demo for a similar example with a time loop.

Hope this answers your question.

Hi Mikael,

I really appreciate your help! However, I have attempted to implement your suggestion above and it just doesn't seem to work. I am copying my altered stokes-iterative demo below. All I have done at this point is put in the two lines at the beginning...

parameters['krylov_solver']['nonzero_initial_guess'] = True
parameters['krylov_solver']['monitor_convergence'] = True

and run the solver twice, hoping the second time it runs will only take one step as you suggest. Unfortunately, both times through, it takes 33 steps. Here is my code. Please let me know if I have misunderstood your suggestion.

Thanks again!

Begin demo

from dolfin import *

Test for PETSc or Epetra

if not has_linear_algebra_backend("PETSc") and not has_linear_algebra_backend("Epetra"): info("DOLFIN has not been configured with Trilinos or PETSc. Exiting.")
exit()
if not has_krylov_solver_preconditioner("amg"):
info("Sorry, this demo is only available when DOLFIN is compiled with AMG preconditioner, Hypre or
ML.");
exit()

parameters['krylov_solver']['nonzero_initial_guess'] = True
parameters['krylov_solver']['monitor_convergence'] = True

Load mesh

mesh = UnitCubeMesh(16, 16, 16)

Define function spaces

V = VectorFunctionSpace(mesh, "CG", 2) Q = FunctionSpace(mesh, "CG", 1) W=V* Q

Boundaries

def right(x, on_boundary): return x[0] > (1.0 - DOLFIN_EPS) def left(x, on_boundary): return x[0] < DOLFIN_EPS
def top_bottom(x, on_boundary):
return x[1] > 1.0 - DOLFIN_EPS or x[1] < DOLFIN_EPS

No-slip boundary condition for velocity

noslip = Constant((0.0, 0.0, 0.0))
bc0 = DirichletBC(W.sub(0), noslip, top_bottom)

Inflow boundary condition for velocity

inflow = Expression(("-sin(x[1]*pi)", "0.0", "0.0"))
bc1 = DirichletBC(W.sub(0), inflow, right)

Boundary condition for pressure at outflow

zero = Constant(0)
bc2 = DirichletBC(W.sub(1), zero, left)

Collect boundary conditions

bcs = [bc0, bc1, bc2]

Define variational problem

(u, p) = TrialFunctions(W)
(v, q) = TestFunctions(W)
f = Constant((0.0, 0.0, 0.0))
a = inner(grad(u), grad(v))dx + div(v)pdx + qdiv(u)dx
L = inner(f, v)
dx

Form for use in constructing preconditioner matrix

b = inner(grad(u), grad(v))dx + pq*dx

Assemble system

A, bb = assemble_system(a, L, bcs)

Assemble preconditioner system

P, btmp = assemble_system(b, L, bcs)

Create Krylov solver and AMG preconditioner

solver = KrylovSolver("tfqmr", "amg")

Associate operator (A) and preconditioner matrix (P)

solver.set_operators(A, P)

Solve

U = Function(W)
solver.solve(U.vector(), bb)

**# Test for KrylovSolver initial guess.
solver = KrylovSolver("tfqmr", "amg")

Associate operator (A) and preconditioner matrix (P)

solver.set_operators(A, P)

Solve

U = Function(W)
solver.solve(U.vector(), bb)**

Get sub-functions

u, p = U.split()

Save solution in VTK format

ufile_pvd = File("velocity.pvd")
ufile_pvd << u
pfile_pvd = File("pressure.pvd")
pfile_pvd << p

Plot solution

plot(u)
plot(p)
interactive()

You might want to edit your question...

I'm not saying you should run the entire file twice. Run it once in a python shell, then when everything is finished, simply call the solver from the command-line:

solver.solve(U.vector(), bb)

If you're not already using IPython I strongly suggest you get started with it.

Hi Mikael,

I think I got it. Thanks again for all your help!

Amanda

Hi Mikael, I read this post and still don't figure out how to provide a nonzero initial guess for the solver. Could you please take a look at my question here. Thank you so much in advance.

...