|
PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
|
This page documents PICurv's local testing model. The suite is intentionally split by intent so users can choose the smallest command that answers the question they actually have.
PICurv exposes four validation layers plus aggregate gates:
Canonical commands:
make test-pythonmake coverage-pythonmake coverage-cmake coveragemake audit-buildmake doctormake unitmake unit-geometrymake unit-setupmake unit-solvermake unit-particlesmake unit-iomake unit-loggingmake unit-postmake unit-gridmake unit-metricmake unit-boundariesmake unit-poisson-rhsmake unit-runtimemake unit-simulationmake unit-mpimake unit-periodicmake smokemake smoke-mpimake smoke-mpi-matrixmake smoke-stressmake smoke-periodicmake checkmake check-mpimake check-mpi-matrixmake check-fullmake check-stressmake install-git-hooksCompatibility aliases remain available:
make test -> make test-pythonmake install-check -> make doctormake ctest* -> make unit*Fast local checks:
Guidance:
python3 tests/tooling/audit_function_docs.py when changing C/Python function signatures, docstrings, or test helpers. It scans production code, generators, tests, and tooling; it rejects missing documentation and name-only descriptions such as “helper function” or “internal helper implementation.”make test when working on picurv_cli/core.py, schemas, or repository metadata.python3 tests/tooling/check_markdown_links.py when changing docs/examples.python3 tests/tooling/audit_starter_content.py when changing examples/ or config/. It checks the complete top-level template and configuration inventories, validates every declared composition, and verifies that picurv init faithfully copies each template without carrying a site-specific execution sample into the new case.make audit-build when you want a clean compilation audit with logs/build.log and logs/build.warnings.log captured under the repo logs/ directory.make doctor after provisioning PETSc on a new machine.make unit-setup when changing setup, teardown, initialization, or rank-info lifecycle code.make unit-setup when changing FieldId, FieldDescriptor, runtime field views, or the typed ghost-update interface; it directly checks catalog completeness, bindings, failure behavior, and representative layouts.make unit-simulation for the normal simulation-core debugging loop (unit-boundaries + unit-solver + unit-poisson-rhs + unit-runtime + unit-particles).make unit-<area> while changing a subsystem in isolation.make smoke after building binaries to execute tiny real solve/post/restart workflows.make smoke-mpi-matrix when you need a rank-sweep MPI runtime sanity check.make smoke-stress when you want the opt-in medium-budget runtime extension tier.make unit-periodic and make smoke-periodic when changing geometric-periodic Eulerian behavior; both are included in the standard gates.make coverage to enforce line-coverage floors for core Python scripts and C sources.make check as the pre-merge gate at the end of a development cycle.make check-mpi when multi-rank MPI behavior is in scope.make check-full for comprehensive branch/CI/release validation that must cover all MPI layers.make check-stress when you want the full default gate plus the stress tier in one pass.make install-git-hooks once per clone to make make certify-docs an automatic pre-push gate for updates to remote main. The hook validates only the checked-out commit and blocks the push on failure; GitHub Actions then repeats the lighter structural documentation checks after the push.The tracked .githooks/pre-push hook enforces a commit-scoped documentation certificate before a local Git client updates refs/heads/main. Enable it in each clone with:
The hook runs make certify-docs, which requires a clean worktree and includes the PETSc/MPI runtime tier, whenever runtime-relevant files changed. For Markdown, documentation-site, hook, and workflow-only changes it instead runs make certify-docs-fast only if a full certificate for an ancestor of the target commit exists in local logs/ and is no more than three days old. Missing or stale certificates always cause a full run. Override the interval for a single push with PICURV_FULL_CERT_MAX_AGE_DAYS=<days>.
The hook deliberately rejects a push that maps some other local commit directly to main, because it can only certify the exact checked-out HEAD. This is a local safeguard: Git permits bypassing hooks with git push --no-verify, so the post-push GitHub documentation gates remain a separate redundancy layer.
make certify-docs includes Markdown-link, function-documentation, user-facing-reporting, starter-template/configuration, option-ingress, example/configuration regression, and zero-warning Doxygen gates before the PETSc/MPI make check-full tier. Therefore, with the tracked hook enabled, a normal push to main cannot publish the checked-out commit until all applicable local gates pass. The starter-content gate specifically rejects an unregistered example directory/YAML, an unregistered config/ asset, a broken declared composition, or a template that picurv init does not copy faithfully.
Purpose:
picurv_cli/core.pyThis suite is implemented with pytest and does not require PETSc.
Current coverage includes:
For newly added or modified C test helpers, keep Doxygen blocks concise but descriptive: the @brief should state what the test or helper verifies rather than using a placeholder label.
Run locally:
CI note:
.github/workflows/quality.yml runs python tests/tooling/audit_function_docs.py explicitly before pytest -q, then runs markdown link checks on pull requests and pushes to main.Current Python files and primary responsibilities:
tests/test_cli_smoke.pysubmit, cancel, and sweepsummarize configuration/health JSON/text output, time-history discovery/plot orchestration, standalone plot.gen, and failure-path checkstests/test_case_maintenance.pybuild, sync-binaries, sync-config, status-source, and pull-sourceoverwrite, prune)tests/test_config_regressions.pytests/test_repo_consistency.pypicurv validatetests/tooling/audit_function_docs.py)tests/tooling/audit_starter_content.py)These files are intentionally role-specific to keep failures actionable.
Purpose:
PETSC_DIR is present and usableThe doctor target builds and runs a small C smoke binary under tests/c/test_install_check.c.
It validates:
environment-visible for PETSC_DIR visibilitybasic-petsc-objects for PetscInitialize, DMDA, Vec, DMSwarm, and PetscFinalizeThis target answers: "Is this machine set up correctly for PICurv development?"
Run locally:
Purpose:
Current suites:
make unit-geometrymake unit-setupmake unit-solvermake unit-particlesmake unit-iomake unit-postmake unit-gridmake unit-metricmake unit-boundariesmake unit-poisson-rhsmake unit-runtimemake unit-mpimake unit (all of the above)Suite focus areas:
These tests use real PETSc objects and run single-rank by default. unit-mpi is the dedicated multi-rank suite (default TEST_MPI_NPROCS=2).
Current C test files and their main purpose:
tests/c/test_install_check.c: PETSc installation viability (doctor: environment-visible, basic-petsc-objects)tests/c/test_geometry.c: interpolation/signed-distance helperstests/c/test_setup_lifecycle.c: setup/cleanup lifecycle, RNG, and initialized particle-settlement checkstests/c/test_solver_kernels.c: analytical geometry/particle dispatch, LES filter/eddy-viscosity, and FlowSolver guardrailstests/c/test_particle_kernels.c: walking-search helper kernelstests/c/test_io.c: I/O path, parser, scaling-ingestion, and startup-banner checkstests/c/test_logging.c: logging-contract checks (log level, allow-list, continuity/min-max/interpolation diagnostics, string conversion, profiling, snapshot cadence)tests/c/test_postprocessing.c: post kernel checks (specific KE, displacement, nodal averaging, normalization, dimensionalization, Q-criterion)tests/c/test_vtk_io.c: VTK prep/writer checks (Eulerian + particle data shaping)tests/c/test_postprocessor.c: postprocessor pipeline/orchestration checkstests/c/test_post_compute_mpi.c: analytic decomposition-independent postprocessor compute checkstests/c/test_post_eulerian_vtk_mpi.c: serial/MPI Eulerian VTK equivalence checkstests/c/test_post_particle_vtk_mpi.c: serial/MPI particle VTK equivalence checkstests/c/test_statistics.c: statistics-kernel checks (MSD CSV behavior)search_metrics.csv instrumentation complements Particle_Metrics.log for particle-enabled runs and is covered through logging/runtime test surfaces plus the examples/search_robustness/ bundletests/c/test_grid.c: bounding-box exchange checkstests/c/test_metric.c: metric and face-geometry checkstests/c/test_boundaries.c: boundary factory plus direct handler-behavior checkstests/c/test_poisson_rhs.c: pressure/rhs/projection/diffusivity helper checkstests/c/test_runtime_kernels.c: runtime orchestration, interpolation/scatter, particle lifecycle, wall, and walltime-guard checkstests/c/test_mpi_kernels.c: dedicated multi-rank consistency and restart-migration checkstests/c/test_support.{c,h}: shared PETSc fixture and assertion layerPurpose:
The current smoke runner verifies:
bin/simulator launches and responds to -helpbin/postprocessor launches and responds to -helpbin/picurv init creates a case directory with origin metadata (no binary copies)flat_channel, bent_channel, and brownian_motionpicurv run --dry-run --format json emits a valid solve/post execution plan--restart-from into the expected restart source directoryload and init)examples/search_robustness/ family provides a dedicated end-to-end runtime characterization path for search and migration observabilitymake smoke-mpi)load/init) runs (make smoke-mpi)make smoke-mpi-matrix)make smoke-stress)make smoke-periodic, included in check)These checks are intentionally tiny but execute real solver/postprocessor runtime paths. For the -help smoke checks, banner presence is authoritative: the local PETSc debug build may exit with code 62 (PETSC_ERR_ARG_WRONG) after printing help, and that still counts as a pass.
Run locally:
Environment controls used by the smoke layer:
KEEP_SMOKE_TMP=1:SMOKE_MPI_NPROCS=<n>:make smoke-mpi.SMOKE_MPI_MATRIX_NPROCS="<n1> <n2> ...":make smoke-mpi-matrix.Smoke orchestration lives in tests/smoke/run_smoke.sh; runtime profile mutation helpers there are part of the tested contract.
make check is the top-level local validation sweep.
It runs, in order:
make test-pythonmake doctormake unitmake smokeUse it when you want maximum local confidence before ending a development cycle.
make check-mpi extends this sweep by running make smoke-mpi and make unit-mpi afterward.
make check-mpi-matrix extends this sweep by running make smoke-mpi-matrix and make unit-mpi.
make check-full is the comprehensive MPI-inclusive gate. It runs make check, then make unit-mpi, make smoke-mpi, and make smoke-mpi-matrix.
make check-stress extends make check-full by running make smoke-stress afterward. make smoke-periodic runs as part of make check; make unit-periodic runs as part of make unit.
Use check-full for release candidates or CI workflows where both focused multi-rank tests and rank-matrix runtime checks are required in a single pass.
Coverage gates are script-backed and checked in-repo:
make coverage-python:tests/tooling/python_coverage_gate.pytrace and currently focuses on core runtime scripts (default: picurv_cli/core.py)make coverage-c:unit + smoke, then executes tests/tooling/c_coverage_gate.pysrc/*.cCoverage artifacts:
coverage/python/summary.txtcoverage/c/summary.txtThis dated snapshot records non-periodic C sources that still look thinly exercised after the 2026-07-31 local audit. Treat these numbers as test-readiness guidance for future work, not as evidence of confirmed product defects.
src/les.c: 29.46%. Add a direct dynamic-Smagorinsky fixture that executes the filtered-stress procedure, rather than only the constant-model and eddy-viscosity paths.src/poisson.c: 47.61%. Add multigrid-cycle, periodic/IBM, solid-aware restriction/interpolation, and driven-flux correction cases.src/momentum_newton_krylov.c: 62.50%. The focused residual/constraint/Jacobian/rollback suite is strong; extend it across less-common solver-option and nonlinear-error branches.src/runloop.c: 66.46%. Add controlled live-run coverage for signal receipt and automatic walltime-guard shutdown/restart output.src/postprocessor.c: 69.42%. Add malformed/empty/unknown pipeline-stage and optional-field combination coverage.Next test work priorities from this snapshot:
Common issues:
PETSC_DIR is unset:make doctor, make unit*, make smoke*, and make check* will fail.PETSC_ARCH points to the wrong build:mpicc or MPI runtime wrappers are missing:/tmp/picurv-test-* for preserved intermediate artifacts.pytest is unavailable:gcov is unavailable:make coverage-c cannot produce C line-coverage reports.When adding new tests:
test-python, doctor, unit-*, or smoke)tests/c/test_support.* for PETSc-backed fixtures; it now provides both a fast minimal fixture and a richer tiny-runtime fixture while mirroring the production da/fda/swarm contract instead of a same-size synthetic DM/tmpFor detailed C test maintenance guidance, see C Test Suite Developer Guide.
The smoke suite uses these named runtime sequences:
S0: template matrix init/validate/dry-run across flat_channel, bent_channel, and brownian_motionS1: tiny flat-channel solve+post runS1b: tiny bent-channel solve+post runS2: tiny flat-channel solve+post with particles enabled (default Trilinear interpolation)S2b: tiny flat-channel particle solve+post with CornerAveraged interpolation (legacy path regression)S3: tiny restart runs from S2 with particle_restart_mode=load and particle_restart_mode=initS4: tiny Brownian analytical solve+post with particle outputs and MSD statisticsS5: multi-rank tiny solve+post runs for flat and bent channels, plus flat particle base/restart (load and init) branchesS6: restart-equivalence run for flat channel (continuous vs split restart continuity metric agreement)S7: periodic constant-flux validate + dry-run contract coverage in the opt-in stress tierS8: geometric-periodic real runtime harness (make smoke-periodic, gating)Runtime file coverage map (unit targets + runtime sequences):
src/AnalyticalSolutions.c: unit-solver, S4src/BC_Handlers.c: unit-boundaries, unit-periodic, unit-runtime, S1, S1b, S2, S3, S5, S6, S7, S8src/BodyForces.c: unit-solver, unit-poisson-rhs, S1, S2src/Boundaries.c: unit-boundaries, unit-periodic, S1, S1b, S2, S3, S5, S6, S7, S8src/Filter.c: unit-solversrc/field_catalog.c, src/particle_field_catalog.c: unit-setup, unit-periodic, unit-runtime, unit-solver, unit-logging, S1, S1b, S2, S3, S4, S5, S6, S8src/Metric.c: unit-metric, unit-grid, S1, S1b, S2, S5, S6src/ParticleMotion.c: unit-runtime, S2, S3, S4, S5src/ParticlePhysics.c: unit-runtime, S2, S3, S4, S5src/ParticleSwarm.c: unit-runtime, S2, S3, S4, S5src/grid.c: unit-grid, unit-setup, S1, S1b, S2, S4, S5, S6, S8src/initialcondition.c: unit-runtime, S1, S1b, S2, S4, S5, S6src/interpolation.c: unit-geometry, unit-runtime, unit-particles, S2, S2b, S3, S4, S5src/io.c: unit-io, S1, S1b, S2, S3, S4, S5, S6src/les.c: unit-solver, unit-runtimesrc/logging.c: unit-logging, S1, S1b, S2, S3, S4, S5, S6, S8src/momentumsolvers.c: S1, S1b, S2, S5, S6src/particle_statistics.c: unit-post, S4src/poisson.c: unit-poisson-rhs, S1, S1b, S2, S5, S6src/postprocessing_kernels.c: unit-post, S1, S1b, S2, S4, S5, S6src/postprocessor.c: unit-post, S1, S1b, S2, S3, S4, S5, S6src/rhs.c: unit-poisson-rhs, S1, S1b, S2, S5, S6src/runloop.c: unit-runtime, S1, S1b, S2, S3, S4, S5, S6src/setup.c: unit-setup, unit-runtime, S1, S1b, S2, S3, S4, S5, S6, S8src/simulator.c: S1, S1b, S2, S3, S4, S5, S6src/solvers.c: unit-solver, S1, S1b, S2, S5, S6src/vtk_io.c: S1, S1b, S2, S3, S4, S5, S6src/walkingsearch.c: unit-geometry, unit-particles, S2, S3, S4src/wallfunction.c: unit-runtimeP0 (implemented):
make coverage-python, make coverage-c, make coverageS6)make smoke-mpi-matrix)P1 (implemented):
unit-runtimeunit-boundariesP1 (next):
LocateParticleOrFindMigrationTarget:LOST and MIGRATING_OUT outcomesGuessParticleOwnerWithBBox heuristicMomentumSolver_Explicit_RungeKutta4MomentumSolver_DualTime_Picard_JamesonRKPoissonSolver_MG and periodic/IBM stencil behavior checks beyond the current helper-level unit-poisson-rhs surfaceSMOKE_MPI_MATRIX_NPROCS="2 3 4 6") in CI/nightly profiles2026-07-31 audit: dynamic LES, Poisson multigrid/stencils, live walltime/signal shutdown, postprocessor pipeline errors, and remaining Newton–Krylov option/error paths (see section 8.1 for measured coverage and scope).P2 (deeper hardening):
This page describes Testing and Validation Guide within the PICurv workflow. For CFD users, the most reliable reading strategy is to map the page content to a concrete run decision: what is configured, what runtime stage it influences, and which diagnostics should confirm expected behavior.
Treat this page as both a conceptual reference and a runbook. If you are debugging, pair the method/procedure described here with monitor output, generated runtime artifacts under runs/<run_id>/config, and the associated solver/post logs so numerical intent and implementation behavior stay aligned.