the method of manufactured solutions
/ MMS /
To check whether your code solves an equation correctly, you would love to compare its answer to the true answer. But for most interesting differential equations, the true answer is unknown — that is precisely why you are solving them numerically. The method of manufactured solutions sidesteps this beautifully by running the logic backwards: instead of finding the solution to a given equation, you PICK a solution you like, then engineer the equation that has it. Now you possess an exact answer to compare against, by construction.
Here is the recipe in plain steps. Say your code claims to solve a PDE of the form L(u) = f, where L is some differential operator (for instance L(u) = -u'' for a 1D Poisson problem) and f is the right-hand side. First, CHOOSE a smooth function you fancy as the 'solution' — pick something with no special structure, like u_manufactured(x) = sin(3x) + x^2. Second, plug it into the left side and DIFFERENTIATE symbolically to compute what f must be: f(x) = L(u_manufactured) = 9 sin(3x) - 2. Third, also evaluate u_manufactured on the boundary to get the exact boundary conditions. Now feed that f and those boundary conditions to your code. Because you cooked up the problem so that u_manufactured solves it exactly, the code's output should match u_manufactured — and you can measure the error precisely at every point, on every mesh.
MMS is the gold standard for code VERIFICATION because it tests the full code path on a problem with a known exact answer, yet places no restriction on the answer's shape — you are free to choose solutions that exercise every term in the equations. Combined with mesh refinement, it powers an order-of-accuracy study: if your scheme is supposed to be second-order, the measured error should fall by a factor of four each time you halve the mesh, and if it does not, you have a bug. Honest caveats: MMS verifies the CODE, not the MODEL — your manufactured solution need not be physically meaningful, and indeed should not be, so MMS says nothing about whether your equations match reality. Also, you must apply the operator exactly (symbolically or by hand) when computing f; if you compute f with the same numerical approximation you are testing, the bug hides itself.
To verify a Poisson solver for -u'' = f on (0,1), pick u(x) = sin(pi x). Then f(x) = -u''(x) = pi^2 sin(pi x), and u(0) = u(1) = 0. Feed that f and those boundary values to the code. The numerical answer should approach sin(pi x); halving the mesh should cut the max error by about four for a second-order method. If it does not, the scheme is buggy.
Choose the answer first, derive the forcing term by differentiating it, then check the code reproduces it.
Compute the forcing term f exactly — symbolically or by hand. If you generate f using the very discretization you are trying to test, any bug in that discretization is baked into f too and becomes invisible.