Equation
Equation concept
Apart from doing explicit calculations, an important requirement of numerical methods is the ability to
solve implicit systems, especially linear systems. Such a problem is represented by the Equation
object in OpFlow:
// an equation for 2D Poisson equation
auto eqn = (d2x(p) + d2y(p) == div);
Construct an equation
Equation
is constructed by the operator==
by putting left hand side and right hand side expression
on each side. You may noticed that in the Operator section the equality operator is not listed in the table.
It’s used for generate equations in OpFlow, which we think is the more common use case than the equality test.
Tip
For equality test, you can use the NotEqualTo operator!=
to do the job.
Linear solver & equation solving
The code above actually cannot be solved directly, since p
and div
are expressions that can be directly
evaluated. The target variable must be explicitly marked out and the linear system can thus be generated.
This is accomplished by introducing a StencilField
of the target field and replace the target field with
the stencil field:
// generate the stencil field object for p
auto stField = p.getStencilField();
auto eqn = (d2x(stField) + d2y(stField) == div);
After the equation has been constructed, it’s time to pick a proper linear solver and solve the linear system. OpFlow currently uses HYPRE as its backend for linear system solving. HYPRE provides high performance preconditioners and linear solvers for various types of linear systems including structured, semi-structured, unstructured and matrix form linear systems. The available solvers include:
BiCGSTAB
CycRed
FGMRES
GMRES
Jacobi
LGMRES
PCG
PFMG
SMG
The default solver for general equations in OpFlow is GMRES. We can construct a solver as:
// params & precParams are parameters for the solver and preconditioner
auto solver = PrecondStructSolver<type, pType>(params, precParams);
// bind the solver, target and equation to an equation handler
auto handler = HYPREEqnSolveHandler(eqn, p, solver);
// call the solve method to solve the system
handler.solve();
To simplify the solving procedure, OpFlow introduce a unified Solve
function to automatically
do the work aforementioned. The above codes can be replaced by:
Solve([&](auto&& e) { return d2x(e) + d2y(e) == div; }, p, params, precParams);
Solve
takes a functor as the equation generator, which takes a general field and returns an
corresponding equation. The target field’s getStencilField
method is automatically called,
and the generated stencil field is feed into the functor to get the equation; meanwhile a solver
is constructed with the parameters provided; then the equation is finally solved and the result
is written into the target field.
Caution
It’s the user’s responsibility to ensure that the linear system is well purposed. For details of the linear solvers, please refer to HYPRE’s documentation.
Note
You can now checkout the Poisson equation example in the Example section. Try it out!