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 )
0 commit comments