Set number of V-cycles in multigrid preconditioner

1 year 2 months ago - 1 year 2 months ago #3059 by JanWesterdiep
Hey!

I am trying to use your multigrid preconditioner and set its number of V-cycles. When taking the following page as a starting point:
ngsolve.org/docu/nightly/i-tutorials/uni.../preconditioner.html
I see how I can build a multigrid preconditioner object.

In this file in the C++ code, I can see how this object is constructed:
github.com/NGSolve/ngsolve/blob/bef34e5a...ython_comp.cpp#L2474

Moreover, it shows me the existence of a `MultiGridPreconditioner` object in Python, which is the `MGPreconditioner` class in C++. This class has a `ngmg::MultigridPreconditioner` pointer which drives the multigrid, and *this* class has a method "SetCycle" that sounds to me like the right method:
github.com/NGSolve/ngsolve/blob/3e0c9cac...tigrid/mgpre.cpp#L50

In the constructor of the `MGPreconditioner` class, it calls this method,
github.com/NGSolve/ngsolve/blob/29f288b8...conditioner.cpp#L388
which indicates to me that when I create the preconditioner from Python using `MultiGridPreconditioner(A, cycle=N)`, it should set the cycles. However, no matter how I change the N, the preconditioner does not seem to improve. See the following code. Am I missing something? Is perhaps `cycle` not the number of V-cycles?
import matplotlib.pyplot as plt
import netgen.gui
from netgen.csg import unit_cube
from netgen.geom2d import unit_square
from ngsolve import *


def SolveProblem(h=0.5,
                 p=1,
                 levels=1,
                 condense=False,
                 precond="local",
                 cycle=5):
    """
    Solve Poisson problem on l refinement levels.
        h: coarse mesh size
        p: polynomial degree
        l: number of refinement levels
        condense: if true, perform static condensations
        precond: name of a built-in preconditioner
        cycle: (non-working) number of cycles of the multigrid preconditioner
    OUTPUT:
        List of tuples of ndofs and iterations
    """
    mesh = Mesh(unit_square.GenerateMesh(maxh=h))
    fes = H1(mesh, order=p, dirichlet="bottom|left")

    u, v = fes.TnT()
    a = BilinearForm(fes, eliminate_internal=condense)
    a += grad(u) * grad(v) * dx
    f = LinearForm(fes)
    f += v * dx
    gfu = GridFunction(fes)
    Draw(gfu)
    if precond == 'multigrid':
        c = MultiGridPreconditioner(a, cycle=5)
    else:
        c = Preconditioner(a, precond)

    steps = []

    for l in range(levels):
        if l > 0:
            mesh.Refine()
        fes.Update()
        gfu.Update()

        with TaskManager():
            a.Assemble()
            f.Assemble()

            # Conjugate gradient solver
            inv = CGSolver(a.mat, c.mat, maxsteps=1000)

            # Solve steps depend on condense
            if condense:
                f.vec.data += a.harmonic_extension_trans * f.vec

            gfu.vec.data = inv * f.vec

            if condense:
                gfu.vec.data += a.harmonic_extension * gfu.vec
                gfu.vec.data += a.inner_solve * f.vec
        steps.append((fes.ndof, inv.GetSteps()))
        if fes.ndof < 15000:
            Redraw()
    return steps


print([
    SolveProblem(levels=5, precond="multigrid"),
    SolveProblem(levels=5, precond="multigrid", cycle=5)
])

Please Log in or Create an account to join the conversation.

© 2019 Netgen/NGSolve