|
PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
|
converged = residual_abs_pass OR (residual_rel_pass AND update_pass). The absolute residual test is sufficient on its own; the relative test keeps the relative_tol update guard. Requiring the guard alongside the absolute test made the latter unable to fire: on the laminar channel at step 793, |R| fell below the floor at pseudo-iteration 8 and the step still ran to 20.residual_absolute_tol is now dimensionless, tested as |R| <= tol * resid_ref with resid_ref = a0*|Ucont|_inf/dt. A raw bound on |R| is not portable: across the shipped cases step-1 |R| spans 1.2e-2 (plane channels) to 2.0 (driven duct), a ~165x spread that normalising collapses to ~4x. Set to 1.0e-8 in all shipped configs.absolute_tol / -mom_atol no longer participates while a residual tolerance is set. |dU| ~ dtau*|R|, so bounding it absolutely is a disguised residual bound |R| <= absolute_tol/dtau that tightens as the controller grows dtau; it was in practice the criterion that gated convergence. It is retained, annotated, for the legacy update-only branch only. It is now deprecated: removed from all shipped configs (commented, with a note, in the master template), still accepted, and the CLI warns when it is set while it cannot take effect.-mom_resid_atol 1e-8, -mom_resid_rtol 1e-3, previously both 0.0). The update-only branch it replaces can converge falsely, since |dU| also goes small when dtau collapses. Setting both non-positive remains an explicit opt-out.U_b 0.999446, u_max 1.497795, u_tau 0.1729983 and profile error 1.470e-03 before and after; fields agree to 5.06e-13 at step 6000 and the gap between the two runs shrinks from 2.2e-07 (step 500) to 3.4e-13, so error does not accumulate. Worst |div u| unchanged (7.457e-11 vs 7.443e-11). Total pseudo-iterations fell 28,247 -> 16,390 (-42%), concentrated in the settled regime (3% over steps 1-500, ~50% thereafter); a flow that never settles should expect the smaller figure.monitor.yml -> solution_monitoring.convergence, preserving its existing flags, every-completed-step behavior, and log format while adding an effective enable switch;control as the single C-ingress artifact and removed the premature observation sidecar, schema/version envelope, exposed cadence, and unsupported-window startup gate;SimCtx::averaging, legacy sum vectors, su0/su1/su2/sp read/write hooks, the dead averaging call, old templates, and the reserved averaged-field postprocessor passthrough; andinclude/statistics_accumulator.h and src/statistics_accumulator.c allocate one accumulator set per window from the vector factory, duplicating every vector from one the factory already built, and apply an accepted state pointwise through the centered kernels. A three-vector's second moment is the six symmetric co-moments between component pairs in fixed (xx, xy, xz, yy, yz, zz) order, not three per-component variances. Per-point occupancy is tracked separately from the moments because the fluid mask can move. Storage is released through the same teardown that releases the block's other vectors, and the runloop driver applies accepted weights to every block. Covered by a new unit-statistics-accumulator suite, including an integration case that drives the runloop entry point and asserts only scheduled states reach the fields.include/statistics_window.h and src/statistics_window.c decide whether a completed state is accepted and what weight it carries, applying right-rectangle weighting, final-interval clipping, and the rule that a zero-length interval is not a sample. Step and physical-time cadences are both supported, with time targets on an absolute grid so the schedule cannot drift, and a step overshooting several targets accepted exactly once. Duplicate offers of the same completed step are rejected. The runloop calls the window update immediately before physical-solution monitoring, after the Lagrangian block and before history rotation, and an optional console snapshot mirroring the particle console reports window-level progress through the logging sink. Covered by a new unit-statistics-window suite whose central case asserts that sample and physical-time weighting agree on a constant-timestep run.KSKE workspace was allocated and freed on every Poisson solve from inside the solver, with a defensive second free in teardown; it is now allocated once by CreateAndInitializeAllVectors and freed once in teardown, which is safe because FullyBlocked guards every read with its own flag array and so carries no state between solves. The corner-staging workspace was created lazily inside the interpolation routine and rebuilt whenever the block size changed; it is now two explicitly typed pairs, CellScalarAtCorner and CellVectorAtCorner, created by the same factory.offsetof requirement, so the hand-rolled global-to-local scatter in the interpolation path is replaced by UpdateLocalGhosts. Corner anatomy logging takes the field identity from its caller rather than inferring the degree of freedom from a cached vector's block size.include/statistics_target.h and src/statistics_target.c resolve, for one field on one block, an iteration domain that excludes PETSc halo storage and solver-layout boundary, dummy, and duplicate-periodic indices, which are distinct categories. Layout classification comes from the typed field catalog: cell-like dimensions span the shifted interior, node-like dimensions carry one more entry, and each face family is node-like only in its own direction. Periodic directions drop the wrapped duplicate plane, which leaves cell-like spans unchanged because their duplicates already sat outside. Component- staggered fields are rejected, since their components live on different face families and cannot share one pointwise domain. SpatialTargetPlan exists with only the pointwise identity mapping so later spatial bins extend rather than retrofit it. Covered by a new unit-statistics-target suite across cell, node, and I/J/K-face layouts in nonperiodic, mixed, and fully periodic domains, plus a multi-rank case asserting the resolved domain is decomposition independent.include/statistics_moments.h and src/statistics_moments.c implement the stable weighted Welford update, the compatible co-moment update, and the weighted parallel-merge formula, plus weighted variance, covariance, and Kish effective sample size. The module is pure: no configuration, no PETSc vectors, and no window or scheduling knowledge. Non-positive sample weights are rejected rather than silently corrupting an accumulator. Covered by a new unit-statistics suite asserting bitwise-zero variance for constant signals, known scalar and two-sample results under equal and unequal weights, all six symmetric velocity components of a three-sample self-product, exact agreement between a self-paired co-moment and the scalar second moment, high-mean/low-fluctuation precision where a raw sum-of-squares would cancel, and merge-equals-sequential including empty-partition no-ops.include_initial control. Also fixes the user contract, cross-field covariance spelling, window identity hash inputs, the indexed control-option scheme with its ingress-audit extension, the statistics/ checkpoint namespace, the postprocessing contract, and the seven implementation stages. Amended page 58 accordingly.Ucont_rm1 preserves the order of the restart, not bitwise identity.FieldId/FieldDescriptor catalog with canonical names, active aliases, DM family, degree of freedom, shifted/staggered layout, synchronization class, availability, capabilities, and existing UserCtx vector bindings;FieldView resolution without changing PETSc vector allocation or teardown;ParticleFieldId catalog for DMSwarm component count, PETSc data type, registration ownership, initialization, model-update, and Eulerian-scatter metadata;run_control.start_step: 0 instead of treating a fresh start as an in-place continuation and appending misleading step-zero separators to existing logs.dtau = pseudo_cfl × dt to dtau = pseudo_cfl / lambda_max, where lambda_max is the global maximum convective spectral radius computed once per physical timestep. This makes pseudo_cfl.* true dimensionless Courant numbers, independent of dt, grid size, and flow speed.pseudo_cfl.initial: 0.5 and pseudo_cfl.maximum: 2.0 (stable 4-stage Jameson range ~0–2.83); existing configs with 0.1/1.0 still run but now produce physically smaller, safer dtau values.lambda_max >= COEF_TIME_ACCURACY/dt so zero-flow startup yields a finite dtau.mom_last_lambda_max to the simulation context.Pseudo-cfl/ cfl_after to dtau/cfl_eff and dtau_after/cfl_eff_after; picurv summarize parsing, JSON payload, console output, and plot series were updated to match.generated and file modes.Ucat and Ucont startup through the existing field reader.ic_gen run/precompute orchestration, defaulting to generators/ic.gen with an optional compatible script override.generators/ic.gen expression engine for grid-aware Ucat and staggered Ucont PETSc vectors.max_iterations, and guaranteed nonfatal exits retain the last accepted finite state.residual_absolute_tol and residual_relative_tol; configurations without enabled residual tolerances retain legacy update-only convergence semantics.step_tol while retaining compatibility ingestion.logs/search_metrics.csv with timestep-level search, traversal, tie-break, boundary-clamp, bbox-guess, pass-depth, per-step loss, run-local cumulative loss, V2 population/outcome counters, and derived search_failure_fraction, search_work_index, and re_search_fraction signals.LOG_SEARCH_METRICS for compact DEBUG-gated console summaries when explicitly allow-listed.examples/search_robustness/ example family with Brownian Cartesian/curvilinear baselines plus deterministic Cartesian/curvilinear UNIFORM_FLOW migration-stress variants, a study starter, and a dedicated metrics-reference docs page.LOG_PROFILE log level from the C logging enum and all code paths.profiling.timestep_output (off, selected, all) and writes timestep rows to a dedicated profiling log file.profiling.final_summary.enabled now controls whether the end-of-run ProfilingSummary_*.log file is written.LOG_LEVEL=PROFILE is no longer a supported runtime setting.profiling.critical_functions compatibility shorthand; monitors must now use profiling.timestep_output.pic.flow to picurv.picsolver to simulator.init now creates config-only case directories; binaries are resolved from bin/ via PATH.init --pin-binaries copies simulator/postprocessor into the case for version-pinning (protects running jobs from concurrent rebuilds).bin/picurv is now a launcher for the picurv_cli/picurv source-tree entrypoint.sync-binaries pins specific binary versions into a case directory (optional, equivalent to --pin-binaries after init).--copy-binaries init flag.programmatic_c.im/jm/km are now treated as cell counts as documented.picurv now converts those values to node counts before emitting -im/-jm/-km.grid_gen remains unchanged: grid.gen still accepts cell counts and writes node counts into .picgrid.programmatic_c case with im=32 previously yielded 31 physical cells; it now yields the documented 32 physical cells.Dual Time Picard RK4 to the more precise Dual Time Picard Jameson RK; deprecated RK4 selector, YAML-block, noise-control, C API, and C CLI spellings remain accepted as compatibility aliases.PICGRID headers are required for file-based grids in C runtime ingestion.grid.gen legacy1d converter and optional grid.legacy_conversion wrapper in picurv for headerless 1D-axis legacy payload migration.run --num-procs now applies to solver and field postprocessor stage sizing.post.sbatch and sweep post arrays reuse the configured cluster resources.cluster.yml Slurm contract support to picurv run (--cluster, --scheduler, --no-submit).picurv submit as the delayed-submit counterpart to --no-submit for existing run/study artifacts.picurv cancel so Slurm jobs can be stopped by --run-dir instead of manual job-id lookup; picurv cancel --stage solve --graceful requests solver final-output shutdown with SIGUSR1.solver.sbatch, post.sbatch, submission.json, manifest.json).picurv sweep for parameter studies using Slurm job arrays with post-stage dependency chaining.picurv sweep --continue --study-dir <path> for resuming partially-completed studies: detects per-case completion status, prepares checkpoint restarts via resolve_restart_source, and submits sparse solver arrays for incomplete cases only.picurv sweep --reaggregate --study-dir <path> for manual metrics re-aggregation on existing study outputs.metrics_aggregate.sbatch, afterany dependency on post array).detect_last_checkpoint_step now falls back to particle checkpoint files (position*.dat) for analytical-mode cases with no eulerian output.metrics_table.csv, results/plots, summary.json).master_cluster.yml, master_study.yml.SIGUSR1, SIGTERM, SIGINT) with launcher-specific Slurm signal guidance.execution.walltime_guard policy and exported batch metadata (PICURV_JOB_START_EPOCH, PICURV_WALLTIME_LIMIT_SECONDS).tests/tooling/audit_function_docs.py as the repository-wide audit gate.picurv summarize for read-only per-step health summaries derived from existing run artifacts.picurv summarize with additive --overview, --case, --solver, and --monitor configuration views that work before timestep artifacts exist.summarize --list-plot-series and --plot time-history workflows backed by standalone generators/plot.gen, with append-order windows, automatic residual/norm log scaling, explicit saves, and headless fallback.matplotlib as an actionable DEPENDENCY_MISSING plotting error instead of a configuration-value error.matplotlib by default in the bootstrap-managed Python environment so plotting works after a standard install.--upgrade-pip for environments that need it.runs/<run_id>/scheduler/ instead of runs/<run_id>/logs/.picurv -> C contract.docs/assets/curv.gif, docs/assets/paraview_flat_channel.png).config/build/.grid.gen profile to config/grids/coarse_square_tube_curved.cfg.sandbox/ into explicit developer-sandbox documentation.guide.md (non-root).docs/assets/.README.md files (single top-level README.md retained).logs/doxygen.warnings.da_processors_* contract with validation.tests/tooling/audit_ingress.pytests/tooling/audit_ingress_manifest.jsonstubs/ archive from repository after extracting useful documentation content.