model_input package#

Writes interpreted geophysical information back into hydrological model inputs. This is the return leg of the coupling: model_output reads a simulation, and model_input writes a new one. The conversion step is explicit, so the relationship used to turn resistivity into a hydrological quantity stays a stated choice rather than a hidden default.

See Write updates back to hydrological models for the workflow these functions belong to.

Submodules#

PyHydroGeophysX.model_input.conversion module#

Maps an interpreted quantity onto a hydrological grid and prepares the update.

Explicit petrophysics and distance-limited transfer to hydrological grids.

class PyHydroGeophysX.model_input.conversion.HydroGrid(centers: ndarray, active: ndarray)[source]#

Bases: object

Cell centres in a shared metric XYZ frame; Z is elevation, increasing up.

active: ndarray#
centers: ndarray#
classmethod from_modflow(model)[source]#

Use FloPy cell centres, including model offsets and rotation.

classmethod from_parflow(config, *, active)[source]#

Build uniform-grid PFB centres, bottom-up. Supply an explicit domain mask.

Variable-dz / terrain-following grids need explicitly constructed centres.

class PyHydroGeophysX.model_input.conversion.MappedField(values: ndarray, updated: ndarray, distance: ndarray, source_index: ndarray)[source]#

Bases: object

Mapped values and an audit of which target cells were updated.

distance: ndarray#
source_index: ndarray#
updated: ndarray#
values: ndarray#
PyHydroGeophysX.model_input.conversion.interpret_resistivity(resistivity, *, rho_fluid, m, n, a=1.0, sigma_sur=0.0, porosity=None, saturation=None)[source]#

Infer S and water content given porosity, or porosity given known S.

Uses the package’s unscaled surface-conductivity convention: 1/rho = phi**m/(a*rho_fluid)*S**n + sigma_sur*S**(n-1). Supply exactly one of porosity or saturation. Parameters may be scalar or broadcast to rho.shape. n must exceed 1. No clipping or fallback is applied to physically incompatible observations. rho uses ohm-m; sigma_sur uses S/m.

PyHydroGeophysX.model_input.conversion.map_to_hydro_grid(source_xyz, values, grid, *, baseline, max_distance, source_valid=None)[source]#

Transfer nearest valid samples within an explicit distance; keep other cells.

source_xyz must be N×3 in the same CRS, metre units and vertical datum as grid.centers. No CRS guessing, depth-to-elevation conversion or extrapolation beyond max_distance is performed. This is point transfer, not conservative cell-volume averaging. Pass DOI/coverage exclusions through source_valid.

PyHydroGeophysX.model_input.conversion.prepare_hydro_updates(source_xyz, resistivity, grid, *, petrophysics, field_transforms, baselines, max_distance, source_valid=None)[source]#

Convert source cells, derive requested fields and map to writer-ready arrays.

field_transforms maps writer field names to either an interpreted field name (e.g. ‘porosity’) or a callable accepting the interpreted source dictionary. Use a calibrated callable for conductivity or a retention relation for pressure. Returns {field: MappedField}; pass each .values to the input writer.

PyHydroGeophysX.model_input.conversion.saturation_to_pressure(saturation, *, alpha, n, residual_saturation, saturated_pressure=None)[source]#

Invert van Genuchten for pressure head (negative in unsaturated cells).

alpha is inverse length; output uses that length unit. m=1-1/n. Fully saturated cells need an explicit pressure (scalar or matching array), because saturation alone cannot determine positive pressure. S at/below residual is rejected because its inverse pressure is unbounded.

PyHydroGeophysX.model_input.writers module#

Exports the mapped fields into a new MODFLOW 6 or ParFlow simulation directory, leaving the source model untouched.

Model-input adapters. Values must already be in the target grid and units.

PyHydroGeophysX.model_input.writers.write_modflow6_inputs(simulation, output_dir, updates, *, model_name=None)[source]#

Write a copy of a FloPy MF6 simulation with mapped GWF array updates.

Supported keys are hydraulic_conductivity (NPF k), vertical_conductivity (NPF k33), specific_storage (STO ss), specific_yield (STO sy), and initial_head (IC strt). bottom_elevation updates structured DIS layer bottoms and requires strictly positive layer thickness in every column. Arrays must match the model grid exactly, in model length/time units. Structured grids use (layer, row, column), top layer first. Existing packages are required; stress periods and boundary conditions remain as configured. This writes inputs only and never runs MODFLOW.

PyHydroGeophysX.model_input.writers.write_parflow_inputs(run, source_dir, output_dir, updates, *, domain='domain')[source]#

Copy a ParFlow workspace and write PFB updates plus a PFIDB definition.

Keys: permeability, porosity, initial_pressure. Values use the existing run’s units and (z, y, x) grid order, bottom layer first. Permeability retains the run’s tensor settings. Initial pressure is pressure head, not saturation. Other input files must be inside source_dir with relative paths. The source workspace is copied, including forcing files; no solver is run. run may be a ParFlow Run or a flat key/value dictionary from read_pfidb. Only the full-domain field is replaced; this is not a partial-facies update.

Module contents#

Export explicitly mapped hydrological updates without modifying source models.

class PyHydroGeophysX.model_input.HydroGrid(centers: ndarray, active: ndarray)[source]#

Bases: object

Cell centres in a shared metric XYZ frame; Z is elevation, increasing up.

active: ndarray#
centers: ndarray#
classmethod from_modflow(model)[source]#

Use FloPy cell centres, including model offsets and rotation.

classmethod from_parflow(config, *, active)[source]#

Build uniform-grid PFB centres, bottom-up. Supply an explicit domain mask.

Variable-dz / terrain-following grids need explicitly constructed centres.

class PyHydroGeophysX.model_input.MappedField(values: ndarray, updated: ndarray, distance: ndarray, source_index: ndarray)[source]#

Bases: object

Mapped values and an audit of which target cells were updated.

distance: ndarray#
source_index: ndarray#
updated: ndarray#
values: ndarray#
PyHydroGeophysX.model_input.interpret_resistivity(resistivity, *, rho_fluid, m, n, a=1.0, sigma_sur=0.0, porosity=None, saturation=None)[source]#

Infer S and water content given porosity, or porosity given known S.

Uses the package’s unscaled surface-conductivity convention: 1/rho = phi**m/(a*rho_fluid)*S**n + sigma_sur*S**(n-1). Supply exactly one of porosity or saturation. Parameters may be scalar or broadcast to rho.shape. n must exceed 1. No clipping or fallback is applied to physically incompatible observations. rho uses ohm-m; sigma_sur uses S/m.

PyHydroGeophysX.model_input.map_to_hydro_grid(source_xyz, values, grid, *, baseline, max_distance, source_valid=None)[source]#

Transfer nearest valid samples within an explicit distance; keep other cells.

source_xyz must be N×3 in the same CRS, metre units and vertical datum as grid.centers. No CRS guessing, depth-to-elevation conversion or extrapolation beyond max_distance is performed. This is point transfer, not conservative cell-volume averaging. Pass DOI/coverage exclusions through source_valid.

PyHydroGeophysX.model_input.prepare_hydro_updates(source_xyz, resistivity, grid, *, petrophysics, field_transforms, baselines, max_distance, source_valid=None)[source]#

Convert source cells, derive requested fields and map to writer-ready arrays.

field_transforms maps writer field names to either an interpreted field name (e.g. ‘porosity’) or a callable accepting the interpreted source dictionary. Use a calibrated callable for conductivity or a retention relation for pressure. Returns {field: MappedField}; pass each .values to the input writer.

PyHydroGeophysX.model_input.saturation_to_pressure(saturation, *, alpha, n, residual_saturation, saturated_pressure=None)[source]#

Invert van Genuchten for pressure head (negative in unsaturated cells).

alpha is inverse length; output uses that length unit. m=1-1/n. Fully saturated cells need an explicit pressure (scalar or matching array), because saturation alone cannot determine positive pressure. S at/below residual is rejected because its inverse pressure is unbounded.

PyHydroGeophysX.model_input.write_modflow6_inputs(simulation, output_dir, updates, *, model_name=None)[source]#

Write a copy of a FloPy MF6 simulation with mapped GWF array updates.

Supported keys are hydraulic_conductivity (NPF k), vertical_conductivity (NPF k33), specific_storage (STO ss), specific_yield (STO sy), and initial_head (IC strt). bottom_elevation updates structured DIS layer bottoms and requires strictly positive layer thickness in every column. Arrays must match the model grid exactly, in model length/time units. Structured grids use (layer, row, column), top layer first. Existing packages are required; stress periods and boundary conditions remain as configured. This writes inputs only and never runs MODFLOW.

PyHydroGeophysX.model_input.write_parflow_inputs(run, source_dir, output_dir, updates, *, domain='domain')[source]#

Copy a ParFlow workspace and write PFB updates plus a PFIDB definition.

Keys: permeability, porosity, initial_pressure. Values use the existing run’s units and (z, y, x) grid order, bottom layer first. Permeability retains the run’s tensor settings. Initial pressure is pressure head, not saturation. Other input files must be inside source_dir with relative paths. The source workspace is copied, including forcing files; no solver is run. run may be a ParFlow Run or a flat key/value dictionary from read_pfidb. Only the full-domain field is replaced; this is not a partial-facies update.