Spatially varying anisotropy#
Spatially varying anisotropy (SVA) lets the variogram behaviour change from one estimation block to the next. Use it when the continuity direction, effective range, or local uncertainty is not constant across the domain.
KrigeKit supports three levels of spatial variation:
rangescale: a per-block multiplier on the effective variogram range.localnugget: a per-block additional nugget term.varying_vgm=Trueplusset_vgm_block: a full per-block variogram model, including block-specific ranges and rotation angles.
Range scale#
rangescale is the lightest-weight SVA option. It scales the lag vector
before variogram evaluation:
h_scaled = h / rangescale[ib]
Values greater than 1 make observations behave as if they are closer together, which increases the effective range and usually lowers kriging variance. Values between 0 and 1 shorten the effective range.
import numpy as np
from krigekit import Kriging
rng = np.random.default_rng(42)
obs_coord = rng.uniform(0, 100, (80, 2))
obs_value = rng.normal(0.0, 1.0, 80)
x, y = np.mgrid[0:101:5, 0:101:5]
grid_coord = np.column_stack([x.ravel(), y.ravel()])
# Longer continuity in the eastern half of the grid.
rangescale = np.where(grid_coord[:, 0] > 50.0, 2.0, 0.75)
k = Kriging(ndim=2, nvar=1)
k.set_obs(ivar=1, coord=obs_coord, value=obs_value)
k.set_vgm(ivar=1, jvar=1, vtype="sph", nugget=0.05, sill=0.95, a_major=35.0)
k.set_grid(coord=grid_coord, rangescale=rangescale)
k.set_search(ivar=1, nmax=24)
k.solve()
est, var = k.get_results()
rangescale must have one value per point-kriging node. For block kriging,
pass one value per block, not one value per quadrature sub-node.
Local nugget#
localnugget adds local uncertainty at each estimation block. It is useful
for locations where the target support or measurement quality varies over
space, for example a zone where the mapped variable is known to be less
reliable.
localnugget = np.zeros(len(grid_coord))
localnugget[grid_coord[:, 1] > 75.0] = 0.10
k = Kriging(ndim=2, nvar=1)
k.set_obs(ivar=1, coord=obs_coord, value=obs_value)
k.set_vgm(ivar=1, jvar=1, vtype="sph", nugget=0.05, sill=0.95, a_major=35.0)
k.set_grid(coord=grid_coord, localnugget=localnugget)
k.set_search(ivar=1, nmax=24)
k.solve()
est, var = k.get_results()
You can use rangescale and localnugget together:
k.set_grid(
coord=grid_coord,
rangescale=rangescale,
localnugget=localnugget,
)
Defaults are rangescale=1.0 and localnugget=0.0 for every block, so
omitting both gives ordinary global-variogram kriging.
Per-block variograms#
For full SVA, construct the object with varying_vgm=True, call set_grid,
then call set_vgm_block for each block. Block indices are 1-based.
k = Kriging(ndim=2, nvar=1, varying_vgm=True)
k.set_obs(ivar=1, coord=obs_coord, value=obs_value)
k.set_grid(coord=grid_coord)
for ib, (gx, gy) in enumerate(grid_coord, start=1):
if gx < 50.0:
# Western domain: NW-SE continuity.
azimuth = 315.0
a_major = 45.0
a_minor = 18.0
else:
# Eastern domain: NE-SW continuity.
azimuth = 45.0
a_major = 70.0
a_minor = 25.0
k.set_vgm_block(
ib=ib,
ivar=1,
jvar=1,
vtype="sph",
nugget=0.05,
sill=0.95,
a_major=a_major,
a_minor1=a_minor,
azimuth=azimuth,
)
k.set_search(ivar=1, nmax=24)
k.solve()
est, var = k.get_results()
Call set_vgm_block multiple times for the same block to build a nested
model. Product covariance groups are not supported for per-block variograms.
Block kriging#
Both rangescale and localnugget are also available on set_grid_block.
The arrays are sized by block:
k.set_grid_block(
coord=block_points,
block_type=1,
nblockpnt=nblockpnt,
pointweight=pointweight,
rangescale=block_rangescale, # shape (nblock,)
localnugget=block_localnugget, # shape (nblock,)
)
Choosing an SVA mode#
Need |
Use |
|---|---|
Regional range gets longer or shorter |
|
Local estimation uncertainty changes |
|
Continuity direction rotates over space |
|
Full per-block variogram parameters |
|
rangescale and localnugget are usually the best starting point because they
reuse one global variogram model and only add per-block modifiers. Use
per-block variograms when the anisotropy orientation or nested structures
really need to vary by location.
Practical checks#
Keep
rangescalepositive.Make
rangescaleandlocalnuggetarrays the same length as the number of point grid nodes, or the number of blocks for block kriging.For
set_vgm_block, callset_gridfirst and use 1-based block indices.Start with smooth spatial fields for SVA parameters; abrupt changes can create sharp changes in variance and weights.
See also#
../auto_examples/s_ok2d_sva - runnable SVA gallery example
Ordinary kriging - basic
KrigingworkflowVariogram models - model types and anisotropy
Performance tuning -
nthread,ncache, and factor reuseAPI reference - full
Krigingclass documentation