Skip to content

Commit 151da29

Browse files
Add manager
1 parent 5aef594 commit 151da29

File tree

3 files changed

+442
-0
lines changed

3 files changed

+442
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import os
2+
from experiment_manager_tool.git_manager.git_manager import payu_clone_from_commit_hash
3+
from experiment_manager_tool.utils.util_functions import update_diag_table
4+
from experiment_manager_tool.configuration_updater.f90nml_updater import f90nmlUpdater
5+
from experiment_manager_tool.configuration_updater.nuopc_runconfig_updater import NuopcRunConfigUpdater
6+
from experiment_manager_tool.configuration_updater.nuopc_runseq_updater import NuopcRunSeqUpdater
7+
from experiment_manager_tool.configuration_updater.config_updater import ConfigUpdater
8+
from experiment_manager_tool.configuration_updater.mom6_updater import MOM6Updater
9+
from experiment_manager_tool.mixins.mixins import FullPathMixin
10+
from experiment_manager_tool.pbs_job_manager.pbs_job_manager import PBSJobManager
11+
from experiment_manager_tool.utils.base_manager import BaseManager
12+
13+
class ControlExperiment(BaseManager, FullPathMixin):
14+
def __init__(self, yamlfile: str) -> None:
15+
super().__init__(yamlfile)
16+
17+
# YAML inputs for control experiment
18+
self.base_url = self.indata.get("base_url")
19+
self.base_commit = self.indata.get("base_commit")
20+
self.base_branch_name = self.indata.get("base_branch_name")
21+
self.base_path = self.full_path("base_dir_name")
22+
23+
# diag_table updates
24+
self.diag_ctrl = self.indata.get("diag_ctrl", False)
25+
self.diag_path = self.full_path("diag_dir_name")
26+
27+
# configuration updaters
28+
self.f90nmlupdater = f90nmlUpdater()
29+
self.configupdater = ConfigUpdater()
30+
self.nuopcrunsequpdater = NuopcRunSeqUpdater()
31+
self.nuopcrunconfigupdater = NuopcRunConfigUpdater(yamlfile)
32+
self.mom6updater = MOM6Updater(yamlfile)
33+
34+
# PBS job manager and control runs
35+
self.check_duplicate_jobs = self.indata.get("check_duplicate_jobs", True)
36+
ctrl_nruns = self.indata.get("ctrl_nruns", 0)
37+
self.pbsjobmanager = PBSJobManager(self.dir_manager, self.check_duplicate_jobs, ctrl_nruns)
38+
39+
def manage_experiment(self) -> None:
40+
print(f"-- Setting up control experiment at {self.base_path}")
41+
42+
if os.path.exists(self.base_path):
43+
print(f"-- Control experiment {self.base_path} already exists, hence skipping cloning.")
44+
print(f" However, control experiment can still be updated based on the YAML inputs.")
45+
else:
46+
payu_clone_from_commit_hash(
47+
self.base_url,
48+
self.base_commit,
49+
self.base_branch_name,
50+
self.base_path,
51+
)
52+
53+
# update diag_table if enabled
54+
update_diag_table(self.base_path,
55+
self.diag_path,
56+
self.diag_ctrl,
57+
self.model,
58+
)
59+
60+
# setup control experiment
61+
self._setup_control_expt()
62+
63+
# run control experiment
64+
self.pbsjobmanager.pbs_job_runs(self.base_path)
65+
66+
def _setup_control_expt(self) -> None:
67+
"""
68+
Modifies parameters based on the input YAML configuration for the control experiment.
69+
70+
Updates configuration files:
71+
1. config.yaml,
72+
2. f90 namelist files (.in, .nml),
73+
3. nuopc.runconfig,
74+
4. MOM_input,
75+
5. nuopc.runseq,
76+
for the control experiment if needed.
77+
"""
78+
for curr_dir, sub_dirs, files_curr_dir in os.walk(self.base_path):
79+
sub_dirs[:] = [tmp_d for tmp_d in sub_dirs if ".git" not in tmp_d]
80+
for f in files_curr_dir:
81+
if ".git" in f:
82+
continue
83+
84+
target_file = os.path.relpath(os.path.join(curr_dir, f), self.base_path)
85+
yaml_data = self.indata.get(target_file)
86+
87+
if yaml_data:
88+
# Updates config entries from f90nml files
89+
if target_file.endswith("_in") or target_file.endswith(".nml"):
90+
self.f90nmlupdater.update_nml_params(self.base_path, yaml_data, target_file)
91+
92+
# Updates config entries from `nuopc.runconfig`
93+
if target_file == "nuopc.runconfig":
94+
self.nuopcrunconfigupdater.update_runconfig_params(self.base_path, yaml_data, target_file)
95+
96+
# Updates config entries from `config_yaml`
97+
if target_file == "config.yaml":
98+
self.configupdater.update_config_params(self.base_path, yaml_data, target_file)
99+
100+
# Updates config entries from `MOM_input`
101+
if target_file == "MOM_input":
102+
self.mom6updater.update_mom6_params(self.base_path, yaml_data, target_file)
103+
104+
# Update only coupling timestep from `nuopc.runseq`
105+
if target_file == "nuopc.runseq":
106+
self.nuopcrunsequpdater.update_cpl_dt_params(self.base_path, yaml_data, target_file)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import os
2+
from experiment_manager_tool.utils.load_external_tools import ExternalTools
3+
from experiment_manager_tool.manager.control_experiment import ControlExperiment
4+
from experiment_manager_tool.manager.perturb_experiment import PerturbExperiment
5+
from experiment_manager_tool.utils.base_manager import BaseManager
6+
7+
class ExperimentManager(BaseManager):
8+
def __init__(self, yamlfile) -> None:
9+
super().__init__(yamlfile)
10+
self.yamlfile = yamlfile
11+
self.external_tools = None
12+
self.control_experiment = None
13+
self.perturb_experiment = None
14+
15+
def create_test_path(self) -> None:
16+
"""
17+
Creates the local test directory for blocks of parameter testing.
18+
"""
19+
if os.path.exists(self.test_path):
20+
print(f"-- Test directory {self.test_path} already exists!")
21+
else:
22+
os.makedirs(self.test_path)
23+
print(f"-- Test directory {self.test_path} has been created!")
24+
25+
def model_selection(self) -> None:
26+
"""
27+
Ensures the model to be either "access-om2" or "access-om3"
28+
"""
29+
if self.model not in (("access-om2", "access-om3")):
30+
raise ValueError(
31+
f"{self.model} requires to be either " f"access-om2 or access-om3!"
32+
)
33+
34+
def run(self) -> None:
35+
self.create_test_path()
36+
self.model_selection()
37+
self.external_tools = ExternalTools(self.yamlfile)
38+
39+
self.external_tools.clone_om3utils()
40+
self.external_tools.update_diag_table()
41+
42+
self.control_experiment = ControlExperiment(self.yamlfile)
43+
self.control_experiment.manage_experiment()
44+
45+
self.perturb_experiment = PerturbExperiment(self.yamlfile)
46+
self.perturb_experiment.manage_perturb_expt()

0 commit comments

Comments
 (0)