docs: audit-driven fixes — stale claims, missing v0.9.0 entries

Follow-up to the test-count centralisation + release-policy commit:
applies the findings of the parallel doc-audit.

Stale claims fixed
──────────────────
* CLAUDE.md line 14-17 (phase block summary): expanded from
  "Phase 1-7 done, 8-9 planned, 10+ research" to reflect that
  Phase 8a MVP + 8b-Lite + 9a + 9b are now done (v0.9.0), with
  Phase 9b-analytic + 9c as the next planned milestones.
* CLAUDE.md line 251-252 (release state): "v0.7.0 ... Phase 7 next"
  → "v0.9.0 ... Phase 9c + 9b-analytic next".
* CLAUDE.md "Three geometry modes" → "Five DCE models" table.
  Adds CP-Euclidean and Inversive-Distance rows with their CGAL
  public entries.  DOF-assignment pattern subsection rewritten to
  cover vertex-only / vertex+edge / face-based assignments.
* CLAUDE.md "Newton solver" section: gradient sign and Hessian
  convention for all five solvers (was: three).  Replaces the
  "Hessian is FD" claim for HyperIdeal with the block-FD note
  (Phase 9b shipped).
* CLAUDE.md "Known quirks": stale GTEST_SKIP entry removed (v0.9.0
  cleaned up the HDS-port stubs).
* README.md line 86: "all 24 headers with descriptions" →
  "all public headers with descriptions" (was undercounting).

Missing entries added — `doc/api/headers.md`
─────────────────────────────────────────────
* New section **"Circle-packing functionals (Phase 9a)"** with
  `cp_euclidean_functional.hpp` and `inversive_distance_functional.hpp`.
* New section **"Math utilities"** documenting four previously-
  undocumented public helpers: `matrix_utility.hpp`,
  `projective_math.hpp`, `p2_utility.hpp`, `discrete_elliptic_utility.hpp`.
* New section **"CGAL public API (Phase 8b-Lite)"** documenting all
  six new public headers under `include/CGAL/`.
* `newton_solver.hpp` row expanded to list all five Newton functions.

Header count summary (before vs after):
* Before: 24 headers in 8 sections (missing 6 of the 30 actually present).
* After:  30 headers in 11 sections (complete coverage).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tarik Moussa
2026-05-22 08:04:55 +02:00
parent 0f78d181e1
commit 84258921df
3 changed files with 71 additions and 26 deletions

View File

@@ -11,10 +11,12 @@ conformallab++ is a C++17 reimplementation of [ConformalLab](https://github.com/
**The long-term goal is a CGAL package** — a submission to the CGAL library that brings discrete conformal maps (hyper-ideal, spherical, Euclidean) to the CGAL ecosystem using `CGAL::Surface_mesh` as the underlying halfedge data structure, with a traits-class design compatible with arbitrary CGAL-conforming mesh types.
The project has three distinct phases:
- **Phase 17 (done):** Direct port of the Java library algorithms to C++
- **Phase 89 (planned):** CGAL package infrastructure + remaining Java features not yet ported (inversive-distance functional, analytic HyperIdeal Hessian, genus-g > 1 fundamental domain)
- **Phase 10+ (research):** New mathematics beyond the Java original — holomorphic differentials, Siegel period matrix Ω ∈ H_g, full uniformization for genus g ≥ 2
The project has four distinct phase blocks (updated 2026-05-22):
- **Phase 17 (done, v0.7.0):** Direct port of the Java library algorithms to C++.
- **Phase 8a MVP + 8b-Lite (done, v0.9.0):** CGAL public-API surface for all five DCE models via `<CGAL/Discrete_*.h>`. Phase 8a.2 (generic FaceGraph), 8c (manuals), 8d (CGAL-test-format), 8e (YAML pipeline) deferred on-demand.
- **Phase 9a + 9b (done, v0.9.0):** Two new functionals (CP-Euclidean port, Inversive-Distance research), two new Newton solvers, block-FD HyperIdeal Hessian.
- **Phase 9b-analytic + 9c (planned):** Full analytic HyperIdeal Hessian via Schläfli identity (research, see `doc/roadmap/research-track.md`); 4g-polygon fundamental domain for genus g > 1 (mixed port + research).
- **Phase 10+ (research):** Holomorphic differentials, Siegel period matrix Ω ∈ H_g, full uniformization for genus g ≥ 2.
## Language
@@ -90,17 +92,22 @@ This replaces the Java `CoHDS` (half-edge data structure) and its intrusive `CoV
`CGAL_DISABLE_GMP` and `CGAL_DISABLE_MPFR` are defined for all CGAL targets — the library deliberately uses `Simple_cartesian<double>` (floating-point, no exact arithmetic) because conformal geometry does not require exact predicates.
### The three geometry modes
### The five DCE models
Each mode has its own Maps struct that bundles all property maps, plus functional, Hessian, and Newton function:
Each model has its own Maps struct that bundles all property maps, plus a functional, optional Hessian, Newton solver, and (since v0.9.0) a CGAL public-API entry function:
| Mode | Space | Maps struct | Key headers | Newton function |
|---|---|---|---|---|
| Euclidean | ℝ² | `EuclideanMaps` | `euclidean_functional.hpp`, `euclidean_hessian.hpp` | `newton_euclidean()` |
| Spherical | S² | `SphericalMaps` | `spherical_functional.hpp`, `spherical_hessian.hpp` | `newton_spherical()` |
| Hyper-ideal | H² (Poincaré disk) | `HyperIdealMaps` | `hyper_ideal_functional.hpp`, `hyper_ideal_hessian.hpp` | `newton_hyper_ideal()` |
| Model | Space | DOFs | Maps struct | Key headers | Newton function | CGAL entry |
|---|---|---|---|---|---|---|
| Euclidean | ℝ² | vertex | `EuclideanMaps` | `euclidean_functional.hpp`, `euclidean_hessian.hpp` | `newton_euclidean()` | `discrete_conformal_map_euclidean()` |
| Spherical | S² | vertex | `SphericalMaps` | `spherical_functional.hpp`, `spherical_hessian.hpp` | `newton_spherical()` | `discrete_conformal_map_spherical()` |
| Hyper-ideal | H² (Poincaré disk) | vertex + edge | `HyperIdealMaps` | `hyper_ideal_functional.hpp`, `hyper_ideal_hessian.hpp` (block-FD, Phase 9b) | `newton_hyper_ideal()` | `discrete_conformal_map_hyper_ideal()` |
| CP-Euclidean (BPS 2010) | face-based circle packing | **face** | `CPEuclideanMaps` | `cp_euclidean_functional.hpp` | `newton_cp_euclidean()` | `discrete_circle_packing_euclidean()` |
| Inversive-Distance (Luo 2004) | vertex-based circle packing | vertex | `InversiveDistanceMaps` | `inversive_distance_functional.hpp` | `newton_inversive_distance()` | `discrete_inversive_distance_map()` |
HyperIdeal also has edge DOFs (`e_idx[e]`); Euclidean and Spherical are vertex-DOF only. For HyperIdeal: `assign_all_dof_indices(mesh, maps)` assigns all vertex and edge DOFs automatically. For Euclidean/Spherical: pin one vertex manually (`maps.v_idx[first_vertex] = -1`) then assign sequential indices.
DOF-assignment patterns:
- **Vertex-only models** (Euclidean, Spherical, Inversive-Distance): pin one vertex manually (`maps.v_idx[first_vertex] = -1`) then assign sequential indices. The CGAL public entries do this automatically with the "natural-theta" trick (so calling them with no arguments returns x = 0 as the equilibrium).
- **HyperIdeal**: `assign_all_dof_indices(mesh, maps)` assigns vertex + edge DOFs automatically.
- **CP-Euclidean**: face-based — `assign_cp_euclidean_face_dof_indices(mesh, maps, pinned_face)` pins one face and indexes the rest.
### The full pipeline
@@ -125,18 +132,19 @@ After `compute_*_lambda0_from_mesh()` the original vertex positions are no longe
### Newton solver (`newton_solver.hpp`)
The gradient sign convention differs between modes:
- **Euclidean/Spherical:** `G_v = Θ_v actual_angle_sum` (target minus actual)
- **HyperIdeal:** `G_v = actual_angle_sum Θ_v` (actual minus target)
Gradient sign convention differs across the five models:
- **Euclidean / Spherical / Inversive-Distance:** `G_v = Θ_v actual_angle_sum` (target minus actual).
- **HyperIdeal:** `G_v = actual_angle_sum Θ_v` (actual minus target).
- **CP-Euclidean:** `G_f = φ_f Σ_{h:face(h)=f} (p(θ*,Δρ) + θ*)` (face-based; see `cp_euclidean_functional.hpp` header for the full formula).
Hessian sign and solver:
- **Euclidean:** H is PSD (cotangent Laplacian) → `SimplicialLDLT(H)`
- **Spherical:** H is NSD (concave energy) → `SimplicialLDLT(H)` (sign flip inside `newton_spherical`)
- **HyperIdeal:** H is PSD (strictly convex) → `SimplicialLDLT(H)`
Hessian sign and solver per model:
- **Euclidean:** H is PSD (cotangent Laplacian) → `SimplicialLDLT(H)`.
- **Spherical:** H is NSD (concave energy) → `SimplicialLDLT(H)` (sign flip inside `newton_spherical`).
- **HyperIdeal:** H is PSD (strictly convex) → `SimplicialLDLT(H)`. Phase 9b uses a **block-FD Hessian** (per-face 6×6 local block, ~96× speed-up vs full FD on V=200). Full analytic Hessian via the chain `(bᵢ, aₑ) → lᵢⱼ → ζ₁₃/ζ₁₄/ζ₁₅ → αᵢⱼ/βᵢ` is planned research — see `doc/roadmap/research-track.md` Phase 9b-analytic.
- **CP-Euclidean:** analytic 2×2-per-edge `h_jk = sin θ / (cosh Δρ cos θ)` (BPS 2010), strictly convex → `SimplicialLDLT(H)`.
- **Inversive-Distance:** FD Hessian (inline in `newton_inversive_distance`). Analytic via Glickenstein 2011 eq. (4.6) is planned research (Phase 9a.2-analytic).
When `SimplicialLDLT` fails (rank-deficient H — gauge mode on closed mesh without pinned vertex), the solver automatically retries with `Eigen::SparseQR` to find the minimum-norm step orthogonal to the null space. Public API: `solve_linear_system(H, rhs, &used_fallback)`.
The HyperIdeal Hessian is currently a **symmetric finite-difference approximation** (O(ε²), costs n extra gradient evaluations per Newton step). The analytic Hessian via the chain `(bᵢ, aₑ) → lᵢⱼ → ζ₁₃/ζ₁₄/ζ₁₅ → αᵢⱼ/βᵢ` is deferred to Phase 9b.
When `SimplicialLDLT` fails (rank-deficient H — gauge mode on a closed mesh without pinned vertex/face), the solver automatically retries with `Eigen::SparseQR` to find the minimum-norm step orthogonal to the null space. Public API: `solve_linear_system(H, rhs, &used_fallback)`.
### Layout and holonomy (`layout.hpp`)
@@ -248,8 +256,8 @@ Expected results: full test suite passing, 0 skipped, 0 failed. The canonical c
## Release state
Current release: **v0.7.0** (tag on `origin/dev`, PR to `main` open).
Phase 7 is complete. Phase 7.5 (Doxygen) and Phase 8 (CGAL package) are next.
Current release: **v0.9.0** (tag on `main`, released 2026-05-22).
Phases 19a complete, Phase 8b-Lite CGAL API surface complete (all 5 DCE models reachable via `<CGAL/Discrete_*.h>`), Phase 9b block-FD HyperIdeal Hessian shipped (~96× speed-up). Next planned milestones: Phase 9c (4g-polygon, genus g > 1) and Phase 9b-analytic (Schläfli identity). See `doc/release-policy.md` for the version-tag policy and `doc/roadmap/phases.md` for the phase plan.
## Phase 8 strategic decisions (2026-05-19)