Builder API

The runners never construct solver components directly. They split the parameter dictionary into namespaces with extract_namespace and call one build_* function per component. Every builder dispatches on a Val of a configuration value, so new components are added by defining a method, without changing HyperCloud.

The builders come from two packages:

Build order and context

The builders share a context::Dict{Symbol, Any}. Each one reads what earlier builders stored and adds its own result. run_direct_simulation runs them in this order:

StepBuilderReads from contextStores
0runner—:T, :Storage (storage_for), :MemoryLimit (only with set_memory_limit!)
1build_equation:Trunner stores :Equation, :D, :M, :ExplicitSources, :ImplicitSources
2build_domain:T, :Drunner stores :Domain, :WeightConf
3build_particle_grid:T, :D, :M, :Domain, :WeightConf, :Storage:max_dx, :Grid
3abuild_weights, build_mover, build_volume_estimator (called by step 3):T, :max_dx, :Domain:interp_range
3bbuild_adaptivity:T—
4build_flux, build_limiter, build_mood:T, :Grid (MOOD)runner stores :Flux, :Limiter, :MOOD
5build_scheme:T, :D, :M, :Flux, :Limiter, :Storagerunner stores :Scheme
6build_tableau, build_timesteppereverything aboverunner stores :Tableau; :Memory (with a memory limit)
7build_ic:T, :D, :M (macroscopic)—

The particle grid is built on a CPU backend and then moved to the device when :Storage is a device array type, and the time stepper's memory reservation is checked against a fingerprint of the grid (see Running on a GPU).

run_kinetic_simulation builds the initial condition right after step 1, while :M still holds the macroscopic size. Then build_kinetic_system overwrites :Equation and :M with the kinetic system and puts the relaxation term into :ImplicitSources, and the remaining steps run on the kinetic variables.

:T is the floating-point type (params[:T], default Float64). The runners set :ExplicitSources and :ImplicitSources to () unless a source term is added.

Extending the builders

BuilderPackageDispatches onExtend with
build_equationHyperCloud:PDE_nameHyperCloud.build_equation(::Val{:x}, conf, ctx)
build_icHyperCloud:IC_nameHyperCloud.build_ic(::Val{:x}, conf, ctx)
build_domainHyperCloudCore:Grid_domainHyperCloudCore.build_domain(::Val{:x}, conf, ctx)
build_weightsHyperCloudCore:Weight_nameHyperCloudCore.build_weights(::Val{:x}, conf, ctx)
build_moverHyperCloudCore:Grid_moverHyperCloudCore.build_mover(::Val{:x}, conf, ctx)
build_volume_estimatorHyperCloudCore:Grid_volumesHyperCloudCore.build_volume_estimator(::Val{:x}, conf, ctx)
build_fluxHyperCloudCore:Flux_nameHyperCloudCore.build_flux(::Val{:x}, conf, ctx)
build_limiterHyperCloudCore:Limiter_nameHyperCloudCore.build_limiter(::Val{:x}, conf, ctx)
build_mood_criterionHyperCloudCore:MOOD_criterionHyperCloudCore.build_mood_criterion(::Val{:x}, conf, ctx)
build_mood_strategyHyperCloudCore:MOOD_strategyHyperCloudCore.build_mood_strategy(::Val{:x}, conf, ctx)
build_schemeHyperCloudCore:Scheme_nameHyperCloudCore.build_scheme(::Val{:x}, conf, ctx)
build_tableauHyperCloudCore:Time_stepperHyperCloudCore.build_tableau(::Val{:x}, conf, ctx)

Because HyperCloud re-exports HyperCloudCore, HyperCloud.build_scheme and HyperCloudCore.build_scheme are the same function; qualifying with the owning package makes it clear where the method goes. Unknown names raise an error naming the missing method. A complete example for initial conditions is in Initial Conditions; a new equation is described in PDE Architecture.

A custom spatial scheme follows the same pattern. The returned object must be a DivergenceInterpolator that implements HyperCloudCore's scheme contract:

function HyperCloudCore.build_scheme(::Val{:my_scheme}, conf::Dict, context::Dict)
    T = context[:T]::DataType
    D = context[:D]::Int
    M = context[:M]::Int
    return MyScheme(T, D, M, conf[:my_param]; flux = context[:Flux])
end

:Scheme_name => :my_scheme, :Scheme_my_param => 3 then selects it.

Custom boundary conditions

:Grid_bc maps boundary tags to boundary conditions (parse_bc). Besides instances and the names :outflow and :fixed_dirichlet, it accepts the name of any zero-argument constructor defined in HyperCloudCore or in Main:

struct MyWall <: AbstractBoundaryCondition end   # plus the functor HyperCloudCore requires
params[:Grid_bc] = Dict(1 => :MyWall, 2 => :outflow)

The functor a boundary condition implements is described in HyperCloudCore's Boundary Conditions.

API

HyperCloud.build_equation — Function
build_equation(pde_conf::Dict, context::Dict)

Constructs the physical equation system based on the provided configuration dictionary. Strictly requires a :name Symbol (e.g., :linear, :burgers, :euler) in the configuration to dynamically dispatch to the correct specific constructor using Val.

source
build_equation(eq_name::Val, pde_conf::Dict, context::Dict)

Constructs the physical equation system based on the provided configuration dictionary. Strictly requires a :name Symbol (e.g., :linear, :burgers, :euler) in the configuration to dynamically dispatch to the correct specific constructor using Val.

source
HyperCloud.build_ic — Function
build_ic(ic_conf::Dict, context::Dict)

Reads the :IC namespace and dispatches to the matching builder via Val(ic_conf[:name]). Extend it by defining build_ic(::Val{:my_ic}, conf::Dict, ctx::Dict).

source
HyperCloud.build_kinetic_system — Function
build_kinetic_system(kin_conf::Dict, context::Dict)

Constructs the kinetic equation and relaxation source term for kinetic simulations. Requires a :velocities key in the kinetic configuration dictionary. Extracts the relaxation parameter (epsilon), edge indices (indices), and interior_factor to build a Kin2Macro mapping, a LinearAdvection kinetic equation, and a RelaxationSourceTerm. Returns the tuple (eq_kin, source_term).

source