← Back to team overview

dolfin team mailing list archive

Re: [Bug 745903] Re: PETScKrylovSolver fails to iterate with PETScKrylovMatrix

 

On Monday April 4 2011 12:09:16 Christian Clason wrote:
> It seems it's still a problem with how the vectors are passed to and
> from PETScKrylovMatrix by PSKSolver. Tweaking the KSP parameters (e.g.,
> KSPSetNormType(*_ksp,  KSP_NORM_NO)) made no difference. On the other
> hand, the following does work:
> 
> class NewtonMatrix3(PETScKrylovMatrix) :
>     def __init__(self) :
>         PETScKrylovMatrix.__init__(self, V.dim(), V.dim())
> 
>     def mult(self, *args) :
>         x = args[0]; bc.apply(x)
>         y = Function(V)
>         solve(A,y.vector(),x)
>         args[1].zero()
>         args[1].axpy(1.0,y.vector())
> 
> 
> (If there's a better way than axpy, I'm all ears.)

Yes, I think you found a subtle problen with:

  args[1][:] = y.vector()[:]

as this one will create a new PETSc Vec, which might create problems with the 
underlying PETSc solver.

Your new suggestion does not create a new Vec object but rather works on the 
passed Vec object.

Johan

-- 
You received this bug notification because you are a member of DOLFIN
Team, which is subscribed to DOLFIN.
https://bugs.launchpad.net/bugs/745903

Title:
  PETScKrylovSolver fails to iterate with PETScKrylovMatrix

Status in DOLFIN:
  New

Bug description:
  When using PETScKrylovSolver with a virtual PETScKrylovMatrix, the
  solver returns the right hand side without actually iterating. Setting
  "monitor_convergence" to True shows that after the first iteration,
  the preconditioned residual is zero, although no preconditioner is
  used. (The "true residual norm" is correctly given as nonzero.)

  This happens both in Python and in C++, and for all available Krylov
  solvers, but not for all such matrices. It seems to be related to the
  way the return argument is passed.

  Below is a minimal Python example with one working and one non-working
  PETScKrylovMatrix.

  ###
  from dolfin import *

  def boundary(x,on_boundary):
      return on_boundary

  mesh = UnitSquare(32, 32)
  V = FunctionSpace(mesh, 'CG', 1)

  bc = DirichletBC(V, Constant(0.0), boundary)
  u = TrialFunction(V); v = TestFunction(V); 
  A, b = assemble_system( inner(grad(u), grad(v))*dx, Constant(1.0)*v*dx, bc)

  class NewtonMatrix(PETScKrylovMatrix) :
      def __init__(self) :
          PETScKrylovMatrix.__init__(self, V.dim(), V.dim())

      def mult(self, *args) :  
          x = args[0]; bc.apply(x)
          solve(A,args[1],x)

  class NewtonMatrix2(PETScKrylovMatrix) :
      def __init__(self) :
          PETScKrylovMatrix.__init__(self, V.dim(), V.dim())

      def mult(self, *args) :  
          x = args[0]; bc.apply(x)
          y = Function(V)
          solve(A,y.vector(),x)
          args[1][:] = y.vector()[:]

  NewtonSolver = PETScKrylovSolver('cg', 'none')
  NewtonSolver.parameters["monitor_convergence"] = True

  y = Function(V)
  solve(A,y.vector(),b)

  x_petsc = PETScVector(V.dim())

  print NewtonSolver.solve(NewtonMatrix(), x_petsc, down_cast(y.vector()))
  print (b - x_petsc).norm('l2') # works: this is zero 

  x_petsc.zero()

  print NewtonSolver.solve(NewtonMatrix2(), x_petsc, down_cast(b)) # only one iteration
  print (y.vector() - x_petsc).norm('l2') # doesn't work: this is not zero
  print (b - x_petsc).norm('l2') # but this is

  x_petsc.zero()

  print NewtonSolver.solve(NewtonMatrix2(), x_petsc, down_cast(b)) # only one iteration
  print (y.vector() - x_petsc).norm('l2') # doesn't work: this is not zero
  print (b - x_petsc).norm('l2') # but this is



References