Skip to content

GBMSCApproximation

GBMSCApproximation builds the Grid-Based Multinode Shepard approximation on a SourceGrid.

from gbmsc_pde import GBMSCApproximation

approximation = GBMSCApproximation(
    grid,
    step=(2, 2),
    mu=2.005,
    support_mode="nodal_limit",
)

Purpose

The approximation blends local tensor-product Lagrange interpolants defined on sampled local subgrids. It is used for:

  • interpolation at arbitrary query coordinates,
  • sparse nodal differential operators,
  • rectangular LinearPDE assembly.

Constructor

GBMSCApproximation(
    grid,
    step=(1, 1),
    mu=2.005,
    eps=1e-12,
    support_mode="active",
)

Parameters:

  • grid: a SourceGrid.
  • step: sampled subgrid step.
  • mu: Shepard exponent parameter. It must satisfy mu > 2.
  • eps: defensive distance floor used by legacy/source-free paths.
  • support_mode: nodal LinearPDE support policy.

Support Modes

support_mode="active"

Uses only sampled subgrids containing the evaluated source node. This is the original sparse rectangular mode. It uses an eps-regularized nodal formula.

support_mode="all"

Uses active contributors at source nodes but normalizes with all sampled subgrids. This mode is useful for comparison but is more expensive and is not the recommended rectangular LinearPDE mode.

support_mode="nodal_limit"

Uses the source-node limiting formula. At a source node, all active subgrids share the same singular distance factor. This mode cancels that common factor before evaluating the normalized Shepard weights and their first and second derivatives.

For rectangular LinearPDE rows, this is the recommended mode for new experiments.

Important Attributes

  • approximation.grid: underlying SourceGrid.
  • approximation.step: sampled subgrid stride.
  • approximation.subgrids_step_grid: sampled local windows.
  • approximation.subgrids_step_row: sampled local windows flattened by row.
  • approximation.support_mode: selected nodal support policy.

Interpolation

values = grid.eval_function_at_nodes(lambda x, y: np.sin(np.pi * x) * np.sin(np.pi * y))
u_eval, = approximation.interpolator(xq, yq, values)

With first derivatives:

u_eval, ux_eval, uy_eval = approximation.interpolator(
    xq,
    yq,
    values,
    return_derivatives=True,
)

The interpolation path uses all sampled subgrids for arbitrary non-source query points.

Interpolation Modes

interpolator supports two distance policies:

approximation.interpolator(
    xq,
    yq,
    values,
    interpolation_mode="exact_nodal",
    tolerance=1e-12,
)

"exact_nodal" is the default. If a query point coincides with a source node within tolerance, the method returns the corresponding nodal value exactly. All other query points use true distances without an epsilon floor.

approximation.interpolator(
    xq,
    yq,
    values,
    interpolation_mode="regularized",
)

"regularized" preserves the legacy behavior: all query distances are floored by eps.

When return_derivatives=True and source-node hits are present, derivatives at the hit nodes are evaluated with first-derivative operator rows. If these operators were already built by a solver call, pass them to avoid rebuilding:

u, data = LinearSolver(pde, boundary_conditions).solve(return_data=True)
Mx, My = data["first_derivatives"]

u_eval, ux_eval, uy_eval = approximation.interpolator(
    xq,
    yq,
    u,
    return_derivatives=True,
    Mx=Mx,
    My=My,
)

For support_mode="nodal_limit", passing Mx and My reuses the same nodal-limit derivative matrices produced during the solve.