include/pops/runtime/builders/block/block_builder.hpp Source File

adc_cpp: include/pops/runtime/builders/block/block_builder.hpp Source File
adc_cpp 0.3.0
Model-free C++23 core for coupled hyperbolic-elliptic systems on adaptive (AMR) meshes, with MPI and GPU (Kokkos) backends
block_builder.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <pops/core/foundation/cold.hpp> // POPS_COLD_FN: COLD block-builder no-optimize attribute (ADC-337)
6#include <pops/mesh/execution/for_each.hpp> // for_each_cell (projection ponctuelle post-pas, ADC-177)
13#include <pops/numerics/spatial/embedded_boundary/operator.hpp> // assemble_rhs_eb (cut-cell EB) + detail::DiscLevelSet (T5-PR2)
16#include <pops/runtime/config/dispatch_tags.hpp> // UNIQUE registry of tags (validate_limiter/riemann, limiter_n_ghost)
17#include <pops/runtime/context/grid_context.hpp> // GridContext + BlockClosures (shared lightweight header)
18#include <pops/numerics/spatial/embedded_boundary/domain.hpp> // detail::DiscDomain (built-in level-set domain instance)
19
20#include <cmath> // std::sqrt (ARS(2,2,2) coefficients: gamma = 1 - 1/sqrt(2), host)
21#include <functional>
22#include <memory> // std::shared_ptr (shared scratch of the HLL wave speed cache, opt-in)
23#include <stdexcept>
24#include <string>
25#include <type_traits> // std::is_same_v (cache engages only for the HLL flux)
26#include <utility>
27#include <vector>
28
42
43namespace pops {
44
45// GridContext and BlockClosures: defined in pops/runtime/grid_context.hpp (lightweight header, also
46// included by system.hpp to expose grid_context() / install_block() without pulling in the numerics).
47
48namespace detail {
56template <class Limiter, class Flux, class Model>
58 Model model;
65 std::shared_ptr<MultiFab> ws_cache;
66 void operator()(MultiFab& U, MultiFab& R) const {
67 fill_ghosts(U, ctx->dom, ctx->bc);
68 if constexpr (std::is_same_v<Flux, HLLFlux>) {
69 if (ws_cache) {
70 // Re-allocate the scratch at the current layout (4 components, 1 ghost): covers an AMR regrid
71 // or a first call (shared_ptr to an empty MultiFab). Otherwise reuse the existing allocation.
72 if (ws_cache->local_size() != U.local_size() || ws_cache->ncomp() != 4)
73 *ws_cache = MultiFab(U.box_array(), U.dmap(), 4, 1);
74 assemble_rhs_hll_cached<Limiter>(model, U, *ctx->aux, ctx->geom, R, *ws_cache, recon_prim,
75 pos_floor);
76 return;
77 }
78 }
79 assemble_rhs<Limiter, Flux>(model, U, *ctx->aux, ctx->geom, R, recon_prim, pos_floor);
80 }
81};
82
87template <class Limiter, class Flux, class Model, class Stepper = SSPRK2Step>
89 Model m;
93 std::shared_ptr<MultiFab> ws_cache;
94 void operator()(MultiFab& U, Real dt, int n) const {
95 const Real h = dt / static_cast<Real>(n);
97 run_explicit_substeps<Stepper>(rhs, U, h, n);
98 }
99};
100
105template <class Limiter, class Flux, class Model>
107 Model m;
111 NewtonOptions nopts{}; // block Newton options (defaults = historical: 2 iters, 1e-7)
112 NewtonReport* nreport = nullptr; // OPT-IN diagnostics (stable address, owned by System::Impl)
114 void operator()(MultiFab& U, Real dt, int n) const {
115 const Real h = dt / static_cast<Real>(n);
118 if (nreport)
119 nreport->reset(); // report AGGREGATED over the n substeps of THIS advance
120 for (int s = 0; s < n; ++s) {
121 ForwardEuler{}.take_step(rhs, U, h); // explicit half-step: source-free transport
123 nreport); // implicit source (stiff relaxation)
124 }
125 }
126};
127
163template <class Limiter, class Flux, class Model>
165 Model m;
168 NewtonOptions nopts{}; // Newton options of the stage solves (defaults = historical)
169 NewtonReport* nreport = nullptr; // OPT-IN diagnostics (stable address, owned by System::Impl)
171 void operator()(MultiFab& U, Real dt, int n) const {
172 const Real h = dt / static_cast<Real>(n);
173 const Real gamma = Real(1) - Real(1) / std::sqrt(Real(2));
174 const Real delta = Real(1) - Real(1) / (Real(2) * gamma);
175 const Real cS2 = (Real(1) - gamma) / gamma; // factor of (U^(2) - base2) at stage 3
176 const ImplicitMask<Model::n_vars> mask{}; // FULLY implicit source (inactive mask)
177 // Source-free transport residual (L = -div F): SAME mechanism as the explicit half-step of AdvanceImex.
180 const int nc = U.ncomp();
181 MultiFab Un(U.box_array(), U.dmap(), nc, 0); // U^n
182 MultiFab L1(U.box_array(), U.dmap(), nc, 0); // L(U^n)
183 MultiFab L2(U.box_array(), U.dmap(), nc, 0); // L(U^(2))
184 MultiFab base2(U.box_array(), U.dmap(), nc, 0); // U^n + dt*gamma*L1
185 MultiFab work(U.box_array(), U.dmap(), nc, U.n_grow()); // stage state (passed to transport)
186 if (nreport)
187 nreport->reset(); // report AGGREGATED over the substeps AND the 2 stage solves
188 for (int s = 0; s < n; ++s) {
189 // Stage 1: U^(1) = U^n; L1 = L(U^n).
190 lincomb(Un, Real(1), U, Real(0), U); // Un = U^n (valid cells)
191 rhs(U, L1); // L1 = L(U^n) (fill_ghosts(U) + assemble_rhs)
192 // Stage 2: U^(2) = base2 + dt*gamma*S(U^(2)), base2 = U^n + dt*gamma*L1.
193 lincomb(base2, Real(1), Un, h * gamma, L1); // base2 = U^n + dt*gamma*L1
194 lincomb(work, Real(1), base2, Real(0), base2); // work = base2
195 backward_euler_source(m, *ctx.aux, work, h * gamma, nopts, mask, nreport); // work = U^(2)
196 rhs(work, L2); // L2 = L(U^(2))
197 // Stage 3: U <- base3 = U^n + dt*delta*L1 + dt*(1-delta)*L2 + ((1-gamma)/gamma)*(U^(2) - base2).
198 lincomb(U, Real(1), Un, h * delta, L1); // U = U^n + dt*delta*L1
199 saxpy(U, h * (Real(1) - delta), L2); // + dt*(1-delta)*L2
200 saxpy(U, cS2, work); // + ((1-gamma)/gamma)*U^(2)
201 saxpy(U, -cS2, base2); // - ((1-gamma)/gamma)*base2 -> U = base3
202 backward_euler_source(m, *ctx.aux, U, h * gamma, nopts, mask,
203 nreport); // U = U^(3) = U^{n+1}
204 }
205 }
206};
207
211template <class Model>
212struct HotspotFn {
213 Model m;
215 void operator()(const MultiFab& U, Real& w, int& i, int& j) const {
216 max_wave_speed_hotspot_mf(m, U, *ctx.aux, ctx.dom.nx(), w, i, j);
217 }
218};
219
224template <class Model>
226 Model m;
227 Array4 u; // ecriture (etat du bloc)
228 ConstArray4 uc; // lecture (meme fab, vue const)
229 ConstArray4 a; // aux du System (phi, grad phi, champs extra)
230 POPS_HD void operator()(int i, int j) const {
231 const typename Model::State p =
232 m.project(load_state<Model>(uc, i, j), load_aux<aux_comps<Model>()>(a, i, j));
233 for (int c = 0; c < Model::n_vars; ++c)
234 u(i, j, c) = p[c];
235 }
236};
237
242template <class Model>
244 Model m;
246 void operator()(MultiFab& U) const {
247 for (int li = 0; li < U.local_size(); ++li)
248 for_each_cell(U.box(li),
249 ProjectCellKernel<Model>{m, U.fab(li).array(), U.fab(li).const_array(),
250 ctx.aux->fab(li).const_array()});
251 }
252};
253
254template <class Limiter, class Flux, class Model>
255struct RhsInto {
256 Model m;
260 std::shared_ptr<MultiFab> ws_cache;
261 void operator()(MultiFab& U, MultiFab& R) const {
262 // Delegates to BlockRhsEval (fill_ghosts + assemble_rhs OR cached path): single source of the residual.
264 }
265};
266
272template <class Model>
274 Model m;
275 ConstArray4 u; // block state (read)
276 ConstArray4 a; // System aux (phi, grad phi, extra fields)
277 Array4 r; // residual (write)
278 POPS_HD void operator()(int i, int j) const {
279 const auto S = m.source(load_state<Model>(u, i, j), load_aux<aux_comps<Model>()>(a, i, j));
280 for (int c = 0; c < Model::n_vars; ++c)
281 r(i, j, c) = S[c];
282 }
283};
284
293template <class Model>
295 Model m;
297 void operator()(MultiFab& U, MultiFab& R) const {
298 for (int li = 0; li < U.local_size(); ++li)
299 for_each_cell(R.box(li),
300 SourceOnlyKernel<Model>{m, U.fab(li).const_array(),
301 ctx.aux->fab(li).const_array(), R.fab(li).array()});
302 }
303};
304
305// ============================================================================
306// DISC ROUTING (T5-PR3 work): DISC residual evaluators + the advances that carry them.
307// ============================================================================
308// The transport residual of a block goes through BlockRhsEval (assemble_rhs, full cartesian). The two
309// evaluators below SUBSTITUTE the disc operator for assemble_rhs, reading the System geometry BY
310// POINTER (stable address of an Impl member) at step time -- so the add_block / set_disc_domain order
311// is indifferent. NAMED functors (same device contract as BlockRhsEval).
312
318template <class Limiter, class Flux, class Model>
320 Model model;
322 const MultiFab* mask; // Impl::domain_mask_ (NOT owned; stable address)
325 void operator()(MultiFab& U, MultiFab& R) const {
326 fill_ghosts(U, ctx->dom, ctx->bc);
327 assemble_rhs_masked<Limiter, Flux>(model, U, *ctx->aux, *mask, ctx->geom, R, recon_prim,
328 pos_floor);
329 }
330};
331
339template <class Limiter, class Flux, class Model>
341 Model model;
343 const DiscDomain* eb_domain; // Impl::eb_domain_ (NOT owned; stable address)
346 void operator()(MultiFab& U, MultiFab& R) const {
347 fill_ghosts(U, ctx->dom, ctx->bc);
348 assemble_rhs_eb<Limiter, Flux>(model, U, *ctx->aux, disc_level_set(*eb_domain), ctx->geom, R,
350 }
351};
352
355template <class Limiter, class Flux, class Model, class Stepper = SSPRK2Step>
357 Model m;
362 void operator()(MultiFab& U, Real dt, int n) const {
363 const Real h = dt / static_cast<Real>(n);
365 run_explicit_substeps<Stepper>(rhs, U, h, n);
366 }
367};
368
371template <class Limiter, class Flux, class Model, class Stepper = SSPRK2Step>
373 Model m;
378 void operator()(MultiFab& U, Real dt, int n) const {
379 const Real h = dt / static_cast<Real>(n);
381 run_explicit_substeps<Stepper>(rhs, U, h, n);
382 }
383};
384
390template <class Limiter, class Flux, class Model>
392 Model m;
400 void operator()(MultiFab& U, Real dt, int n) const {
401 const Real h = dt / static_cast<Real>(n);
404 if (nreport)
405 nreport->reset();
406 for (int s = 0; s < n; ++s) {
407 ForwardEuler{}.take_step(rhs, U, h);
409 }
410 }
411};
412
415template <class Limiter, class Flux, class Model>
417 Model m;
425 void operator()(MultiFab& U, Real dt, int n) const {
426 const Real h = dt / static_cast<Real>(n);
429 if (nreport)
430 nreport->reset();
431 for (int s = 0; s < n; ++s) {
432 ForwardEuler{}.take_step(rhs, U, h);
434 }
435 }
436};
437} // namespace detail
438
443template <int N>
444POPS_COLD_FN ImplicitMask<N> make_implicit_mask(const std::vector<int>& implicit_components) {
445 ImplicitMask<N> mask;
446 if (implicit_components.empty())
447 return mask; // inactive: model default
448 mask.active = true;
449 for (int c : implicit_components)
450 if (c >= 0 && c < N)
451 mask.flag[c] = true;
452 return mask;
453}
454
474template <class Limiter, class Flux, class Model>
475POPS_COLD_FN BlockClosures build_block(const Model& m, const GridContext& ctx, bool imex,
476 bool recon_prim, const std::string& method = "ssprk2",
477 const std::vector<int>& implicit_components = {},
478 const NewtonOptions& newton_opts = {},
479 NewtonReport* newton_report = nullptr,
480 Real pos_floor = Real(0), bool wave_speed_cache = false) {
481 const MultiFab* domain_mask = ctx.domain_mask;
482 const detail::DiscDomain* eb_domain = ctx.eb_domain;
483 BlockClosures bc;
484 const ImplicitMask<Model::n_vars> impl_mask =
485 make_implicit_mask<Model::n_vars>(implicit_components);
486 // SHARED scratch of the HLL wave speed cache (opt-in): a single MultiFab for the explicit advance and
487 // rhs_into (never called concurrently). nullptr when the option is OFF -> BlockRhsEval keeps the
488 // per-face path (bit-identical). Allocated at the real layout on the first call (cf. BlockRhsEval).
489 std::shared_ptr<MultiFab> ws_cache =
490 wave_speed_cache ? std::make_shared<MultiFab>() : std::shared_ptr<MultiFab>{};
491 if (imex) {
492 if (method == "imexrk_ars222") {
493 // IMEX-RK FAMILY, ARS(2,2,2) scheme (order 2): advance PARALLEL to AdvanceImex, FULLY implicit
494 // source (impl_mask ignored: the facade already rejects a partial mask with this scheme). FULL
495 // CARTESIAN ONLY: we do NOT build an embedded-boundary advance (advance_masked / advance_eb stay
496 // empty) -> an embedded-boundary geometry mode on this block throws an EXPLICIT error at step time
497 // (SystemStepper::advance_transport_n), never a silent cartesian.
498 bc.advance = detail::AdvanceImexRkArs222<Limiter, Flux, Model>{
499 m, ctx, recon_prim, newton_opts, newton_report, pos_floor};
500 } else {
501 // Historical IMEX (local backward-Euler, order 1): UNTOUCHED, bit-identical.
502 bc.advance = detail::AdvanceImex<Limiter, Flux, Model>{
503 m, ctx, recon_prim, impl_mask, newton_opts, newton_report, pos_floor};
504 if (domain_mask)
505 bc.advance_masked = detail::AdvanceImexMasked<Limiter, Flux, Model>{
506 m, ctx, domain_mask, recon_prim, impl_mask, newton_opts, newton_report, pos_floor};
507 if (eb_domain)
508 bc.advance_eb = detail::AdvanceImexEb<Limiter, Flux, Model>{
509 m, ctx, eb_domain, recon_prim, impl_mask, newton_opts, newton_report, pos_floor};
510 }
511 } else if (method == "euler") {
512 bc.advance = detail::AdvanceExplicit<Limiter, Flux, Model, ForwardEuler>{m, ctx, recon_prim,
513 pos_floor, ws_cache};
514 if (domain_mask)
515 bc.advance_masked = detail::AdvanceExplicitMasked<Limiter, Flux, Model, ForwardEuler>{
516 m, ctx, domain_mask, recon_prim, pos_floor};
517 if (eb_domain)
518 bc.advance_eb = detail::AdvanceExplicitEb<Limiter, Flux, Model, ForwardEuler>{
519 m, ctx, eb_domain, recon_prim, pos_floor};
520 } else if (method == "ssprk3") {
521 bc.advance = detail::AdvanceExplicit<Limiter, Flux, Model, SSPRK3Step>{m, ctx, recon_prim,
522 pos_floor, ws_cache};
523 if (domain_mask)
524 bc.advance_masked = detail::AdvanceExplicitMasked<Limiter, Flux, Model, SSPRK3Step>{
525 m, ctx, domain_mask, recon_prim, pos_floor};
526 if (eb_domain)
527 bc.advance_eb = detail::AdvanceExplicitEb<Limiter, Flux, Model, SSPRK3Step>{
528 m, ctx, eb_domain, recon_prim, pos_floor};
529 } else if (method == "ssprk2") {
530 bc.advance = detail::AdvanceExplicit<Limiter, Flux, Model, SSPRK2Step>{m, ctx, recon_prim,
531 pos_floor, ws_cache};
532 if (domain_mask)
533 bc.advance_masked = detail::AdvanceExplicitMasked<Limiter, Flux, Model, SSPRK2Step>{
534 m, ctx, domain_mask, recon_prim, pos_floor};
535 if (eb_domain)
536 bc.advance_eb = detail::AdvanceExplicitEb<Limiter, Flux, Model, SSPRK2Step>{
537 m, ctx, eb_domain, recon_prim, pos_floor};
538 } else {
539 throw std::runtime_error("System: unknown explicit time method '" + method +
540 "' (euler|ssprk2|ssprk3)");
541 }
542 bc.rhs_into = detail::RhsInto<Limiter, Flux, Model>{m, ctx, recon_prim, pos_floor, ws_cache};
543 // FLUX-ONLY residual R <- -div F(U) (ADC-425): the SAME RhsInto path on SourceFreeModel<Model> (the
544 // canonical zero-source adapter the IMEX explicit half-step already uses, state_access.hpp), so the
545 // flux / ghost / geometry / positivity handling is bit-identical to rhs_into -- only the model's
546 // default/composite source is dropped. A compiled time Program's hyperbolic stage reads it so a
547 // Lie/Strang split assembles "flux but no source" without the default source leaking in (spec
548 // criterion 17). NO HLL cache: the explicit/IMEX advances and rhs_into share ws_cache (never
549 // concurrent), but a flux-only RHS can interleave with them, so it keeps the per-face path. The
550 // residual is identical either way with limiter='none'; the HLL wave-speed cache -- rejected on the
551 // aot/production backends compiled Programs use -- is the only path where cached cell-center speeds
552 // differ from the per-face reconstruction, so for a compiled Program the cache is a perf scratch,
553 // not a numerics change.
554 bc.rhs_flux_only = detail::RhsInto<Limiter, Flux, SourceFreeModel<Model>>{
555 SourceFreeModel<Model>{m}, ctx, recon_prim, pos_floor, nullptr};
556 // SOURCE-ONLY residual R <- S(U, aux) (ADC-430): the exact MIRROR of rhs_flux_only. SourceInto
557 // evaluates m.source per cell (the SAME source term assemble_rhs / rhs_into add) with no numerical-flux
558 // dispatch, so it is bit-identical to the source half of rhs_into and flux-template agnostic (a
559 // zero-flux model adapter could not zero HLL/Roe, which recombine via wave_speeds). A compiled time
560 // Program's source stage reads it so a Lie/Strang split assembles "the default source but no flux"
561 // without the -div F base leaking in (spec: rhs flux=False is source-only). No Limiter/Flux: the
562 // source is cell-local, independent of the spatial scheme.
563 bc.source_only = detail::SourceInto<Model>{m, ctx};
564 bc.hotspot =
565 detail::HotspotFn<Model>{m, ctx}; // dt_hotspot diagnostic (ADC-182), off the hot path
566 // PROJECTION PONCTUELLE post-pas (ADC-177) : fabriquee SEULEMENT si le modele declare le trait
567 // (HasPointwiseProjection, cf. core/physical_model.hpp) ; vide sinon -> le stepper ne l'interroge
568 // jamais (chemin historique bit-identique). Partagee par add_block ET add_compiled_model (les deux
569 // passent par make_block) : un .so 'production' la transporte donc nativement.
570 if constexpr (HasPointwiseProjection<Model>)
571 bc.project = detail::PointwiseProject<Model>{m, ctx};
572 return bc;
573}
574
582// Per-flux limiter ladders, split out of make_block (ADC-335) so each flux's build_block leaves can be
583// instantiated in their OWN translation unit (python/system_compressible_<flux>.cpp). Each body is the
584// VERBATIM content of make_block's old `if (riem == "<flux>")` branch (same capability if-constexpr,
585// same limiter ladder, same throws) -> bit-identical. make_block (below) is now a thin riem dispatcher
586// that calls these; it stays the entry point for the non-subdivided callers (exb/isothermal seams, the
587// .so/AOT loader path). The flux string is implied by which helper is called -> validation moves to the
588// make_block dispatcher (kept) and, for the per-flux seam path, to the caller (System).
589template <class Model>
590POPS_COLD_FN BlockClosures make_block_rusanov(const Model& m, const std::string& lim,
591 const GridContext& ctx, bool imex, bool recon_prim,
592 const std::string& method,
593 const std::vector<int>& implicit_components,
594 const NewtonOptions& newton_opts,
595 NewtonReport* newton_report, Real pos_floor) {
596 if (lim == "none")
597 return build_block<NoSlope, RusanovFlux>(m, ctx, imex, recon_prim, method, implicit_components,
598 newton_opts, newton_report, pos_floor);
599 if (lim == "minmod")
600 return build_block<Minmod, RusanovFlux>(m, ctx, imex, recon_prim, method, implicit_components,
601 newton_opts, newton_report, pos_floor);
602 if (lim == "vanleer")
603 return build_block<VanLeer, RusanovFlux>(m, ctx, imex, recon_prim, method, implicit_components,
604 newton_opts, newton_report, pos_floor);
605 if (lim == "weno5")
606 return build_block<Weno5, RusanovFlux>(m, ctx, imex, recon_prim, method, implicit_components,
607 newton_opts, newton_report, pos_floor);
608 throw_registry_dispatch_mismatch("System", "limiteur", lim);
609}
610
611template <class Model>
612POPS_COLD_FN BlockClosures make_block_hll(const Model& m, const std::string& lim,
613 const GridContext& ctx, bool imex, bool recon_prim,
614 const std::string& method,
615 const std::vector<int>& implicit_components,
616 const NewtonOptions& newton_opts,
617 NewtonReport* newton_report, Real pos_floor,
618 bool wave_speed_cache) {
619 // HLL (Harten-Lax-van Leer, 2 waves): less diffusive than Rusanov (dissipation ~ signed |sR-sL|
620 // instead of symmetric 2*max|v|), but does NOT require pressure (unlike HLLC/Roe) -- only SIGNED
621 // wave speeds model.wave_speeds. Available as soon as a model exposes its signed eigenvalues (the
622 // DSL emits wave_speeds as soon as a primitive 'p' is declared, even cold isothermal p=0 -> c=0 ->
623 // HLL degenerates to upwind, still less diffusive than Rusanov at the contact). Does NOT REQUIRE
624 // n_vars==4 nor a pressure: usable by a 3-var isothermal model (rho, m_x, m_y) exposing signed
625 // wave speeds but no pressure, where hllc/roe are rejected. Gated on the presence of wave_speeds
626 // (otherwise a CLEAR error, not a compilation failure for a scalar model without a signed wave,
627 // e.g. ExB transport).
628 if constexpr (requires(const Model mm, typename Model::State s, Aux a, Real r) {
629 mm.wave_speeds(s, a, 0, r, r);
630 }) {
631 // wave_speed_cache (opt-in) forwarded ONLY here: the wave speed cache only engages for the HLL
632 // flux (BlockRhsEval guarded by Flux == HLLFlux). rusanov/hllc/roe ignore it.
633 if (lim == "none")
634 return build_block<NoSlope, HLLFlux>(m, ctx, imex, recon_prim, method, implicit_components,
635 newton_opts, newton_report, pos_floor, wave_speed_cache);
636 if (lim == "minmod")
637 return build_block<Minmod, HLLFlux>(m, ctx, imex, recon_prim, method, implicit_components,
638 newton_opts, newton_report, pos_floor, wave_speed_cache);
639 if (lim == "vanleer")
640 return build_block<VanLeer, HLLFlux>(m, ctx, imex, recon_prim, method, implicit_components,
641 newton_opts, newton_report, pos_floor, wave_speed_cache);
642 if (lim == "weno5")
643 return build_block<Weno5, HLLFlux>(m, ctx, imex, recon_prim, method, implicit_components,
644 newton_opts, newton_report, pos_floor, wave_speed_cache);
645 throw_registry_dispatch_mismatch("System", "limiteur", lim);
646 } else {
647 throw std::runtime_error(
648 "System: flux 'hll' requires signed wave speeds "
649 "(model.wave_speeds: declare a primitive 'p' / eigenvalues); "
650 "this transport -> 'rusanov'");
651 }
652}
653
654template <class Model>
655POPS_COLD_FN BlockClosures make_block_hllc(const Model& m, const std::string& lim,
656 const GridContext& ctx, bool imex, bool recon_prim,
657 const std::string& method,
658 const std::vector<int>& implicit_components,
659 const NewtonOptions& newton_opts,
660 NewtonReport* newton_report, Real pos_floor) {
661 // HLLC PATHS: (a) HasHLLCStructure capability (the model provides contact_speed +
662 // hllc_star_state -> GENERIC contact-resolving algorithm, no assumed layout), OR
663 // (b) the CANONICAL Euler 2D path (n_vars == 4 + pressure, bit-identical historical
664 // implementation). Without either, explicit rejection with the capability remedy.
665 if constexpr (HasHLLCStructure<Model> ||
666 (Model::n_vars == 4 &&
667 requires(const Model mm, typename Model::State s) { mm.pressure(s); })) {
668 if (lim == "none")
669 return build_block<NoSlope, HLLCFlux>(m, ctx, imex, recon_prim, method, implicit_components,
670 newton_opts, newton_report, pos_floor);
671 if (lim == "minmod")
672 return build_block<Minmod, HLLCFlux>(m, ctx, imex, recon_prim, method, implicit_components,
673 newton_opts, newton_report, pos_floor);
674 if (lim == "vanleer")
675 return build_block<VanLeer, HLLCFlux>(m, ctx, imex, recon_prim, method, implicit_components,
676 newton_opts, newton_report, pos_floor);
677 if (lim == "weno5")
678 return build_block<Weno5, HLLCFlux>(m, ctx, imex, recon_prim, method, implicit_components,
679 newton_opts, newton_report, pos_floor);
680 throw_registry_dispatch_mismatch("System", "limiteur", lim);
681 } else {
682 throw std::runtime_error(
683 "System: flux 'hllc' requires a compressible Euler 2D transport "
684 "(4 variables + pressure) OR the model's HLLC capability "
685 "(pressure + wave_speeds + contact_speed + hllc_star_state, cf. "
686 "HasHLLCStructure); this transport -> 'hll'/'rusanov'");
687 }
688}
689
690template <class Model>
691POPS_COLD_FN BlockClosures make_block_roe(const Model& m, const std::string& lim,
692 const GridContext& ctx, bool imex, bool recon_prim,
693 const std::string& method,
694 const std::vector<int>& implicit_components,
695 const NewtonOptions& newton_opts,
696 NewtonReport* newton_report, Real pos_floor) {
697 // ROE PATHS: (a) HasRoeDissipation capability (the model provides its full Roe dissipation
698 // d = |A_roe| dU -> GENERIC Roe-like solver), OR (b) the CANONICAL ideal-gas Euler 2D path
699 // (bit-identical historical). Without either, explicit rejection.
700 if constexpr (HasRoeDissipation<Model> ||
701 (Model::n_vars == 4 &&
702 requires(const Model mm, typename Model::State s) { mm.pressure(s); })) {
703 if (lim == "none")
704 return build_block<NoSlope, RoeFlux>(m, ctx, imex, recon_prim, method, implicit_components,
705 newton_opts, newton_report, pos_floor);
706 if (lim == "minmod")
707 return build_block<Minmod, RoeFlux>(m, ctx, imex, recon_prim, method, implicit_components,
708 newton_opts, newton_report, pos_floor);
709 if (lim == "vanleer")
710 return build_block<VanLeer, RoeFlux>(m, ctx, imex, recon_prim, method, implicit_components,
711 newton_opts, newton_report, pos_floor);
712 if (lim == "weno5")
713 return build_block<Weno5, RoeFlux>(m, ctx, imex, recon_prim, method, implicit_components,
714 newton_opts, newton_report, pos_floor);
715 throw_registry_dispatch_mismatch("System", "limiteur", lim);
716 } else {
717 throw std::runtime_error(
718 "System: flux 'roe' requires a compressible Euler 2D transport "
719 "(4 variables + pressure) OR the model's Roe capability "
720 "(roe_dissipation, cf. HasRoeDissipation); this transport -> "
721 "'hll'/'rusanov'");
722 }
723}
724
725template <class Model>
726POPS_COLD_FN BlockClosures make_block(const Model& m, const std::string& lim,
727 const std::string& riem, const GridContext& ctx, bool imex,
728 bool recon_prim, const std::string& method = "ssprk2",
729 const std::vector<int>& implicit_components = {},
730 const NewtonOptions& newton_opts = {},
731 NewtonReport* newton_report = nullptr,
732 Real pos_floor = Real(0), bool wave_speed_cache = false) {
733 // CENTRALIZED VALIDATION (registry dispatch_tags.hpp) BEFORE the dispatch: same tag acceptances /
734 // rejections as before, identical messages (validate_* keeps the historical wording). The flux
735 // dispatch now forwards to the per-flux helpers above (each holds the unchanged capability
736 // `if constexpr` guard + limiter ladder); the final throw stays a registry/dispatch-inconsistency
737 // guard (unreachable after validate_riemann).
738 validate_riemann(riem, /*polar=*/false, "System");
739 validate_limiter(lim, "System");
740 if (riem == "rusanov")
741 return make_block_rusanov(m, lim, ctx, imex, recon_prim, method, implicit_components,
742 newton_opts, newton_report, pos_floor);
743 if (riem == "hll")
744 return make_block_hll(m, lim, ctx, imex, recon_prim, method, implicit_components, newton_opts,
745 newton_report, pos_floor, wave_speed_cache);
746 if (riem == "hllc")
747 return make_block_hllc(m, lim, ctx, imex, recon_prim, method, implicit_components, newton_opts,
748 newton_report, pos_floor);
749 if (riem == "roe")
750 return make_block_roe(m, lim, ctx, imex, recon_prim, method, implicit_components, newton_opts,
751 newton_report, pos_floor);
752 throw_registry_dispatch_mismatch("System", "flux", riem);
753}
754
759inline int block_n_ghost(const std::string& lim) {
760 // SINGLE source: limiter_n_ghost(lim) (registry dispatch_tags.hpp). The default 2 (MUSCL) for an
761 // unknown limiter is carried by the registry -> same historical allocation, bit-identical. The
762 // static_asserts below (this TU sees BOTH the registry AND the types) guarantee that the kLimiters
763 // table never drifts from the real::n_ghost constants.
764 static_assert(limiter_n_ghost_ct("none") == NoSlope::n_ghost, "kLimiters[none].n_ghost drifted");
765 static_assert(limiter_n_ghost_ct("minmod") == Minmod::n_ghost,
766 "kLimiters[minmod].n_ghost drifted");
767 static_assert(limiter_n_ghost_ct("vanleer") == VanLeer::n_ghost,
768 "kLimiters[vanleer].n_ghost drifted");
769 static_assert(limiter_n_ghost_ct("weno5") == Weno5::n_ghost, "kLimiters[weno5].n_ghost drifted");
770 return limiter_n_ghost(lim);
771}
772
773namespace detail {
777template <class Model>
778struct MaxSpeed {
779 Model m;
781 Real operator()(const MultiFab& U) const { return max_wave_speed_mf(m, U, *ctx.aux); }
782};
783
786template <class Model>
788 Model m;
790 Real operator()(const MultiFab& U) const { return max_stability_speed_mf(m, U, *ctx.aux); }
791};
792
794template <class Model>
796 Model m;
798 Real operator()(const MultiFab& U) const { return max_source_frequency_mf(m, U, *ctx.aux); }
799};
800
802template <class Model>
804 Model m;
806 Real operator()(const MultiFab& U) const { return min_stability_dt_mf(m, U, *ctx.aux); }
807};
808
810template <class Model>
812 Model m;
813 void operator()(const MultiFab& U, MultiFab& rhs) const {
814 for (int li = 0; li < rhs.local_size(); ++li) {
815 Array4 r = rhs.fab(li).array();
816 const ConstArray4 u = U.fab(li).const_array();
817 const Box2D b = rhs.box(li);
818 for (int j = b.lo[1]; j <= b.hi[1]; ++j)
819 for (int i = b.lo[0]; i <= b.hi[0]; ++i)
820 r(i, j) += m.elliptic_rhs(load_state<Model>(u, i, j));
821 }
822 }
823};
824} // namespace detail
825
830template <class Model>
831std::function<Real(const MultiFab&)> make_max_speed(const Model& m, const GridContext& ctx) {
832 if constexpr (HasStabilitySpeed<Model>)
834 else
835 return detail::MaxSpeed<Model>{m, ctx};
836}
837
841template <class Model>
842std::function<Real(const MultiFab&)> make_source_frequency(const Model& m, const GridContext& ctx) {
843 if constexpr (HasSourceFrequency<Model>)
844 return detail::MaxSourceFreq<Model>{m, ctx};
845 else
846 return {};
847}
848
851template <class Model>
852std::function<Real(const MultiFab&)> make_stability_dt(const Model& m, const GridContext& ctx) {
853 if constexpr (HasStabilityDt<Model>)
854 return detail::MinStabilityDt<Model>{m, ctx};
855 else
856 return {};
857}
858
860template <class Model>
861std::function<void(const MultiFab&, MultiFab&)> make_poisson_rhs(const Model& m) {
863}
864
873template <class Model>
874std::pair<std::function<void(const double*, double*)>, std::function<void(const double*, double*)>>
875make_cell_convert(const Model& m) {
876 constexpr int NV = Model::n_vars;
877 if constexpr (HasPrimitiveVars<Model>) {
878 auto p2c = [m](const double* in, double* out) {
879 typename Model::Prim p{};
880 for (int c = 0; c < NV; ++c)
881 p[c] = static_cast<Real>(in[c]);
882 const typename Model::State u = m.to_conservative(p);
883 for (int c = 0; c < NV; ++c)
884 out[c] = static_cast<double>(u[c]);
885 };
886 auto c2p = [m](const double* in, double* out) {
887 typename Model::State u{};
888 for (int c = 0; c < NV; ++c)
889 u[c] = static_cast<Real>(in[c]);
890 const typename Model::Prim p = m.to_primitive(u);
891 for (int c = 0; c < NV; ++c)
892 out[c] = static_cast<double>(p[c]);
893 };
894 return {std::function<void(const double*, double*)>(p2c),
895 std::function<void(const double*, double*)>(c2p)};
896 } else {
897 auto id = [](const double* in, double* out) {
898 for (int c = 0; c < NV; ++c)
899 out[c] = in[c];
900 };
901 return {std::function<void(const double*, double*)>(id),
902 std::function<void(const double*, double*)>(id)};
903 }
904}
905
906} // namespace pops
BoxArray: the set of boxes tiling a level (disjoint, covering).
ConstArray4 const_array() const
READ handle (POD device-copyable) over this Fab. Valid as long as the Fab lives.
Definition fab2d.hpp:96
Array4 array()
WRITE handle (POD device-copyable) over this Fab. Valid as long as the Fab lives.
Definition fab2d.hpp:91
Field distributed over a level: decomposition (BoxArray) + distribution (DistributionMapping) + ncomp...
Definition multifab.hpp:33
Fab2D & fab(int li)
Local fab at index li (0 <= li < local_size()), for writing.
Definition multifab.hpp:67
int ncomp() const
Number of components.
Definition multifab.hpp:60
const DistributionMapping & dmap() const
GLOBAL distribution (owner rank per box).
Definition multifab.hpp:58
int n_grow() const
Number of ghost layers.
Definition multifab.hpp:62
const BoxArray & box_array() const
GLOBAL decomposition of the level (all boxes, all ranks).
Definition multifab.hpp:56
const Box2D & box(int li) const
VALID box of local fab li.
Definition multifab.hpp:71
int local_size() const
Number of fabs OWNED by this rank (bound on local indices).
Definition multifab.hpp:65
POPS_COLD_FN: opt out the COLD host factories from the optimizer (ADC-337, P1-B).
#define POPS_COLD_FN
Definition cold.hpp:25
HLLC capability: the model provides the CONTACT wave speed and the STAR STATE on side k.
Definition numerical_flux.hpp:142
OPTIONAL extension of a PhysicalModel: primitive variables + cons<->prim conversions.
Definition physical_model.hpp:167
Roe capability: the model provides its FULL Roe dissipation d = |A_roe(UL, UR)| (UR - UL) – Roe avera...
Definition numerical_flux.hpp:156
OPTIONAL trait: local source frequency mu [1/s] (bound dt <= cfl / max mu, without h).
Definition physical_model.hpp:137
OPTIONAL trait: direct admissible step per cell (bound dt <= min stability_dt, without cfl).
Definition physical_model.hpp:143
OPTIONAL trait: stability speed lambda* replacing max_wave_speed in the block CFL.
Definition physical_model.hpp:131
SINGLE registry of spatial scheme tags (limiters + Riemann fluxes): shared source of truth for ALL di...
Generic EMBEDDED-BOUNDARY / LEVEL-SET DOMAIN contract (ADC-327).
for_each_cell and reductions: the parallelism SEAM over the cells of a Box2D; sync_host / sync_device...
Geometry: index-space (Box2D) <-> Cartesian physical-space mapping; PolarGeometry: SIBLING for a glob...
Block grid context plus closures, shared between System (which installs them) and block_builder....
Implicit / IMEX block step as a named CONTRACT.
MultiFab: a field DISTRIBUTED over a level (equivalent of AMReX's MultiFab).
POPS_HD DiscLevelSet disc_level_set(const DiscDomain &d)
Builds the disc level set callable from a DiscDomain (sugar: disc_level_set(d)).
Definition operator.hpp:122
constexpr Real kEbKappaMin
Definition operator.hpp:109
Definition amr_hierarchy.hpp:29
int block_n_ghost(const std::string &lim)
Number of ghosts required by the spatial scheme lim (single source: Limiter::n_ghost).
Definition block_builder.hpp:759
std::function< Real(const MultiFab &)> make_stability_dt(const Model &m, const GridContext &ctx)
Closure of the block min admissible step (bound dt <= stability_dt * substeps / stride,...
Definition block_builder.hpp:852
void throw_registry_dispatch_mismatch(const char *ctx, const char *kind, const std::string &tag)
DEFENSE-IN-DEPTH guard: reached only if a VALID tag (already accepted by validate_*) is routed by NO ...
Definition dispatch_tags.hpp:138
void validate_riemann(const std::string &riem, bool polar=false, const char *ctx="System")
Validates a Riemann FLUX tag against kRiemanns.
Definition dispatch_tags.hpp:111
constexpr int limiter_n_ghost_ct(const char *lim)
COMPILE-TIME variant of limiter_n_ghost (const char* literal): -1 if unknown.
Definition dispatch_tags.hpp:88
void for_each_cell(const Box2D &b, F f)
Applies f to EACH cell (i, j) of box b (bounds inclusive), via Kokkos::parallel_for (Serial / OpenMP ...
Definition for_each.hpp:138
void max_wave_speed_hotspot_mf(const Model &model, const MultiFab &U, const MultiFab &aux, int nx, Real &w_out, int &i_out, int &j_out)
dt_hotspot diagnostic (ADC-182): the cell (GLOBAL indices) that dominates the block's transport CFL b...
Definition wave_speed.hpp:109
double Real
Definition types.hpp:30
POPS_HD Aux load_aux(const ConstArray4 &a, int i, int j)
load_aux<NComp>: reads NComp components of the auxiliary from an Array4 at (i,j).
Definition state_access.hpp:141
POPS_COLD_FN BlockClosures make_block_hll(const Model &m, const std::string &lim, const GridContext &ctx, bool imex, bool recon_prim, const std::string &method, const std::vector< int > &implicit_components, const NewtonOptions &newton_opts, NewtonReport *newton_report, Real pos_floor, bool wave_speed_cache)
Definition block_builder.hpp:612
void backward_euler_source(const Model &model, const MultiFab &aux, MultiFab &U, Real dt, const NewtonOptions &opts, const ImplicitMask< Model::n_vars > &mask={}, NewtonReport *report=nullptr)
Definition implicit_stepper.hpp:486
void validate_limiter(const std::string &lim, const char *ctx="System")
Validates a LIMITER tag against kLimiters.
Definition dispatch_tags.hpp:99
void saxpy(MultiFab &y, Real a, const MultiFab &x)
y <- y + a x over ALL components of the valid cells. Identical layouts required.
Definition mf_arith.hpp:102
Real min_stability_dt_mf(const Model &model, const MultiFab &U, const MultiFab &aux)
Global min of the declared admissible step (HasStabilityDt trait), via max(1/dt) (cf.
Definition wave_speed.hpp:222
POPS_COLD_FN BlockClosures make_block(const Model &m, const std::string &lim, const std::string &riem, const GridContext &ctx, bool imex, bool recon_prim, const std::string &method="ssprk2", const std::vector< int > &implicit_components={}, const NewtonOptions &newton_opts={}, NewtonReport *newton_report=nullptr, Real pos_floor=Real(0), bool wave_speed_cache=false)
Definition block_builder.hpp:726
Real max_source_frequency_mf(const Model &model, const MultiFab &U, const MultiFab &aux)
Global max of the source frequency (HasSourceFrequency trait). 0 if the source does not constrain.
Definition wave_speed.hpp:209
int limiter_n_ghost(const std::string &lim)
Halo width required by the limiter lim (source: kLimiters).
Definition dispatch_tags.hpp:65
void lincomb(MultiFab &z, Real a, const MultiFab &x, Real b, const MultiFab &y)
z <- a x + b y over ALL components of the valid cells. Identical layouts; aliasing safe.
Definition mf_arith.hpp:133
POPS_COLD_FN BlockClosures make_block_roe(const Model &m, const std::string &lim, const GridContext &ctx, bool imex, bool recon_prim, const std::string &method, const std::vector< int > &implicit_components, const NewtonOptions &newton_opts, NewtonReport *newton_report, Real pos_floor)
Definition block_builder.hpp:691
POPS_COLD_FN BlockClosures build_block(const Model &m, const GridContext &ctx, bool imex, bool recon_prim, const std::string &method="ssprk2", const std::vector< int > &implicit_components={}, const NewtonOptions &newton_opts={}, NewtonReport *newton_report=nullptr, Real pos_floor=Real(0), bool wave_speed_cache=false)
Closures (advance + residual) for a frozen spatial scheme (Limiter x Flux).
Definition block_builder.hpp:475
std::function< void(const MultiFab &, MultiFab &)> make_poisson_rhs(const Model &m)
Block contribution to the Poisson right-hand side: rhs += elliptic_rhs(U) (host loop).
Definition block_builder.hpp:861
POPS_COLD_FN ImplicitMask< N > make_implicit_mask(const std::vector< int > &implicit_components)
Builds the device-clean POD implicit mask of an N-variable model from a list of component indices (em...
Definition block_builder.hpp:444
std::function< Real(const MultiFab &)> make_max_speed(const Model &m, const GridContext &ctx)
Closure of the speed used by the block CFL step.
Definition block_builder.hpp:831
Real max_stability_speed_mf(const Model &model, const MultiFab &U, const MultiFab &aux)
Global max of the STABILITY speed (HasStabilitySpeed trait) – counterpart of max_wave_speed_mf.
Definition wave_speed.hpp:197
std::function< Real(const MultiFab &)> make_source_frequency(const Model &m, const GridContext &ctx)
Closure of the block max source frequency (bound dt <= cfl * substeps / (stride * mu)).
Definition block_builder.hpp:842
POPS_COLD_FN BlockClosures make_block_rusanov(const Model &m, const std::string &lim, const GridContext &ctx, bool imex, bool recon_prim, const std::string &method, const std::vector< int > &implicit_components, const NewtonOptions &newton_opts, NewtonReport *newton_report, Real pos_floor)
Dispatch of the spatial scheme (limiter x Riemann flux) -> compiled closures.
Definition block_builder.hpp:590
POPS_COLD_FN BlockClosures make_block_hllc(const Model &m, const std::string &lim, const GridContext &ctx, bool imex, bool recon_prim, const std::string &method, const std::vector< int > &implicit_components, const NewtonOptions &newton_opts, NewtonReport *newton_report, Real pos_floor)
Definition block_builder.hpp:655
void fill_ghosts(MultiFab &mf, const Box2D &domain, const BCRec &bc)
COMPLETE ghost filling: fill_boundary (interior + periodic, periodicity deduced from bc) THEN fill_ph...
Definition physical_bc.hpp:227
std::pair< std::function< void(const double *, double *)>, std::function< void(const double *, double *)> > make_cell_convert(const Model &m)
PER-CELL (one cell) cons <-> prim conversions of the MODEL, type-erased over arrays of Model::n_vars ...
Definition block_builder.hpp:875
Real max_wave_speed_mf(const Model &model, const MultiFab &U, const MultiFab &aux)
max_wave_speed_mf: global max of the wave speed over the whole MultiFab (CFL).
Definition wave_speed.hpp:66
Single-interface numerical flux policies: Rusanov, HLL, HLLC, Roe.
CUT-CELL / EMBEDDED BOUNDARY (EB) spatial operator: R = -div_eb F + S on a disc, in CONSERVATIVE fini...
PHYSICAL boundary conditions at the domain edge (BCType, BCRec, fill_physical_bc, fill_ghosts).
Interface reconstruction policies: MUSCL limiters and WENO5-Z.
Cartesian spatial operator: assembles R(U, aux) = -div F + S over the cells of a level.
WRITE POD handle (raw pointer + strides) over a Fab2D buffer, indexed by (i, j, c) IN GLOBAL INDICES ...
Definition fab2d.hpp:29
POINTWISE auxiliary fields shared with the physics: single coupling channel.
Definition state.hpp:123
Compiled block closures, frozen at add time.
Definition grid_context.hpp:61
2D integer index space, cell-centered.
Definition box2d.hpp:37
POPS_HD int nx() const
Width (direction 0). POPS_HD (called from Geometry::dx() in a device kernel).
Definition box2d.hpp:50
int hi[2]
Definition box2d.hpp:39
int lo[2]
Definition box2d.hpp:38
READ-only handle (const counterpart of Array4): same layout and same contract (POD device-copyable,...
Definition fab2d.hpp:44
Definition time_steppers.hpp:39
void take_step(RhsEval &&rhs, MultiFab &U, Real dt, Scratch &s) const
Definition time_steppers.hpp:48
Mesh + transport BC + aux shared by a block closures.
Definition grid_context.hpp:41
const MultiFab * domain_mask
0/1 domain mask (Impl::domain_mask_); NOT owned
Definition grid_context.hpp:46
Geometry geom
geometry (dx, dy, bounds)
Definition grid_context.hpp:44
BCRec bc
transport BC
Definition grid_context.hpp:43
const detail::DiscDomain * eb_domain
level-set domain descriptor (Impl::eb_domain_); NOT owned
Definition grid_context.hpp:47
Box2D dom
domain (without ghost)
Definition grid_context.hpp:42
MultiFab * aux
System aux (phi, grad phi); NOT owned.
Definition grid_context.hpp:45
Definition implicit_stepper.hpp:84
bool active
Definition implicit_stepper.hpp:85
bool flag[N]
Definition implicit_stepper.hpp:86
Options of the local Newton of the implicit source (backward-Euler).
Definition implicit_stepper.hpp:114
AGGREGATED report (whole block, all substeps of one advance) of the implicit-source Newton.
Definition implicit_stepper.hpp:165
void reset()
Definition implicit_stepper.hpp:173
SourceFreeModel<M>: adapter that cancels the source of M (explicit IMEX half-step).
Definition state_access.hpp:50
CUT-CELL / EB EXPLICIT advance: n substeps of the Stepper stepper on the EB transport residual.
Definition block_builder.hpp:372
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive, bit-identical)
Definition block_builder.hpp:377
const DiscDomain * eb_domain
Definition block_builder.hpp:375
Model m
Definition block_builder.hpp:373
void operator()(MultiFab &U, Real dt, int n) const
Definition block_builder.hpp:378
GridContext ctx
Definition block_builder.hpp:374
bool recon_prim
Definition block_builder.hpp:376
MASKED EXPLICIT advance: n substeps of the Stepper stepper on the MASKED transport residual.
Definition block_builder.hpp:356
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive, bit-identical)
Definition block_builder.hpp:361
GridContext ctx
Definition block_builder.hpp:358
void operator()(MultiFab &U, Real dt, int n) const
Definition block_builder.hpp:362
bool recon_prim
Definition block_builder.hpp:360
const MultiFab * mask
Definition block_builder.hpp:359
Model m
Definition block_builder.hpp:357
EXPLICIT advance: n substeps of the Stepper stepper (SSPRK2 by default, SSPRK3 optional) on the trans...
Definition block_builder.hpp:88
Model m
Definition block_builder.hpp:89
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive, bit-identical)
Definition block_builder.hpp:92
bool recon_prim
Definition block_builder.hpp:91
GridContext ctx
Definition block_builder.hpp:90
void operator()(MultiFab &U, Real dt, int n) const
Definition block_builder.hpp:94
std::shared_ptr< MultiFab > ws_cache
HLL wave speed cache (opt-in); nullptr -> per-face path.
Definition block_builder.hpp:93
CUT-CELL / EB IMEX advance: EB EXPLICIT half-step (source-free transport) + stiff IMPLICIT source.
Definition block_builder.hpp:416
void operator()(MultiFab &U, Real dt, int n) const
Definition block_builder.hpp:425
GridContext ctx
Definition block_builder.hpp:418
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive)
Definition block_builder.hpp:424
ImplicitMask< Model::n_vars > mask_impl
Definition block_builder.hpp:421
NewtonReport * nreport
Definition block_builder.hpp:423
NewtonOptions nopts
Definition block_builder.hpp:422
bool recon_prim
Definition block_builder.hpp:420
Model m
Definition block_builder.hpp:417
const DiscDomain * eb_domain
Definition block_builder.hpp:419
MASKED IMEX advance: MASKED EXPLICIT half-step (source-free transport) + stiff IMPLICIT source.
Definition block_builder.hpp:391
ImplicitMask< Model::n_vars > mask_impl
Definition block_builder.hpp:396
bool recon_prim
Definition block_builder.hpp:395
GridContext ctx
Definition block_builder.hpp:393
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive)
Definition block_builder.hpp:399
void operator()(MultiFab &U, Real dt, int n) const
Definition block_builder.hpp:400
NewtonOptions nopts
Definition block_builder.hpp:397
Model m
Definition block_builder.hpp:392
NewtonReport * nreport
Definition block_builder.hpp:398
const MultiFab * mask
Definition block_builder.hpp:394
IMEX-RK ARS(2,2,2) advance (Ascher, Ruuth, Spiteri 1997; "Implicit-explicit Runge-Kutta methods for t...
Definition block_builder.hpp:164
bool recon_prim
Definition block_builder.hpp:167
NewtonReport * nreport
Definition block_builder.hpp:169
NewtonOptions nopts
Definition block_builder.hpp:168
void operator()(MultiFab &U, Real dt, int n) const
Definition block_builder.hpp:171
GridContext ctx
Definition block_builder.hpp:166
Model m
Definition block_builder.hpp:165
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive)
Definition block_builder.hpp:170
IMEX advance: per substep, EXPLICIT half-step (source-free transport) + stiff IMPLICIT source.
Definition block_builder.hpp:106
GridContext ctx
Definition block_builder.hpp:108
Model m
Definition block_builder.hpp:107
bool recon_prim
Definition block_builder.hpp:109
NewtonReport * nreport
Definition block_builder.hpp:112
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive)
Definition block_builder.hpp:113
NewtonOptions nopts
Definition block_builder.hpp:111
ImplicitMask< Model::n_vars > mask
Definition block_builder.hpp:110
void operator()(MultiFab &U, Real dt, int n) const
Definition block_builder.hpp:114
CUT-CELL / EB transport residual (CutCell mode): fill_ghosts then assemble_rhs_eb on the level set of...
Definition block_builder.hpp:340
void operator()(MultiFab &U, MultiFab &R) const
Definition block_builder.hpp:346
bool recon_prim
Definition block_builder.hpp:344
const GridContext * ctx
Definition block_builder.hpp:342
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive, bit-identical)
Definition block_builder.hpp:345
Model model
Definition block_builder.hpp:341
const DiscDomain * eb_domain
Definition block_builder.hpp:343
MASKED transport residual (Staircase mode): fill_ghosts then assemble_rhs_masked on the cell-centered...
Definition block_builder.hpp:319
const MultiFab * mask
Definition block_builder.hpp:322
const GridContext * ctx
Definition block_builder.hpp:321
void operator()(MultiFab &U, MultiFab &R) const
Definition block_builder.hpp:325
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive, bit-identical)
Definition block_builder.hpp:324
bool recon_prim
Definition block_builder.hpp:323
Model model
Definition block_builder.hpp:320
Residual functor -div F + S (fill_ghosts then assemble_rhs), passed TO THE TimeStepper as RhsEval.
Definition block_builder.hpp:57
const GridContext * ctx
Definition block_builder.hpp:59
std::shared_ptr< MultiFab > ws_cache
Per-cell wave speed scratch (HLL cache, opt-in).
Definition block_builder.hpp:65
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive, bit-identical)
Definition block_builder.hpp:61
void operator()(MultiFab &U, MultiFab &R) const
Definition block_builder.hpp:66
Model model
Definition block_builder.hpp:58
bool recon_prim
Definition block_builder.hpp:60
CIRCLE / DISC level-set domain: the canonical instance of the contract and the SINGLE SOURCE of truth...
Definition domain.hpp:69
Frozen residual (fill_ghosts + assemble_rhs) installed as the block's rhs_into.
Definition block_builder.hpp:212
void operator()(const MultiFab &U, Real &w, int &i, int &j) const
Definition block_builder.hpp:215
Model m
Definition block_builder.hpp:213
GridContext ctx
Definition block_builder.hpp:214
Block max source frequency functor (HasSourceFrequency trait, bound dt <= cfl/mu without h).
Definition block_builder.hpp:795
Model m
Definition block_builder.hpp:796
GridContext ctx
Definition block_builder.hpp:797
Real operator()(const MultiFab &U) const
Definition block_builder.hpp:798
Block max wave speed functor (max_wave_speed_mf, reduction over the seam).
Definition block_builder.hpp:778
GridContext ctx
Definition block_builder.hpp:780
Model m
Definition block_builder.hpp:779
Real operator()(const MultiFab &U) const
Definition block_builder.hpp:781
Block max STABILITY speed functor (HasStabilitySpeed trait): replaces MaxSpeed in the CFL when the mo...
Definition block_builder.hpp:787
Model m
Definition block_builder.hpp:788
Real operator()(const MultiFab &U) const
Definition block_builder.hpp:790
GridContext ctx
Definition block_builder.hpp:789
Block min admissible step functor (HasStabilityDt trait; 0 = no cell constrains it).
Definition block_builder.hpp:803
Model m
Definition block_builder.hpp:804
GridContext ctx
Definition block_builder.hpp:805
Real operator()(const MultiFab &U) const
Definition block_builder.hpp:806
Foncteur HOTE de la projection ponctuelle : for_each_cell du kernel sur les cellules VALIDES de chaqu...
Definition block_builder.hpp:243
void operator()(MultiFab &U) const
Definition block_builder.hpp:246
GridContext ctx
Definition block_builder.hpp:245
Model m
Definition block_builder.hpp:244
Poisson contribution functor: rhs += elliptic_rhs(U) (pure HOST loop, no device kernel).
Definition block_builder.hpp:811
Model m
Definition block_builder.hpp:812
void operator()(const MultiFab &U, MultiFab &rhs) const
Definition block_builder.hpp:813
Kernel device de la PROJECTION PONCTUELLE post-pas (ADC-177) : U(i, j) <- m.project(U(i,...
Definition block_builder.hpp:225
Array4 u
Definition block_builder.hpp:227
Model m
Definition block_builder.hpp:226
ConstArray4 uc
Definition block_builder.hpp:228
ConstArray4 a
Definition block_builder.hpp:229
POPS_HD void operator()(int i, int j) const
Definition block_builder.hpp:230
Definition block_builder.hpp:255
GridContext ctx
Definition block_builder.hpp:257
std::shared_ptr< MultiFab > ws_cache
HLL wave speed cache (opt-in); nullptr -> per-face path.
Definition block_builder.hpp:260
bool recon_prim
Definition block_builder.hpp:258
Model m
Definition block_builder.hpp:256
Real pos_floor
Zhang-Shu positivity limiter (<= 0: inactive, bit-identical)
Definition block_builder.hpp:259
void operator()(MultiFab &U, MultiFab &R) const
Definition block_builder.hpp:261
SOURCE-ONLY residual R <- S(U, aux) installed as the block's source_only closure (ADC-430).
Definition block_builder.hpp:294
void operator()(MultiFab &U, MultiFab &R) const
Definition block_builder.hpp:297
GridContext ctx
Definition block_builder.hpp:296
Model m
Definition block_builder.hpp:295
SOURCE-ONLY residual kernel R(i,j) <- m.source(U(i,j), aux(i,j)): the EXACT source term of AssembleRh...
Definition block_builder.hpp:273
Array4 r
Definition block_builder.hpp:277
POPS_HD void operator()(int i, int j) const
Definition block_builder.hpp:278
ConstArray4 u
Definition block_builder.hpp:275
ConstArray4 a
Definition block_builder.hpp:276
Model m
Definition block_builder.hpp:274
Time integrators as first-class OBJECTS with a take_step method: TimeStepper concept,...
Base scalar types and the POPS_HD macro (host+device portability).
#define POPS_HD
Definition types.hpp:25