From 8ed06421d94cf53181651dd19704354300689c10 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Tue, 14 Jul 2026 11:48:49 -0600 Subject: [PATCH 1/3] Add ww3_bounc preprocessing to build boundary conditions for regional grids Mirrors the existing ww3_grid prestaging pattern: builds nest.ww3 from ww3_bounc and boundary-condition input files when WW3_NEST is 'unset', or stages a pre-built nest.ww3 when WW3_NEST points to an existing file. Supports any combination of fresh/pre-built grid and fresh/pre-built nest. --- cime_config/buildnml | 101 +++++++++++++++++++++---------- cime_config/config_component.xml | 9 +++ 2 files changed, 77 insertions(+), 33 deletions(-) diff --git a/cime_config/buildnml b/cime_config/buildnml index b9cf573..55c748d 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -204,60 +204,95 @@ def _prestage_inputs(case): # Prestage necessary files to rundir #---------------------------------------------------- rundir = case.get_value("RUNDIR") - - # Create rundir/ww3_moddef_create + mod_def_in = case.get_value("WW3_MODDEF") + nest_in = case.get_value("WW3_NEST") + # Create a moddef build directory in case of need + ww3_moddef_dir = os.path.join(rundir, "ww3_moddef_create") + if not os.path.exists(ww3_moddef_dir): + os.makedirs(ww3_moddef_dir) + + # Copy preprocessing executables to ww3_moddef_create directory if they exist in the build directory bldroot = os.path.join(case.get_value("EXEROOT"),"wav","obj") bld_ww3_grid = os.path.join(bldroot, "ww3_grid") # executable to create mod_def.ww3 file + bld_ww3_bounc = os.path.join(bldroot, "ww3_bounc") if os.path.isfile(bld_ww3_grid): - ww3_moddef_dir = os.path.join(rundir, "ww3_moddef_create") - if not os.path.exists(ww3_moddef_dir): - os.makedirs(ww3_moddef_dir) if not os.path.exists(os.path.join(ww3_moddef_dir, "ww3_grid")): safe_copy(bld_ww3_grid, ww3_moddef_dir) - - if case.get_value("WW3_MODDEF") == 'unset': - # Create output dir ww3_moddef_create if appropriate - output_dir = os.path.join(rundir, "ww3_moddef_create") - if not os.path.exists(output_dir): - os.makedirs(output_dir) - - # Copy ww3_inp and other needed info to ww3_moddef_create directory - input_dir = case.get_value("WW3_GRID_INP_DIR") - if os.path.isdir(input_dir): - files = os.listdir(input_dir) - for filename in files: - if not os.path.isfile(os.path.join(output_dir, filename)): - safe_copy(os.path.join(input_dir, filename), os.path.join(output_dir, filename)) - + if os.path.isfile(bld_ww3_bounc): + if not os.path.exists(os.path.join(ww3_moddef_dir, "ww3_bounc")): + safe_copy(bld_ww3_bounc, ww3_moddef_dir) + + # Copy ww3_inp and other needed info to ww3_moddef_create directory + input_dir = case.get_value("WW3_GRID_INP_DIR") + if os.path.isdir(input_dir): + for filename in os.listdir(input_dir): + if not os.path.isfile(os.path.join(ww3_moddef_dir, filename)): + safe_copy(os.path.join(input_dir, filename), os.path.join(ww3_moddef_dir, filename)) + + if mod_def_in == 'unset': # Create mod_def file using ww3_grid and the grid_input files - if not os.path.isfile(os.path.join(output_dir,"ww3_grid")): + if not os.path.isfile(os.path.join(ww3_moddef_dir,"ww3_grid")): logger.warning("ww3_grid file not found. The mod_def.ww3 file will be created after the build phase.") - elif not os.path.isfile(os.path.join(output_dir,"ww3_grid.inp")): + elif not os.path.isfile(os.path.join(ww3_moddef_dir,"ww3_grid.inp")): logger.warning("ww3_grid.inp file not found. The file will automatically be downloaded at the ./case.submit phase.") else: # Generate mod_def.ww3 file using ww3_grid executable and the grid_input files - run_cmd("./ww3_grid > mod_def.ww3.log", from_dir=output_dir) - if not os.path.isfile(os.path.join(output_dir,"mod_def.ww3")): + run_cmd("./ww3_grid > mod_def.ww3.log", from_dir=ww3_moddef_dir) + if not os.path.isfile(os.path.join(ww3_moddef_dir,"mod_def.ww3")): raise RuntimeError("mod_def.ww3 was not created, check mod_def.ww3.log for errors.") - # Copy mod_def.ww3 to rundir. No binary initial-condition file is - # generated: WW3 initial runs start from in-core calm conditions - # (or a user-supplied initfile), and restarts are netCDF. - shutil.move(os.path.join(output_dir,"mod_def.ww3"), os.path.join(rundir, "mod_def.ww3")) else: - # Use mod_def already created - mod_def_in = case.get_value("WW3_MODDEF") if os.path.isfile(mod_def_in): import filecmp copy_file = False - if not os.path.isfile(os.path.join(rundir, "mod_def.ww3")): + if not os.path.isfile(os.path.join(ww3_moddef_dir, "mod_def.ww3")): copy_file = True - elif not filecmp.cmp(mod_def_in, os.path.join(rundir, "mod_def.ww3")): + elif not filecmp.cmp(mod_def_in, os.path.join(ww3_moddef_dir, "mod_def.ww3")): copy_file = True if copy_file: - shutil.copy(mod_def_in, os.path.join(rundir, "mod_def.ww3")) + shutil.copy(mod_def_in, os.path.join(ww3_moddef_dir, "mod_def.ww3")) + else: raise RuntimeError("mod_def_in {} does not exist on disk".format(mod_def_in)) + + if nest_in == "unset": + boundary_nml = os.path.join(ww3_moddef_dir, "ww3_bounc.nml") # Copied from WW3_GRID_INP_DIR + if not os.path.isfile(os.path.join(ww3_moddef_dir, "ww3_bounc")): + logger.warning("ww3_bounc file not found. The nest.ww3 file will be created after the build phase.") + elif not os.path.isfile(boundary_nml): + logger.warning("ww3_bounc.nml file not found; skipping nest.ww3 generation.") + elif not os.path.isfile(os.path.join(ww3_moddef_dir,"mod_def.ww3")): + logger.warning("mod_def.ww3 not found; skipping nest.ww3 generation until the grid is built.") + else: + # Generate boundary conditions using ww3_bounc executable and the boundary input files + run_cmd("./ww3_bounc > nest.ww3.log", from_dir=ww3_moddef_dir) + if not os.path.isfile(os.path.join(ww3_moddef_dir,"nest.ww3")): + raise RuntimeError("nest.ww3 was not created, check nest.ww3.log for errors.") + # Copy nest.ww3 to rundir. + shutil.move(os.path.join(ww3_moddef_dir,"nest.ww3"), os.path.join(rundir, "nest.ww3")) + + + + else: + if os.path.isfile(nest_in): + import filecmp + copy_file = False + if not os.path.isfile(os.path.join(rundir, "nest.ww3")): + copy_file = True + elif not filecmp.cmp(nest_in, os.path.join(rundir, "nest.ww3")): + copy_file = True + if copy_file: + shutil.copy(nest_in, os.path.join(rundir, "nest.ww3")) + else: + raise RuntimeError("nest_in {} does not exist on disk".format(nest_in)) + + # now move mod_def.ww3, after ww3_bounc has had a chance to read it + # Copy mod_def.ww3 to rundir. No binary initial-condition file is + # generated: WW3 initial runs start from in-core calm conditions + # (or a user-supplied initfile), and restarts are netCDF. + if os.path.isfile(os.path.join(ww3_moddef_dir,"mod_def.ww3")): + shutil.move(os.path.join(ww3_moddef_dir,"mod_def.ww3"), os.path.join(rundir, "mod_def.ww3")) + ############################################################################### def _main_func(): diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 2019866..912898e 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -50,6 +50,15 @@ + + char + unset + case_comp + env_build.xml + nest file to use in regional model. If 'unset', nest.ww3 is generated from ww3_bounc and the boundary condition input files Note that this file is renamed to nest.ww3 in the run directory. + + + char $DIN_LOC_ROOT/wav/ww3/grid_inp.${WAV_GRID} From 8d103c70c21760908d1bb3901010370e501075db Mon Sep 17 00:00:00 2001 From: manishvenu Date: Tue, 14 Jul 2026 15:36:16 -0600 Subject: [PATCH 2/3] Bump WW3 submodule to include ww3_bounc executable target Points at CROCODILE-CESM/WW3 branch add-ww3-bounc-executable (ESCOMP/WW3#41, pending upstream merge), which adds ww3_bounc as a standalone CMake executable so the ww3_bounc preprocessing added here has something to run. --- .gitmodules | 2 +- WW3 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 710f790..6e4f6c9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "WW3"] path = WW3 -url = https://github.com/ESCOMP/WW3.git +url = git@github.com:CROCODILE-CESM/WW3.git fxtag = dev/unified_0.1.0 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/WW3.git diff --git a/WW3 b/WW3 index cc6f1a3..98fe1e3 160000 --- a/WW3 +++ b/WW3 @@ -1 +1 @@ -Subproject commit cc6f1a35661d0285eb8c6f7c36dcfe4c9bf9505f +Subproject commit 98fe1e3fb69f13581a201c54b1c9cdf5c6ce3e75 From 017ade968207ffe9b981e0f0ed5ad92c5754655f Mon Sep 17 00:00:00 2001 From: manishvenu Date: Tue, 14 Jul 2026 16:33:07 -0600 Subject: [PATCH 3/3] Bump WW3 submodule: link ww3_bounc against netCDF-Fortran --- WW3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WW3 b/WW3 index 98fe1e3..077ea52 160000 --- a/WW3 +++ b/WW3 @@ -1 +1 @@ -Subproject commit 98fe1e3fb69f13581a201c54b1c9cdf5c6ce3e75 +Subproject commit 077ea5244c161e819c051baf1c4e894224d4ac3a