Mondaic

salvus.mesh.layered_meshing.meshing_protocol.coarsening_policy.interlayer_detail

salvus.mesh.layered_meshing.meshing_protocol.coarsening_policy.interlayer_detail salvus mesh layered_meshing meshing_protocol coarsening_policy interlayer_detail

Solvers for the interlayer coarsening problem.

Adjacent layers must have element counts that differ by an exact power of their shared coarsening factor, so that a connector block can join them. The task is to choose, for every layer, the number of elements along each horizontal dimension that minimizes the total number of elements while respecting those relations, the requested (minimum) counts, and any modulo constraints.

Two exact solvers are provided:

  • solve_via_shortest_path treats the problem as a shortest path over (layer, element count) states. It applies whenever a single element count per layer describes the solution — either because there is one horizontal dimension, or because all horizontal dimensions request the same counts, as happens for full spherical shells. It is linear in the number of layers.
  • solve_via_enumeration searches over the relative shapes of the solution. It handles the general case in which the horizontal dimensions request different counts.

Both are dispatched from solve_interlayer_coarsening, and both minimize the total number of elements first and the number of coarsenings second, so that a mesh is never coarsened more often than it needs to be. Which solver runs follows from the requested element counts alone, so a given model always takes the same one.

Functions

solve_interlayer_coarsening()

def solve_interlayer_coarsening(
    nh: list[tuple[int, ...]],
    boundaries: list[Boundary],
    layer_modulo_constraint: int = 1,
    bottom_layer_modulo_constraint: int = 1,
) -> list[list[int]]: ...

Compute the number of horizontal elements across successive layers.

Parameters
  • nh list[tuple[int, ...]] — The requested number of elements in each dimension, per layer.
  • boundaries list[Boundary] — The coarsening factor and maximum coarsening per boundary. Must have one entry fewer than nh.
  • layer_modulo_constraint int — Ensure that all layers include elements along each dimension that are multiples of this number.
  • bottom_layer_modulo_constraint int — Ensure that the bottom layer (i.e. the last entry in nh) is a multiple of this number.
Returns list[list[int]] — The optimal number of horizontal elements spanning each layer.

solve_via_enumeration()

def solve_via_enumeration(
    nh: list[tuple[int, ...]], boundaries: list[Boundary], moduli: list[int]
) -> list[list[int]]: ...

Solve the coarsening problem for arbitrary requested element counts.

Searches over the relative shapes the boundaries admit, computing the cheapest element counts for each in closed form. A shape is abandoned as soon as no scaling of it can satisfy every layer’s bounds, which for more than one horizontal dimension has to hold in all of them at once and hence prunes the search sharply.

Where several solutions use equally many elements, the one coarsening the fewest times is chosen, and among those the one coarsening the least in the upper layers. This is a property of the result rather than of the order the search happens to take, so it does not change if the traversal does.

Parameters
  • nh list[tuple[int, ...]] — The requested number of elements in each dimension, per layer.
  • boundaries list[Boundary] — The coarsening factor and maximum coarsening per boundary.
  • moduli list[int] — The number each layer’s element counts must be a multiple of.
Returns list[list[int]] — The optimal number of horizontal elements spanning each layer.

solve_via_shortest_path()

def solve_via_shortest_path(
    nh: list[tuple[int, ...]], boundaries: list[Boundary], moduli: list[int]
) -> list[list[int]]: ...

Solve the coarsening problem when all horizontal dimensions agree.

A single element count then describes each layer, the constraints couple only adjacent layers, and the total number of elements is a sum over layers. The problem is thus a shortest path through the layers, which is solved here in a single sweep per boundary.

Where several solutions use equally many elements, the one coarsening the fewest times is chosen. Should several of those coarsen equally often, the winner is fixed but arbitrary, and need not be the one solve_via_enumeration settles on: both stay optimal and coarsen equally often, but may place the coarsenings at different boundaries.

Parameters
  • nh list[tuple[int, ...]] — The requested number of elements in each dimension, per layer. All dimensions of a layer must request the same count.
  • boundaries list[Boundary] — The coarsening factor and maximum coarsening per boundary.
  • moduli list[int] — The number each layer’s element counts must be a multiple of.
Returns list[list[int]] — The optimal number of horizontal elements spanning each layer.