docs: correct why IndexSwarmVariable level sets keep inverse distance - #453
Conversation
The recorded reason was wrong. It argued that a material indicator is piecewise constant, so linear exactness has nothing to gain away from an interface and cannot help at one. That conflates two fields: the indicator is the PARTICLE data, but the quantity estimated at a node is the local material FRACTION, which near an interface is a smooth ramp -- precisely what a constants-only scheme cannot reproduce. The supporting measurement was also unsound: it applied a gather-form variant, which models update_type=1, while the shipped default is update_type=0, a scatter (each particle accumulates 1/d into its nearest node, masked by is_nearest). There is no stencil there to re-weight, so the branches have to be measured separately. Its interface metric grouped unstructured nodes into rows by y, and its maximum was set by node spacing rather than by the weights. Re-measured against a known analytic fraction: particles take material 1 with probability p(x) = x, so the exact nodal value is p(x_node). scheme bias rms range shipped update_type=0 (scatter) ~1e-3 0.09-0.11 [0, 1] shipped update_type=1 (gather) ~1e-3 0.18 [0, 1] gather order=1 ~1e-3 0.18-0.20 [-0.35, 1.32] The conclusion stands but the mechanism is variance, not bias. A node estimates the fraction from a handful of INTEGER samples, so Var(estimate) = sum_j w_j^2 Var(f_j). Uniform weights minimise sum(w^2) at 1/nnn; inverse distance stays near that floor while linear-exact weights, being signed, sit 6-12x above it -- and, unlike inverse distance, do not come down as the stencil grows: dim nnn sum w^2 IDW sum w^2 order=1 1/nnn amplification 2 6 0.223 2.314 0.167 10.4x 2 20 0.079 0.922 0.050 11.7x 3 6 0.188 1.290 0.167 6.9x 3 20 0.061 0.657 0.050 10.9x The bias linear exactness would remove is already ~1e-3 for every scheme, because a roughly symmetric stencil reproduces a linear ramp in expectation. Partition of unity holds for any weight sign (shared denominator, indicator flags sum to one per particle) and was never the objection. Actionable consequence: the lever for material-fraction accuracy is more samples per node, not better polynomial reproduction -- consistent with the scatter branch, which aggregates every particle nearest to a node, having the lowest rms. Script and output: ~/+Simulations/linear-rbf-proxy/step4_*. Underworld development team with AI support from Claude Code
Adversarial reviewThe new measurement still cannot resolve biasEvery scheme reports bias ~1e-3, and the run averages three seeds. That is not enough to claim the bias terms are equal — it is enough to say all are small compared with an rms of 0.1–0.2. If linear exactness removes a bias of, say, 5e-3 that inverse distance carries, this test would not see it, because the noise floor is two orders of magnitude larger and only three seeds are averaged. The claim in the doc is therefore stated as "already ~1e-3 for every scheme", not "identical". The stronger statement — that a symmetric stencil reproduces a linear ramp in expectation under inverse distance — is an analytical argument, not something this measurement establishes.
|
Documentation only. Corrects the reasoning recorded in #430 for leaving
IndexSwarmVariableon inverse-distance weighting. The conclusion is unchanged; the stated mechanism was wrong and the supporting measurement was unsound.What was wrong
The argument. It claimed a material indicator is piecewise constant, so linear exactness has nothing to gain away from an interface and cannot help at one. That conflates two fields: the indicator is the particle data, but the quantity estimated at a node is the local material fraction, which near an interface is a smooth ramp — precisely what a constants-only scheme cannot reproduce. Raised by the maintainer.
The measurement. It applied a gather-form variant, which models
update_type=1, while the shipped default isupdate_type=0— a scatter, where each particle accumulates1/dinto its nearest node (thek=nnnquery is masked byis_nearest). There is no stencil there to re-weight, so the branches must be measured separately. Its interface metric also grouped unstructured nodes into rows byy, and its maximum was set by node spacing rather than by the weights.Re-measured
Particles take material 1 with probability
p(x) = x, so the exact nodal fraction is a known linear function. Three seeds,cellSize1/16 and 1/32:update_type=0(scatter)[0, 1]update_type=1(gather)[0, 1]order=1[-0.35, 1.32]The actual mechanism: variance, not bias
A node estimates the fraction from a handful of integer samples, so
For weights summing to one, uniform weighting minimises
sum(w^2)at1/nnn. Inverse-distance weights are positive and stay near that floor; linear-exact weights are signed and sit well above it:nnnsum w²IDWsum w²order=11/nnnInverse distance averages the noise down as the stencil grows;
order=1barely moves. The noise cannot be bought off with more neighbours.The bias that linear exactness would remove is already ~1e-3 for every scheme, because a roughly symmetric stencil reproduces a linear ramp in expectation. Partition of unity holds for any weight sign (shared denominator; per-particle indicator flags sum to one) and was never the objection.
Consequence worth having
The lever for material-fraction accuracy is more samples per node, not better polynomial reproduction. That is consistent with the scatter branch — which aggregates every particle nearest to a node, typically many more than
nnn— having the lowest rms of the three.Script and output:
~/+Simulations/linear-rbf-proxy/step4_index_swarm_volume_fraction.{py,txt}. Docs build verified.Underworld development team with AI support from Claude Code