PeanoClaw - PyClaw working with Peano
( Directory )
This is a very brief documentation of PyClaw
working with Peano as adaptive mesh refinement
(AMR) environment. It is not a user guide, but emphasises design rationale and developer remarks from the Peano point-of-view.
State-of-the-art non-AMR PyClaw
Lets first briefly summarise how we understand that PyClaw
works. The fundamental persistent datastructure is a Solution object holding a Domain
object and a couple of States. Domain
in turn holds a couple of Patches.
- The domain is basically only a container for grids.
- However, currently all PyClaw algorithms/kernels work per grid.
- A state is a variable living on the grid (such as velocity).
- Solution holds all the states (i.e. unknowns), but each state knows on which grid it is defined.
- Whereas the states are only unknown arrays, grid holds the metadata, i.e. the offset of the grid, the size, and so forth.
A typical setup is sketched above for the shallow-water equations. The solution holds a domain, and this domain in turn holds one grid
describing the geometrical properties of the simulation (computational domain and mesh width). There's three unknowns (fluid
height, velocity, and depth of the sea).
now instantiates an instance of yet another class Solver
(due to a controller, but the controller is not of interest for this piece of text
) and passes this solver
the solution. The solver
then does the time step on the solution, i.e. it modifies the State
Design of PeanoClaw
PeanoClaw realises two design paradigms:
- Don't call us, we call you.
- Don't change any solver algorithms.
The idea is pretty simple:
- The user creates a PeanoSolution instead of Solution.
- The user writes his/her code with respect to one single grid.
- The user uses a PeanoSolver instead of the standard solver.
- The PeanoSolver instance holds an instance of any PyClaw Solver.
- The PeanoSolver runs over all tree grids and invokes the Solver's routines for each grid.
- To the solver, the current state of solution always seems to be a single grid.
- There is exactly one state per grid.
- Peano ensures the memory consistency, i.e. it takes care of the grid boundary data exchange.
For the image above, that means that each time you call the operation evolve_to_time() on an PeanoSolver instance, this instance calls six times your solver
. Each time, the solution holds a different grid
. In that sense, the design follows a flyweight pattern, i.e. only the Python Solution and Domain
object are persistent. The other objects are exchanged permanently by Peano.
The big advantage of this approach is that neither does your solver
have to handle the (adaptive) boundaries within evolve_to_time() nor does your solver
have to be able to support multiple grids. You don't have to change a thing. The disadvantage is that this operation forbids you to change properties of a grid
dynamically (such as grid
size). Also, you are not allowed to modify entries of grids in a random
access manner. More on this subject in the
Initialisation and Initial/Boundary Values
Build shared library
Before you run PyClaw
together with Peano, you have to build Peano into a shared library. We provide an scons script to do so. Change into the
directory of peano
scons target=peanoclaw dim=2
There's tons of options coming along with our scons script (in particular this call creates a debug version that's horrible slow and does not run in parallel
). You may study the script for more details. When scons has terminated successfully, you find in the build path a shared library that you finally have to copy into your LD_LIBRARY_PATH or extend the library path accordingly.
Exchange of Boundary Data Between Patches
This paragraph aims to describe some realisation algorithms of PeanoClaw. It starts with a description of how regular
grids interact. Lets study two adjacent cells.
PeanoClaw runs through the grid
and enters grid
(the one with green and blue cells). It calls evolve_to_time() of the solver
. At this time, Peano already has copied the yellow cells into the blue cells, i.e. you can consider the boundary
cells to be set. The kernel
then will modify the cells within the grid
After the algorithm has terminated, Peano next calls evolve_to_time() for the next grid
. This time, again the red boundary
data is set. However, this is not the new data (green) from the grid
before, but is the green cell data before the first cell update has happened. Peano does this saving of the boundary
in its touchVertexLastTime()
For adaptive grids, the procedure is similar but has two additional steps. First, the PeanoSolver not only needs an instance of Solver
(which is already available for all kernels), but it also needs an instance of AMRProjector. There's already a couple of AMRProjectors available, but you will at some time want to write your own one. It comprises three different operations:
- projectToFinerGrid, and
The latter is a callback telling Peano to refine or remove a grid
. The project operations take a grid
and map it onto another grid
Whenever a fine grid
is entered, you can rely on Peano having called projectToFineGrid() before. This projectToFineGrid() is given the yellow grid
as source and you have to fill the blue boundary
. The latter is not persistent.
Afterwards, Peano again evolve_to_time() for the fine grid
. This is the gray one. The implementation
of evolve_to_time() can remain as it has been for a non-adaptive grid
After the grid
has been processed, Peano invokes the projection of the grid
data to the coarser grid
(from green to red). This data then in the next time step is used as boundary
data for the coarse grid
For generating the Prototype of PeanoClaw you can use the script
java -cp PeProt.jar:DaStGen.jar de.tum.peano.peprot.PeProt \
$PEANO_DIR/ $PEPROT_DIR/templates/ $PEANO_DIR/peano/kernel spacetreegrid
This is an open issue.
To be written
The documentation for this Directory was generated from the following files: