中文版本: CONTRIBUTING_zh.md
This document is for practical project work: build, test, benchmark, reference generation, and parity debugging.
When you change code:
- Build your active tree:
cmake --build build -j32
- Run the full local suite:
ctest --test-dir build --output-on-failure -j 4
- If a test fails, read the assertion message first. Most numeric tests already print the compared values.
- Update the live docs when project status changes:
README.md,docs/AUDIT_MMA_PARITY.md,CHANGELOG.md.
When you add or fix functionality:
- Put the code in the correct domain module under
src/<domain>/(numeric / algebra / ode / qft / ibp / pipeline / api / cli). - Add or extend the matching test file under
tests/. - If the change alters public surface or project status, update docs in the same turn.
- If the change closes or exposes a parity issue, preserve the Mathematica side of the comparison.
- Mathematica AMFlow is the spec.
- The immediate parity screen is sampled single-point values at
eps = 1/1000. - Do not make broader fitted/Laurent coverage the first move when a sampled parity comparison is open.
- Preserve every Mathematica output used to establish parity.
Single test:
./build/tests/amflow_tests \
--gtest_filter='AmfsystemTest.*'Run a single domain group:
./build/tests/amflow_tests \
--gtest_filter='*Numeric*:*Qft*'List tests:
ctest --test-dir build -NThe Wolfram driver lives at tools/math_ref/run_amflow_kira.wl and
reads its config from AMF_REF_CFG.
cd tools/math_ref
AMF_REF_CFG=$PWD/cfg_bubble_1L.wl math -script run_amflow_kira.wlThe committed direct reference JSON files live under
tests/data/math_ref/. Sampled parity benchmark references live under
tools/bench/.
Use this workflow for current family bring-up:
- Choose integral targets and fix
eps = 1/1000. - Generate or preserve Mathematica sampled values.
- Save summarized values in
tools/bench/*_mma_reference.json. - Preserve raw Mathematica caches in
tools/bench/mma_refs/whenever they contain useful intermediate values. - Run the C++ sampled path on exactly the same family, replacements, numeric values, and targets.
- If C++ mismatches, compare the first wrong direct subintegral or child-system value before touching fit/Laurent code.
- If C++ matches, add or extend a focused regression when runtime is reasonable.
Usually one of:
precwas omitted or became zero before an Arb call;- a normalization path received invalid precision or a singular transform;
- the path generator produced a degenerate step;
- a Kira reduction returned incomplete data and downstream code accepted it blindly.
First checks:
./build/tests/amflow_tests \
--gtest_filter='OdeAmflowTest.*'
./build/tests/amflow_tests \
--gtest_filter='AmfsystemTest.BubblePipeline_RunsToCompletion'Usually one of:
- 1-based vs 0-based translation;
- reverse coefficient indexing around the sparse system;
- missing prefactor propagation in a recursive boundary chain;
- wrong numeric substitution into family replacements before setup.
Check docs/INVARIANTS.md first.
Look for:
- missing pattern-zero boundary entries;
- wrong
deinfconstruction; - wrong
determine_boundary_orderinput type; - ending/global value stitching problems.
Check:
ending_qparity withAMFlow.m;- whether child families truly drop loops or propagators;
- whether a child setup is being built from the fully substituted family data instead of a partly symbolic one.
You mixed symbolic objects created in different contexts. Re-parse via string round-trip into the target context. Do not compare contexts by name; the runtime rule is shared ownership identity.
Check:
- absolute
kira_pathandfermat_path; FERMATPATHdirectory contents;- dumped Kira workdir via
AMFLOW_KIRA_DUMP=1; - generated
integralfamilies.yaml,jobs.yaml,kinematics.yaml,preferred, andtarget.
Runtime environment variables — the canonical list lives in
include/amflow/numeric/log.hpp;
add new trace categories there when introducing them. Currently:
| Env var | Effect |
|---|---|
AMFLOW_KIRA_DUMP=1 |
Keep the Kira workdir after a run |
AMFLOW_JORDAN_DUMP=... |
Dump Jordan-form intermediate matrices to file |
AMFLOW_NO_SPARSE_CHOP=1 |
Disable the sparse-row chop heuristic |
AMFLOW_SPARSE_CHOP_DIGITS=N |
Override sparse-chop digit count (default = numeric::chop_pre()) |
AMFLOW_DEBUG_BC=1 |
Emit boundary-condition and solve_one_eps diagnostics |
AMFLOW_DEBUG_DBO=1 |
Emit determine_block_boundary_order diagnostics |
AMFLOW_DEBUG_PRECISE=1 |
Verbose precision tracing in normalize / Jordan paths |
AMFLOW_DEBUG_REGULAR=1 |
Emit regular_run step-by-step trace |
AMFLOW_DEBUG_STAGES=1 |
Emit per-stage system traces (Inf→Reg, RegRun, Zero) |
AMFLOW_DEBUG_CT_PERM=1 |
Emit ct_perm Cutkosky permutation trace |
AMFLOW_DEBUG_SCHEME=1 |
Emit [scheme] ... EndingScheme dispatch trace from amf_system_setup_master (Cutkosky / SingleMass firing) |
AMFLOW_TRACE_LAYER6=1 |
Fine-grained src/ode/inf.cpp trace (boundary-Taylor / Frobenius diagnostics) |
Use the existing pattern:
class Layer5Test : public ::testing::Test {
protected:
void SetUp() override { set_default_options(); }
void TearDown() override { set_default_options(); }
};Always reset options in tests. Many failures that look numerical are just leaked global settings.
For numeric checks, prefer helpers already used in the suite rather than string comparison. Relax tolerances only when the workflow genuinely accumulates more numerical error.
- Modifying the upstream Mathematica AMFlow to match C++ behaviour (the upstream is the spec; we conform to it, not the other way around).
- Replacing parity work with weaker tests or looser tolerances.
- Mixing symbolic contexts without re-parsing.
- Excluding a ported Mathematica path from parity checks instead of debugging the mismatch.