Adaptive Mesh Refinement

There are two ways to control AMR in parthenon. First, built-in refinemnt criteria can be activated at runtime via the input file. Second, package developers can create a package-specific refinement tagging function to allow for more tailored criteria of less generic applicability.

Enable AMR

To enable AMR, the following lines are required in the <parthenon/mesh> block of your input file.

refinement = adaptive    # enable adaptive mesh refinement
numlevel = 5             # how many refined levels can parthenon produce

Built-in

Parthenon includes the ability to tag cells for refinement/derefinement based on predefined criteria that can be enabled at runtime in the input file. Multiple criteria can be enabled simultaneously, in which case the most refined criteria wins. If refinement=adaptive has been specified as above, parthenon will initialize your AMR choices by looking for blocks with names <parthenon/refinement#> where # is a zero-based sequential indexing of Refinement criteria. An input file might looks like

<parthenon/mesh>
refinement = adaptive
...

<parthenon/refinement0>
...

<parthenon/efinement1>
...

<parthenon/refinement2>
...

In each refinement block, you are required to provide a method which is a string that selects among the provided critera (listed below). Additionally, you are required to provide a field which must be a valid variable name in the application. Optionally, you can provide a refine_tol value (defaults to 0.5) indicating that a block should be tagged for refinement if the criteria selected evaluates to a value above this threshold anywhere on the block. Similarly, the derefine_tol value (default 0.05) determines when derefinement can occur (all values of the criteria function must be less than this). Finally, an integer max_level value can be specified that limits refinement triggered by this criteria to no greater than this level. The default is to allow each criteria to refine to numlevel, which is the global maximum number of refinement levels specified in the <parthenon/mesh> block.

Predefined Criteria

The predefined refinement criteria are calculated in terms of the user selected variable \(q\) as follows. Method:

  • derivative_order_1: \(|\partial \ln q / \partial \ln x|\)

  • derivative_order_2: \(\frac{\delta x^2}{4\|q\|} \left\| \frac{\partial^2 q}{\partial x^2} \right\| = \frac{ \| q_{i-1} - 2 q_{i} + q_{i+1} \| }{ 2\| q_{i} \| + \| q_{i-1} + q_{i+1} \| }\) Note that this quantity is bounded by \([0,1]\).

Package-specific Criteria

As a package developer, you can define a tagging function that takes a Container as an argument and returns an integer in {-1,0,1} to indicate the block should be derefined, left alone, or refined, respectively. This function should be registered in a StateDescriptor object by assigning the CheckRefinement function pointer to point at the packages function. An example is demonstrated here.

Ensuring your data is consistent after re-meshing

When re-meshing happens, a few operations happen, which can be plugged in to in various ways. The operations performed (in order) are: - The function InitMeshBlockUserData is called. This function can be set by setting it in the ApplicationInputs field of the problem generator:

void MyInitMeshBlockUserData(MeshBlock *pmb, ParameterInput *pin) {
  // Do something on a meshblock
}
pman.app_input.InitMeshBlockUserData = MyInitMeshBlockUserData;
// continue with initialization...
  • When the mesh is being generated at initialization, the problem generator is called after every re-meshing.

  • Prolongation, restriction, physical boundaries, and ghost zone communication are performed

  • The FillDerived functions set per-package and per-application are called.

If you have a function that you would like called every cycle, you may wish to put it in FillDerived. If you have a function you would like performed only at re-meshing, you may wish to put it in InitMeshBlockUserData.