Skip to content

Commit

Permalink
introduce ninst variable (backend) and adjust case creation
Browse files Browse the repository at this point in the history
  • Loading branch information
alperaltuntas committed Jan 8, 2025
1 parent 1eeeb5c commit daf3ade
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 62 deletions.
5 changes: 4 additions & 1 deletion visualCaseGen/config_vars/launcher_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from ProConPy.out_handler import handler as owh
from ProConPy.config_var import cvars
from ProConPy.config_var_str import ConfigVarStr
from ProConPy.config_var_int import ConfigVarInt

logger = logging.getLogger("\t" + __name__.split(".")[-1])

Expand All @@ -17,4 +18,6 @@ def initialize_launcher_variables(cime):
default_value = cime.machine,
)
ConfigVarStr("PROJECT", widget_none_val="") # Project ID for the machine
ConfigVarStr("CASE_CREATOR_STATUS", widget_none_val="") # a status variable to prevent the completion of the stage
ConfigVarStr("CASE_CREATOR_STATUS", widget_none_val="") # a status variable to prevent the completion of the stage
ConfigVarInt("NINST", default_value=1) # Number of model instances (Currently, can only be controlled in the backend,
# particularly when visualCaseGen is used as an external library)
53 changes: 26 additions & 27 deletions visualCaseGen/custom_widget_types/case_creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class CaseCreator:

def __init__(self, cime, output=None, allow_xml_override=False):
"""Initialize CaseCreator object.
Parameters
----------
cime : CIME
Expand Down Expand Up @@ -149,10 +149,10 @@ def create_case(self, do_exec):
print(f"cd {caseroot}\n")

# Apply case modifications, e.g., xmlchanges and user_nl changes
self._apply_all_xmlchanges(caseroot, do_exec)
self._apply_all_xmlchanges(do_exec)

# Run case.setup
self._run_case_setup(caseroot, do_exec)
run_case_setup(do_exec, self._is_non_local(), self._out)

# Apply user_nl changes
self._apply_all_namelist_changes(do_exec)
Expand All @@ -167,11 +167,11 @@ def create_case(self, do_exec):
f"{SUCCESS}Case created successfully at {caseroot}.{RESET}\n\n"
f"{COMMENT}To further customize, build, and run the case, "
f"navigate to the case directory in your terminal. To create "
f"another case, restart the notebook.{RESET}\n"
f"another case, restart the notebook.{RESET}\n"
)

def _update_ccs_config(self, do_exec):
"""Update the modelgrid_aliases and component_grids xml files with custom grid
"""Update the modelgrid_aliases and component_grids xml files with custom grid
information if needed. This function is called before running create_newcase."""

# If Custom grid is selected, update modelgrid_aliases and component_grids xml files:
Expand Down Expand Up @@ -206,7 +206,7 @@ def _update_ccs_config(self, 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
Expand Down Expand Up @@ -309,7 +309,7 @@ def _update_component_grids(
):
"""Update the component_grids xml file with custom ocnice grid information.
This function is called before running create_newcase.
Parameters
----------
custom_grid_path : Path
Expand Down Expand Up @@ -420,7 +420,7 @@ def _update_component_grids(

def _run_create_newcase(self, caseroot, compset, resolution, do_exec):
"""Run CIME's create_newcase tool to create a new case instance.
Parameters
----------
caseroot : Path
Expand Down Expand Up @@ -450,6 +450,11 @@ def _run_create_newcase(self, caseroot, compset, resolution, do_exec):
if project := cvars["PROJECT"].value:
cmd += f"--project {project} "

# append number of model instances if needed:
ninst = 1 if cvars["NINST"].value is None else cvars["NINST"].value
if ninst != 1:
cmd += f"--ninst {ninst} "

# append --nonlocal if needed:
if self._is_non_local():
cmd += "--non-local "
Expand All @@ -473,7 +478,7 @@ def _run_create_newcase(self, caseroot, compset, resolution, do_exec):
if runout.returncode != 0:
raise RuntimeError("Error creating case.")

def _apply_all_xmlchanges(self, caseroot, do_exec):
def _apply_all_xmlchanges(self, do_exec):

lnd_grid_mode = cvars["LND_GRID_MODE"].value
if lnd_grid_mode == "Modified":
Expand All @@ -485,30 +490,25 @@ def _apply_all_xmlchanges(self, caseroot, do_exec):
# 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, caseroot, do_exec, self._is_non_local(), self._out)
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, caseroot, do_exec, self._is_non_local(), self._out)
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_case_setup(self, caseroot, do_exec):
"""Run the case.setup script to set up the case instance."""
run_case_setup(caseroot, do_exec, self._is_non_local(), self._out)

def _apply_user_nl_changes(self, user_nl_filename, var_val_pairs, do_exec, comment=None, log_title=True):
def _apply_user_nl_changes(self, model, var_val_pairs, do_exec, comment=None, log_title=True):
"""Apply changes to a given user_nl file."""
caseroot = cvars["CASEROOT"].value
append_user_nl(user_nl_filename, var_val_pairs, caseroot, do_exec, comment, log_title, self._out)
append_user_nl(model, var_val_pairs, do_exec, comment, log_title, self._out)

def _apply_all_namelist_changes(self, do_exec):
"""Apply all the necessary user_nl changes to the case.
Parameters
----------
caseroot : Path
Expand Down Expand Up @@ -565,7 +565,7 @@ def _apply_mom_namelist_changes(self, do_exec):

# apply custom MOM6 grid changes:
self._apply_user_nl_changes(
"user_nl_mom",
"mom",
[
("INPUTDIR", ocn_grid_path),
("TRIPOLAR_N", "False"),
Expand All @@ -589,7 +589,7 @@ def _apply_mom_namelist_changes(self, do_exec):
)

self._apply_user_nl_changes(
"user_nl_mom",
"mom",
[
("DT", str(dt)),
("DT_THERM", str(dt_therm)),
Expand All @@ -602,7 +602,7 @@ def _apply_mom_namelist_changes(self, do_exec):
# Set MOM6 Initial Conditions parameters:
if cvars["OCN_IC_MODE"].value == "Simple":
self._apply_user_nl_changes(
"user_nl_mom",
"mom",
[
("TS_CONFIG", "fit"),
("T_REF", cvars["T_REF"].value),
Expand All @@ -626,7 +626,7 @@ def _apply_mom_namelist_changes(self, do_exec):
shutil.copy(temp_salt_z_init_file, ocn_grid_path / temp_salt_z_init_file.name)
# Apply the user_nl changes:
self._apply_user_nl_changes(
"user_nl_mom",
"mom",
[
("INIT_LAYERS_FROM_Z_FILE", "True"),
("TEMP_SALT_Z_INIT_FILE", temp_salt_z_init_file.name),
Expand All @@ -653,7 +653,7 @@ def _apply_cice_namelist_changes(self, do_exec):

cice_grid_file_path = MOM6BathyLauncher.cice_grid_file_path()
self._apply_user_nl_changes(
"user_nl_cice",
"cice",
[
("grid_format", '"nc"'),
("grid_file", f'"{cice_grid_file_path}"'),
Expand Down Expand Up @@ -685,7 +685,7 @@ def _apply_clm_namelist_changes(self, do_exec):
inittime = cvars["INITTIME"].value
if inittime is None:
inittime = cvars["COMPSET_LNAME"].value.split("_")[0]

# For transient runs, we need to:
# - set check_dynpft_consistency to .false.
# - set flanduse_timeseries
Expand All @@ -702,5 +702,4 @@ def _apply_clm_namelist_changes(self, do_exec):
# cft dimensions included in clm namelist xml files don't match the dimensions that clm expects: 64 vs 2.
])

self._apply_user_nl_changes("user_nl_clm", user_nl_clm_changes, do_exec)

self._apply_user_nl_changes("clm", user_nl_clm_changes, do_exec)
78 changes: 44 additions & 34 deletions visualCaseGen/custom_widget_types/case_tools.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
from pathlib import Path
import subprocess

from ProConPy.config_var import cvars
from visualCaseGen.custom_widget_types.dummy_output import DummyOutput

COMMENT = "\033[01;96m" # bold, cyan
RESET = "\033[0m"


def run_case_setup(caseroot, do_exec, is_non_local=False, out=None):
def run_case_setup(do_exec, is_non_local=False, out=None):
"""Run the case.setup script to set up the case instance.
Parameters
----------
caseroot : Path
The path to the case directory.
do_exec : bool
If True, execute the commands. If False, only print them.
If True, execute the commands. If False, only print them.
is_non_local : bool, optional
If True, the case has been created on a machine different from the one
that runs visualCaseGen.
"""

caseroot = cvars["CASEROOT"].value

# Run ./case.setup
cmd = "./case.setup"
if is_non_local:
Expand All @@ -37,17 +38,15 @@ def run_case_setup(caseroot, do_exec, is_non_local=False, out=None):
if runout.returncode != 0:
raise RuntimeError(f"Error running {cmd}.")

def append_user_nl(user_nl_filename, var_val_pairs, caseroot, do_exec, comment=None, log_title=True, out=None):
def append_user_nl(model, var_val_pairs, do_exec, comment=None, log_title=True, out=None):
"""Apply changes to a given user_nl file.
Parameters
----------
user_nl_filename : str
The name of the user_nl file to modify.
model : str
The model whose user_nl file will be modified.
var_val_pairs : list of tuples
A list of tuples, where each tuple contains a variable name and its value.
caseroot: Path or str
The path to the case directory
do_exec : bool
If True, execute the commands. If False, only print them.
comment : str, optional
Expand All @@ -62,35 +61,44 @@ def append_user_nl(user_nl_filename, var_val_pairs, caseroot, do_exec, comment=N
assert isinstance(var_val_pairs, list)
assert all(isinstance(pair, tuple) for pair in var_val_pairs)

# Print the changes to the user_nl file:
out = DummyOutput() if out is None else out
with out:
if log_title:
print(f"{COMMENT}Adding parameter changes to {user_nl_filename}:{RESET}\n")
if comment:
print(f" ! {comment}")
for var, val in var_val_pairs:
print(f" {var} = {val}")
print("")

if not do_exec:
return

# Apply the changes to the user_nl file:
with open(Path(caseroot) / user_nl_filename, "a") as f:
if comment:
f.write(f"\n! {comment}\n")
for var, val in var_val_pairs:
f.write(f"{var} = {val}\n")

caseroot = cvars["CASEROOT"].value
ninst = cvars["NINST"].value

def xmlchange(var, val, caseroot, do_exec=True, is_non_local=False, out=None):
def _do_append_user_nl(user_nl_filename):
# Print the changes to the user_nl file:
with out:
if log_title:
print(f"{COMMENT}Adding parameter changes to {user_nl_filename}:{RESET}\n")
if comment:
print(f" ! {comment}")
for var, val in var_val_pairs:
print(f" {var} = {val}")
print("")

if not do_exec:
return

# Apply the changes to the user_nl file:
with open(Path(caseroot) / user_nl_filename, "a") as f:
if comment:
f.write(f"\n! {comment}\n")
for var, val in var_val_pairs:
f.write(f"{var} = {val}\n")

ninst = 1 if ninst is None else ninst
if ninst==1:
_do_append_user_nl(f"user_nl_{model}")
else:
for i in range(1, ninst+1):
_do_append_user_nl(f"user_nl_{model}_{str(i).zfill(4)}")

def xmlchange(var, val, do_exec=True, is_non_local=False, out=None):
"""Apply custom xml changes to the case.
Parameters
----------
caseroot : Path
The path to the case directory.
do_exec : bool
If True, execute the commands. If False, only print them.
is_non_local : bool
Expand All @@ -100,6 +108,8 @@ def xmlchange(var, val, caseroot, do_exec=True, is_non_local=False, out=None):
The output widget to use for displaying log messages.
"""

caseroot = cvars["CASEROOT"].value

cmd = f"./xmlchange {var}={val}"
if is_non_local is True:
cmd += " --non-local"
Expand Down

0 comments on commit daf3ade

Please sign in to comment.