Peano
Loading...
Searching...
No Matches
Design philosophy and principles

ExaHyPE 2 is built as a layer on top of Peano 4 and the Peano 4 Technical Architecture.

This C++ ExaHyPE 2 layer is built as a set of Peano 4 C++ utility files compiled into one shared library plus a Python API. It is relatively straightforward to understand by browsing through the C++ files, but it provides limited structure: You find most of the compute ingredients of an ExaHyPE code in there, but the actual logic are not encoded in the C++.

For this, ExaHyPE 2 provides a Python API that allows users to describe their solver and its behaviour in a more abstract way.

Python layer

Architecture

At the heart of ExaHyPE 2 are the solver classes and its aggregate. They model what is solved, i.e.~encode the physics. Any implementation details how things are solved - either from a numerics point of view or from a performance point of view - are omitted from this description. This is the layer users interact with.

Each solver is tied to generators which determine which numerical scheme is employed. They determine how the solver is mapped onto mesh entities, which compute kernels are generated, and which solver steps make up one time step. These generators map the solver description (see above) onto a task graph of activities.

The task graph is then mapped onto Peano 4's action sets and traversals. This part is already an element of the Peano core architecture. and is not specific to ExaHyPE 2.

I/O and user interface conventions

  • All steps report against the Peano logger. It enlists information through which steps the generation runs through (but not what exactly has been produced).
  • The individual ingredients dump their specific information (which papers to cite, or what actual solver/ingredient combination has been used) into the readme tied to the Peano project. So the readme hosts information what has been done (cmp remarks on logger above).
  • The individual code parts tend not to write any terminal output or at least keep it very minimalist. This way, the user can write their own terminal output tailored towards their need.

Top-level ExaHyPE 2 layer

This layer is what most users will consider to be ExaHyPE 2. It is a thin Python package which allows a user to model a hyperbolic PDE solver. By plugging many different objects together, users describe what their solver will look like. In short, most ExaHyPE applications only create an instance of exahype2.api.Project, and then they add instances of exahype2.api.Solver to it.

Once the structure of the solvers is in place, users attach generators to their static solver description. Generators can be used to tailor all kinds of behaviour, but, most importantly, the type of generator picked for a solver implies what numerical scheme you want to apply on a solver description.

ExaHyPE'2 implememntation layer

The generators take the specification objects and they lower them into implementation objects. This is where, for example, a Runge-Kutta scheme tells the implementation that each time step consists of four substeps, which compute kernels we need to generate, and so forth.

Once we have constructed this implementation representation, there's a second layer of generators tied to the implementation: They take the implementation representation and lower it into a Peano 4 representation. On this level, idnividual solver steps are now for example mapped onto action sets or traversals.

Python design principles

At the heart of ExaHyPE2 are the solver classes and its aggregate. Each solver class and each aggregate are tied to a generator class. The generator classes take the solver description and either lower them into a Peano 4 class or a plain C++ file tied to the present project. Here, the same pattern repeats, i.e. Peano Python classes again hold generators which then ultimately lower the code in to plain C++.

  1. The solver classes and their aggregates are purely descriptive. That is, users build up these classes (instantiate them), set some attributes, attach them to each other, and so forth. They build up a representation what their solver features and can do. However, this is a description of the code bare of any information how these properties translate into code.
  2. Each descriptive class holds a generator. The generator knows how to translate what the class describes into functionality. This is where the how is encoded. By exchanging generators or writing their own ones, users can tailor a solver's behaviour.
  3. A generator is allowed to do two things: yield a Peano 4 object, i.e. add something to the generated Peano 4 repository or generate plain C++ code. In the latter case, the Peano 4 project is informed about the source code, but nothing else. Where possible, the generator should not generate partial strings that are handed down into the Peano Python layer, even though this sometimes cannot be avoided.

The aim of our architecture is to decouple implementation details (how) from mathematical modelling (what) that inform the solver's numerical behaviour. For example, whether to use a GPU and whether to use task fusion fall under implementation details and should be handled by a generator not the description. How many variables to use, which PDE terms to enable and the patch size should be used however is a property of the model itself.

For general design patterns and idioms that recur across Peano and its extensions, see the developer guidelines and tips page.