Coefficient Workflows¶
This page is a quick map for staged coefficient work. The detailed examples remain in fitting, but the ownership split is:
ufp.leastsquares.CoefficientSelectorselects fitted or frozen coefficient blocks for direct least squares;ufp.coefficients.CoefficientSelectoris the same public selector, exposed next to coefficient-copy helpers for staged workflows;ufp.coefficientscopies, zeros, clones, and validates compatible physical coefficient channels;ufp.projectionwrites prior functions or existing spline channels into ordinary coefficient tensors before runtime evaluation starts;ufp.training.freeze_model_coefficients()applies the same selector language to optimizer-time freezing.
Selection¶
Use string blocks when whole families are enough:
from ufp.leastsquares import LinearFitter
LinearFitter(model, fit_blocks=["threebody"])
LinearFitter(model, freeze_blocks=["twobody"])
Use CoefficientSelector when a workflow needs one physical channel or a
specific knot range:
from ufp.coefficients import CoefficientSelector
from ufp.leastsquares import LinearFitter
selector = CoefficientSelector(
block="twobody",
channel=(1, 8),
coeff_slice=slice(2, 6),
)
LinearFitter(model, fit_blocks=[selector])
Pair and two-body channels use (Z_i, Z_j). Three-body and 2D-triplet channels
use source-distinguished triplets (Z_center, Z_neighbor_1, Z_neighbor_2);
neighbor entries are canonicalized according to the term’s symmetry rules.
Interchange¶
Use coefficient interchange when one fit should initialize another model without copying incompatible channels by position:
from ufp.coefficients import (
clone_model_with_zeroed_coefficients,
copy_matching_coefficients,
)
mixed = clone_model_with_zeroed_coefficients(mixed_template)
report = copy_matching_coefficients(source_model, mixed)
report.copied_count
report.skipped
The helpers validate channel identity, grid, cutoff, spline family, dtype,
device, active masks, symmetry, and category ordering. Use
copy_coefficient_channel() for one explicit source/target selector pair when
silent skipping would hide a workflow error.
Projection¶
Projection is offline model preparation. It samples a callable or existing spline channel, solves for spline coefficients, writes those coefficients into a normal term, and returns diagnostics:
import torch
from ufp.projection import project_radial_function
projection = project_radial_function(
lambda r: torch.exp(-r),
coeff_size=12,
full_support_start=0.0,
cutoff=6.0,
dtype=torch.float64,
)
projection.coeffs
projection.diagnostics.summary.max_value_rmse
Runtime term evaluation does not call projection code. After projection, least squares and training see ordinary coefficient tensors.
Freezing¶
The training freeze helper uses the same selector objects as least squares:
import torch
from ufp.coefficients import CoefficientSelector
from ufp.training import freeze_model_coefficients
freeze_state = freeze_model_coefficients(
model,
[CoefficientSelector(block="pair", coeff_slice=slice(0, 2))],
)
optimizer = torch.optim.AdamW(model.parameters(), lr=1.0e-3)
freeze_state.wrap_optimizer(optimizer)
The wrapper masks gradients, restores frozen entries after optimizer steps, and clears optimizer state entries for the frozen coefficients.