Skip to content

Tracking from Head Maps (SSP&A Workflow)

When to Choose SSP&A

The S.S. Papadopulos & Associates (SSP&A) method is ideal when you have a map of hydraulic heads (e.g., from a regional model or interpolated field data) but lack the detailed cell-by-cell flow budgets required by the Waterloo method. It provides a smooth, kriged velocity field that can be augmented with analytic elements (drifts) to represent local features like pumping wells.

Required Inputs Checklist

Input Type Shape Notes
grid GridHandle N/A The model geometry (passed to fit_sspa()).
heads np.ndarray[float64] (N,) Hydraulic head for each cell.
hydraulic_conductivity or hhk np.ndarray[float64] (N,) Hydraulic conductivity for each cell. Provide exactly one.
porosity np.ndarray[float64] (N,) Porosity for each cell.
well_mask np.ndarray[bool] (N,) Boolean array over cells indicating cells with wells.
config SspaConfig N/A Fitting configuration (search_radius, krig_offset).
drifts list[dict] N/A List of drift definitions (see Drift Schema).

Note: N is the total number of cells in the grid.

Step-by-Step Workflow

1. Build the Grid

First, create the model grid using mp3du.build_grid(). This requires defining the cell vertices and centers.

2. Prepare Input Arrays

Prepare the required 1D numpy arrays for heads, conductivity, porosity, and well_mask. Ensure they all have a length equal to the number of cells in the grid.

3. Hydrate SSP&A Inputs

Use mp3du.hydrate_sspa_inputs() to package the arrays into an SspaInputs object.

4. Define Drift Elements

Create a list of dictionaries defining any analytic elements (wells, line-sinks, no-flow boundaries) that should be superimposed on the velocity field.

5. Fit the Velocity Field

Call mp3du.fit_sspa(config, grid, inputs, drifts) with an SspaConfig, the grid, hydrated inputs, and drift list to generate the VelocityFieldHandle. Note: well_mask is part of the hydrated SspaInputs, not a separate argument.

6. Configure and Run Simulation

Create a SimulationConfig, define ParticleStart locations, and call mp3du.run_simulation() using the fitted velocity field.

Common Mistakes

Passing Both conductivity Arguments

When calling hydrate_sspa_inputs(), you must provide either hydraulic_conductivity OR hhk (an alias for the same thing), but not both.

Mismatched Array Lengths

All input arrays (heads, conductivity, porosity, well_mask) must have exactly the same length as the number of cells in the grid.

well_mask Shape Confusion

The well_mask is a boolean array over cells (1D array covering all cells), not a list of well indices or coordinates.

Reusing GridHandle After Fitting

The GridHandle is consumed by fit_sspa(). If you need to run multiple simulations or fit different fields, you must recreate the grid or clone it (if supported).

Unsupported Drift Types

Ensure the type key in your drift dictionaries is one of the supported string values: well, linesink (or line_sink, line-sink), noflow (or no_flow, no-flow). Integer aliases are not supported.

Zero-Length Line Segments

For linesink and noflow drifts, the start (x1, y1) and end (x2, y2) coordinates must not be identical.

Expecting Line/NoFlow Capture

While line-sinks and no-flow boundaries influence the velocity field, particles will not currently be captured (terminated) or reflected by them. Only well capture is fully implemented.

Underestimating Fitting Time

The SSP&A fitting process uses kriging, which has an O(n²) computational cost. For large grids, this step can take a significant amount of time.

Next Steps