Code Structure
HydroBayesCal is organised into three cooperating layers, tied together by a small set of driver scripts:
Full-complexity model bindings — run the numerical model and extract its outputs at the calibration points. A solver-agnostic abstract base class,
HydroSimulations(inhydroBayesCal.hysim), defines the contract; each solver provides a concrete subclass (TelemacModel,OpenFOAMModel,Delft3DModel).Surrogate model and Bayesian Active Learning — the
hydroBayesCal.surrogatepackage builds Gaussian Process Emulators (single- and multi-output) and performs Bayesian inference and sequential design (BAL).Post-processing — the
hydroBayesCal.visualizepackage plots calibration results (BayesianPlotter), andhydroBayesCal.extract_results()samples 2D/3D results at arbitrary points, inside and outside the calibration workflow (see Using HydroBayesCal with TELEMAC).
The driver scripts templates/bal_telemac.py, templates/bal_openfoam.py
and templates/bal_delft3d.py wire these layers
together and read all user input from a configuration file. The rendered UML
class diagram is maintained in the repository under UML/BayesCal-UML.pdf
(LaTeX/TikZ source next to it).
Architecture at a glance (UML)
The base class owns everything common to a calibration — calibration parameters, observations and their variances, and the standard result-folder layout — so each binding only implements the two solver-specific steps (running the model and processing its output). This is what keeps the TELEMAC, OpenFOAM and Delft3D-FLOW workflows aligned.
classDiagram
class HydroSimulations {
<<abstract>>
+model_dir, res_dir, control_file
+calibration_parameters, param_values
+observations, variances, measurement_errors
+calibration_folder, restart_data_folder
+run_multiple_simulations()*
+output_processing()*
+update_model_controls()
+set_observations_and_variances()
}
class TelemacModel {
+tm_xd "Telemac2d / Telemac3d"
+friction_file (.tbl)
+gaia_steering_file
+run_multiple_simulations()
+output_processing()
+extract_data_point()
}
class OpenFOAMModel {
+solver_name "interFoam"
+alpha_water_name, control_points
+run_multiple_simulations()
+output_processing()
}
class OpenFOAMController {
+decompose_parallel_case()
+run_simulation()
+extract_fields_from_vtk()
}
class Delft3DModel {
+env_script "env.sh"
+roughness_formulation "Manning / Chezy / ..."
+run_multiple_simulations()
+output_processing()
}
class Delft3DController {
+update_mdf_parameter()
+ensure_netcdf_output()
+run_simulation()
+extract_map_results()
}
class BayesianPlotter {
+plot_posterior_updates()
+plot_bme_re()
+evaluate_calibration()
+observed_vs_modeled_compare()
}
class extract {
<<module>>
+extract_results(result_file, variable, x, y, z)
}
HydroSimulations <|-- TelemacModel : implements
HydroSimulations <|-- OpenFOAMModel : implements
HydroSimulations <|-- Delft3DModel : implements
OpenFOAMModel ..> OpenFOAMController : uses
Delft3DModel ..> Delft3DController : uses
extract ..> TelemacModel : standalone twin of extract_data_point()
The calibration pipeline
The drivers orchestrate the surrogate-assisted calibration loop. Experimental
design and parameter sampling are delegated to BayesValidRox; the GPE
training, Bayesian inference and training-point selection live in
hydroBayesCal.surrogate.
flowchart TD
CFG[Configuration file] --> ED["setup_experiment_design()<br/>BayesValidRox Input + ExpDesigns"]
ED -->|initial collocation points| RUN["run_complex_model()<br/>HydroSimulations.run_multiple_simulations"]
RUN -->|model_evaluations| TRAIN["Train GPE<br/>surrogate.gpe_gpytorch / gpe_skl"]
TRAIN --> INFER["Bayesian inference<br/>surrogate.bal_functions.BayesianInference"]
INFER --> CONV{max_runs reached<br/>or converged?}
CONV -->|no| SD["Select new training point<br/>SequentialDesign (BME / relative entropy)"]
SD -->|new collocation point| RUN
CONV -->|yes| OUT[(auto-saved-results-HydroBayesCal:<br/>posteriors, GPEs, outputs)]
Package layout
src/hydroBayesCal/
├── hysim.py # HydroSimulations: abstract base class (the binding contract)
├── function_pool.py # shared helpers (subprocess, IO, logging, mesh utilities)
├── extract.py # extract_results(): standalone 2D/3D point extraction
│ # (TELEMAC SELAFIN and OpenFOAM VTK)
├── telemac/
│ ├── control_telemac.py # TelemacModel(HydroSimulations)
│ ├── config_telemac.py # TELEMAC/GAIA keyword templates
│ └── pputils/ # SELAFIN result-file IO (ppmodules)
├── openfoam/
│ └── control_openfoam.py # OpenFOAMModel(HydroSimulations) + OpenFOAMController
├── delft3d/
│ └── control_delft3d.py # Delft3DModel(HydroSimulations) + Delft3DController
├── surrogate/ # owned GPE + BAL implementation
│ ├── gpe_gpytorch.py # GPyTraining / MultiGPyTraining (single- & multi-output GP)
│ ├── gpe_skl.py # scikit-learn GP training
│ ├── bal_functions.py # BayesianInference, SequentialDesign
│ └── exploration.py # parameter-space exploration for BAL
├── visualize/ # BayesianPlotter, assembled from thematic plot mixins
│ ├── plotter.py # BayesianPlotter (public API)
│ ├── posterior_plots.py # prior/posterior distributions
│ ├── bal_plots.py # BME/RE evolution, BME surfaces
│ ├── model_comparison_plots.py # surrogate vs complex model vs observations
│ ├── metrics_plots.py # metric evolution and per-location exports
│ ├── calibration_assessment.py # multi-model calibration assessment
│ └── axis_utils.py # shared axis/tick/limit helpers
└── utils/, doepy/ # logging/config, design-of-experiments helpers
templates/ # runnable drivers and config templates (copy & adapt)
├── bal_telemac.py / bal_openfoam.py / bal_delft3d.py # entry-point drivers
├── config_Telemac.py / config_OpenFOAM.py / config_Delft3D.py
└── telemac_extract.py, main_plots.py, main_validate.py, ...
Note
BayesValidRox is used only for the experimental design / parameter
sampling (Input and ExpDesigns). The Gaussian-process emulators and
the Bayesian active-learning logic are maintained in-tree under
hydroBayesCal.surrogate.
A detailed description of each module’s API is available under API Reference.