diff --git a/docs/grid.rst b/docs/grid.rst index 9da180d..05b69c3 100644 --- a/docs/grid.rst +++ b/docs/grid.rst @@ -74,8 +74,9 @@ to launch the `mom6_forge` tool for final customization. After specifying all ocean grid parameters, click `Launch mom6_forge`. This will open an auto-generated Jupyter notebook where you can fine-tune the ocean grid, topography, and vertical grid. -You can then generate the corresponding MOM6 input files, which will be saved under `ocnice` subdirectory -within the directory you specified earlier for saving the new grid files. +You can then generate the corresponding MOM6 input files, which will be saved under the `ocn` subdirectory +(with the CICE grid file saved under the `ice` subdirectory), within the directory you specified earlier +for saving the new grid files. For more details on mom6_forge, refer to its documentation: https://ncar.github.io/mom6_forge/ .. note:: If the `mom6_forge` notebook doesn't open automatically, make sure that your browser allows diff --git a/docs/ridge.rst b/docs/ridge.rst index 07b23d3..590de4c 100644 --- a/docs/ridge.rst +++ b/docs/ridge.rst @@ -232,19 +232,19 @@ vertical grid files (needed by MOM6), CICE grid file (needed by the sea ice mode # Do NOT modify this cell! # MOM6 supergrid file. - grid.write_supergrid(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocnice/ocean_grid_my1deg_grid_f2343a.nc") + grid.write_supergrid(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocn/ocean_grid_my1deg_grid_f2343a.nc") # Save MOM6 topography file: - topo.write_topo(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocnice/ocean_topog_my1deg_grid_f2343a.nc") + topo.write_topo(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocn/ocean_topog_my1deg_grid_f2343a.nc") # Save MOM6 vertical grid file: - vgrid.write(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocnice/ocean_vgrid_my1deg_f2343a.nc") + vgrid.write(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocn/ocean_vgrid_my1deg_f2343a.nc") # CICE grid file: - topo.write_cice_grid(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocnice/cice_grid.my1deg_grid_f2343a.nc") + topo.write_cice_grid(f"/Users/altuntas/projects/scratch/myRidgeGrid/ice/cice_grid.my1deg_grid_f2343a.nc") # Save ESMF mesh file: - topo.write_esmf_mesh(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocnice/ESMF_mesh_my1deg_grid_f2343a.nc") + topo.write_esmf_mesh(f"/Users/altuntas/projects/scratch/myRidgeGrid/ocn/ESMF_mesh_my1deg_grid_f2343a.nc") After running the cell above, return to visualCaseGen and click the **Confirm completion** button to proceed. diff --git a/external/mom6_forge b/external/mom6_forge index 67b4e4b..ace3a53 160000 --- a/external/mom6_forge +++ b/external/mom6_forge @@ -1 +1 @@ -Subproject commit 67b4e4b5fc55496a0daa8d502bac918c6f1e873a +Subproject commit ace3a53956314a4913be565d3a4c64f2118ad41c diff --git a/visualCaseGen/cime_interface.py b/visualCaseGen/cime_interface.py index 9d93dd0..c5b18a5 100644 --- a/visualCaseGen/cime_interface.py +++ b/visualCaseGen/cime_interface.py @@ -418,7 +418,7 @@ def _retrieve_domains_and_resolutions(self): grids = self._grids_obj.get_child("grids") # Domains, i.e., component grids, are stored in self.domains dict. The keys of - # self.domains are component names, e.g., "ocnice". The values are dicts where keys are domain names, + # self.domains are component names, e.g., "ocnice". The values are dicts where keys are domain names, # e.g., "tx2_3v2", and values are ComponentGrid named tuples with attributes name, nx, ny, mesh, desc, # compset_constr, and not_compset_constr. Since these constraints are resolution-specific, and # not domain-specific, they are initially inserted into sets and then processed appropriately diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index 6dc65db..892951b 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -173,8 +173,8 @@ def create_case(self, do_exec): and custom_grid_path_val is not None and self._wav_uses_custom_ocn_grid() ): - # copy all *.inp files under the ocnice grid directory to RUNDIR: - inp_files = list(Path(custom_grid_path_val).glob("ocnice/*.inp")) + # copy all *.inp files under the wave grid directory to RUNDIR: + inp_files = list(Path(custom_grid_path_val).glob("wav/*.inp")) if inp_files: print(f"{COMMENT}Copying WW3 input files to the case RUNDIR{RESET}\n") if do_exec: @@ -395,7 +395,7 @@ def _update_component_grids( """ if ocn_grid_mode == "Create New": - ocn_dir = custom_grid_path / "ocnice" + ocn_dir = custom_grid_path / "ocn" assert ocn_dir.exists(), f"Ocean grid directory {ocn_dir} does not exist." ocn_mesh = ( @@ -906,7 +906,7 @@ def _update_grids_via_xmlchange(self, do_exec): def _update_component_grids_xml( self, custom_grid_path, ocn_grid, ocn_grid_mode, do_exec ): - """Update the component_grids xml file with custom ocnice grid information. + """Update the component_grids xml file with custom ocn, ice, wave grid information. This function is called before running create_newcase. Parameters @@ -922,7 +922,7 @@ def _update_component_grids_xml( """ if ocn_grid_mode == "Create New": - ocn_dir = custom_grid_path / "ocnice" + ocn_dir = custom_grid_path / "ocn" assert ocn_dir.exists(), f"Ocean grid directory {ocn_dir} does not exist." ocn_mesh = ( diff --git a/visualCaseGen/custom_widget_types/mom6_forge_launcher.py b/visualCaseGen/custom_widget_types/mom6_forge_launcher.py index fa73ca0..262d619 100644 --- a/visualCaseGen/custom_widget_types/mom6_forge_launcher.py +++ b/visualCaseGen/custom_widget_types/mom6_forge_launcher.py @@ -80,7 +80,19 @@ def disabled(self, value): def get_custom_ocn_grid_path(): """Return the path to the directory where the custom ocean grid files are to be stored.""" custom_grid_path = cvars["CUSTOM_GRID_PATH"].value - return Path(custom_grid_path) / "ocnice" + return Path(custom_grid_path) / "ocn" + + @staticmethod + def get_custom_ice_grid_path(): + """Return the path to the directory where the custom CICE grid file is to be stored.""" + custom_grid_path = cvars["CUSTOM_GRID_PATH"].value + return Path(custom_grid_path) / "ice" + + @staticmethod + def get_custom_wav_grid_path(): + """Return the path to the directory where the custom WW3 input files are to be stored.""" + custom_grid_path = cvars["CUSTOM_GRID_PATH"].value + return Path(custom_grid_path) / "wav" def _on_required_var_change(self, change): """If any of the required variables are changed, reset the attempt id and mom6_forge_status.""" @@ -213,6 +225,11 @@ def _create_notebook_object(): custom_ocn_grid_path = MOM6ForgeLauncher.get_custom_ocn_grid_path() os.makedirs(custom_ocn_grid_path, exist_ok=True) + # The CICE grid file goes in its own directory, and Topo.write_cice_grid + # doesn't create parent directories, so create it up front here. + if "CICE" in cvars["COMP_ICE_PHYS"].value: + os.makedirs(MOM6ForgeLauncher.get_custom_ice_grid_path(), exist_ok=True) + # Create a new notebook: nb = nbf.v4.new_notebook() @@ -421,5 +438,5 @@ def esmf_mesh_file_path(): @staticmethod def cice_grid_file_path(): - custom_ocn_grid_path = MOM6ForgeLauncher.get_custom_ocn_grid_path() - return custom_ocn_grid_path / f"cice_grid_{MOM6ForgeLauncher.nc_file_suffix()}" + custom_ice_grid_path = MOM6ForgeLauncher.get_custom_ice_grid_path() + return custom_ice_grid_path / f"cice_grid_{MOM6ForgeLauncher.nc_file_suffix()}" diff --git a/visualCaseGen/custom_widget_types/ww3_input_generator.py b/visualCaseGen/custom_widget_types/ww3_input_generator.py index 556a7e7..8402c25 100644 --- a/visualCaseGen/custom_widget_types/ww3_input_generator.py +++ b/visualCaseGen/custom_widget_types/ww3_input_generator.py @@ -14,7 +14,7 @@ class WW3InputGenerator(VBox): When the user opts to use the newly created custom ocean grid as the wave grid (WW3), this widget reconstructs the mom6_forge Grid/Topo from the already-saved ocean grid files and - writes the WW3 ``*.inp`` files into the custom grid's ``ocnice`` directory. Those files are + writes the WW3 ``*.inp`` files into the custom grid's ``wav`` directory. Those files are later copied into the case RUNDIR by the case creator.""" def __init__(self, **kwargs): @@ -64,7 +64,7 @@ def on_btn_generate_clicked(self, b): grid_alias = cvars["CUSTOM_OCN_GRID_NAME"].value supergrid_file = MOM6ForgeLauncher.supergrid_file_path() topo_file = MOM6ForgeLauncher.topo_file_path() - ocnice_dir = MOM6ForgeLauncher.get_custom_ocn_grid_path() + wave_dir = MOM6ForgeLauncher.get_custom_wav_grid_path() # The custom ocean grid files must already exist (created via the mom6_forge notebook). for f in (supergrid_file, topo_file): @@ -94,8 +94,9 @@ def on_btn_generate_clicked(self, b): min_depth = float(ds_topo.attrs["min_depth"]) grid = Grid.from_supergrid(supergrid_file.as_posix()) topo = Topo.from_topo_file(grid, topo_file.as_posix(), min_depth=min_depth) - topo.write_ww3_input(ocnice_dir.as_posix(), grid_alias=grid_alias) - print(f"WW3 input files written to {ocnice_dir} (min_depth={min_depth}).") + wave_dir.mkdir(parents=True, exist_ok=True) + topo.write_ww3_input(wave_dir.as_posix(), grid_alias=grid_alias) + print(f"WW3 input files written to {wave_dir} (min_depth={min_depth}).") cvars["WW3_INPUT_STATUS"].value = "Complete" except Exception as e: alert_warning(f"An error occurred while generating the WW3 input files: {e}")