PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Modular Selector Extension Guide

This page is the contributor checklist for adding new selector-driven options without drifting the YAML -> launcher -> C runtime contract.

1. Standard Checklist For Any Selector

For every new selector value:

  1. define the canonical user-facing value in YAML docs/templates,
  2. add or update Python normalization/validation in picurv_cli/core.py,
  3. emit the correct generated control/post artifact mapping,
  4. add any C enum/storage and parser wiring,
  5. add the runtime dispatch/consumer branch,
  6. add tests,
  7. declare the value in the capability registry, and
  8. write its Tier-2 capability entry.

Use the canonical value only. Do not add placeholder enum values or compatibility aliases for unimplemented options.

1.1 The Documentation Obligation Is Enforced

Steps 7 and 8 are not advisory. Coverage is enforced for every registered family, so make audit-capability fails until they are done, and the full source chain - validator, C parser, enum, runtime dispatch - must agree. If the value belongs to a family nothing yet covers, make audit-family-census will have already refused the new public surface.

Concretely, adding a selector value means:

# 1. Declare it: add an entry to value_metadata in
# tests/tooling/capability_families.json with its status, canonical/alias
# relationship, and evidence sources.
# 2. Scaffold the entry with every required part already present:
python3 tests/tooling/scaffold_documentation.py capability \
--family <family.id> --value '<Your Value>'
# 3. Paste it into the family page, fill in the TODOs, then:
make docs-inventory # regenerate the inventory and its tables
make audit-capability # parity, coverage, evidence, lifecycle

The audit checks four things a reviewer would otherwise have to check by hand:

  • Parity - the value is accepted end to end, and nothing accepts a value the validator does not expose.
  • Coverage - an entry exists, anchored outside code blocks, with all eight contract parts (three for a deprecated alias).
  • Evidence - each declared source exists and is cited in the entry's Evidence part, so the registry and the prose cannot drift.
  • Lifecycle - a supported value has evidence, an experimental or known-defective value states limitations, a deprecated value gives migration.

If the value is a synonym rather than a new capability, declare spelling_of instead and it inherits the canonical value's status without needing its own entry. If it is a retired name, declare alias_of and scaffold the three-part stub with scaffold_documentation.py alias.

Full contract: Documentation Extension Framework.

2. Momentum Solver Selector

3. Boundary Condition Type Or Handler

4. Particle Initialization Mode

5. Interpolation Method

6. Field Initialization Mode

  • Schema home: case.yml -> properties.initial_conditions.mode
  • Canonical values:
    • generated with generator: zero|constant|streamwise_constant|poiseuille|ic_gen|spectral_random_velocity|resampled_velocity|channel_spectral_velocity|duct_spectral_velocity
    • file with field: Ucat|Ucont
  • Python hooks:
    • resolve_initial_condition_config()
    • stage_initial_condition_file()
    • run_initial_condition_generator()
    • normalize_flow_direction_token()
    • resolve_ic_cli_params()
  • Generated mapping:
    • built-in generator -> matching -finit and parameter flags
    • file or ic_gen -> -finit 4 -ic_field ... -ic_dir ...
  • C storage/parser:
    • initialConditionMode, initialConditionField, initialConditionDirectory, icVelocityPhysical, and flowDirection in SimCtx
  • Runtime:
  • Tests/docs to update:

7. Analytical Type

8. Verification Source Overrides

  • Schema home: solver.yml -> verification.sources.*
  • Design intent:
    • reserved for verification-only source injections when no ordinary end-to-end path is sufficient
    • keep runtime call sites thin and centralize override implementations in verification_sources.*
  • Current support:
    • verification.sources.diffusivity
    • verification.sources.scalar
    • diffusivity profile LINEAR_X
    • scalar profiles CONSTANT, LINEAR_X, SIN_PRODUCT
  • Python hooks:
  • Generated mapping:
    • verification.sources.diffusivity.mode -> -verification_diffusivity_mode
    • verification.sources.diffusivity.profile -> -verification_diffusivity_profile
    • verification.sources.diffusivity.gamma0 -> -verification_diffusivity_gamma0
    • verification.sources.diffusivity.slope_x -> -verification_diffusivity_slope_x
    • verification.sources.scalar.mode -> -verification_scalar_mode
    • verification.sources.scalar.profile -> -verification_scalar_profile
    • verification.sources.scalar.value -> -verification_scalar_value
    • verification.sources.scalar.phi0 -> -verification_scalar_phi0
    • verification.sources.scalar.slope_x -> -verification_scalar_slope_x
    • verification.sources.scalar.amplitude -> -verification_scalar_amplitude
    • verification.sources.scalar.kx/ky/kz -> -verification_scalar_kx/-verification_scalar_ky/-verification_scalar_kz
  • C storage/parser:
  • Runtime:
  • Design boundary:
    • verification sources exist only for otherwise-unreachable verification scenarios
    • analytical truth definitions belong in AnalyticalSolutions, not in model-evolution code such as ParticlePhysics
  • Tests/docs to update:

9. Grid Selector / Generator Selector

10. Profiling Selector

  • Schema home: monitor.yml -> profiling.timestep_output.mode
  • Canonical values:
    • off
    • selected
    • all
  • Python hooks:
  • Generated mapping:
    • timestep_output.mode -> -profiling_timestep_mode
    • timestep_output.file -> -profiling_timestep_file
    • final_summary.enabled -> -profiling_final_summary
    • selected function list -> profile.run + -profile_config_file
  • C storage/parser:
  • Runtime:
  • Tests/docs to update:

11. Postprocessing / Statistics Tasks

12. Turbulence Closure Selectors

One LES closure is active per run, chosen from an enum and dispatched by a branch, the same shape the momentum solvers use. There is no registry object: a closure is a function, not an instance with a lifecycle, which is what separates this from the boundary-condition handlers in section 3.

  • Schema home:
    • case.yml -> models.physics.turbulence.les
  • Canonical values:
    • model: constant_smagorinsky, dynamic_smagorinsky, vreman, wale
    • filter_width: cube_root_volume, geometric_mean, max_edge, scotti
    • test_filter.kernel: volume_weighted_box, simpson_ik
    • averaging.mode: local, homogeneous, global
    • clipping.mode: clamp, clip_negative, none
  • Python hooks in picurv_cli/core.py:
    • normalize_les_model()
    • normalize_les_filter_width()
    • normalize_les_test_filter()
    • normalize_les_averaging_mode()
    • normalize_les_clip_mode()
    • normalize_les_averaging_directions()
    • validate_les_configuration() for cross-key rules
    • append_les_parameter_flags() for emission
  • Generated mapping:
  • C enum/storage in include/variables.h:
    • LESModelType, LESFilterWidthModel, LESTestFilterKernel, LESAveragingMode, LESClipMode, and the LESConfig block on SimCtx
  • C parser:
  • Runtime dispatch:
  • Implementation:

12.1 Reusable Kernels

A new closure should consume the existing kernels rather than restate them. They are declared in include/les.h and are the reason a second eddy-viscosity model is one function: StrainRateFromGradients, ComputeCellFilterWidth, SymTensorDeviator, SymTensorContract, SymTensorTimesVector, ClipModelCoefficient, and EddyViscosityFromCoefficient. The Germano-specific pieces, LeonardStress and GermanoModelTensor, belong to the dynamic procedure alone.

Coefficient averaging is not an LES function. It is PicurvSpatialRatioAverage in include/statistics_target.h, the module that already owns which points a spatial operation may touch. The closure resolves a SpatialTargetPlan for its loops through the same entry point the statistics pipeline uses, so both agree on which indices are physical and neither carries its own copy of the fluid threshold.

13. Related Pages