From 1ac5b2c8dc71987b7319845a11e1bec5f6d3d54b Mon Sep 17 00:00:00 2001 From: Gabriel Bellido Date: Wed, 19 Nov 2025 12:28:55 +0100 Subject: [PATCH 1/4] [GBP] add case_context to base_wrappers class postrocess method --- bluemath_tk/wrappers/_base_wrappers.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bluemath_tk/wrappers/_base_wrappers.py b/bluemath_tk/wrappers/_base_wrappers.py index 9383d48..151f265 100644 --- a/bluemath_tk/wrappers/_base_wrappers.py +++ b/bluemath_tk/wrappers/_base_wrappers.py @@ -838,15 +838,24 @@ def postprocess_cases( cases_dir_to_postprocess = [ self.cases_dirs[case] for case in cases_to_postprocess ] + cases_context_to_postprocess = [ + self.cases_context[case] for case in cases_to_postprocess + ] else: cases_to_postprocess = list(range(len(self.cases_dirs))) cases_dir_to_postprocess = copy.deepcopy(self.cases_dirs) + cases_context_to_postprocess = copy.deepcopy(self.cases_context) postprocessed_files = [] - for case_num, case_dir in zip(cases_to_postprocess, cases_dir_to_postprocess): + for case_num, case_dir, case_context in zip( + cases_to_postprocess, cases_dir_to_postprocess, cases_context_to_postprocess + ): try: postprocessed_file = self.postprocess_case( - case_num=case_num, case_dir=case_dir, **kwargs + case_num=case_num, + case_dir=case_dir, + case_context=case_context, + **kwargs, ) postprocessed_files.append(postprocessed_file) except Exception as e: From 18299583c8a3645a4794de5ecabca3164660b1aa Mon Sep 17 00:00:00 2001 From: manzoragu Date: Mon, 1 Dec 2025 13:32:40 +0100 Subject: [PATCH 2/4] [MZA] xbeach_wrapper updated --- bluemath_tk/wrappers/xbeach/xbeach_wrapper.py | 71 ++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/bluemath_tk/wrappers/xbeach/xbeach_wrapper.py b/bluemath_tk/wrappers/xbeach/xbeach_wrapper.py index 32acb53..108cf3d 100644 --- a/bluemath_tk/wrappers/xbeach/xbeach_wrapper.py +++ b/bluemath_tk/wrappers/xbeach/xbeach_wrapper.py @@ -6,6 +6,9 @@ import pandas as pd import xarray as xr +from wavespectra.construct.frequency import jonswap +from wavespectra.construct.direction import cartwright + from .._base_wrappers import BaseModelWrapper @@ -37,6 +40,7 @@ class XBeachModelWrapper(BaseModelWrapper): available_launchers = { "geoocean-cluster": "launchXbeach.sh", + "docker_serial": "docker run --rm -v .:/case_dir -w /case_dir geoocean/rocky8 xbeach", } def __init__( @@ -63,7 +67,31 @@ def __init__( self.set_logger_name( name=self.__class__.__name__, level="DEBUG" if debug else "INFO" ) - + + def create_vardens(self, ds): + t = "" + + # Frequencies + t += "{0} \n".format(len(ds.freq)) + for freq in ds.freq.values: + t += "{0}\n".format(freq) + + # Directions + t += "{0} \n".format(len(ds.dir)) + for dirt in sorted(ds.dir.values): + t += "{0}\n".format(dirt) + + # Sea_surface_wave_directional_variance_spectral_density + for _, freq in enumerate(ds.freq.values): + for _, dirt in enumerate(sorted(ds.dir.values)): + var = ds.sel(freq=freq, dir=dirt).efth.values + if np.isnan(var): + var = 0.0 + t += "{0}\t".format(var) + t += "\n" + + return t + def build_case( self, case_context: dict, @@ -81,12 +109,49 @@ def build_case( """ if case_context["wbctype"] == "jonstable": + # Conversion needed by XBeach's jonswap forcing (https://xbeach.readthedocs.io/en/latest/xbeach_manual.html) + spr_rad = np.radians(np.array(case_context["SPR"])) + s = (2 / (spr_rad**2)) - 1 + with open(f"{case_dir}/jonswap.txt", "w") as f: - for _i in range(math.ceil(case_context["comptime"] / 3600)): + for _i in range(math.ceil(case_context["tstop"] / 3600)): f.write( - f"{case_context['Hs']} {case_context['Tp']} {case_context['Dir']} 3.300000 30.000000 3600.000000 1.000000 \n" + f"{case_context['Hs']} {case_context['Tp']} {case_context['Dir']} 3.300000 {s} 3600.000000 1.000000 \n" ) + if case_context["wbctype"] == "vardens": + ef = jonswap( + freq=case_context["freqs"], + fp=1 / case_context["Tp"], + gamma=case_context["gamma"], + hs=case_context["Hs"], + ) + gth = cartwright( + dir=case_context["dirs"], + dm=case_context["Dir"], + dspr=case_context["SPR"], + ) + efth = ef * gth + + spectrum = xr.Dataset( + { + "efth": ( + ["freq", "dir"], + efth.data, + ) + }, + coords={ + "dir": case_context["dirs"], + "freq": case_context["freqs"], + }, + ).sortby(["freq", "dir"]) + + spectrum['dir'] = (270 - (spectrum['dir'])) % 360 + spec = self.create_vardens(spectrum) + with open(f"{case_dir}/vardens.txt", "w") as f: + f.write(spec) + + def _get_average_var(self, case_nc: xr.Dataset, var: str) -> np.ndarray: """ Get the average value of a variable except for the first hour of the simulation From 64118842d3d7eeba2a971312bce5776ac7ef8344 Mon Sep 17 00:00:00 2001 From: manzoragu Date: Wed, 10 Dec 2025 14:15:27 +0100 Subject: [PATCH 3/4] [MZA] case_context added to swan_wrapper --- bluemath_tk/wrappers/swan/swan_wrapper.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/bluemath_tk/wrappers/swan/swan_wrapper.py b/bluemath_tk/wrappers/swan/swan_wrapper.py index a22c410..29ef549 100644 --- a/bluemath_tk/wrappers/swan/swan_wrapper.py +++ b/bluemath_tk/wrappers/swan/swan_wrapper.py @@ -265,30 +265,33 @@ def postprocess_case( self, case_num: int, case_dir: str, + case_context: dict, output_vars: List[str] = ["Hsig", "Tm02", "Dir"], ) -> xr.Dataset: """ Convert mat ouput files to netCDF file. - + Parameters ---------- case_num : int The case number. case_dir : str The case directory. + case_context : dict + The case context. output_vars : list, optional The output variables to postprocess. Default is None. - + Returns ------- xr.Dataset The postprocessed Dataset. """ - + if output_vars is None: self.logger.info("Postprocessing all available variables.") output_vars = list(self.output_variables.keys()) - + output_nc_path = os.path.join(case_dir, "output.nc") if not os.path.exists(output_nc_path): # Convert tab files to netCDF file @@ -302,7 +305,7 @@ def postprocess_case( else: self.logger.info("Reading existing output.nc file.") output_nc = xr.open_dataset(output_nc_path) - + return output_nc def join_postprocessed_files( From 1478601c5c5a7279a8ed479db70a4b49a6470c03 Mon Sep 17 00:00:00 2001 From: Javier Tausia Hoyal Date: Mon, 15 Dec 2025 10:38:06 +0100 Subject: [PATCH 4/4] [JTH] little edit to homogenize new base_wrappers posprocess_cases function --- bluemath_tk/wrappers/lisflood/__init__.py | 0 .../wrappers/lisflood/lisflood_wrapper.py | 0 bluemath_tk/wrappers/swash/swash_wrapper.py | 3 +++ bluemath_tk/wrappers/xbeach/xbeach_wrapper.py | 17 +++++++++-------- 4 files changed, 12 insertions(+), 8 deletions(-) delete mode 100644 bluemath_tk/wrappers/lisflood/__init__.py delete mode 100644 bluemath_tk/wrappers/lisflood/lisflood_wrapper.py diff --git a/bluemath_tk/wrappers/lisflood/__init__.py b/bluemath_tk/wrappers/lisflood/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/bluemath_tk/wrappers/lisflood/lisflood_wrapper.py b/bluemath_tk/wrappers/lisflood/lisflood_wrapper.py deleted file mode 100644 index e69de29..0000000 diff --git a/bluemath_tk/wrappers/swash/swash_wrapper.py b/bluemath_tk/wrappers/swash/swash_wrapper.py index 540541c..e2ae5cd 100644 --- a/bluemath_tk/wrappers/swash/swash_wrapper.py +++ b/bluemath_tk/wrappers/swash/swash_wrapper.py @@ -341,6 +341,7 @@ def postprocess_case( self, case_num: int, case_dir: str, + case_context: dict, output_vars: List[str] = None, overwrite_output: bool = True, overwrite_output_postprocessed: bool = True, @@ -356,6 +357,8 @@ def postprocess_case( The case number. case_dir : str The case directory. + case_context : dict + The case context. output_vars : list, optional The output variables to postprocess. Default is None. overwrite_output : bool, optional diff --git a/bluemath_tk/wrappers/xbeach/xbeach_wrapper.py b/bluemath_tk/wrappers/xbeach/xbeach_wrapper.py index 108cf3d..ff17b51 100644 --- a/bluemath_tk/wrappers/xbeach/xbeach_wrapper.py +++ b/bluemath_tk/wrappers/xbeach/xbeach_wrapper.py @@ -5,9 +5,8 @@ import numpy as np import pandas as pd import xarray as xr - -from wavespectra.construct.frequency import jonswap from wavespectra.construct.direction import cartwright +from wavespectra.construct.frequency import jonswap from .._base_wrappers import BaseModelWrapper @@ -67,7 +66,7 @@ def __init__( self.set_logger_name( name=self.__class__.__name__, level="DEBUG" if debug else "INFO" ) - + def create_vardens(self, ds): t = "" @@ -89,9 +88,9 @@ def create_vardens(self, ds): var = 0.0 t += "{0}\t".format(var) t += "\n" - + return t - + def build_case( self, case_context: dict, @@ -131,7 +130,7 @@ def build_case( dm=case_context["Dir"], dspr=case_context["SPR"], ) - efth = ef * gth + efth = ef * gth spectrum = xr.Dataset( { @@ -146,12 +145,11 @@ def build_case( }, ).sortby(["freq", "dir"]) - spectrum['dir'] = (270 - (spectrum['dir'])) % 360 + spectrum["dir"] = (270 - (spectrum["dir"])) % 360 spec = self.create_vardens(spectrum) with open(f"{case_dir}/vardens.txt", "w") as f: f.write(spec) - def _get_average_var(self, case_nc: xr.Dataset, var: str) -> np.ndarray: """ Get the average value of a variable except for the first hour of the simulation @@ -241,6 +239,7 @@ def postprocess_case( self, case_num: int, case_dir: str, + case_context: dict, output_vars: List[str] = None, overwrite_output: bool = True, ) -> xr.Dataset: @@ -253,6 +252,8 @@ def postprocess_case( The case number. case_dir : str The case directory. + case_context : dict + The case context. output_vars : list, optional The output variables to postprocess. Default is None. overwrite_output : bool, optional