# Cross-validation potential of the Java `@Ignore`d tests

> **Purpose.** The upstream Java library (`de.varylab.discreteconformal`) has
> 22 test files with `@Ignore`d tests.  This document classifies them by *why*
> they are ignored and by their *cross-validation value for the C++ port*, so
> that the highest-value golden oracles get ported first.
>
> **Created:** 2026-05-29 (external-reviewer pass).  See also
> `doc/reviewer/java-port-audit.md` and PR #27 (`tests/java-golden-oracles`).

---

## 1 — Two root causes for `@Ignore`

| Cause | Count | Meaning for the C++ port |
|---|---|---|
| **`requires ARM64 PETSc native lib`** (class-level) | 15 files | **Not a logic problem.** Java solves via PETSc/TAO (native lib) which does not run on ARM64. The C++ port uses **Eigen** (no PETSc) and *can* run these scenarios — **iff** the feature is ported **and** the Java test carries a hard-coded expected value. |
| **Logic / known-issue** (method-level) | ~8 methods | Mostly mark **Java gaps** (no Hessian, layout unfinished) or **ARM64 FP flakiness**. Usually **not** reliable oracles. |

A critical distinction: PR #27 cross-validates **functional evaluations**
(energy/gradient — no solver, so no PETSc needed). The **full-solve** golden
values exist **only** as hard-coded vectors recorded from a historical x86
PETSc run — and those live exclusively in `HyperIdealConvergenceTest`.

---

## 2 — Already locked by PR #27 (do not duplicate)

`tests/java-golden-oracles` pins, bit-for-bit (1e-12), against compiled Java:
- `HyperIdealGoldenJava` — Clausen/Л/ImLi₂, ζ₁₃/₁₄/₁₅/ζ, both tetrahedron-volume formulas.
- `EuclideanGoldenJava` / `SphericalGoldenJava` — angle formulas, β relations, Л energy terms, **small full-mesh oracles** on a tetrahedron (gradient `Θ−Σα`, `ΔE = E(x)−E(0)`).
- `SphericalGoldenJava.FullMeshEdgeDofGradient` — edge-DOF gradient.
- `PeriodMatrix.NormalizeModulus_GoldenJava` — τ-reduction fold convention.

These cover the **unit math cores** and **functional evaluation**. They do
**not** cover **solver/convergence** or **full uniformization**.

---

## 3 — Priority ranking for new cross-validation

### 🟢 HIGH — real golden oracle, feature already in C++

| Item | Java source | Oracle | Blocker / effort |
|---|---|---|---|
| **HyperIdeal Lawson convergence** ✅ | `HyperIdealConvergenceTest.testHyperIdealConvergence` | **hard-coded golden u\*** (perfectly symmetric — robust to DOF order) | **DONE — PR #30** via low-level half-edge `make_lawson_square_tiled` (CGAL `add_face` can't: multi-edges, §5). |

Golden solution (Lawson square-tiled, BLMVM, tol 1e-10), 22 DOFs:
```
vertices (×4,  θ=2π)   : 1.1462158341786262
edges    (×12, θ=π/2)  : 1.7627471737467797 / …7866   (symmetric pair)
edges    (×6,  θ=π aux): 2.633915794495759
```
Assertion strategy: because the values are symmetric per DOF-class, assert
*per class* (every vertex DOF ≈ 1.14621…, every π/2-edge ≈ 1.76274…, every
π-edge ≈ 2.63391…) to 1e-6 — **no DOF-order fidelity required**.

### 🟡 MEDIUM — golden/strong oracle, needs asset or near-term phase

| Item | Java source | Oracle | Blocker |
|---|---|---|---|
| **Genus-1 uniformization** | `UniformizerTest.testGenus1` (Wente, 1240 V) | angle-sum = 2π + vertex count (self-consistency) | needs `wente.obj` asset + a "load OBJ → uniformize" path; C++ Euclidean solver exists. |
| **HyperIdeal Lawson + branch points** ✅ | `…WithBranchPoints` | hard-coded golden u\* | **DONE — PR #30** (stellar subdivision + ideal centres; per-class symmetric @1e-4). |
| **HyperIdeal layout** | `HyperIdealLayoutTest` | layout positions | needs the generator + `layout.hpp` hyper-ideal path exercised. |
| **Euclidean big-model scale** | `EuclideanUnwrapperPetscTest.testStaticUnwrapBigModel` | mostly self-check | scale/robustness cross-check; low oracle strength. |

### 🔵 LATER — feature not yet in C++ (Phase 9d.2 / 10c / 13 / 11)

| Item | Java source | Maps to |
|---|---|---|
| Genus-2 uniformization | `UniformizerTest.testGenus2` (Lawson 2498) | Phase 10c / 13 |
| HyperIdeal hyperelliptic convergence | `…HyperEllipticCurveLawson` (has golden u\*) | Phase 13 |
| Hyperbolic disk uniformization | `HyperbolicDiskUniformizationTest` | Phase 10c (gated on holonomy bug) |
| Möbius centring (grad/Hessian/convergence golden) | `MobiusCenteringFunctionalTest` | Phase 9d.4 |
| Quasi-isothermic suite (SinCondition, SNES, Utility, Layout, ConformalStructure) | `…quasiisothermic.*` | Phase 10e |
| Schottky uniformisation | `SchottkyUtilityTest` | Phase 11a |
| Circle-domain (multiply-connected) | `CircleDomainUnwrapperTest` | Phase 11c |
| Electrostatic-sphere baseline | `ElectrostaticSphereFunctionalTest` | Phase 10c′ (optional) |

### ⚪ NON-ORACLE — do **not** port as cross-validation

| Item | Why it is not an oracle |
|---|---|
| `HyperIdealFunctionalTest.testHessian` (`@Ignore@Override`, empty) | Java has **no** HyperIdeal Hessian (`hasHessian()==false`). C++ *adds* it (block-FD, Phase 9b) → validate against C++ FD, not Java. Documents the C++ delta. |
| `ElectrostaticSphereFunctionalTest.testHessian` | same — Hessian not implemented in Java. |
| `HyperbolicLayoutTest.testDoLayout` | throws `"Not implemented correctly yet!"` — **Java itself unfinished**; no reference to validate against. |
| `SurfaceCurveUtilityTest.testCreateSurfaceCurves` | known issue: non-deterministic edge count on ARM64 — **flaky**, not a stable oracle. |
| `HyperbolicCyclicConvergenceTest.testEuclideanConvergence` | known issue: ARM64 FP accumulation, angle sum outside 1e-8 — **flaky**. |
| `HyperIdealUtilityTest.testZeta13` | asserts ζ₁₃(0.1,0.1,0.1)=0.1, which looks **wrong**; the other volume/ζ tests already run and are ported. Verify the correct value before any use. |
| `HyperIdealPluginTest` | plugin/TAO-application wiring, not pure math. |
| `TwoHoleExample.testLetterB` | demo/example, no assertion of record. |
| `SphericalUnwrapperTest` PETSc variants | the **MTJ** variants (not ignored) already cover the same cases on `cathead`. |

---

## 3b — Effort-adjusted tiering (2026-05-29 inventory)

> A broader scan (not just `@Ignore`d tests) revealed that the §3 ranking was
> **effort-blind**: cheaper, equally-valuable oracles exist than the Lawson
> generator. Re-tiered by **value / cost**:

| Tier | Oracle | Mesh / asset | Solver | Golden | C++ status | Cost |
|---|---|---|---|---|---|---|
| **1** | `EuclideanCyclicConvergenceTest` | `cathead.obj` *(already in C++)* | MTJ BiCGstab (no PETSc) | `α_opp+α_opp = π−0.1` @1e-12 (per-edge φ target) | `euclidean_functional` ✅, `phi_e` ✅, cathead ✅ | **near-zero** |
| **1** | `SphericalConvergenceTest` | octahedron | MTJ Newton (no PETSc) | self-consistency (const. curvature) | spherical ✅, `make_octahedron_face` ✅ | low |
| **2** | Wente genus-1 uniformization | `wente_torus02.obj` + `wente_uniformization.xml` | — (stored result) | exact `IsometryPSL2R` uniformizing-group generators | holonomy/`MobiusMap` ✅; **needs XML reader** | medium |
| ~~2~~ → **4** | `regular_uniformization.xml`, `LetterB01_canonical_group.xml` | (stored) | — | full `IsometryPSL2R` Fuchsian group + 12-edge `FundamentalPolygon` | **genus ≥ 2 hyperbolic** (not genus-1) → Phase 13 | future |
| **3** ✅ | HyperIdeal Lawson convergence — plain + branch-points | low-level half-edge `make_lawson_square_tiled` | `newton_hyper_ideal` | hard-coded golden u\* | **DONE — PR #30** (`test_lawson_hyperideal.cpp`) | done |
| **3** ⏸️ | HyperIdeal Lawson **hyperelliptic** | `lawson_curve_source.xml` + `HyperIdealHyperellipticUtility` | — | non-symmetric golden u\* | **deferred** — needs XML-format reader + jReality-geometry θ port | future |
| **4** | genus-2 (`genus2.xml`/`lawson2498.obj`), holomorphic forms (`HolomorphicEuclideanUniformization_*.xml`), Schottky (`genus2.xml`) | assets present in Java | — | various | Phases 10a/10c/11/13 | future |

**Tier-2 status (2026-05-30): exhausted.** The only genus-1 case is Wente
(deferred to Phase 9f, quad/cyclic). `regular_uniformization.xml` and
`LetterB01_canonical_group.xml` are **genus ≥ 2 hyperbolic** uniformizations
(full PSL(2,ℝ) Fuchsian groups + a 12-edge fundamental polygon) → Phase 13, not
Tier 2.

**Tier-3 status (2026-05-30): DONE for plain + branch-points (PR #30).** The
Lawson base is a genus-2 surface with **4 vertices / 12 edges → multi-edges**, so
CGAL `add_face`/OFF/polygon-soup cannot build it; `make_lawson_square_tiled`
(`test_lawson_hyperideal.cpp`) uses the **low-level Surface_mesh half-edge API**
(`add_edge` + `set_target`/`set_next`/`set_face`/`set_halfedge`), then
`triangulate_faces` (plain) or `Euler::add_center_vertex` (branch-points,
stellar). Two key findings made this clean:
1. The golden vectors are **symmetric per geometric class**, so the external jtem
   `Triangulator`/`StellarLinear` orderings need **not** be replicated — any
   consistent triangulation/stellar reproduces the values.
2. Java's index-based θ split is actually **geometric** (original vs diagonal;
   base vs spoke); branch-point centres are **ideal vertices** (b = 0).

`newton_hyper_ideal` converges (from x0 = 1.0, **unconstrained** — Java needed
bounded BLMVM) to both golden vectors:
- plain: vertices 1.1462158341786262 / original 1.7627471737467797 / aux 2.633915794495759
- branch-points: vertices 1.3169579 / base 2.2924317 / spokes 0

**Hyperelliptic (the 3rd Lawson variant) is deferred (option c).** It needs a
reader for `lawson_curve_source.xml` (Java conformal-data `HalfedgeEmbedding`,
26 vtx / 144 half-edges, a *cut* surface) **and** a port of
`HyperIdealHyperellipticUtility.calculateCircleIntersections`, which derives θ via
jReality `Pn` (elliptic/hyperbolic), `MatrixBuilder` (rotate / hyperbolic
translate) and stereographic projection. Its golden vector is **not**
class-symmetric (mixed ±values), so no symmetry shortcut — mesh and θ must match
exactly. Viable approaches: (A) port the jReality geometry, or (B) run a Java
dumper for θ + connectivity (no PETSc needed) and hard-code them. Both are
multi-step with numerical-replication risk → its own future task.

**Key correction:** the Lawson generator (originally flagged HIGH) is actually
**Tier 3** — higher effort than Tier 1/2. Cheapest first wins:

1. **Tier 1 — `EuclideanCyclicConvergenceTest` on cathead** (asset already
   present; the C++ edge gradient `G_e = α_opp(f⁺)+α_opp(f⁻) − φ_e` makes the
   Java assertion `α_opp+α_opp = π−0.1` exactly the converged `G_e = 0`
   condition with `phi_e = π−0.1`). Fails if the solver ignores a non-default
   `φ`, so it is a genuine check, not a tautology.
2. **Tier 1 — `SphericalConvergenceTest`** on the octahedron.
3. **Tier 2 — Wente genus-1 uniformization** — deferred to Phase 9f (quad/cyclic
   pipeline; `wente_torus02.obj` is a quad mesh, not triangle).
4. **Tier 3 — Lawson generator** — ✅ DONE (PR #30): plain + branch-points golden
   oracles GREEN; hyperelliptic deferred (option c).

### Status summary (2026-05-30)
- **Tier 1** ✅ done (PR #29): cyclic φ oracle + full analytic edge-DOF Hessian.
- **Tier 2** — exhausted; Wente → Phase 9f, the rest → Phase 13.
- **Tier 3** ✅ done (PR #30): plain + branch-points Lawson golden oracles;
  hyperelliptic deferred.

### Build-verification finding (2026-05-29) → resolved (2026-05-30)

Attempting the Tier-1 `EuclideanCyclicConvergenceTest` port **build-verified** a
blocker first: `newton_euclidean` → `euclidean_hessian` threw *"edge DOFs are
not supported"*. The cyclic functional needs **vertex + edge** DOFs (the
*gradient* supported them; the *analytic cotangent Hessian* did not). That is
why PR #27 cross-validated only the cyclic *evaluation*, never a solve.

**Resolved (2026-05-30):** implemented a **block-FD edge-DOF Euclidean Hessian**
(`euclidean_hessian_block_fd` / `_sym` in `euclidean_hessian.hpp`, mirroring
`hyper_ideal_hessian_block_fd`); `newton_euclidean` now routes cyclic layouts
(edge DOFs present) through it, vertex-only layouts still use the analytic
cotangent Laplacian.

**Landed (`test_euclidean_functional.cpp`, all GREEN, 259/259 cgal tests pass):**
- ✅ `CyclicCircularEdge_PhiEntersGradient_CatHead` — solver-free check that the
  circular-edge φ enters the gradient exactly (`ΔG_e = −Δφ_e` @1e-12).
- ✅ `CyclicCircularEdge_CatHead_JavaXVal` — **the full Java convergence
  oracle**: prescribe φ = π−0.1 on one interior ("circular") edge of cathead,
  solve the cyclic Newton, assert the realised `α_opp+α_opp = π−0.1` @1e-9.
- ✅ `CyclicHessian_BlockFD_MatchesGradientFD_Tetrahedron` — the block-FD edge-DOF
  Hessian matches the column-wise gradient FD on the full cyclic layout.

> DOF note: only the **single** circular edge gets an edge DOF (as in Java's
> one `circularHoleEdge`). Giving *every* edge a DOF makes λ_e redundant with
> u_i+u_j (a V-dim null space) and stalls Newton.

Spherical convergence (Tier-1 #2) was found **already covered** by
`test_newton_solver` (`Spherical_ConvergesFromPerturbation` et al.), and
`make_octahedron_face()` is a single face, not a closed octahedron — so it adds
little.

### Tier-2 (Wente) finding (2026-05-30) — needs a quad/cyclic pipeline

`wente_torus02.obj` is a **quad mesh** (1240 quads, genus 1), and the Java
`wente_uniformization.xml` golden (uniformizing group → τ = (√2+i√6)/(2√2) =
½ + i·√3/2, the hexagonal torus) comes from Java's **cyclic (quad) net**
uniformization. The C++ period-matrix pipeline (`run_torus_pipeline`) is
**triangle-based**, so a faithful bit-vs-Java comparison would require triangulating
(which changes the discrete conformal structure → no exact match) or a
**quad/cyclic period-matrix pipeline** — that belongs to **Phase 9f** (general
polygon meshes), not the triangle path. → Tier 2 deferred to Phase 9f; the
hexagonal golden τ is recorded here for when that lands.

### Done instead (2026-05-30): full analytic edge-DOF Hessian
With Tier-2 gated on a quad pipeline, the higher-value clean win was upgrading
the cyclic Hessian from block-FD to **fully analytic** (closed-form
`∂α_i/∂s_i = ℓ_i²/4A`, `∂α_i/∂s_j = ½cot α_i − ℓ_j²/4A`), satisfying the
`novelty-statement.md §3.2` "analytic Hessians, not finite difference" claim for
the Euclidean path. Verified against block-FD and gradient-FD.

### Other generators in the Java tree
`HyperellipticCurveGenerator` (→ Phase 13), `SchottkyGenerator` (→ Phase 11a),
`FunctionalTest.createOctahedron/createTetrahedron` (trivial — C++ has
`make_octahedron_face` / `make_tetrahedron`).

---

## 4 — Recommended order of work

1. ✅ **DONE (PR #29)** — Tier 1: cyclic φ oracle + full analytic edge-DOF Hessian.
2. ✅ **DONE (PR #30)** — Tier 3: `make_lawson_square_tiled()` (low-level
   half-edge; §5) + plain & branch-points golden oracles (per-class symmetric,
   no DOF-order matching needed).
3. ⏸️ **Deferred** — Lawson **hyperelliptic** variant (XML-format reader +
   `HyperIdealHyperellipticUtility` / jReality θ; non-symmetric golden).
4. ⏸️ **Phase 9f** — Wente genus-1 uniformization (quad/cyclic pipeline).
5. **Phase 10a/10c/11/13** — LATER items (genus-2, holomorphic forms, Schottky);
   golden u\* / data recorded in the Java tests for reuse then.

---

## 5 — Why the Lawson mesh needs a low-level generator

`HyperIdealGenerator.createLawsonSquareTiledBase()` builds a **genus-2**
surface with **4 vertices and 12 edges** (24 half-edges), then triangulates
6 quad faces (adding 6 diagonal "aux" edges, θ=π; the 12 originals get θ=π/2).

With only 4 vertices and 12 edges, **most vertex pairs carry more than one
edge** (multi-edges). CGAL `Surface_mesh::add_face` and polygon-soup builders
key edges by their endpoint vertex pair and therefore **cannot represent
multi-edges** — they would either fail or glue the surface into the wrong
topology. Java sidesteps this with explicit half-edge IDs and
`linkOppositeEdge` / `linkNextEdge`.

The C++ port must replicate this with the **low-level half-edge API**
(`add_vertex`, `add_edge`, and explicit `set_next` / `set_target` /
`set_face` connectivity), mirroring the exact opposite/next links from
`createLawsonSquareTiledBase()` (edges 0–23). The symmetric golden vector
then makes the resulting test robust even though CGAL's DOF ordering differs
from Java's.
