Skip to main content

Module high_order

Module high_order 

Source
Expand description

§High-order reconstruction and the level set

Not tied to one geometry: the stencil rules and the schemes built on them are checked in one dimension and, for the finite-volume scheme, in several. Test paths are relative to crates/merlin-finite-volume/tests/ unless they start with crates/. “Drift” is the relative change of an integrated quantity between the first and last snapshot.

CaseReferenceHeadline result
The stencil rulespolynomials, smooth data, a literature tableexact to degree 4 and 10; orders 4.96, 4.98 and 10.65
The reconstruction schemeexact derivative, exact translationoperator orders 5.1, 5.0 and 10.9; time-integrated 5.00
The stability limitsan independent von Neumann analysisCourant limits 1.43 (fifth order) and 1.04 (eleventh)
A square wave and a bumpexact translation$L_1$ 4.7e-3 (WENO5), 4.5e-3, 3.7e-3 against MUSCL’s 8.8e-3
The level setthe exact derivative, exact translation, exact time dependenceoperator order 5.00 in 1D and 2D (point values), run order 4.9, third order in time
Zalesak’s disk and the vortexthe initial shape after a cycle that returns itZalesak: 99.2% of the area, 3.1% shape error (WENO5); vortex: order 4.5 to 5.2
PDE reinitialisationthe exact signed distance of a circlegradient within 4 cells 0.03% at 128 cells, interface unmoved after 500 passes
Fast sweeping, and the two comparedthe exact signed distance of a circlewhole-grid first-order distance, 1.2% at 128 cells, about 85 times cheaper than the PDE method
The Euler equationsthe flux Jacobian, exact translation, exact Riemann solution, a fine runeigenvectors to 1e-14; order 5.0; WENO5 beats MUSCL; primitive is robust, characteristic is accurate

§The stencil rules

Problem. A rule turns the $2r+1$ cell values around a cell into the value at the cell’s right face. Weno5 (Jiang and Shu 1996) weights three third-order candidates by their smoothness; LinearUpwind<5> and LinearUpwind<11> use one fixed combination, the face value of the polynomial through the cells, whose coefficients are derived from the polynomial-exactness conditions (the derivative of the Lagrange basis of the primitive function), not tabulated.

Result.

RuleExact up to degreeOrder on smooth data (face value of $\sin$)
LinearUpwind<5>4 (not 5)4.98
LinearUpwind<11>10 (not 11)10.65, rising to 11 as the cells shrink
Weno5linear data exactly4.96

The five-cell coefficients are $(2, -13, 47, 27, -3)/60$, the table of Shu (1998), reproduced to 1e-14.

Reading it. The exactness tests fail by design for the next degree, so a rule of the wrong order is caught. The eleventh-order rule reaches round-off after a few halvings, so its order is measured on cells up to one radian wide; the pairwise orders climb 10.4, 10.7, 10.8.

Tests that enforce this

Enforced by schemes/stencil_rules.rs: linear_upwind_is_exact_up_to_its_order_minus_one_and_no_further, the_fifth_order_coefficients_are_those_of_the_literature, the_coefficients_sum_to_one_so_a_constant_is_reproduced, weno5_weights_are_positive_and_sum_to_one, weno5_on_linear_data_has_the_ideal_weights_and_is_exact, weno5_is_fifth_order_on_smooth_data, the_linear_rules_have_their_design_order_on_smooth_data, weno5_stays_inside_the_data_at_a_step_where_the_linear_rule_overshoots.

§The reconstruction scheme

Problem. Reconstruction reconstructs the states on both sides of a face with a rule, in the conserved variables, and takes the flux from a Riemann flux. For linear advection with the upwind flux the semi-discrete operator is compared with the exact $-(\sin b - \sin a)/h$ of each cell, and a run of one period with SSP-RK3 is compared with the initial data.

Result. Order of the spatial operator (maximum norm, 32 to 256 cells; 12 to 32 for the eleventh order):

RuleFitted order
Weno55.07
LinearUpwind<5>5.00
LinearUpwind<11>10.90

A run of one period, $L_1$ norm, 20 to 160 cells with the time step falling as $h^{5/3}$ so that the third-order time error falls as $h^5$ instead of dominating: Weno5 5.00, LinearUpwind<5> 4.99. A Burgers shock sits at the Rankine-Hugoniot position (0.50000 for WENO5) and WENO5 stays within $10^{-5}$ of the data, where the linear fifth-order scheme overshoots by 0.17. A periodic run conserves the integral to round-off, and the answer is identical to the last bit for any block layout (1, 2, 3 per axis) and any number of threads (up to 8), with the eleventh-order rule too, which needs six ghost layers per side; a block narrower than that is refused with a message naming both numbers.

In more than one dimension the unsplit operator uses the value at the face centre as the face average, which is second order, so the finite-volume scheme is second order there whatever the rule. The rules keep their order in the level set, which works on point values.

Tests that enforce this

Enforced by schemes/reconstruction.rs: the_spatial_operator_has_the_order_of_its_rule, a_time_integrated_run_is_fifth_order, a_shock_moves_at_the_rankine_hugoniot_speed_and_only_the_nonlinear_rule_stays_inside_the_data, a_periodic_run_conserves_the_integral_to_round_off, the_answer_does_not_depend_on_the_blocks_or_the_threads, threads_alone_do_not_change_the_answer, blocks_narrower_than_the_ghost_layers_are_refused_with_a_clear_error. A file run reproduces the library-driven run bit for bit (the_high_order_runs_match_the_library_driven_runs_bit_for_bit in crates/merlin-cli/tests/run/run_from_file.rs).

§The stability limits

Problem. The spectrum of a high-order upwind-biased operator has a large imaginary part. For a Fourier mode $e^{ik x}$ the semi-discrete eigenvalue is $z(\theta) = -\big(\sum_j c_j e^{\mathrm{i}(j-r)\theta}\big)(1 - e^{-\mathrm{i}\theta})$ with $\theta = k\,\Delta x$, and one step multiplies it by the amplification polynomial $R(\nu z)$ of the Runge-Kutta method. The scheme is stable when $|R(\nu z(\theta))| \le 1$ for all $\theta$.

-3 -2 -1 0 solid: Courant number 1.43 (inside: stable) dashed: Courant number 1.8 (leaves the region: unstable) shaded: |R(z)| ≤ 1, SSP-RK3 Re z Im z

The scaled eigenvalues $\nu z(\theta)$ of the fifth-order linear operator, against the stability region of SSP-RK3. At the Courant number $\nu=1.43$ the curve fits inside, just short of the limit 1.435; at 1.8 it leaves.

Result.

RuleSSP-RK3SSP-RK2Forward Euler
fifth order1.4350.063below 0.1
eleventh order1.0490.006below 0.1

The rule reports the SSP-RK3 limit rounded down to 0.01 (1.43 and 1.04; Weno5 takes the fifth-order value), the solver refuses a larger Courant number with a typed error, and a problem file naming a lower-order integrator is rejected with the key named. The limits were computed first in an independent Python implementation (1.435 and 1.0493) and the Rust analysis is held to within 0.006 of them.

Tests that enforce this

Enforced by schemes/reconstruction.rs: the_stability_limits_agree_with_an_independent_von_neumann_analysis, the_solver_refuses_a_courant_number_above_the_limit_of_the_rule, a_shock_is_stable_at_the_advertised_courant_number.

§A square wave and a bump

Problem. The shipped files advection/weno5.toml, advection/upwind5.toml and advection/upwind11.toml carry a square wave and a smooth bump once around a periodic unit domain at speed 1 (1000 cells, SSP-RK3, Courant number 0.5, 2000 steps). After one period the exact solution is the initial data.

Result.

Problem file$L_1$ errorMin / max of $u$Drift
advection/weno5.toml4.7e-3-2.4e-37 / 1.00101.2e-13
advection/upwind5.toml4.5e-3-0.0607 / 1.06071.2e-13
advection/upwind11.toml3.7e-3-0.0660 / 1.06601.2e-13

For comparison, the shipped MUSCL file has an error of 8.8e-3 (see the one-dimensional page).

The four schemes overlaid at t = 1

Reading it. All three beat MUSCL on this problem. The linear schemes ring at the jumps (about 6%, a little more at eleventh order), as a fixed stencil must (Godunov’s theorem); WENO5 overshoots by 1e-3 and has no undershoot. Higher order does not remove the ringing of a linear scheme, it narrows it.

Tests that enforce this

Enforced by crates/merlin-cli/tests/run/high_order_problems.rs: the_high_order_schemes_beat_muscl_on_the_square_wave_and_bump, only_weno5_keeps_the_square_wave_inside_its_range.

§The level set

Problem. The crate merlin-levelset advects a level-set function $\phi$ in a velocity field, $\phi_t + u\cdot\nabla\phi = 0$ (Osher and Fedkiw 2003). The velocity is a field of its own, a BlockedField with one component per axis in the blocks of $\phi$, that a source fills at the time of each Runge-Kutta stage (a formula, an expression of the problem file, and in the multi-material phase the gas); the operator reads it at the cell it updates. The Hamiltonian $u\cdot p$ is linear in the gradient, so the upwind choice is the sign of $u$: the backward-biased derivative where it is positive, the forward-biased one where it is negative. Each one-sided derivative is a stencil rule applied to the differences of $\phi$ (Jiang and Peng 2000), so the three rules and the first-order upwind rule (LinearUpwind<1>) are the ones used for the flux schemes, with no second copy. The values are point values at the cell centres, not cell averages.

Result. Order of the operator $-u\cdot\nabla\phi$ alone, against the exact derivative of $\sin 2\pi x$ (maximum norm; 32 to 256 cells, 12 to 32 for the eleventh order, 64 to 512 for the first):

RuleOrder in 1DOrder in 2D ($\sin 2\pi x \sin 2\pi y$, velocity $(1, 0.6)$, 24 to 64 cells)
first-order upwind1.00
Weno55.005.00
Upwind55.004.98
Upwind1110.91, rising to 11

Unlike the finite-volume schemes, which are second order in more than one dimension because they use the value at the face centre as the face average, the level set keeps its design order in every dimension: point values need no transverse quadrature. One period of a translated wave with SSP-RK3 and the time step falling as $h^{5/3}$: fitted order 0.94 (first order), 4.89 (Weno5) and 4.99 (Upwind5) in 1D, and 4.76 and 4.98 in 2D. With tiny steps on 32 cells, Upwind11 has an error of 2.3e-11 against 1.9e-5 for Upwind5. The operator differentiates a linear function exactly to round-off for every rule and either sign of the velocity.

Time dependence. A uniform velocity $1 + \tfrac12\sin 2\pi t$ carries a wave through exactly one period, so the exact solution after time 1 is the initial data. The error falls as the third power of the step, which requires the velocity to be evaluated at the time of each Runge-Kutta stage (the stage times come from the Shu-Osher form, $c_k = b_k (c_{k-1} + 1)$, giving 0, 1 and 1/2 for SSP-RK3); a velocity frozen at the start of the step would make the method first order.

Layout. A rotating disk on a 36 by 30 grid gives bit-identical results for one block and for 2 by 3, 3 by 2 and 4 by 1 blocks on one to eight threads, with Weno5 and with Upwind11 (six ghost layers). The solver refuses a field with too few ghost layers, a Courant number outside the rule’s limit (1.43 for Weno5), a velocity of zero, an integrator of order below three, a mismatched periodic pair, an end time in the past, and reports a field that has become non-finite. Outflow ghost cells keep a ramp’s error within 5% of what a wrap-around would give at the ends and many times smaller inside.

The velocity as a field. A named velocity (Uniform, Rotation, ReversingVortex) is sampled into the field at the cell centres; reading the field gives the same bits as evaluating the formula in every cell, for every rule, block layout and thread count. The first stage reads the velocity sampled at the end of the previous step (or at time 0), the others are sampled at their own stage times, and a snapshot holds the velocity of its own time. A named velocity keeps its analytic bound for the time step. A source with no bound (type = "expression", one expression per axis in x, y, z, or r and z on a curvilinear domain, and t) is measured instead: the largest $|u_d|$ of the field, taken as a maximum over each block and then over the blocks (exact in any order, so the same for any number of threads), at the start of every step and at the stage times of the step before. For a uniform velocity that is the exact bound, and the run is bit for bit the one with the bound. For a rotation of the unit square it is that of the corner-cell centres, about 1% under the bound of the box. Being a sample, it can miss a peak between the times sampled or see a growing speed one step late (see the limitations). A velocity that is not finite is refused at the stage that produces it. The vortex written as an expression (levelset/vortex_expression.toml, 64 cells) has the velocity of the named vortex to the last bit and a $\phi$ within 1.2e-4 of it, the difference of the two time steps; the rotating circle written as an expression differs by 1.1e-7, and a three-dimensional constant expression equals the uniform velocity bit for bit. Snapshots hold phi and then the velocity components u, v, w; the integral reported for a velocity component is not a conserved quantity to check.

From a problem file. [[material]] system = "level_set" gives the interface a velocity (uniform, rotation about a centre, reversing_vortex, or an expression per axis), the region states give phi, and [numerics] takes the stencil rule from flux_scheme (first_order for first-order upwind, weno5, upwind5, upwind11) and the time integrator (third order or more). The run uses the same scheduled driver as the gas, so the snapshot schedule, the checkpoints and the restart work unchanged. The shipped levelset/translation.toml (a sine wave carried once round the unit domain) reproduces the library-driven run bit for bit. The shipped levelset/rotating_circle.toml turns a circle of radius 0.15 once about the centre of the unit square on a 100 by 100 grid:

RuleMean $\lvert\phi-\phi_0\rvert$ inside radius 0.45Largest change in the band $\lvert\phi_0\rvert<0.05$Area inside the zero level set, start and end
first-order upwind1.8e-26.9e-20.0716 and 0.0261
Weno53.4e-56.4e-5 (0.6% of a cell)0.0716 and 0.0716
Upwind54.1e-54.1e-40.0716 and 0.0716
Upwind112.3e-52.3e-40.0716 and 0.0716

First-order upwind smears away 63% of the circle in one turn; the high-order rules keep the interface within a small fraction of a cell. The error is taken inside radius 0.45 of the centre because the rotation carries values out through the walls beyond radius 0.5, where the outflow ghost cells supply the wrong ones; the orbit of the circle (radius 0.1 to 0.4) never reaches them. A run restarted from a checkpoint on another number of threads ends with the bytes of the uninterrupted run, and the results do not depend on the blocks or the threads.

Tests that enforce this

Enforced by (paths below crates/merlin-levelset/tests/) advection/operator.rs: the_operator_has_the_order_of_its_rule, in_two_dimensions_the_operator_keeps_its_full_order_unlike_the_finite_volume_schemes, a_linear_function_is_differentiated_exactly_by_every_rule_for_either_sign_of_the_velocity; advection/translation.rs: a_translated_wave_has_the_order_of_its_rule_with_the_time_step_refined, the_eleventh_order_rule_is_far_more_accurate_on_coarse_cells_once_the_time_error_is_small, in_two_dimensions_a_translated_wave_keeps_the_fifth_order, a_velocity_that_depends_on_time_is_third_order_in_time_because_each_stage_has_its_own_time; advection/layout.rs: the_answer_does_not_depend_on_the_block_layout_or_the_thread_count; advection/errors.rs: a_field_with_too_few_ghost_layers_is_refused, the_courant_number_must_be_positive_and_within_the_limit_of_the_rule, the_integrator_must_be_of_third_order_or_more, an_outflow_boundary_keeps_a_ramp_much_closer_to_its_exact_motion_than_a_wrap_around; advection/driver.rs: snapshots_are_written_at_exactly_the_requested_times, a_run_stopped_at_a_checkpoint_and_restored_continues_with_the_same_bits; advection/velocity.rs: a_measured_bound_gives_the_bits_of_the_analytic_one_when_they_are_equal, the_time_step_follows_the_largest_speed_of_the_field_when_it_is_measured, the_velocity_field_holds_the_velocity_of_the_current_time, a_peak_between_the_starts_of_two_steps_lowers_the_next_step_when_a_stage_sees_it, a_velocity_that_cannot_be_produced_at_the_time_of_a_checkpoint_is_reported_as_the_velocity, a_velocity_that_is_not_finite_is_refused_when_it_is_sampled_and_stops_a_run; and, in crates/merlin-levelset/src/operator.rs, reading_the_velocity_from_a_field_gives_the_bits_of_evaluating_it_in_the_operator. The problem files, in crates/merlin-cli/tests/run/levelset_problems.rs: a_level_set_file_run_matches_the_library_driven_run_bit_for_bit, a_circle_comes_back_after_one_turn_with_weno5_and_is_smeared_away_by_first_order, a_level_set_run_does_not_depend_on_the_blocks_or_the_threads, a_restarted_level_set_run_ends_exactly_where_the_uninterrupted_run_does, the_snapshots_hold_the_velocity_the_solver_advected_with, expression_velocities_agree_with_the_named_types_they_spell_out, an_expression_velocity_works_in_three_dimensions_and_equals_the_uniform_one; and the configuration, in crates/merlin-cli/src/config/tests.rs: a_level_set_takes_its_stencil_rule_from_flux_scheme_and_names_its_variable_phi, a_level_set_refuses_what_is_not_a_level_set_rule_naming_the_key, the_velocity_of_a_level_set_is_checked_against_the_dimension, an_expression_velocity_is_checked_for_its_entries_and_its_variables, a_level_set_writes_its_velocity_with_its_variable.

§Zalesak’s disk and the vortex

Problem. Two standard tests of an interface that is carried and returns to where it started, so that the initial shape is the exact solution. Both use the unit square, $100\times100$ cells for Zalesak and 32 to 128 for the vortex, SSP-RK3 and a Courant number of 0.4 and 0.5.

  • Zalesak’s slotted disk (Zalesak 1979): a disk of radius 0.15 centred at $(0.5, 0.75)$, with a slot 0.05 wide and 0.25 long cut up from its bottom edge, turned once about the centre of the square ($\omega = 2\pi$). $\phi=\max(\text{distance to the disk}, -\text{distance to the slot})$, negative inside. It has kinks (the slot corners) but no jumps. The shipped file is levelset/zalesak.toml.
  • LeVeque’s single vortex (LeVeque 1996): a circle of radius 0.15 at $(0.5, 0.75)$ is pulled into a thin spiral by the stream function $\sin^2(\pi x)\sin^2(\pi y)/\pi$, whose flow reverses at half the period, so that at $t=2$ the circle returns. The shipped file is levelset/vortex.toml (128 cells).
ω = 2π Zalesak's slotted disk r = 0.15, slot 0.05 × 0.25 LeVeque's single vortex streamlines of ψ circle

The two test problems on the unit square. The disk is turned once about the centre; the circle is stretched into a filament by the streamlines of $\psi=\sin^2(\pi x)\sin^2(\pi y)/\pi$ and carried back when the flow reverses at half the period.

Measures. With the smoothed Heaviside function of one cell’s width, $H_\varepsilon(\phi)$ (Osher and Fedkiw 2003, Section 1.4), the area is $\sum (1-H_\varepsilon(\phi))\,\Delta x^2$ and the shape error is the area where the shape differs from the initial one, $\sum |H_\varepsilon(\phi_0)-H_\varepsilon(\phi)|\,\Delta x^2$, as a percentage of the initial area. Both shapes are measured the same way, so the smoothing does not bias the difference.

Zalesak, one turn on 100 by 100 cells.

RuleArea keptShape error
first-order upwind0.56%100.3%
Weno599.18%3.08%
Upwind598.65%3.27%
Upwind11100.05%0.90%

The zero level set of each rule after one turn of Zalesak’s disk

The vortex, after the flow has reversed. Shape error on 32, 64 and 128 cells, and the observed order between neighbouring grids:

Rule32 cells64 cells128 cellsOrders
first-order upwind100%99.0% (1% of the area kept)46.0% (54% kept)0.02, 1.11
Weno59.83%0.74%0.034%3.74, 4.50
Upwind53.49%0.47%0.020%2.91, 4.57
Upwind111.48%0.13%0.0035%3.56, 5.19

The interfaces at the most deformed moment (t = 1) and after the return (t = 2)

1 2 4 1 1e−1 1e−2 1e−3 slope 1 slope 2 slope 5 Weno5 Upwind5 Upwind11 first-order upwind refinement factor (cells ÷ coarsest grid) error ÷ coarsest error

Shape error of the vortex against refinement, each series divided by its own coarsest error.

Reading it.

  • First-order upwind cannot carry a thin interface: it keeps 0.6% of Zalesak’s disk and loses the vortex on 64 cells.
  • The three high-order rules return the circle after a stretch into a filament a few cells thick with a shape error of 0.03% or less on 128 cells, converging at about the fifth order between 64 and 128 cells (the first pair of grids is still before the asymptotic range). The order is that of the smooth interface, where the error is that of $\phi$ itself, not of the first order that a discontinuity would limit it to.
  • On both problems the linear eleventh-order rule is the most accurate and the linear fifth-order rule is no worse than Weno5. This is because $\phi$ has kinks but no jumps, the case a fixed stencil handles well; a function with a jump would make the linear rules ring (see the square wave above). Weno5 rounds the closed end of Zalesak’s slot, where the kink is sharpest, and the other rules do not.
  • The level set is the interface’s position only: nothing here conserves area, and the near-exact areas of the high-order rules are a consequence of their accuracy, not a property of the scheme.
Tests that enforce this

Enforced by crates/merlin-cli/tests/run/levelset_problems.rs: zalesaks_disk_keeps_its_area_and_its_slot_with_the_high_order_rules, first_order_upwind_smears_zalesaks_disk_away, the_vortex_returns_at_fourth_order_or_better_with_weno5, the_vortex_returns_at_fourth_order_or_better_with_the_linear_fifth_order_rule, the_vortex_returns_at_fourth_order_or_better_with_the_linear_eleventh_order_rule, first_order_upwind_loses_the_vortex_even_on_128_cells.

§PDE reinitialisation

Problem. Advection stretches and compresses a level-set function, so $|\nabla\phi|$ drifts away from 1. The reinitialisation rebuilds a signed distance function with the same zero level set by solving, in pseudo-time, $\phi_\tau + S(\phi_0)(|\nabla\phi| - 1) = 0$ (Sussman, Smereka and Osher 1994) with the Godunov upwind gradient (Osher and Fedkiw 2003, Section 7.2) and the WENO5 derivatives of the advection (Jiang and Peng 2000). Three choices make it work:

  • The smoothed sign is $S = \phi_0/\sqrt{\phi_0^2 + |\nabla\phi_0|^2\Delta x^2}$ (Peng et al. 1999), so that a function that is 0.2 or 3 times a distance is treated like one that is a distance. With $\phi_0/\sqrt{\phi_0^2+\Delta x^2}$ the 0.2 case had not converged in a band of 8 cells (the gradient was 35% off).
  • The cells next to the interface are held at their sub-cell distance $\phi_0/|\nabla\phi_0|$, estimated from central differences (Russo and Smereka 2000), so that the interface does not move. A cell whose slope is already within 5% of one keeps its value (the dead band). Without it, an estimate with an error of its own applied pass after pass moved the interface by 0.11 cells in 10 passes, 0.26 in 100 and nearly a whole cell in 200 (64 cells).
  • The derivatives are WENO5 whatever rule advects the function: a distance function has kinks where the nearest point of the interface jumps, and the linear eleventh-order rule makes the pseudo-time equation blow up there (the vortex run kept 708% of its area). The reinitialiser works on its own copy of the function, with the three ghost layers WENO5 needs.

Result. A circle of radius 0.25 in the unit square, reinitialised from the exact distance and from 3 and 0.2 times it (a band of 12 cells; the gradient is measured with independent central differences within 4 cells of the interface):

CellsGradient error, distance3 times0.2 timesInterface position (cells, before and after)
321.2%1.3%1.2%0.0102 and 0.0102
640.17%0.29%0.19%0.0072 and 0.0072
1280.031%0.18%0.07%0.0026 and 0.0026

The interface position is where the function changes sign, found by linear interpolation along the grid lines, so it contains the error of reading a position that way; reinitialising does not change it. From the exact distance the gradient error falls at order 2.6. After 500 passes on 64 or 128 cells the position error is the same to four digits and the gradient error has not grown. A function whose gradient varies by a factor of three ($1 + \tfrac12 \sin 6\pi x \sin 4\pi y$ times the distance) is restored to 8.5%, 4.0% and 2.35% on 32, 64 and 128 cells, at about first order, because the distance of a cell next to the interface is estimated from the slope of $\phi_0$ and that slope changes over the cell. A scaled ramp in one dimension becomes the distance to within 0.006 of a cell. The pseudo-time runs to band cells and the distance function is accurate within about half of it (two thirds for a wider band): for 3 times a distance on 64 and 128 cells, a band of 8 cells leaves the gradient 1.0% and 1.3% off within 4 cells and 15% and 17% off at 6, where the front that rebuilds it has only just arrived; a band of 12 cells leaves it 0.3% to 0.8% off within 6 cells and 1.3% to 1.8% off within 8.

In a run. reinitialisation = { method = "pde", every_steps = N, band = 8 } on the level-set material (default { method = "none" }) rebuilds the function every N steps; the schedule counts the steps of the run, so a restarted run continues it. Measured on the shipped problems (a band of 8 cells):

ProblemReinitialisationArea keptShape error$\bigl\lvert\lvert\nabla\phi\rvert-1\bigr\rvert$ near the interface, end
Zalesak, Weno5, 100 cellsnone99.18%3.08%
every 40 steps99.36%2.68%
every 10 steps100.37%2.33%
Vortex, Weno5, 64 cellsnone99.40%0.74%0.117
every 40 steps99.18%2.02%0.022
every 10 steps98.93%5.11%0.035
Vortex, Upwind11, 64 cellsnone100.03%0.13%0.059
every 40 steps100.09%3.47%0.25

Reading it. Reinitialisation does what it is for: it rebuilds a distance function without moving the interface, from any scale, and as often as asked. It is not free of cost. On the vortex, at its most deformed moment the filament is about two cells thick, thinner than a distance function can be represented there, and reinitialising then rounds it: the shape error after the flow has reversed is 3 to 7 times larger than without for Weno5, and 27 to 36 times larger for the linear eleventh-order rule, whose error without reinitialisation is the smallest of all (0.13%). On Zalesak’s disk, whose features are at least five cells wide, it slightly improves the corners. So the default is not to reinitialise, and it should be done as seldom as the use of $\phi$ allows (curvature and normals need a distance function; transport alone does not).

Tests that enforce this

Enforced by (paths below crates/merlin-levelset/tests/) advection/reinit.rs: a_distance_function_is_restored_from_any_scale_and_the_interface_stays_put, the_gradient_error_of_a_distance_function_falls_at_about_second_order, a_function_that_is_not_a_multiple_of_a_distance_is_also_restored, reinitialising_many_times_does_not_move_the_interface, in_one_dimension_a_scaled_ramp_becomes_the_distance_to_its_zero, reinitialising_does_not_depend_on_the_blocks_or_the_threads, a_field_with_a_single_ghost_layer_is_reinitialised_in_place_all_the_same, a_reinitialiser_refuses_what_it_cannot_do; and, in crates/merlin-cli/tests/run/levelset_problems.rs, reinitialising_the_vortex_restores_a_distance_function_and_costs_the_thin_filament, reinitialising_zalesaks_disk_keeps_its_area_and_slightly_improves_its_shape, a_linear_rule_that_advects_can_be_reinitialised_because_the_reinitialisation_uses_weno5; the key of the problem file in crates/merlin-cli/src/config/tests.rs: a_level_set_is_only_advected_unless_the_file_asks_for_reinitialisation, the_reinitialisation_of_a_level_set_is_checked_naming_the_key.

§Fast sweeping, and the two compared

Problem. The Eikonal equation $|\nabla\phi| = 1$ can be solved directly, without a pseudo-time, by the fast sweeping method of Zhao (2005): Gauss-Seidel sweeps over the grid in each of the $2^D$ orderings, each cell taking the first-order Godunov upwind solution of $\sum_d ((u - a_d)/\Delta x_d)^2 = 1$ from its smaller neighbour along every axis, until nothing changes (8 sweeps, two rounds of four, for the circle below). The cells next to the interface are held at the same sub-cell distance as in the pseudo-time method, from one shared estimate (crates/merlin-levelset/src/estimate.rs), so the interface is placed in the same way. The method is global, because information crosses the grid in one sweep, so it does not split into blocks: the field is gathered into one array, solved on the calling thread, and written back. It reaches the whole grid (no band) and has no time step, but it is first-order accurate.

Result. The circle of the previous section, from the exact distance and from 3 and 0.2 times it (the answer is the same for all three, because the held values and the sign are):

CellsGradient error within 4 cellsWithin 16 cellsInterface position (cells, before and after)
326.9%8.1%0.0102 and 0.0102
642.9%7.9%0.0072 and 0.0072
1281.2%2.0%0.0026 and 0.0026

The error falls at order 1.25, as a first-order update gives. A second pass changes nothing, to the last bit (the held cells are kept by the dead band and the rest is a deterministic function of them), so repeating it cannot drift. A straight line in one dimension is a distance function and is reproduced to round-off; a scaled sphere on $32^3$ cells has a gradient 9.1% off within three cells of the surface. The distorted function of the previous section is restored to 10.1%, 4.3% and 2.4% on 32, 64 and 128 cells (against 8.5%, 4.0% and 2.35% for the pseudo-time method): at these values the error is that of the distance estimated for the cells next to the interface, which the two share. A function of one sign has no interface and is left as it is, and a NaN is refused with nothing written back.

The two compared, on the circle on 128 cells (a band of 12 cells for the pseudo-time method, one thread each):

Pseudo-time (WENO5)Fast sweeping
Gradient error within 4 cells, from the exact distance0.03%1.2%
The same, from 3 times the distance0.18%1.2%
Gradient error at 16 cells, from 3 times the distance190% (not reached by the band)2.0%
Time for one reinitialisation (test build)144 ms1.7 ms
A second passunchanged to four digits over 500 passesunchanged to the last bit
Order of the gradient errorabout 2.6 (exact distance)1.25

In a run (a reinitialisation every 40 steps, WENO5 advection):

ProblemNonePseudo-timeFast sweeping
Zalesak, 100 cells: shape error, area kept3.08%, 99.18%2.68%, 99.36%5.29%, 97.65%
Zalesak, every 10 steps2.33%, 100.37%6.75%, 96.68%
Vortex, 64 cells: shape error, area kept0.74%, 99.40%2.02%, 99.18%2.50%, 98.54%
Vortex: $\bigl\lvert\lvert\nabla\phi\rvert-1\bigr\rvert$ at the end, near the interface0.1170.0220.061
Vortex, Upwind11 advection: shape error, area kept0.13%, 100.03%3.47%, 100.09%3.39%, 101.31%

Reading it. Each method wins something, so both are kept. The pseudo-time method is 10 to 40 times more accurate near the interface and slightly improves Zalesak’s corners, but it is confined to its band and about 85 times dearer. Fast sweeping is first-order, so its distance function rounds the corners of the slot (shape error 5 to 7% against 3%) and loses 2 to 3% of the area there, but it costs almost nothing, covers the whole grid, and is exactly idempotent. Use the pseudo-time method where the gradient near the interface matters (normals, curvature) and the features are wide; use fast sweeping where a cheap whole-grid distance is wanted (a signed distance to place things from, or a rough one every few steps). On the vortex’s thin filament both cost accuracy, about equally.

Tests that enforce this

Enforced by (paths below crates/merlin-levelset/tests/) advection/sweeping.rs: a_distance_function_is_rebuilt_over_the_whole_grid_from_any_scale_and_the_interface_stays_put, the_gradient_error_falls_at_about_first_order, a_function_that_is_not_a_multiple_of_a_distance_is_restored_as_well_as_by_the_pseudo_time_method, a_second_pass_changes_nothing_at_all, in_one_dimension_a_scaled_ramp_becomes_the_distance_exactly, in_three_dimensions_a_scaled_sphere_becomes_a_distance_function, a_function_with_one_sign_has_no_interface_and_is_left_alone, a_field_with_a_nan_is_refused_and_left_alone, compared_with_the_pseudo_time_method_it_is_less_accurate_near_the_interface_but_covers_the_grid; and, in crates/merlin-cli/tests/run/levelset_problems.rs, fast_sweeping_rebuilds_the_distance_function_of_the_vortex_over_the_whole_grid, fast_sweeping_is_less_kind_to_zalesaks_corners_than_the_pseudo_time_method.

§The Euler equations

Problem. The reconstruction works in one of three sets of variables. The conserved ones are the unknowns themselves. The primitive ones are density, velocity and pressure (Equation::to_primitive). The characteristic ones are $w = L u$, with $L$ the left eigenvectors of the flux Jacobian at the face (Equation::left_eigenvectors, built from Toro 2009, Section 3.2), so that each component is one wave; the eigenvectors are evaluated at the mean of the two conserved states next to the face. A state a reconstruction makes unphysical (negative density or pressure) is replaced by the cell value.

Four things are compared with a reference: the eigenvectors with the flux Jacobian; a smooth density wave carried once round a periodic unit domain (the exact solution is the initial data); Toro’s five shock tubes with the exact Riemann solution ($L_1$ error of the density as a fraction of its range, 400 cells, HLLC, SSP-RK3, Courant number 0.4 unless stated); and Shu and Osher’s problem (1989, Example 8), a Mach 3 shock running into a sinusoidal density on $[-5, 5]$ to time 1.8, with a fine run of the same code.

The eigenvectors. For one, two and three velocity components, over 200 random states and two values of $\gamma$, $L R$ equals the identity to 1e-14, and $R\,\mathrm{diag}(\lambda)\,L$ equals the flux Jacobian, computed independently by central differences, to 3e-10 (the error of the differences). Swapping two columns, or two eigenvalues, is caught at 1e-2 or more.

Smooth wave. On 20 to 160 cells, the time step falling as $h^{5/3}$, the fitted order is 4.98 to 5.01 for Weno5 and for the fifth-order linear rule in all three sets of variables.

Toro’s tests.

ProblemMUSCLWeno5 conservedWeno5 primitiveWeno5 characteristicLinear 5, 11
1 (Sod)0.00170.00150.00130.00150.0017 and 0.0024 (0.0012 and 0.0023 primitive)
2 (123, towards vacuum)0.00240.00310.0020blows up, at every Courant number from 0.4 to 0.02blow up
3 (pressure ratio 1e5)0.00770.00560.00570.0053blow up
4 (colliding shocks)0.00520.00460.00430.0046blow up
5 (1e5, flow of speed 19.6)0.0019blows up at every Courant number from 0.4 to 0.010.0031 at 0.3 and below, blows up at 0.40.0013 at 0.15 and below, blows up at 0.2 and aboveblow up

On Sod’s tube Weno5 converges at order 0.9 in every choice of variables from 100 to 800 cells, first order as expected for a problem with a contact; the first-order scheme has 0.0102 at 400 cells.

Shu and Osher’s problem. Error of the density against the reference, as a fraction of its range:

CellsMUSCLWeno5 conservedWeno5 primitiveWeno5 characteristicUpwind5Upwind11
2000.02010.01880.01860.01650.01050.0086
4000.01530.00680.00680.00540.00310.0032
8000.00690.00290.00300.00220.00130.0016

The reference is Weno5 in the characteristic variables with HLLC on 8000 cells (Courant number 0.3), averaged onto 1600 cells and stored in tests/data/shu_osher_reference.csv; the example shu_osher_reference regenerates it. It comes from the code it is used to test, so this measures how a coarser run approaches a much finer one, not that the answer is right. The shipped euler/shu_osher.toml (400 cells, characteristic) has the error 0.0054, and the same file with MUSCL 0.0153.

Cost. Speed of the shipped Shu and Osher problem on 4000 cells, one thread, release build, median of five alternating runs (the spread within each variant is 3% or less):

VariantMillion cell updates per secondRelative to Weno5 conserved
MUSCL, van Leer10.41.87
Weno5 conserved5.571.00
Weno5 primitive4.900.88
Weno5 characteristic3.140.56
Upwind57.191.29
Upwind116.181.11
Upwind11 characteristic3.650.59

The characteristic variables cost about 1.8 times the time of the conserved ones, for the eigenvector products at each face. As a rough equal-cost comparison from the two finest grids above (conserved Weno5 improves 2.3 times from 400 to 800 cells, order about 1.2): matching the characteristic error at 400 cells (0.0054 against 0.0068) takes about 1.2 times the cells and 1.4 times the work, which at these speeds is about 20% cheaper than the characteristic variables. On Shu and Osher’s problem the accuracy they gain therefore does not pay for their cost; their case is Toro’s fifth test, where they are the most accurate choice that survives.

Reading it.

  • Weno5 is more accurate than MUSCL on four of the five of Toro’s problems and on Shu and Osher’s, without a positivity limiter.
  • Primitive variables are the robust choice. They survive tests 1 to 4 and test 5 at a Courant number of 0.3 or less.
  • Characteristic variables are the accurate choice. They are 12% (200 cells) to 24% (800 cells) better than the others on Shu and Osher’s problem and 2.4 times better than the primitive ones on test 5, but they fail on the vacuum-like test 2, where $1/c$ in the eigenvectors is badly conditioned, and need a Courant number of 0.15 or less on test 5.
  • The conserved variables win no case. For Weno5 they are never the most accurate on any problem above (6% to 55% worse than the best choice), and the only choice that cannot pass test 5. They are kept as the default because they are the cheapest and because for the linear rules they are equal to the characteristic variables (next point); whether to keep them as a choice for Weno5 is an open decision (the roadmap, 8.3, drops a variant that wins on no case).
  • For a linear rule the characteristic variables give the conserved result (the flux differs by 4e-16): the reconstruction is linear, the eigenvectors are the same across the window, and a linear operation commutes with a fixed matrix. The choice only matters for the nonlinear rule.
  • The linear rules are the most accurate on Shu and Osher’s problem, about twice as accurate as Weno5 in this range of grids, because the shock is weak and the rest is smooth. They are not positivity preserving: on every strong problem their oscillations take the pressure negative and the run ends with a non-finite solution, in any variables, even though a state that is unphysical at a face is replaced by the cell value (the cell itself is updated unphysically). A positivity-preserving limiter (Zhang and Shu 2010) would be the remedy and is not part of this phase.
  • The answer does not depend on the block layout (1, 4 or 6 blocks) to the last bit.
Tests that enforce this

Enforced by crates/merlin-systems/tests/equations/eigenvectors.rs: the_gas_eigenvectors_invert_each_other_and_diagonalise_the_flux_jacobian, a_wrong_set_of_eigenvectors_is_caught_by_the_same_check, the_acoustic_eigenvectors_of_a_gas_at_rest_are_the_textbook_ones, a_scalar_law_has_the_single_eigenvector_one; equations/euler_high_order.rs: a_smooth_density_wave_is_fifth_order_in_every_choice_of_variables, every_rule_in_every_choice_of_variables_captures_sods_tube_far_better_than_first_order, weno5_converges_on_sods_tube_at_about_first_order, weno5_keeps_the_strong_problems_that_the_linear_rules_cannot, the_characteristic_variables_carry_weno5_through_tests_three_and_four_but_not_two, on_the_fifth_problem_only_the_primitive_and_characteristic_variables_survive_and_the_latter_is_more_accurate, for_a_linear_rule_the_characteristic_variables_give_the_conserved_flux_and_for_weno5_they_do_not, on_the_shu_osher_problem_the_high_order_schemes_beat_muscl_and_weno5_does_best_in_the_characteristic_variables, the_shu_osher_error_falls_as_the_grid_is_refined, the_answer_does_not_depend_on_the_number_of_blocks; schemes/reconstruction.rs: for_a_scalar_law_the_primitive_variables_are_the_conserved_ones. The shipped euler/sod_weno5.toml has the published plateau values (sods_weno5_problem_has_the_published_plateau_values) and reproduces the library-driven run bit for bit (a_weno5_file_run_matches_the_library_driven_run_bit_for_bit), and euler/shu_osher.toml is close to the reference (the_shu_osher_file_run_is_close_to_the_reference_and_muscl_is_not), all in crates/merlin-cli/tests/run/euler_problems.rs.