From 82d448fb8c45da2dc463b9df9b01987d517ee518 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Thu, 23 Oct 2025 17:09:22 -0600 Subject: [PATCH 01/14] First Try --- .../custom_widget_types/case_creator.py | 216 +----------------- 1 file changed, 12 insertions(+), 204 deletions(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index 6f2525c..42a7b14 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -45,29 +45,7 @@ def revert_launch(self, do_exec=True): """This function is called when the case creation fails. It reverts the changes made to the ccs_config xml files.""" - mg = "ccs_config/modelgrid_aliases_nuopc.xml" - if (Path(self._cime.srcroot) / f"{mg}.orig").exists(): - shutil.move( - Path(self._cime.srcroot) / f"{mg}.orig", - Path(self._cime.srcroot) / f"{mg}" - ) - cg = "ccs_config/component_grids_nuopc.xml" - if (Path(self._cime.srcroot) / f"{cg}.orig").exists(): - shutil.move( - Path(self._cime.srcroot) / f"{cg}.orig", - Path(self._cime.srcroot) / f"{cg}" - ) - - def _remove_orig_xml_files(self): - """This function is called when the case creation and modification process is successful. - It removes the backup xml files created before modifying the ccs_config xml files.""" - - mg = "ccs_config/modelgrid_aliases_nuopc.xml" - if (Path(self._cime.srcroot) / f"{mg}.orig").exists(): - os.remove(Path(self._cime.srcroot) / f"{mg}.orig") - cg = "ccs_config/component_grids_nuopc.xml" - if (Path(self._cime.srcroot) / f"{cg}.orig").exists(): - os.remove(Path(self._cime.srcroot) / f"{cg}.orig") + return # Currently no action is needed def _is_non_local(self): """Check if the case is being created on a machine different from the one @@ -138,12 +116,12 @@ def create_case(self, do_exec): with self._out: print(f"{COMMENT}Creating case...{RESET}\n") - # First, update ccs_config xml files to add custom grid information if needed: - self._update_ccs_config(do_exec) - # Run create_newcase self._run_create_newcase(caseroot, compset, resolution, do_exec) + # Add custom grid information to the case if needed: + self._update_grids(do_exec) + # Navigate to the case directory: with self._out: print(f"{COMMENT}Navigating to the case directory:{RESET}\n") @@ -171,11 +149,10 @@ def create_case(self, do_exec): f"another case, restart the notebook.{RESET}\n" ) - def _update_ccs_config(self, do_exec): + def _update_grids(self, do_exec): """Update the modelgrid_aliases and component_grids xml files with custom grid - information if needed. This function is called before running create_newcase.""" + information if needed. This function is called after running create_newcase.""" - # If Custom grid is selected, update modelgrid_aliases and component_grids xml files: if cvars["GRID_MODE"].value == "Standard": return else: @@ -201,109 +178,8 @@ def _update_ccs_config(self, do_exec): if ocn_grid is None: raise RuntimeError("No ocean grid specified.") - self._update_modelgrid_aliases(custom_grid_path, ocn_grid, do_exec) self._update_component_grids(custom_grid_path, ocn_grid, ocn_grid_mode, do_exec) - def _update_modelgrid_aliases(self, custom_grid_path, ocn_grid, do_exec): - """Update the modelgrid_aliases xml file with custom resolution information. - This function is called before running create_newcase. - - Parameters - ---------- - custom_grid_path : Path - The path to the custom grid directory. - ocn_grid : str - The name of the custom ocean grid. - do_exec : bool - If True, execute the commands. If False, only print them. - """ - - resolution_name = custom_grid_path.name - - # Component grid names: - atm_grid = cvars["CUSTOM_ATM_GRID"].value - lnd_grid = cvars["CUSTOM_LND_GRID"].value - # modelgrid_aliases xml file that stores resolutions: - srcroot = self._cime.srcroot - ccs_config_root = Path(srcroot) / "ccs_config" - assert ( - ccs_config_root.exists() - ), f"ccs_config_root {ccs_config_root} does not exist." - modelgrid_aliases_xml = ccs_config_root / "modelgrid_aliases_nuopc.xml" - assert ( - modelgrid_aliases_xml.exists() - ), f"modelgrid_aliases_xml {modelgrid_aliases_xml} does not exist." - modelgrid_aliases_xml = modelgrid_aliases_xml.as_posix() - - # confirm that modelgrid_aliases xml file is writeable: - if not os.access(modelgrid_aliases_xml, os.W_OK): - raise RuntimeError(f"Cannot write to {modelgrid_aliases_xml}.") - - # log the modification of modelgrid_aliases.xml: - with self._out: - print( - f'{BPOINT} Updating ccs_config/modelgrid_aliases_nuopc.xml file to include the new ' - f'resolution "{resolution_name}" consisting of the following component grids.\n' - f' atm grid: "{atm_grid}", lnd grid: "{lnd_grid}", ocn grid: "{ocn_grid}".\n' - ) - - # Read in xml file and generate grids object file: - parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)) - grids_tree = ET.parse(modelgrid_aliases_xml, parser=parser) - grids_root = grids_tree.getroot() - - # Check if a resp;iton with the same name already exists. If so, remove it or raise an error - # depending on the value of self._allow_xml_override: - for resolution in grids_root.findall("model_grid"): - if resolution.attrib["alias"] == resolution_name: - if self._allow_xml_override: - grids_root.remove(resolution) - else: - raise RuntimeError( - f"Resolution {resolution_name} already exists in modelgrid_aliases." - ) - - # Create new resolution entry in xml file: - new_resolution = SubElement( - grids_root, - "model_grid", - attrib={"alias": resolution_name}, - ) - - # Add component grids to resolution entry: - new_atm_grid = SubElement( - new_resolution, - "grid", - attrib={"name": "atm"}, - ) - new_atm_grid.text = atm_grid - - new_lnd_grid = SubElement( - new_resolution, - "grid", - attrib={"name": "lnd"}, - ) - new_lnd_grid.text = lnd_grid - - new_ocnice_grid = SubElement( - new_resolution, - "grid", - attrib={"name": "ocnice"}, - ) - new_ocnice_grid.text = ocn_grid - - if not do_exec: - return - - # back up modelgrid_aliases.xml in case case creation fails: - shutil.copy( - Path(self._cime.srcroot) / "ccs_config/modelgrid_aliases_nuopc.xml", - Path(self._cime.srcroot) / "ccs_config/modelgrid_aliases_nuopc.xml.orig", - ) - - # update modelgrid_aliases.xml to include new resolution: - ET.indent(grids_tree) - grids_tree.write(modelgrid_aliases_xml, encoding="utf-8", xml_declaration=True) def _update_component_grids( self, custom_grid_path, ocn_grid, ocn_grid_mode, do_exec @@ -332,92 +208,24 @@ def _update_component_grids( ) assert ocn_mesh.exists(), f"Ocean mesh file {ocn_mesh} does not exist." - # component_grids xml file that stores resolutions: - srcroot = self._cime.srcroot - ccs_config_root = Path(srcroot) / "ccs_config" - assert ( - ccs_config_root.exists() - ), f"ccs_config_root {ccs_config_root} does not exist." - component_grids_xml = ccs_config_root / "component_grids_nuopc.xml" - assert ( - component_grids_xml.exists() - ), f"component_grids_xml {component_grids_xml} does not exist." - component_grids_xml = component_grids_xml.as_posix() - - # confirm that component_grids xml file is writeable: - if not os.access(component_grids_xml, os.W_OK): - raise RuntimeError(f"Cannot write to {component_grids_xml}.") # log the modification of component_grids.xml: with self._out: print( - f'{BPOINT} Updating ccs_config/component_grids_nuopc.xml file to include ' + f'{BPOINT} Updating case xml variables to include ' f'newly generated ocean grid "{ocn_grid}" with the following properties:\n' f' nx: {cvars["OCN_NX"].value}, ny: {cvars["OCN_NY"].value}.' f' ocean mesh: {ocn_mesh}.{RESET}\n' ) - # Read in xml file and generate component_grids object file: - parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)) - domains_tree = ET.parse(component_grids_xml, parser=parser) - # ET.indent(domains_tree, space=" ", level=0) - domains_root = domains_tree.getroot() - - # Check if a domain with the same name already exists. If so, remove it or raise an error - # depending on the value of self._allow_xml_override: - for domain in domains_root.findall("domain"): - if domain.attrib["name"] == ocn_grid: - if self._allow_xml_override: - domains_root.remove(domain) - else: - raise RuntimeError( - f"Ocean grid {ocn_grid} already exists in component_grids." - ) - - # Create new domain entry in xml file: - new_domain = SubElement( - domains_root, - "domain", - attrib={"name": ocn_grid}, - ) - - nx = SubElement( - new_domain, - "nx", - ) - nx.text = str(cvars["OCN_NX"].value) + xmlchange("OCN_NX", cvars["OCN_NX"].value, do_exec, self._is_non_local(), self._out) - ny = SubElement( - new_domain, - "ny", - ) - ny.text = str(cvars["OCN_NY"].value) + xmlchange("OCN_NY", cvars["OCN_NY"].value, do_exec, self._is_non_local(), self._out) - mesh = SubElement( - new_domain, - "mesh", - ) - mesh.text = ocn_mesh.as_posix() + xmlchange("OCN_DOMAIN_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) - desc = SubElement( - new_domain, - "desc", - ) - desc.text = f"New ocean grid {ocn_grid} generated by mom6_bathy" - - if not do_exec: - return - - shutil.copy( - Path(self._cime.srcroot) / "ccs_config/component_grids_nuopc.xml", - Path(self._cime.srcroot) / "ccs_config/component_grids_nuopc.xml.orig", - ) - - # write to xml file: - ET.indent(domains_tree) - domains_tree.write( - component_grids_xml, encoding="utf-8", xml_declaration=True - ) + xmlchange("MASK_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) + def _run_create_newcase(self, caseroot, compset, resolution, do_exec): """Run CIME's create_newcase tool to create a new case instance. From 8cf5a4bab495635006cf0d840a686e232ede5078 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Thu, 23 Oct 2025 17:11:33 -0600 Subject: [PATCH 02/14] Last remove --- visualCaseGen/custom_widget_types/case_creator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index 42a7b14..1899e5b 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -138,7 +138,7 @@ def create_case(self, do_exec): # Clean up: if do_exec: - self._remove_orig_xml_files() + cvars["CASE_CREATOR_STATUS"].value = "OK" with self._out: caseroot = cvars["CASEROOT"].value From 33ff59b0ef734737633138dd8d8adef10ec67818 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Thu, 23 Oct 2025 17:15:12 -0600 Subject: [PATCH 03/14] Try This --- visualCaseGen/custom_widget_types/case_creator.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index 1899e5b..f3eca11 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -224,7 +224,15 @@ def _update_component_grids( xmlchange("OCN_DOMAIN_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) + xmlchange("ICE_DOMAIN_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) + + xmlchange("ATM_GRID", cvars["CUSTOM_ATM_GRID"].value, do_exec, self._is_non_local(), self._out) + + xmlchange("LND_GRID", cvars["CUSTOM_LND_GRID"].value, do_exec, self._is_non_local(), self._out) + xmlchange("MASK_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) + + def _run_create_newcase(self, caseroot, compset, resolution, do_exec): From 20bd117fd14264191206e8686f933be14c3e4b49 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Fri, 24 Oct 2025 11:35:36 -0600 Subject: [PATCH 04/14] This --- .../custom_widget_types/case_creator.py | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index f3eca11..95e9e6e 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -108,7 +108,7 @@ def create_case(self, do_exec): if cvars["GRID_MODE"].value == "Standard": resolution = cvars["GRID"].value elif cvars["GRID_MODE"].value == "Custom": - resolution = Path(cvars["CUSTOM_GRID_PATH"].value).name + resolution = "a%" + cvars["CUSTOM_ATM_GRID"].value + "_l%" + cvars["CUSTOM_LND_GRID"].value + "_oi%VisualCaseGen_Custom_r%null_g%null_w%null_z%null_m%VisualCaseGen_Custom" else: raise RuntimeError(f"Unknown grid mode: {cvars['GRID_MODE'].value}") @@ -226,15 +226,34 @@ def _update_component_grids( xmlchange("ICE_DOMAIN_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) - xmlchange("ATM_GRID", cvars["CUSTOM_ATM_GRID"].value, do_exec, self._is_non_local(), self._out) + xmlchange("MASK_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) - xmlchange("LND_GRID", cvars["CUSTOM_LND_GRID"].value, do_exec, self._is_non_local(), self._out) + xmlchange("OCN_GRID", "VCG_Changed", do_exec, self._is_non_local(), self._out) - xmlchange("MASK_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) - - + lnd_grid_mode = cvars["LND_GRID_MODE"].value + if lnd_grid_mode == "Modified": + if cvars["COMP_OCN"].value != "mom": + with self._out: + print(f"{COMMENT}Apply custom land grid xml changes:{RESET}\n") + + # TODO: NO LONGER RELEVANT - OCEAN GRIDS ARE DONE THROUGH XML CHANGES AS WELL: instead of xmlchanges, these changes should be made via adding the new lnd domain mesh to + # component_grids_nuopc.xml and modelgrid_aliases_nuopc.xml (just like how we handle new ocean grids) + + # lnd domain mesh + xmlchange("LND_DOMAIN_MESH", cvars["INPUT_MASK_MESH"].value, do_exec, self._is_non_local(), self._out) + + # mask mesh (if modified) + base_lnd_grid = cvars["CUSTOM_LND_GRID"].value + custom_grid_path = Path(cvars["CUSTOM_GRID_PATH"].value) + lnd_dir = custom_grid_path / "lnd" + modified_mask_mesh = lnd_dir / f"{base_lnd_grid}_mesh_mask_modifier.nc" # TODO: the way we get this filename is fragile + assert modified_mask_mesh.exists(), f"Modified mask mesh file {modified_mask_mesh} does not exist." + xmlchange("MASK_MESH", modified_mask_mesh, do_exec, self._is_non_local(), self._out) + else: + assert lnd_grid_mode in [None, "", "Standard"], f"Unknown land grid mode: {lnd_grid_mode}" + def _run_create_newcase(self, caseroot, compset, resolution, do_exec): """Run CIME's create_newcase tool to create a new case instance. @@ -301,28 +320,7 @@ def _run_create_newcase(self, caseroot, compset, resolution, do_exec): raise RuntimeError("Error creating case.") def _apply_all_xmlchanges(self, do_exec): - - lnd_grid_mode = cvars["LND_GRID_MODE"].value - if lnd_grid_mode == "Modified": - if cvars["COMP_OCN"].value != "mom": - with self._out: - print(f"{COMMENT}Apply custom land grid xml changes:{RESET}\n") - - # TODO: instead of xmlchanges, these changes should be made via adding the new lnd domain mesh to - # component_grids_nuopc.xml and modelgrid_aliases_nuopc.xml (just like how we handle new ocean grids) - - # lnd domain mesh - xmlchange("LND_DOMAIN_MESH", cvars["INPUT_MASK_MESH"].value, do_exec, self._is_non_local(), self._out) - - # mask mesh (if modified) - base_lnd_grid = cvars["CUSTOM_LND_GRID"].value - custom_grid_path = Path(cvars["CUSTOM_GRID_PATH"].value) - lnd_dir = custom_grid_path / "lnd" - modified_mask_mesh = lnd_dir / f"{base_lnd_grid}_mesh_mask_modifier.nc" # TODO: the way we get this filename is fragile - assert modified_mask_mesh.exists(), f"Modified mask mesh file {modified_mask_mesh} does not exist." - xmlchange("MASK_MESH", modified_mask_mesh, do_exec, self._is_non_local(), self._out) - else: - assert lnd_grid_mode in [None, "", "Standard"], f"Unknown land grid mode: {lnd_grid_mode}" + """Apply all the necessary xmlchanges to the case.""" # Set NTASKS based on grid size. e.g. NX * NY < max_pts_per_core if cvars["COMP_OCN"].value == "mom": From 84d899c3c483384b84cd2b11057eebb4aa5d207a Mon Sep 17 00:00:00 2001 From: manishvenu Date: Fri, 24 Oct 2025 15:51:55 -0600 Subject: [PATCH 05/14] Changes required --- visualCaseGen/config_vars/grid_vars.py | 5 ++ .../custom_widget_types/case_creator.py | 11 ++++- visualCaseGen/specs/grid_options.py | 47 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/visualCaseGen/config_vars/grid_vars.py b/visualCaseGen/config_vars/grid_vars.py index 3313279..a4627a8 100644 --- a/visualCaseGen/config_vars/grid_vars.py +++ b/visualCaseGen/config_vars/grid_vars.py @@ -40,6 +40,9 @@ def initialize_custom_grid_variables(cime): # A preexisting ATM grid picked for custom grid ConfigVarStrMS("CUSTOM_ATM_GRID", default_value="0.9x1.25") + # The associated domain mesh + ConfigVarStrMS("CUSTOM_ATM_DOMAIN_MESH") + # Custom ocean grid variables ConfigVarStr("OCN_GRID_MODE") # Standard, Modify Existing, Create New @@ -71,6 +74,8 @@ def initialize_custom_grid_variables(cime): "CUSTOM_LND_GRID", default_value="0.9x1.25" ) # A preexisting land grid picked for the custom grid + ConfigVarStr("CUSTOM_LND_DOMAIN_MESH") # The associated domain mesh + # Auto-fill the INPUT_MASK_MESH variable based on the CUSTOM_LND_GRID variable def default_input_mask_mesh(): diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index 95e9e6e..24fd65c 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -108,7 +108,7 @@ def create_case(self, do_exec): if cvars["GRID_MODE"].value == "Standard": resolution = cvars["GRID"].value elif cvars["GRID_MODE"].value == "Custom": - resolution = "a%" + cvars["CUSTOM_ATM_GRID"].value + "_l%" + cvars["CUSTOM_LND_GRID"].value + "_oi%VisualCaseGen_Custom_r%null_g%null_w%null_z%null_m%VisualCaseGen_Custom" + resolution = "visualCaseGen_Custom" else: raise RuntimeError(f"Unknown grid mode: {cvars['GRID_MODE'].value}") @@ -117,6 +117,7 @@ def create_case(self, do_exec): print(f"{COMMENT}Creating case...{RESET}\n") # Run create_newcase + breakpoint() self._run_create_newcase(caseroot, compset, resolution, do_exec) # Add custom grid information to the case if needed: @@ -230,6 +231,14 @@ def _update_component_grids( xmlchange("OCN_GRID", "VCG_Changed", do_exec, self._is_non_local(), self._out) + xmlchange("ATM_GRID", cvars["CUSTOM_ATM_GRID"].value, do_exec, self._is_non_local(), self._out) + + xmlchange("LND_GRID", cvars["CUSTOM_LND_GRID"].value, do_exec, self._is_non_local(), self._out) + + xmlchange("ATM_DOMAIN_MESH", cvars["CUSTOM_ATM_DOMAIN_MESH"].value, do_exec, self._is_non_local(), self._out) + + xmlchange("LND_DOMAIN_MESH", cvars["CUSTOM_LND_DOMAIN_MESH"].value, do_exec, self._is_non_local(), self._out) + lnd_grid_mode = cvars["LND_GRID_MODE"].value if lnd_grid_mode == "Modified": diff --git a/visualCaseGen/specs/grid_options.py b/visualCaseGen/specs/grid_options.py index 8057dac..60b3f1a 100644 --- a/visualCaseGen/specs/grid_options.py +++ b/visualCaseGen/specs/grid_options.py @@ -125,6 +125,26 @@ def custom_atm_grid_options_func(comp_atm, grid_mode): func=custom_atm_grid_options_func, args=(cvars["COMP_ATM"], cvars["GRID_MODE"]) ) + # CUSTOM_ATM_DOMAIN_MESH options + def custom_atm_domain_mesh_options_func(comp_atm, grid_mode): + """Return the options and descriptions for the custom ATM grid variable.""" + compset_lname = cvars["COMPSET_LNAME"].value + compatible_atm_grids = [] + descriptions = [] + meshes = [] + for atm_grid in cime.domains["atm"].values(): + if check_comp_grid("ATM", atm_grid, compset_lname) is False: + continue + compatible_atm_grids.append(atm_grid.mesh) + descriptions.append(atm_grid.desc) + meshes.append(atm_grid.mesh) + return meshes, descriptions + + cv_custom_atm_domain_mesh = cvars["CUSTOM_ATM_DOMAIN_MESH"] + cv_custom_atm_domain_mesh.options_spec = OptionsSpec( + func=custom_atm_domain_mesh_options_func, args=(cvars["COMP_ATM"], cvars["GRID_MODE"]) + ) + def set_custom_ocn_grid_options(cime): """Set the options and options specs for the custom OCN grid variables. @@ -223,6 +243,33 @@ def custom_lnd_grid_options_func(comp_lnd, custom_atm_grid, lnd_grid_mode): args=(cvars["COMP_LND"], cvars["CUSTOM_ATM_GRID"], cvars["LND_GRID_MODE"]), ) + + # CUSTOM_LND_DOMAIN_MESH options + def custom_lnd_domain_mesh_options_func(comp_lnd, custom_atm_grid, lnd_grid_mode): + """Return the options and descriptions for the custom LND grid variable.""" + if comp_lnd != "clm": + return [custom_atm_grid], [ + "(When CLM is not selected, custom LND grid is automatically set to ATM grid.)" + ] + else: + compset_lname = cvars["COMPSET_LNAME"].value + compatible_lnd_grids = [] + descriptions = [] + meshes = [] + for lnd_grid in cime.domains["lnd"].values(): + if check_comp_grid("LND", lnd_grid, compset_lname) is False: + continue + compatible_lnd_grids.append(lnd_grid.name) + descriptions.append(lnd_grid.desc) + meshes.append(lnd_grid.mesh) + return meshes, descriptions + + cv_custom_lnd_domain_mesh = cvars["CUSTOM_LND_DOMAIN_MESH"] + cv_custom_lnd_domain_mesh.options_spec = OptionsSpec( + func=custom_lnd_domain_mesh_options_func, + args=(cvars["COMP_LND"], cvars["CUSTOM_ATM_GRID"], cvars["LND_GRID_MODE"]), + ) + cv_fsurdat_idealized = cvars["FSURDAT_IDEALIZED"] cv_fsurdat_idealized.options = ["True", "False"] From 867343781708ec660884cb784e1f0818984fc592 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Mon, 27 Oct 2025 10:58:22 -0600 Subject: [PATCH 06/14] Try This --- .../custom_widget_types/case_creator.py | 4 +- visualCaseGen/specs/grid_options.py | 48 ------------------- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index 24fd65c..f0f0461 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -235,9 +235,9 @@ def _update_component_grids( xmlchange("LND_GRID", cvars["CUSTOM_LND_GRID"].value, do_exec, self._is_non_local(), self._out) - xmlchange("ATM_DOMAIN_MESH", cvars["CUSTOM_ATM_DOMAIN_MESH"].value, do_exec, self._is_non_local(), self._out) + xmlchange("ATM_DOMAIN_MESH", os.path.expandvars(self._cime.domains["atm"][cvars["CUSTOM_ATM_GRID"].value].mesh), do_exec, self._is_non_local(), self._out) - xmlchange("LND_DOMAIN_MESH", cvars["CUSTOM_LND_DOMAIN_MESH"].value, do_exec, self._is_non_local(), self._out) + xmlchange("LND_DOMAIN_MESH", os.path.expandvars(self._cime.domains["lnd"][cvars["CUSTOM_LND_GRID"].value].mesh), do_exec, self._is_non_local(), self._out) lnd_grid_mode = cvars["LND_GRID_MODE"].value diff --git a/visualCaseGen/specs/grid_options.py b/visualCaseGen/specs/grid_options.py index 60b3f1a..e750e19 100644 --- a/visualCaseGen/specs/grid_options.py +++ b/visualCaseGen/specs/grid_options.py @@ -125,27 +125,6 @@ def custom_atm_grid_options_func(comp_atm, grid_mode): func=custom_atm_grid_options_func, args=(cvars["COMP_ATM"], cvars["GRID_MODE"]) ) - # CUSTOM_ATM_DOMAIN_MESH options - def custom_atm_domain_mesh_options_func(comp_atm, grid_mode): - """Return the options and descriptions for the custom ATM grid variable.""" - compset_lname = cvars["COMPSET_LNAME"].value - compatible_atm_grids = [] - descriptions = [] - meshes = [] - for atm_grid in cime.domains["atm"].values(): - if check_comp_grid("ATM", atm_grid, compset_lname) is False: - continue - compatible_atm_grids.append(atm_grid.mesh) - descriptions.append(atm_grid.desc) - meshes.append(atm_grid.mesh) - return meshes, descriptions - - cv_custom_atm_domain_mesh = cvars["CUSTOM_ATM_DOMAIN_MESH"] - cv_custom_atm_domain_mesh.options_spec = OptionsSpec( - func=custom_atm_domain_mesh_options_func, args=(cvars["COMP_ATM"], cvars["GRID_MODE"]) - ) - - def set_custom_ocn_grid_options(cime): """Set the options and options specs for the custom OCN grid variables. This function is called at initialization.""" @@ -243,33 +222,6 @@ def custom_lnd_grid_options_func(comp_lnd, custom_atm_grid, lnd_grid_mode): args=(cvars["COMP_LND"], cvars["CUSTOM_ATM_GRID"], cvars["LND_GRID_MODE"]), ) - - # CUSTOM_LND_DOMAIN_MESH options - def custom_lnd_domain_mesh_options_func(comp_lnd, custom_atm_grid, lnd_grid_mode): - """Return the options and descriptions for the custom LND grid variable.""" - if comp_lnd != "clm": - return [custom_atm_grid], [ - "(When CLM is not selected, custom LND grid is automatically set to ATM grid.)" - ] - else: - compset_lname = cvars["COMPSET_LNAME"].value - compatible_lnd_grids = [] - descriptions = [] - meshes = [] - for lnd_grid in cime.domains["lnd"].values(): - if check_comp_grid("LND", lnd_grid, compset_lname) is False: - continue - compatible_lnd_grids.append(lnd_grid.name) - descriptions.append(lnd_grid.desc) - meshes.append(lnd_grid.mesh) - return meshes, descriptions - - cv_custom_lnd_domain_mesh = cvars["CUSTOM_LND_DOMAIN_MESH"] - cv_custom_lnd_domain_mesh.options_spec = OptionsSpec( - func=custom_lnd_domain_mesh_options_func, - args=(cvars["COMP_LND"], cvars["CUSTOM_ATM_GRID"], cvars["LND_GRID_MODE"]), - ) - cv_fsurdat_idealized = cvars["FSURDAT_IDEALIZED"] cv_fsurdat_idealized.options = ["True", "False"] From 8622f977253ba28222a35dbc6e3938f6ab4a153f Mon Sep 17 00:00:00 2001 From: manishvenu Date: Mon, 27 Oct 2025 11:01:42 -0600 Subject: [PATCH 07/14] Clean --- visualCaseGen/config_vars/grid_vars.py | 5 ----- visualCaseGen/custom_widget_types/case_creator.py | 6 ++---- visualCaseGen/specs/grid_options.py | 1 + 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/visualCaseGen/config_vars/grid_vars.py b/visualCaseGen/config_vars/grid_vars.py index a4627a8..3313279 100644 --- a/visualCaseGen/config_vars/grid_vars.py +++ b/visualCaseGen/config_vars/grid_vars.py @@ -40,9 +40,6 @@ def initialize_custom_grid_variables(cime): # A preexisting ATM grid picked for custom grid ConfigVarStrMS("CUSTOM_ATM_GRID", default_value="0.9x1.25") - # The associated domain mesh - ConfigVarStrMS("CUSTOM_ATM_DOMAIN_MESH") - # Custom ocean grid variables ConfigVarStr("OCN_GRID_MODE") # Standard, Modify Existing, Create New @@ -74,8 +71,6 @@ def initialize_custom_grid_variables(cime): "CUSTOM_LND_GRID", default_value="0.9x1.25" ) # A preexisting land grid picked for the custom grid - ConfigVarStr("CUSTOM_LND_DOMAIN_MESH") # The associated domain mesh - # Auto-fill the INPUT_MASK_MESH variable based on the CUSTOM_LND_GRID variable def default_input_mask_mesh(): diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index f0f0461..baed2bc 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -42,8 +42,7 @@ def __init__(self, cime, output=None, allow_xml_override=False): self._allow_xml_override = allow_xml_override def revert_launch(self, do_exec=True): - """This function is called when the case creation fails. It reverts the changes made - to the ccs_config xml files.""" + """This function is called when the case creation fails. It reverts any permanent changes made.""" return # Currently no action is needed @@ -117,7 +116,6 @@ def create_case(self, do_exec): print(f"{COMMENT}Creating case...{RESET}\n") # Run create_newcase - breakpoint() self._run_create_newcase(caseroot, compset, resolution, do_exec) # Add custom grid information to the case if needed: @@ -329,7 +327,7 @@ def _run_create_newcase(self, caseroot, compset, resolution, do_exec): raise RuntimeError("Error creating case.") def _apply_all_xmlchanges(self, do_exec): - """Apply all the necessary xmlchanges to the case.""" + """Apply all the necessary xmlchanges (non-grid) to the case.""" # Set NTASKS based on grid size. e.g. NX * NY < max_pts_per_core if cvars["COMP_OCN"].value == "mom": diff --git a/visualCaseGen/specs/grid_options.py b/visualCaseGen/specs/grid_options.py index e750e19..8057dac 100644 --- a/visualCaseGen/specs/grid_options.py +++ b/visualCaseGen/specs/grid_options.py @@ -125,6 +125,7 @@ def custom_atm_grid_options_func(comp_atm, grid_mode): func=custom_atm_grid_options_func, args=(cvars["COMP_ATM"], cvars["GRID_MODE"]) ) + def set_custom_ocn_grid_options(cime): """Set the options and options specs for the custom OCN grid variables. This function is called at initialization.""" From 393442a1868ce1eb5f2b784a37abce7fdc692323 Mon Sep 17 00:00:00 2001 From: manishvenu Date: Mon, 27 Oct 2025 11:16:20 -0600 Subject: [PATCH 08/14] Last Changes --- visualCaseGen/custom_widget_types/case_creator.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index baed2bc..068ed2c 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -227,15 +227,13 @@ def _update_component_grids( xmlchange("MASK_MESH", ocn_mesh.as_posix(), do_exec, self._is_non_local(), self._out) - xmlchange("OCN_GRID", "VCG_Changed", do_exec, self._is_non_local(), self._out) - xmlchange("ATM_GRID", cvars["CUSTOM_ATM_GRID"].value, do_exec, self._is_non_local(), self._out) xmlchange("LND_GRID", cvars["CUSTOM_LND_GRID"].value, do_exec, self._is_non_local(), self._out) - xmlchange("ATM_DOMAIN_MESH", os.path.expandvars(self._cime.domains["atm"][cvars["CUSTOM_ATM_GRID"].value].mesh), do_exec, self._is_non_local(), self._out) + xmlchange("ATM_DOMAIN_MESH", (self._cime.domains["atm"][cvars["CUSTOM_ATM_GRID"].value].mesh).replace("$DIN_LOC_ROOT",self._cime.din_loc_root), do_exec, self._is_non_local(), self._out) - xmlchange("LND_DOMAIN_MESH", os.path.expandvars(self._cime.domains["lnd"][cvars["CUSTOM_LND_GRID"].value].mesh), do_exec, self._is_non_local(), self._out) + xmlchange("LND_DOMAIN_MESH", (self._cime.domains["lnd"][cvars["CUSTOM_LND_GRID"].value].mesh).replace("$DIN_LOC_ROOT",self._cime.din_loc_root), do_exec, self._is_non_local(), self._out) lnd_grid_mode = cvars["LND_GRID_MODE"].value From 5c660545d8978401865ca955f8dbf89a2eab8b2a Mon Sep 17 00:00:00 2001 From: manishvenu Date: Fri, 2 Jan 2026 09:39:05 -0700 Subject: [PATCH 09/14] With Check --- visualCaseGen/custom_widget_types/case_creator.py | 8 ++++---- visualCaseGen/custom_widget_types/case_tools.py | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index ac6d9fd..85a73d0 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -11,7 +11,7 @@ from ProConPy.config_var import cvars from visualCaseGen.custom_widget_types.mom6_bathy_launcher import MOM6BathyLauncher from visualCaseGen.custom_widget_types.dummy_output import DummyOutput -from visualCaseGen.custom_widget_types.case_tools import xmlchange, run_case_setup, append_user_nl +from visualCaseGen.custom_widget_types.case_tools import xmlchange, run_case_setup, append_user_nl, is_ccs_config_writeable COMMENT = "\033[01;96m" # bold, cyan SUCCESS = "\033[1;32m" # bold, green @@ -23,7 +23,7 @@ class CaseCreator: """The base class for CaseCreatorWidget. Here, backend functionalities are implemented.""" - def __init__(self, cime, output=None, allow_xml_override=False, ccs_config_read_only = False): + def __init__(self, cime, output=None, allow_xml_override=False): """Initialize CaseCreator object. Parameters @@ -40,7 +40,7 @@ def __init__(self, cime, output=None, allow_xml_override=False, ccs_config_read_ self._cime = cime self._out = DummyOutput() if output is None else output self._allow_xml_override = allow_xml_override - self._assign_grids_through_ccs_config = not ccs_config_read_only # By default, visualCaseGen assigns grids through ccs_config, if not possible (which is possible if the user does not own the sandbox), it applies the change through xml case changes. + self._assign_grids_through_ccs_config = is_ccs_config_writeable(cime) # By default, visualCaseGen assigns grids through ccs_config, if not possible (which can happen if the user does not own the sandbox), it applies the change through xml case changes. def revert_launch(self, do_exec=True): """This function is called when the case creation fails. It reverts the changes made @@ -248,7 +248,7 @@ def _update_modelgrid_aliases(self, custom_grid_path, ocn_grid, do_exec): modelgrid_aliases_xml = modelgrid_aliases_xml.as_posix() # confirm that modelgrid_aliases xml file is writeable: - if not os.access(modelgrid_aliases_xml, os.W_OK): + if not is_ccs_config_writeable(self.cime): raise RuntimeError(f"Cannot write to {modelgrid_aliases_xml}.") # Construct the component grids string to be logged: diff --git a/visualCaseGen/custom_widget_types/case_tools.py b/visualCaseGen/custom_widget_types/case_tools.py index 433b88f..9ba58b5 100644 --- a/visualCaseGen/custom_widget_types/case_tools.py +++ b/visualCaseGen/custom_widget_types/case_tools.py @@ -8,6 +8,15 @@ RESET = "\033[0m" +def is_ccs_config_writeable(cime): + srcroot = cime.srcroot + ccs_config_root = Path(srcroot) / "ccs_config" + assert ( + ccs_config_root.exists() + ), f"ccs_config_root {ccs_config_root} does not exist." + modelgrid_aliases_xml = ccs_config_root / "modelgrid_aliases_nuopc.xml" + return os.access(modelgrid_aliases_xml, os.W_OK) + def run_case_setup(do_exec, is_non_local=False, out=None): """Run the case.setup script to set up the case instance. From cce2dd7895560b6b7a82721921b6908ebca5b04f Mon Sep 17 00:00:00 2001 From: manishvenu Date: Fri, 2 Jan 2026 09:46:59 -0700 Subject: [PATCH 10/14] Bleh --- visualCaseGen/custom_widget_types/case_tools.py | 1 + 1 file changed, 1 insertion(+) diff --git a/visualCaseGen/custom_widget_types/case_tools.py b/visualCaseGen/custom_widget_types/case_tools.py index 9ba58b5..cb5bfdb 100644 --- a/visualCaseGen/custom_widget_types/case_tools.py +++ b/visualCaseGen/custom_widget_types/case_tools.py @@ -1,5 +1,6 @@ from pathlib import Path import subprocess +import os from ProConPy.config_var import cvars from visualCaseGen.custom_widget_types.dummy_output import DummyOutput From 4e4077e2c3f4a98ba09fb802ea38e66d6a23758e Mon Sep 17 00:00:00 2001 From: manishvenu Date: Fri, 2 Jan 2026 10:06:24 -0700 Subject: [PATCH 11/14] Boop --- visualCaseGen/custom_widget_types/case_creator.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index 85a73d0..1acba87 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -134,7 +134,7 @@ def create_case(self, do_exec): if self._assign_grids_through_ccs_config: resolution = Path(cvars["CUSTOM_GRID_PATH"].value).name else: - resolution = "visualCaseGen_Custom" # Set to a default visualCaseGen Resolution since grids are changed through xml changes + resolution = "inputdir" # Set to a default visualCaseGen Resolution since grids are changed through xml changes else: raise RuntimeError(f"Unknown grid mode: {cvars['GRID_MODE'].value}") @@ -151,7 +151,7 @@ def create_case(self, do_exec): # If we don't pick the grids through ccs_config, use xml changes if not self._assign_grids_through_ccs_config: - self._update_grids() + self._update_grids(do_exec) # Navigate to the case directory: with self._out: @@ -833,10 +833,10 @@ def _update_grids(self, do_exec): if ocn_grid is None: raise RuntimeError("No ocean grid specified.") - self._update_component_grids(custom_grid_path, ocn_grid, ocn_grid_mode, do_exec) + self._update_component_grids_xml(custom_grid_path, ocn_grid, ocn_grid_mode, do_exec) - def _update_component_grids( + 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. @@ -891,7 +891,7 @@ def _update_component_grids( xmlchange("LND_DOMAIN_MESH", (self._cime.domains["lnd"][cvars["CUSTOM_LND_GRID"].value].mesh).replace("$DIN_LOC_ROOT",self._cime.din_loc_root), do_exec, self._is_non_local(), self._out) - if cvars["CUSTOM_ROF_GRID"].value is not None: + if cvars["CUSTOM_ROF_GRID"].value is not None and cvars["CUSTOM_ROF_GRID"].value != "" and cvars["CUSTOM_ROF_GRID"].value != "null": xmlchange("ROF_GRID", cvars["CUSTOM_ROF_GRID"].value, do_exec, self._is_non_local(), self._out) xmlchange("ROF_DOMAIN_MESH", (self._cime.domains["rof"][cvars["CUSTOM_ROF_GRID"].value].mesh).replace("$DIN_LOC_ROOT",self._cime.din_loc_root), do_exec, self._is_non_local(), self._out) From 54b0481eb4c8393bcb0848cfbad22a2ee322162e Mon Sep 17 00:00:00 2001 From: manishvenu Date: Fri, 2 Jan 2026 10:08:51 -0700 Subject: [PATCH 12/14] AsdA --- visualCaseGen/custom_widget_types/case_creator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index 1acba87..ae7b14a 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -41,6 +41,9 @@ def __init__(self, cime, output=None, allow_xml_override=False): self._out = DummyOutput() if output is None else output self._allow_xml_override = allow_xml_override self._assign_grids_through_ccs_config = is_ccs_config_writeable(cime) # By default, visualCaseGen assigns grids through ccs_config, if not possible (which can happen if the user does not own the sandbox), it applies the change through xml case changes. + if not self._assign_grids_through_ccs_config: + with self._out: + print(f"{COMMENT}ccs_config is not writeable, so case grids will be assigned through xml changes{RESET}\n") def revert_launch(self, do_exec=True): """This function is called when the case creation fails. It reverts the changes made From 10a1f023e9fd490bac7122b86597af42de9f66bb Mon Sep 17 00:00:00 2001 From: manishvenu Date: Fri, 2 Jan 2026 10:11:05 -0700 Subject: [PATCH 13/14] Test --- visualCaseGen/custom_widget_types/case_creator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index ae7b14a..b381d9a 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -251,7 +251,7 @@ def _update_modelgrid_aliases(self, custom_grid_path, ocn_grid, do_exec): modelgrid_aliases_xml = modelgrid_aliases_xml.as_posix() # confirm that modelgrid_aliases xml file is writeable: - if not is_ccs_config_writeable(self.cime): + if not is_ccs_config_writeable(self._cime): raise RuntimeError(f"Cannot write to {modelgrid_aliases_xml}.") # Construct the component grids string to be logged: From 20a15f11c431e0a2f26f7e61dd5e36839a8b4dbf Mon Sep 17 00:00:00 2001 From: manishvenu Date: Thu, 8 Jan 2026 14:29:30 -0700 Subject: [PATCH 14/14] Review Comments --- .../custom_widget_types/case_creator.py | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/visualCaseGen/custom_widget_types/case_creator.py b/visualCaseGen/custom_widget_types/case_creator.py index b381d9a..eefc112 100644 --- a/visualCaseGen/custom_widget_types/case_creator.py +++ b/visualCaseGen/custom_widget_types/case_creator.py @@ -23,7 +23,7 @@ class CaseCreator: """The base class for CaseCreatorWidget. Here, backend functionalities are implemented.""" - def __init__(self, cime, output=None, allow_xml_override=False): + def __init__(self, cime, output=None, allow_xml_override=False, add_grids_to_ccs_config = True): """Initialize CaseCreator object. Parameters @@ -40,15 +40,13 @@ def __init__(self, cime, output=None, allow_xml_override=False): self._cime = cime self._out = DummyOutput() if output is None else output self._allow_xml_override = allow_xml_override - self._assign_grids_through_ccs_config = is_ccs_config_writeable(cime) # By default, visualCaseGen assigns grids through ccs_config, if not possible (which can happen if the user does not own the sandbox), it applies the change through xml case changes. - if not self._assign_grids_through_ccs_config: - with self._out: - print(f"{COMMENT}ccs_config is not writeable, so case grids will be assigned through xml changes{RESET}\n") + self._add_grids_to_ccs_config = add_grids_to_ccs_config # By default, visualCaseGen assigns grids through ccs_config, if not possible (which can happen if the user does not own the sandbox), it is possible to apply grid changes through xmlchanges instead. + assert is_ccs_config_writeable or not add_grids_to_ccs_config, "Cannot write to ccs_config xml files. Please set add_grids_to_ccs_config to False to apply grid changes through xmlchanges." def revert_launch(self, do_exec=True): """This function is called when the case creation fails. It reverts the changes made to the ccs_config xml files.""" - if self._assign_grids_through_ccs_config: + if self._add_grids_to_ccs_config: mg = "ccs_config/modelgrid_aliases_nuopc.xml" if (Path(self._cime.srcroot) / f"{mg}.orig").exists(): shutil.move( @@ -134,10 +132,10 @@ def create_case(self, do_exec): if cvars["GRID_MODE"].value == "Standard": resolution = cvars["GRID"].value elif cvars["GRID_MODE"].value == "Custom": - if self._assign_grids_through_ccs_config: + if self._add_grids_to_ccs_config: resolution = Path(cvars["CUSTOM_GRID_PATH"].value).name else: - resolution = "inputdir" # Set to a default visualCaseGen Resolution since grids are changed through xml changes + resolution = "USER_RES" # Set to a default visualCaseGen Resolution since grids are changed through xml changes else: raise RuntimeError(f"Unknown grid mode: {cvars['GRID_MODE'].value}") @@ -146,15 +144,15 @@ def create_case(self, do_exec): print(f"{COMMENT}Creating case...{RESET}\n") # First, update ccs_config xml files to add custom grid information if needed: - if self._assign_grids_through_ccs_config: + if self._add_grids_to_ccs_config: self._update_ccs_config(do_exec) # Run create_newcase self._run_create_newcase(caseroot, compset, resolution, do_exec) # If we don't pick the grids through ccs_config, use xml changes - if not self._assign_grids_through_ccs_config: - self._update_grids(do_exec) + if not self._add_grids_to_ccs_config: + self._update_grids_via_xmlchange(do_exec) # Navigate to the case directory: with self._out: @@ -172,7 +170,7 @@ def create_case(self, do_exec): # Clean up: if do_exec: - if self._assign_grids_through_ccs_config: + if self._add_grids_to_ccs_config: self._remove_orig_xml_files() cvars["CASE_CREATOR_STATUS"].value = "OK" with self._out: @@ -543,7 +541,7 @@ def _apply_lnd_grid_xmlchanges(self, do_exec): """Apply xmlchanges related to custom land grid if needed.""" lnd_grid_mode = cvars["LND_GRID_MODE"].value - if self._assign_grids_through_ccs_config and lnd_grid_mode == "Modified": + if self._add_grids_to_ccs_config and lnd_grid_mode == "Modified": if cvars["COMP_OCN"].value != "mom": with self._out: print(f"{COMMENT}Apply custom land grid xml changes:{RESET}\n") @@ -807,9 +805,9 @@ def _apply_clm_namelist_changes(self, do_exec): self._apply_user_nl_changes("clm", user_nl_clm_changes, do_exec) - def _update_grids(self, do_exec): - """Update the modelgrid_aliases and component_grids xml files with custom grid - information if needed. This function is called after running create_newcase.""" + def _update_grids_via_xmlchange(self, do_exec): + """Update the case with custom grid information if needed. + This function is called after running create_newcase.""" if cvars["GRID_MODE"].value == "Standard": return @@ -889,15 +887,14 @@ def _update_component_grids_xml( xmlchange("ATM_GRID", cvars["CUSTOM_ATM_GRID"].value, do_exec, self._is_non_local(), self._out) xmlchange("LND_GRID", cvars["CUSTOM_LND_GRID"].value, do_exec, self._is_non_local(), self._out) + + xmlchange("ATM_DOMAIN_MESH", self._cime.get_mesh_path("atm",cvars["CUSTOM_ATM_GRID"].value), do_exec, self._is_non_local(), self._out) - xmlchange("ATM_DOMAIN_MESH", (self._cime.domains["atm"][cvars["CUSTOM_ATM_GRID"].value].mesh).replace("$DIN_LOC_ROOT",self._cime.din_loc_root), do_exec, self._is_non_local(), self._out) - - xmlchange("LND_DOMAIN_MESH", (self._cime.domains["lnd"][cvars["CUSTOM_LND_GRID"].value].mesh).replace("$DIN_LOC_ROOT",self._cime.din_loc_root), do_exec, self._is_non_local(), self._out) + xmlchange("LND_DOMAIN_MESH", self._cime.get_mesh_path("lnd",cvars["CUSTOM_LND_GRID"].value), do_exec, self._is_non_local(), self._out) if cvars["CUSTOM_ROF_GRID"].value is not None and cvars["CUSTOM_ROF_GRID"].value != "" and cvars["CUSTOM_ROF_GRID"].value != "null": xmlchange("ROF_GRID", cvars["CUSTOM_ROF_GRID"].value, do_exec, self._is_non_local(), self._out) - xmlchange("ROF_DOMAIN_MESH", (self._cime.domains["rof"][cvars["CUSTOM_ROF_GRID"].value].mesh).replace("$DIN_LOC_ROOT",self._cime.din_loc_root), do_exec, self._is_non_local(), self._out) - + xmlchange("ROF_DOMAIN_MESH", self._cime.get_mesh_path("rof",cvars["CUSTOM_ROF_GRID"].value), do_exec, self._is_non_local(), self._out) lnd_grid_mode = cvars["LND_GRID_MODE"].value