# CAA Verification Kit 1.0 This is the supplied self-check tool for the classical C4 + RK4 baseline in the assignment: A (zero state), B (four periodic plane-wave grids), and C (free-field Gaussian pulse). It reads your raw numerical results and computes the published acceptance criteria independently. It contains no CAA solver. The current brief requires S1--S3, T1--T3 and B1--B2 in addition to this public baseline. Kit 1.0 does not run or grade those experiments. Keep the supplied checker and cases unchanged. Run the additional experiments through your documented configuration entry point and save their required raw evidence. Documentation and scope labels were aligned on 20 October 2026; the numerical acceptance checks and case data remain unchanged. **Start here:** choose MATLAB or Python below, implement the supplied student template, run the command, then read `verification_report/report.md`. The empty template intentionally produces ERROR until you connect your solver. Use the diagnostic in the first failing check to guide your next change. ## What is included | File | Purpose | |---|---| | `cases.json` | Fixed physical parameters, grids, actual time schedules, probe indices, and already-public reference numbers | | `student_solver.m`, `student_solver.py` | Entry-point templates for your own solver | | `validate_solver.m` | MATLAB runner; passes raw results to the shared checker | | `verify.py` | Independent checker, Python runner, and JSON-results reader | | `README.md` | Setup, interface, outputs, and scope | The teacher's reference solver, full reference fields and private assessment materials are not included. The checker and its interface are visible so you can understand its diagnostics. Do not modify `cases.json`, `verify.py` or `validate_solver.m` to obtain a pass. The teacher reruns submitted source with an original copy of the kit. A local report is not an authenticated grade or proof of authorship. ## MATLAB: one entry command Requirements: MATLAB with its Java runtime enabled, plus Python 3.9 or later. The checker needs only Python's standard library: no pip packages or MATLAB toolboxes are required. A Python solver may have its own declared dependencies. 1. Open this folder as MATLAB's current folder. 2. Implement `result = student_solver(case_config)` in `student_solver.m`. You may call your existing solver from this function. 3. Run: ```matlab report = validate_solver(@student_solver, 'verification_report'); ``` If Python is not on MATLAB's executable search path, supply its full executable path as argument 3, for example: ```matlab report = validate_solver(@student_solver, 'verification_report', ... '/absolute/path/to/python3'); ``` On Windows use the installed `python.exe` path. You do not need to configure MATLAB `pyenv`; the runner launches Python as a separate process. If the checker cannot run, the wrapper raises an error instead of returning an older report. ## Python: one entry command Open a terminal in this folder. Implement `solve_case(case)` in `student_solver.py`, returning the dictionary described below, then run: ```text python3 verify.py --solver student_solver.py:solve_case --output verification_report ``` Use `python` instead of `python3` if that is the Python 3 command on your system. For NumPy-based solvers, convert arrays using `.tolist()` before returning them. Use double precision. No plotting or GUI is required by the checker. To start with one case while debugging: ```text python3 verify.py --solver student_solver.py:solve_case --case A_zero --output zero_check python3 verify.py --list ``` A passing subset reports **PARTIAL SCOPE**, never a complete baseline pass. ## Input contract: implement one case at a time The runner calls your function once for each entry of `cases.json`. Python receives a dictionary; MATLAB receives a struct. Read physical parameters, scheme names, initial condition, grid, sponge and probe settings from this argument. `reference` contains published comparison values; it is for the checker, not for generating numerical fields. All cases use `rho0 = c0 = 1`, `U0 = 0.2`, `central4` and `rk4`. For a periodic axis, use `N` points with spacing `(upper-lower)/N` and omit the repeated upper endpoint. For a non-periodic axis, include both endpoints with spacing `(upper-lower)/(N-1)`. Return increasing coordinate vectors. For a plane wave, initialize ```text K = sqrt(kx^2 + ky^2) p = amplitude * cos(kx*x + ky*y + phase) u = kx*p / (rho0*c0*K) v = ky*p / (rho0*c0*K) ``` Case A initializes all three fields to zero. Case C uses the Gaussian pressure in the handout and zero initial velocity. The reference sponge adds `-sigma*q` to each LEE equation. For each outer side at inward distance `d`, its contribution is `strength * max(0, 1-d/width)^power`; take the **maximum** of the four side contributions, including at corners. The reference uses even ghost extension of all fields at the outer edges behind the sponge. These outer numerical closures do not impose a physical rigid-wall condition. ### Use the supplied time schedule The baseline time-step estimate is ```text dt_limit = CFL / ((abs(U0)+c0)/dx + c0/dy) n_steps = ceil(t_end/dt_limit) dt = t_end/n_steps ``` For these verification runs, use the **explicit `n_steps` and `dt` in `cases.json`**. Their fixed values remove floating-point rounding differences at an integer-valued step-count boundary. In particular, C uses 199 steps to match the published reference. Do not round to a different end time or change time labels after integration. Record the initial state at time zero and every actual integration step. | Case | Nx x Ny | Steps | dt | Final time | |---|---:|---:|---:|---:| | A_zero | 24 x 16 | 3 | 0.2/3 | 0.2 | | B_24 | 24 x 24 | 17 | 1/17 | 1 | | B_36 | 36 x 36 | 26 | 1/26 | 1 | | B_48 | 48 x 48 | 34 | 1/34 | 1 | | B_72 | 72 x 72 | 51 | 1/51 | 1 | | C_gaussian | 181 x 151 | 199 | 3/199 | 3 | ### Probe sampling for C Use these **one-based (row y, column x)** indices exactly. Python must subtract one from each index. Do not interpolate or resolve nearest-point ties again. The nominal probe coordinates include midpoints between grid nodes; the indices below specify the nodes used for the published reference. | Probe | Nominal (x,y) | (row,column), one-based | Sampled (x,y) | |---|---|---|---| | 1 | (-1.5, 0.5) | (83, 68) | (-1.53333333333333, 0.46666666666667) | | 2 | (0, 0.5) | (83, 91) | (0, 0.46666666666667) | | 3 | (1.5, 0.5) | (83, 114) | (1.53333333333333, 0.46666666666667) | | 4 | (0, 2) | (106, 91) | (0, 2) | ## Output contract: raw fields, not self-reported scores Return these fields from your function. MATLAB row and column vectors both serialize as JSON vectors. Two-dimensional fields must use **rows = y, columns = x**. Every numeric value must be finite; NaN and Inf are errors. | Field | Required shape or value | |---|---| | `schema_version` | String `caa-verification/1.0` | | `case_id` | Copy `case.case_id` | | `x`, `y` | Vectors of lengths `nx`, `ny` | | `time` | Vector of `n_steps+1` actual step times, including zero | | `p_final`, `u_final`, `v_final` | Three matrices of shape `ny` by `nx` at the last actual time | | `probe_p` | C only: `(n_steps+1)` by 4, ordered as above, including the initial samples | | `zero_history` | A only: one snapshot per time, each containing `time`, `p`, `u`, `v` with matrices `ny` by `nx` | Python returns a dictionary. MATLAB returns a struct; `zero_history` is a struct array. For example, after your own solver has produced the raw data: ```matlab result.schema_version = 'caa-verification/1.0'; result.case_id = case_config.case_id; result.x = x; result.y = y; result.time = actual_times; result.p_final = q(:,:,1); result.u_final = q(:,:,2); result.v_final = q(:,:,3); % Also attach zero_history for A, or probe_p for C. ``` Python uses the same field names. `metrics`, `error`, `passed` and other student-calculated summaries are not used as evidence by this checker. ## What the report means The tool writes `report.md` for reading and `report.json` for structured submission. Direct solver runs also save `results/.json`. Files with these names in the selected output folder are overwritten on the next run. Use a new output folder to preserve a previous run. A solver exception is recorded as ERROR; a previous result is not substituted for a failed run. | Check | Criterion | |---|---| | Coordinates, shape, finite values | Correct grid; absolute coordinate tolerance 1e-10 | | Time | Actual final time and every supplied step time; absolute tolerance 1e-10 | | A | Maximum absolute p, u or v over every returned state is below 1e-12 | | B | Independently recomputed pressure L2 errors agree with each published value within 5%; finest error below 1e-3; finest-pair order above 3.5 | | C | Global final pressure maximum and each probe peak agree within 5%; each peak-time error no greater than max(1% of reference peak time, 3/199) | | C consistency | Each final probe sample agrees with its specified final-field entry within absolute 1e-10 | FAIL means a criterion was not met. ERROR means input, interface or execution failed. NOT_RUN means a preceding requirement must be repaired before a numerical result can be accepted. Fix grid and time failures first: a field at the wrong physical time cannot be accepted using a small error at that time. `baseline_checkpoint_passed` is true only when all six runs and the convergence check pass. The checker does **not** certify nonzero velocity accuracy beyond the checks above, a complete time evolution from a final snapshot, or the S1--S3, T1--T3 and B1--B2 experiments. Those require the evidence and teacher assessment specified in the current handout. For a solver written in another environment, export this contract as one JSON file per case and use: ```text python3 verify.py --results exported_results --output verification_report ``` The Python command exits 0 if all selected checks pass, 1 for a failed check or recorded solver error, and 2 for command-line usage errors. A subset can exit 0 while `baseline_checkpoint_passed` remains false. ## What to submit Include your solver and adapter source, the unchanged kit, and the complete `verification_report/` folder (both reports and raw per-case results). Include all other assignment outputs and the AI log. Explain the required real or supplied diagnostic example, its cause, the correction and the verification evidence. Do not invent a personal debugging history. The teacher can reproduce your submission without giving you the private reference solver.