Skip to content

Latest commit

 

History

History
118 lines (99 loc) · 6.75 KB

File metadata and controls

118 lines (99 loc) · 6.75 KB

Development notes

How some of the answers in FIDELITY.md were arrived at, kept for the record. Nothing here is needed to use pyVIDE. It is here because several of these answers took more than one attempt, and the failed attempts are worth recording.

Three plausible misreadings

Three times the obvious reading of VIDE's C was the wrong one, and reading the line more carefully never helped. What settled each case was the surrounding C: the types, and the places the same value is used elsewhere.

e_computer is not E(z). VIDE's generateMock.cpp:150 displaces the line-of-sight coordinate with z += v/(100*e_computer(z0));, which reads like v / (100 E). Earlier in the same file, TotalExpansion::operator() returns 1/sqrt(Omega_M*cube(1+z) + Omega_L), the inverse expansion function. The proof is elsewhere in the same file, where the same object is integrated to get a comoving distance, and the integrand of D(z) is 1/E, not E. So VIDE's displacement is $v \cdot E(z)/100$. An early pyVIDE computed $v/(100 E)$, wrong by a factor $E(z)^{2}$: 1.29 at $z = 0.25$ and 3.1 at $z = 1$ for $\Omega_M = 0.30$, the cosmology of the table in FIDELITY.md. That is a physics-scale error, not a rounding one, and it survived because previous VIDE reference runs had doRSD=False, so the stages that check every other number in the pipeline say nothing about that line. tests/test_rsd.py now transcribes TotalExpansion independently and asserts both that pyVIDE matches it and that the wrong reading is measurably different, so the test can actually fail.

runsum is not a plain sum. In vozutil.c::vorvol, the squared displacement that positions every Voronoi half-plane is accumulated in a C float while the products around it are doubles. That moves every plane by about $10^{-7}$ and changes roughly a third of the volumes in their last bits. Because scipy bundles its own qhull, a version difference there is the natural suspect for such a disagreement, but the wrong one. Reproducing the cast is what makes the volumes bit-identical.

A stored type is not an evaluation type. pruneVoids.cpp:626 decides membership of the central sphere with if (sqrt(dist2) < centralRad). Both operands are C floats, so the natural reading is a single-precision comparison, but sqrt() returns a double and centralRad promotes to meet it, so the comparison happens in double. Rounding to float32 first would move any member whose distance sits within half a float32 ulp of the boundary, and that void's centralDen would be off by 1/numCentral, 30 to 50 % for a typical count of two or three. The rate is about one member-test in $10^{7}$, so roughly 0.1 members across the whole 1.2 M reference catalog, which is why the verification reported centralDen exact even against an implementation that got this wrong.

The 'fast' volume route: how far the agreement goes

'fast' falls back to the exact route for a cell whenever that cell touches a guard point, or its corner is hard to locate precisely. That is not a guarantee of agreement everywhere. On a well-buffered run with no guard warnings, 15 cells out of 3 766 742 came out different from 'exact', by a few parts in a million, and none of them was one of those two kinds. Why they differ is not known. One configuration that can potentially produce such a difference is known: neighbours lying almost exactly on a common sphere, as on a regular grid with tiny displacements. On a 16^3 lattice displaced by 1e-4 of the spacing, 8 of 4096 cells differ from the values using 'exact' in VIDE_halos and none in float64, and the per-cell check does not flag them, because the tetrahedra involved are not flat. Whether the 15 cells above are of this kind has not been checked.

The obvious suspect was a very flat tetrahedron, which is exactly the case that makes a corner hard to place. Sending those cells down the exact route as well changed nothing, so that is not the reason either. On realistic tracer sets the effect has never appeared on a test box small enough to ship and the lattice above is only an artificial configuration where it might appear. The only evidence for real catalogs is the two full-catalog comparisons, and the honest scope of 'fast' is the measured one in FIDELITY.md.

Three details that could only be measured

Three details of doRSD='VIDE' cannot be read from VIDE's repository at all. They live in a struct the build downloads from CosmoTool, so the source you can clone does not contain them: whether the peculiar velocity and Omega_M reach the displacement as float32 or at full precision, and whether the redshift arrives through a float32 scale-factor round trip.

pyVIDE once guessed all three from a third-party copy of that struct, and one guess was wrong: there is no scale-factor round trip, so the redshift arrives undegraded. Only a comparison against VIDE's own output could settle it, and that comparison is now stage S5. The three casts in rsd.py are measurements. Do not replace them with what a copy of the struct appears to say.

Two kinds of evidence

The claims about VIDE in these docs do not all rest on the same thing.

Most of them are measured. The table in FIDELITY.md compares whole catalogs against a frozen VIDE run, column for column and row for row, at five merging thresholds and across all eight pruned variants. Every column VIDE also writes is covered there, so "densCon matches VIDE" rests on one run against another, not on anyone's reading of the source. The 'pyvide'-against-'VIDE_halos' numbers in that page come from two scripts in the Zenodo dataset record next to the harness: compare_modes.py lines two runs of the same tracers up on input rows, pairs their zones by core particle and reports what differs; compare_merging.py does the same for the merged voids of two catalogs at the same threshold, comparing the set of zones each void absorbed.

The rest are read from VIDE's code: that isLeaf means "has a parent", that jozov2 leaves single-tracer zones out of voidDesc, that VIDE keeps only the rescaled centralDen, that its scripts feed mergingThreshold into maxCentralDen. These agree with the measurements, but no measurement tests them one at a time, and this page opens with three cases where a plausible reading was wrong.

So a page saying pyVIDE reproduces a VIDE number is the first kind of evidence. A page explaining why VIDE behaves as it does is the second.

Numbers measured once and then left alone

A few figures in the documentation come from single runs on data that is not shipped, and they are marked "(measured)" wherever they appear. They are not reproducible from this repository, and they are not tests. The ones that are tests carry "(checked by tests/…)" instead, and you can run those yourself.