# Quantum Finite Volume Method, QFVM
**English** · 简体中文
> Category C6 · Module [`oracq.applications.qfvm`](../../api/applications/qfvm.rst) · Stage V1
## Overview
QFVM constructs all the inputs needed for quantum linear-system solving (QLSS) from classical flow-field data: the matrix-element oracle, the sparse position oracle, and the right-hand-side residual state preparation, then hands the same problem to a replaceable QLSS (either the CKS base route declaring sparse input, or the Costa route declaring block-encoding input). The interface division follows the QFVM paper ([arXiv:2102.03557](https://arxiv.org/html/2102.03557v1); see the input-model review). The current implementation targets the Euler equations on a one-dimensional periodic grid: three conserved quantities (density, momentum, energy) plus the frozen-Roe Jacobian; it does not cover the full set of grids, boundaries, and physical models of the original paper.
The linear system takes the Hermitian dilation in physical coordinates `D = [[0, M], [M.T, 0]] + padding_value·I_pad` (M is the Roe block), and the physical-coordinate block is selected on the output side after solving; this dilation serves the linear solve and must not be taken as a QODE evolution equivalent to the original generator.
## Interface and input model
```python
roe_qfvm_inputs(*, cell_width=2, fmt=None, angle_width=8, prefix="RoeQfvm")
qfvm_sparse_access(inputs, *, padding_value=1.0, **entry_options)
roe_qfvm_block_encoding(inputs, *, amax=8.0, padding_value=1.0, **entry_options)
roe_qfvm_problem(inputs, *, spectrum, rhs_norm=None, amax=8.0, padding_value=1.0, **entry_options)
roe_qfvm_step(inputs, qlss, *, spectrum=None, rhs_norm=None, **options)
bind_qfvm(program, inputs)
qfvm_memories(inputs, flow, *, amax=8.0)
```
API entry points: {obj}`roe_qfvm_inputs `, {obj}`qfvm_sparse_access `, {obj}`roe_qfvm_block_encoding `, {obj}`roe_qfvm_problem `
- {obj}`roe_qfvm_inputs ` returns {obj}`RoeQfvmInputs `: six abstract databases (rho / momentum / energy / geometry / theta / residual values) plus an abstract right-hand-side state preparation. `cell_width` ranges 2..25 (at least four cells) and `angle_width` ranges 1..64; the matrix dimension is `2**width`, where `width = cell_width + 3` (3 conserved quantities + 1 padding component).
- Input-model layering: the flow-field, geometry, and angle data are QRAM (bound via {obj}`qram_database `); the matrix-access artifact is SO ({obj}`qfvm_sparse_access ` returns {obj}`SparseAccess `: position + element oracles, sparsity 9); the right-hand side is SP (the signed residual tree of {obj}`rhs_qram_preparation `).
- {obj}`roe_qfvm_problem ` assembles a {obj}`LinearSystem `: `spectrum` must be an explicit {obj}`SpectralPromise ` (merged with padding_value by taking the wider bound); `amax`, the spectral bounds, and the matrix properties are caller declarations that must hold for the actually quantized matrix; data assumptions are recorded in `data_assumptions` (coherent XOR QRAM, pinned snapshots, raw field quantities rather than matrix tables, etc.).
- {obj}`roe_qfvm_step ` requires a {obj}`QLSSProtocol ` that declares its input_model (bare callables are rejected) and returns `qlss.solve(problem)`; {obj}`bind_qfvm ` replaces the abstract slots with QRAM database bindings, and {obj}`qfvm_memories ` assembles the memory tables from {obj}`RoeFlowData ` snapshots.
`RoeQfvmInputs` has the attributes `width` (= cell_width + 3) and `geometry_width` (= width + 4 + cell_width + 7, packing the seven segments neighbor / reverse / source / rowvar / colvar / band / valid).
## Implementation notes
Matrix elements are not pre-stored as a table: {obj}`roe_entry ` queries the conserved-quantity databases of the source cell and its left/right neighbors, calls the reversibly compiled {obj}`roe_face ` on the two interfaces (the pure function {obj}`frozen_roe_face ` compiled to fixed-point arithmetic via mathfunc {obj}`compile_function `, including sqrt / div / mul / select), selects the west / center / east flux difference by band, and the mass term is written only onto the component diagonal via the `component_equal` Boolean network; on arithmetic failure (status ≠ 0) the element totalizes to zero. The position oracle encodes only neighbors, slots, and component indices ({obj}`geometry_cells `; it contains no matrix values): the 9 structural slots per column (3 neighbors × 3 components) go through 9 coherent value transpositions ({obj}`value_transposition `) to produce the in-place index permutation CKS needs; the padding component (variable 3) is the diagonal `padding_value`, the remaining invalid slots return the zero element, and the boundaries are periodic. The right-hand side uses {obj}`ptheta_cells ` to quantize residual values into rotation angles `2·arccos(min(1, |v|/amax))`; `rhs_qram_preparation` prepares amplitudes from a QRAM angle table and writes the signs via Z kickback from the sign database.
The classical-side Riemann computation and local flow-field updates are managed by `RoeFlowData` (`applications/flow_data.py`): a single-point update recomputes only the adjacent interfaces and the affected tree nodes; modifying a bank on the native backend still requires rematerialization, which is not the constant-time physical write assumed by the paper. The module attribute `correctness="pending"`: what is currently witnessed is the input adaptation and the interchangeability of the two QLSS routes; numerical-solve correctness is not certified. Full assumptions and boundaries are in the [QFVM/QLSS input-model review](../../reference/qfvm-input-models.md).
## Validation approach
Category C6 (composition skeleton; acceptance criteria in `../../development/validation-plan.md` §2: component contracts satisfied + end-to-end small-instance semantic correctness + bind invariance). `validation-coverage.md` registers `qfvm.py`/`qham/` on the application-layer row (C6, V1, no gaps); QFVM's concrete witnesses sit in the evidence column of the ODE/PDE-solver row:
- Structure and numerical: `tests/core/test_differential.py:DifferentialStructureTests.test_qfvm_uses_raw_flow_and_modular_arithmetic` — with {obj}`FixedFormat(4, 1) ` and `amax=4` inputs, {obj}`roe_qfvm_block_encoding ` gives α = 36; the BE program contains exactly 4 unresolved slots, and after closing the resources are the four databases rho / momentum / energy / geometry; the program contains sqrt / div / mul / select arithmetic modules; the geometry table has size exactly `2**(width+4)`; the sparse encoding is annotated with sparsity 9 and the self-adjoint extension.
- Classical side: the same family's `test_local_riemann_updates_only_neighbor_faces_and_tree` — a single-point update of a 16-cell flow field recomputes only interfaces (4, 5) and cells (4, 5, 6), updates fewer rhs angle-tree entries than a full update, and materializes no matrix bank.
- Binding: inside `test_qfvm_uses_raw_flow_and_modular_arithmetic`, after `bind_qfvm` replaces all abstract slots there are no unresolved declarations.
## Known gaps and planned stages
Consistent with the application-layer row of `validation-coverage.md`: no registered gaps, stage V1. The `correctness="pending"` module attribute is a record of the implementation boundary (numerical-solve correctness certification is outside the current validation scope), not a gap on the coverage matrix.
## Numerical validation
Paper-grade numerical validation executed on 2026-09-16 by `tests/verification/verify_qham_qfvm.py` (real backends: the PySparQ native RIR interpreter and the UniQC full-amplitude state vector; no mocks, no skips). This machine has no C++ compiler, so {obj}`arithmetic_native_registry ` is unavailable and the Roe arithmetic executes through gate-level expansion on PySparQ RIR (about 1.6×10⁷ expanded gates per single-entry circuit); entry-level validation therefore uses superposition sampling instead of full-matrix enumeration.
### Experiment design
- **Fixed-point format choice**: `roe_face`'s compile_function requires the row/column inputs of {obj}`Index(2) ` to be representable, and the smallest usable format is `FixedFormat(5,2)`; `entropy_delta=0.5` makes 2δ, δ², and δ all exactly representable in that format. Note: if the fraction bits cannot represent 2δ (e.g. fmt=(4,1) with the default δ=0.125, where 2δ=0.25 truncates to raw 0), the entropy-correction branch divides by zero and the entry silently zeroes out per the documented totalize behavior — the integration test previously covered only the padding diagonal, not nonzero Roe entries.
- **Roe face flux**: the compiled `roe_face` is cross-checked **bit for bit** against an in-script independent fixed-point simulation (re-implemented per the documented toward_zero/modular_wrap semantics of {obj}`fixed_arithmetic `) over 16+8+8=32 superposition branches (all row/col pairs, a density sweep, a momentum sweep); the method error (against float64 `roe_formulas`) is reported separately.
- **Sparse entries/positions**: the entry oracle is checked bit by bit against the fixed-point simulation matrix under an 8-branch superposition on column 5 (three-band nonzeros + zero structure + padding zero); the padding diagonal is a separate case; the position oracle verifies, under a superposition of all 32 columns, the complete permutation and the 9-slot mapping (against independent geometry semantics).
- **RHS and classical identities**: the RHS residual-state preparation (QRAM angle tree + sign kickback) is checked against an independent residual computation; flow_data's F*(L,R)=left·U_L+right·U_R is checked against the matrix-inversion implementation {obj}`riemann_flux `; M·u−mass·u=−residual (implicit-FVM sign convention); the local update patch agrees with a full recomputation; the ptheta angle table is pointwise true. Uniform four-cell flow field ρ=(1,1,1.25,1.25), m=(0,0.25,0,−0.25), E=(1,1,1,1).
### Key metrics
| Case | Scale | Backend path | Value |
|---|---|---|---|
| roe_face bit-level cross-check | 32 branches, fmt=(5,2) | rir-pysparq | raw/status bit-identical (32/32); method error 0.427 |
| entry-matrix sampling | column 5, 8 branches | rir-pysparq | implementation error 0.0 (bit-identical); method error 0.481; zero structure correct |
| padding diagonal | coordinates (7,7)/(23,7) | rir-pysparq | diagonal raw=4 (1.0), 0 outside the dilation block |
| position oracle | 32 columns × 32 inputs | rir-pysparq | complete permutation per column; 288 slot mappings 0 mismatches; geometry table 0 pointwise mismatches; work cleaned |
| RHS preparation | 16 addresses, angle_width 8 | rir-pysparq | amplitude error 1.11e-16, signs 0 mismatches, total probability 1.0; angle tree/sign bank 0 pointwise mismatches |
| flux identity | 4 sampled states | classical independent | F* block form vs inversion implementation 3.33e-16; F*(U,U)=F(U) 2.22e-16 |
| single-step update | 4 cells | classical independent | M·u−mass·u=−residual 2.22e-16; residual bank 0 mismatches; local patch consistent with full recomputation |
The method error is the inherent quantization error of the 5-bit fixed-point pipeline (about 1–2 quanta), not an implementation defect: the implementation side (against the fixed-point-semantics simulation) is bit-exact.
### Reproduce
```bash
PYTHONPATH=src /path/to/backend/python tests/verification/verify_qham_qfvm.py
```
Artifact: `out/verification/qham_qfvm.json` (full metrics and criteria of the 15 cases).
## Related links
- Source: `src/oracq/applications/qfvm.py` (Roe arithmetic `applications/roe.py`, formulas `applications/roe_formulas.py`, classical data `applications/flow_data.py`)
- User guide: [QFVM input models and solver replacement](../qfvm.md)
- API reference: [QFVM application](../../api/applications/qfvm.rst)
- Same-group page: [General QHAM](qham.md)
- Validation matrix: [Validation coverage matrix](../../development/validation-coverage.md)