Source code for hydromodpy.physics.transport.transport
from __future__ import annotations
from collections.abc import Mapping
from dataclasses import dataclass, field
from typing import Annotated, Any
from pydantic import Field
from hydromodpy.core.config_kit.base import HydroModelBase
from hydromodpy.core.config_kit.profile import Profile
from hydromodpy.physics.base import ProcessSpatial
from hydromodpy.physics.transport.transport_config import TransportConfig
@dataclass
class _TransportComponent:
"""Simple container exposing a `.parameters` mapping."""
parameters: dict[str, Any] = field(default_factory=dict)
def set_parameters(self, parameters: Mapping[str, Any] | None = None, **kwargs) -> None:
if parameters is not None:
self.parameters.update(dict(parameters))
if kwargs:
self.parameters.update(kwargs)
class TransportInitialConditions(HydroModelBase):
"""Transport initial-condition wrapper."""
payload: Annotated[dict[str, Any], Profile.USER] = Field(
default_factory=dict,
description="Transport-specific initial-condition mapping.",
)
[docs]
class Transport(ProcessSpatial[TransportInitialConditions]):
def __init__(self, config: TransportConfig | Mapping[str, object] | None = None):
super().__init__()
self.config: TransportConfig | None = None
self.modpath = _TransportComponent()
self.mt3dms = _TransportComponent()
self.modflow6gwt = _TransportComponent()
self.modflow6prt = _TransportComponent()
if config is not None:
self.set_config(config)
def set_config(self, config: TransportConfig | Mapping[str, object]) -> None:
if isinstance(config, TransportConfig):
transport_cfg = config
elif isinstance(config, Mapping):
transport_cfg = TransportConfig.model_validate(dict(config))
else:
raise TypeError("Transport config must be a TransportConfig instance or a mapping")
self.config = transport_cfg
self.modpath.set_parameters(transport_cfg.modpath.parameters.model_dump())
self.mt3dms.set_parameters(transport_cfg.mt3dms.parameters.model_dump())
self.modflow6gwt.set_parameters(transport_cfg.modflow6gwt.parameters.model_dump())
self.modflow6prt.set_parameters(transport_cfg.modflow6prt.parameters.model_dump())
self.parameters["modpath"] = self.modpath.parameters
self.parameters["mt3dms"] = self.mt3dms.parameters
self.parameters["modflow6gwt"] = self.modflow6gwt.parameters
self.parameters["modflow6prt"] = self.modflow6prt.parameters
def set_parameters(self, parameters: dict):
if not isinstance(parameters, Mapping):
raise TypeError("Transport parameters must be provided as a mapping")
modpath_payload = parameters.get("modpath")
if isinstance(modpath_payload, Mapping):
nested = modpath_payload.get("parameters", modpath_payload)
if isinstance(nested, Mapping):
self.modpath.set_parameters(nested)
mt3dms_payload = parameters.get("mt3dms")
if isinstance(mt3dms_payload, Mapping):
nested = mt3dms_payload.get("parameters", mt3dms_payload)
if isinstance(nested, Mapping):
self.mt3dms.set_parameters(nested)
modflow6gwt_payload = parameters.get("modflow6gwt")
if isinstance(modflow6gwt_payload, Mapping):
nested = modflow6gwt_payload.get("parameters", modflow6gwt_payload)
if isinstance(nested, Mapping):
self.modflow6gwt.set_parameters(nested)
modflow6prt_payload = parameters.get("modflow6prt")
if isinstance(modflow6prt_payload, Mapping):
nested = modflow6prt_payload.get("parameters", modflow6prt_payload)
if isinstance(nested, Mapping):
self.modflow6prt.set_parameters(nested)
self.parameters.update(dict(parameters))
self.parameters["modpath"] = self.modpath.parameters
self.parameters["mt3dms"] = self.mt3dms.parameters
self.parameters["modflow6gwt"] = self.modflow6gwt.parameters
self.parameters["modflow6prt"] = self.modflow6prt.parameters
[docs]
def build_initial_conditions(
self,
initial_conditions: object | None,
) -> TransportInitialConditions | None:
if initial_conditions is None:
return None
if isinstance(initial_conditions, TransportInitialConditions):
return initial_conditions
if not isinstance(initial_conditions, Mapping):
raise TypeError("Transport initial conditions must be provided as a mapping")
return TransportInitialConditions(payload=dict(initial_conditions))
[docs]
def set_initial_conditions(self, initial_conditions: object | None) -> None:
super().set_initial_conditions(initial_conditions)
[docs]
def set_boundary_conditions(self, boundary_conditions: dict):
self.boundary_conditions.update(boundary_conditions)
[docs]
def set_sinks_sources(self, sinks_sources: dict):
self.sinks_sources.update(sinks_sources)
[docs]
def update_modpath_parameters(self, **kwargs) -> None:
"""Update `transport.modpath.parameters`."""
self.modpath.set_parameters(kwargs)
self.parameters["modpath"] = self.modpath.parameters
[docs]
def update_mt3dms_parameters(self, **kwargs) -> None:
"""Update `transport.mt3dms.parameters`."""
self.mt3dms.set_parameters(kwargs)
self.parameters["mt3dms"] = self.mt3dms.parameters
[docs]
def update_modflow6gwt_parameters(self, **kwargs) -> None:
"""Update `transport.modflow6gwt.parameters`."""
self.modflow6gwt.set_parameters(kwargs)
self.parameters["modflow6gwt"] = self.modflow6gwt.parameters
[docs]
def update_modflow6prt_parameters(self, **kwargs) -> None:
"""Update `transport.modflow6prt.parameters`."""
self.modflow6prt.set_parameters(kwargs)
self.parameters["modflow6prt"] = self.modflow6prt.parameters