Multigrid solvers¶
pyro solves elliptic problems (like Laplace’s equation or Poisson’s equation) through multigrid. This accelerates the convergence of simple relaxation by moving the solution down and up through a series of grids. Chapter 9 of the pdf notes gives an introduction to solving elliptic equations, including multigrid.
There are three solvers:
The core solver, provided in the class
MG.CellCenterMG2d
solves constant-coefficient Helmholtz problems of the form \((\alpha - \beta \nabla^2) \phi = f\)The class
variable_coeff_MG.VarCoeffCCMG2d
solves variable coefficient Poisson problems of the form \(\nabla \cdot (\eta \nabla \phi ) = f\). This class inherits the core functionality fromMG.CellCenterMG2d
.The class
general_MG.GeneralMG2d
solves a general elliptic equation of the form \(\alpha \phi + \nabla \cdot ( \beta \nabla \phi) + \gamma \cdot \nabla \phi = f\). This class inherits the core functionality fromMG.CellCenterMG2d
.This solver is the only one to support inhomogeneous boundary conditions.
We simply use V-cycles in our implementation, and restrict ourselves to square grids with zoning a power of 2.
The multigrid solver is not controlled through pyro.py since there is no time-dependence in pure elliptic problems. Instead, there are a few scripts in the multigrid/ subdirectory that demonstrate its use.
Examples¶
multigrid test¶
A basic multigrid test is run as (using a path relative to the root of the
pyro2
repository):
./examples/multigrid/mg_test_simple.py
The mg_test_simple.py
script solves a Poisson equation with a
known analytic solution. This particular example comes from the text
A Multigrid Tutorial, 2nd Ed., by Briggs. The example is:
on \([0,1] \times [0,1]\) with \(u = 0\) on the boundary.
The solution to this is shown below.
Since this has a known analytic solution:
We can assess the convergence of our solver by running at a variety of resolutions and computing the norm of the error with respect to the analytic solution. This is shown below:
The dotted line is 2nd order convergence, which we match perfectly.
The movie below shows the smoothing at each level to realize this solution:
You can run this example locally by running the mg_vis.py
script:
./examples/multigrid/mg_vis.py
projection¶
Another example uses multigrid to extract the divergence free part of a velocity field. This is run as:
./examples/multigrid/project_periodic.py
Given a vector field, \(U\), we can decompose it into a divergence free part, \(U_d\), and the gradient of a scalar, \(\phi\):
We can project out the divergence free part by taking the divergence, leading to an elliptic equation:
The project-periodic.py
script starts with a divergence free
velocity field, adds to it the gradient of a scalar, and then projects
it to recover the divergence free part. The error can found by
comparing the original velocity field to the recovered field. The
results are shown below:
Left is the original u velocity, middle is the modified field after adding the gradient of the scalar, and right is the recovered field.
Exercises¶
Explorations¶
Try doing just smoothing, no multigrid. Show that it still converges second order if you use enough iterations, but that the amount of time needed to get a solution is much greater.
Extensions¶
Implement inhomogeneous dirichlet boundary conditions
Add a different bottom solver to the multigrid algorithm
Make the multigrid solver work for non-square domains