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

Iterative solver not working

+2 votes

Hi everybody

No iterative solver is converging for my simulations and I don't know why.

Below is a minimal working example with multiple 'solve' lines, each with another solver.
When I use the default solver, the solution is computed almost instantly, but when I use any iterative solver (gmres, cg, minres, ...) the solution never converges.
I tested it on two different computers (Debian Jessie/fenics 1.4, Ubuntu 14.04/fenics 1.5) and it didn't work on both.

Please give me a hint,
thank you in advance!

#!/usr/bin/env python
# encoding: utf-8

import math as m
import numpy as np
from dolfin import *

Lx = 0.19
Ly = 0.01
Lz = 0.01732

Nx = 380
Ny = 1
Nz = 1
mesh = BoxMesh(0., 0., 0., Lx, Ly, Lz, Nx, Ny, Nz)

c = 343.4
rho = 1.204

########################################################################
# set periodic boundary conditions and create constrained function space
class PeriodicDomain(SubDomain):
    # set periodic boundary conditions

    def inside(self, x, on_boundary):
        # return True if on left or bottom boundary AND NOT on one of the two
        # slave edges
        return bool((near(x[1], 0) or near(x[2], 0.)) and
                    (not ((near(x[1], Ly) and near(x[2], 0.)) or
                     (near(x[1], 0) and near(x[2], Lz)))) and on_boundary)

    def map(self, x, y):
        if near(x[1], Ly) and near(x[2], Lz):
            y[0] = x[0]
            y[1] = x[1] - Ly
            y[2] = x[2] - Lz
        elif near(x[1], Ly):
            y[0] = x[0]
            y[1] = x[1] - Ly
            y[2] = x[2]
        elif near(x[2], Lz):
            y[0] = x[0]
            y[1] = x[1]
            y[2] = x[2] - Lz
        else:
            y[0] = -1000
            y[1] = -1000
            y[2] = -1000

periodicdomain = PeriodicDomain()

# ################################################################################
class ABC_Sommerfeld(SubDomain):
    def inside(self, x, on_boundary):
        return on_boundary and near(x[0], Lx)

abcs = ABC_Sommerfeld()

# Initialize facet function for external boundary domain
external_boundaries = FacetFunction("size_t", mesh)
external_boundaries.set_all(0)
abcs.mark(external_boundaries, 1)

################################################################################
# Define constants and expressions
frequency = 500.
omega = 2.*m.pi*frequency
k = omega/c

p0r = 1.
p0i = 1.
f1 = Expression('2*k_*p0i_', k_=k, p0i_=p0i)
f2 = Expression('2*k_*p0r_', k_=k, p0r_=p0r)
ksquared = Constant(k**2.)
k = Constant(k)

################################################################################
# create two independent function spaces
W = FunctionSpace(mesh, 'Lagrange', 2, constrained_domain=periodicdomain)
W2 = W * W

(pr, pi) = TrialFunction(W2)
(w1, w2) = TestFunction(W2)

a_air = (pr*w1*ksquared + pi*w2*ksquared -
         inner(nabla_grad(pr), nabla_grad(w1)) - 
         inner(nabla_grad(pi), nabla_grad(w2)))*dx()

a_right = (k*pi*w1 - k*pr*w2 )*ds(1)
L = (+f1*w1 - f2*w2)*ds(1)

a = a_air + a_right

# assemble
A = assemble(a, exterior_facet_domains=external_boundaries)
b = assemble(L, exterior_facet_domains=external_boundaries)

# Compute solution
p = Function(W2)
P = p.vector()

# works
solve(A, P, b)

# # doesn't work
# solve(A, P, b, 'gmres', 'none')
# solve(A, P, b, 'gmres', 'ilu')

# # doesn't work
# solve(A, P, b, 'minres', 'none')

# # doesn't work
# solve(A, P, b, "cg", "none")

# # doesn't work (from Fenics Q&A)
# prec = PETScPreconditioner('hypre_amg')
# PETScOptions.set('pc_hypre_boomeramg_relax_type_coarse', 'jacobi')
# solver = PETScKrylovSolver('cg', prec)
# solver.parameters['absolute_tolerance'] = 1.0e-6
# solver.parameters['relative_tolerance'] = 1.0e-10
# solver.parameters['maximum_iterations'] = 1000
# solver.parameters['monitor_convergence'] = True
# A_petsc = as_backend_type(A)
# b_petsc = as_backend_type(b)
# x_petsc = as_backend_type(P)
# solver.set_operator(A_petsc)
# solver.solve(x_petsc, b_petsc)
# solver = KrylovSolver("gmres")
# solver.parameters["monitor_convergence"] = True
# solver.parameters["error_on_nonconvergence"] = False
# solver.solve(A, P, b)

pr, pi = p.split()
plot(pr)
plot(pi)
interactive()
asked Feb 19, 2015 by PaulR FEniCS Novice (420 points)

Ok, I know now why it is not working. The FEM Matrix is not positive definite.
But how can I fix that?

What is the nullspace then?

...