From 4147127baa976ca3c5bf2eeae5e6ad4cb7852128 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Tue, 9 Apr 2024 16:31:45 -0400 Subject: [PATCH 01/37] initial commit --- CMakeLists.txt | 2 ++ gcmpy/CMakeLists.txt | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 gcmpy/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 86c8b109..2b38a9d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectory(gcmpy) + ecbuild_add_executable ( TARGET GEOSgcm.x SOURCES GEOSgcm.F90 diff --git a/gcmpy/CMakeLists.txt b/gcmpy/CMakeLists.txt new file mode 100644 index 00000000..9703faf9 --- /dev/null +++ b/gcmpy/CMakeLists.txt @@ -0,0 +1,24 @@ +# cp (makes exe) +set (programs + construct_extdata_yaml_list.py + ) + +install ( + PROGRAMS ${programs} + DESTINATION bin/gcmpy + ) + +# processed files +set (setup_scripts + gcm_setup + gmichem_setup + geoschemchem_setup + stratchem_setup + ) + +foreach (file ${setup_scripts}) + configure_file(${file} ${file} @ONLY) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION bin/gcmpy) +endforeach () + + From 93554269fa6500fbabb3fe7d90f7f997c675155c Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Tue, 9 Apr 2024 17:46:40 -0400 Subject: [PATCH 02/37] updated directories --- gcmpy/CMakeLists.txt | 14 +++++--------- gcmpy/scripts/CMakeLists.txt | 16 ++++++++++++++++ gcmpy/yaml/CMakeLists.txt | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 gcmpy/scripts/CMakeLists.txt create mode 100644 gcmpy/yaml/CMakeLists.txt diff --git a/gcmpy/CMakeLists.txt b/gcmpy/CMakeLists.txt index 9703faf9..8846312e 100644 --- a/gcmpy/CMakeLists.txt +++ b/gcmpy/CMakeLists.txt @@ -1,7 +1,8 @@ # cp (makes exe) -set (programs - construct_extdata_yaml_list.py - ) +add_subdirectory(scripts) +add_subdirectory(yamls) + +set (programs) install ( PROGRAMS ${programs} @@ -9,12 +10,7 @@ install ( ) # processed files -set (setup_scripts - gcm_setup - gmichem_setup - geoschemchem_setup - stratchem_setup - ) +set (setup_scripts) foreach (file ${setup_scripts}) configure_file(${file} ${file} @ONLY) diff --git a/gcmpy/scripts/CMakeLists.txt b/gcmpy/scripts/CMakeLists.txt new file mode 100644 index 00000000..43be2a33 --- /dev/null +++ b/gcmpy/scripts/CMakeLists.txt @@ -0,0 +1,16 @@ +set (programs + #fill + ) + +install ( + PROGRAMS ${programs} + DESTINATION bin/gcmpy/scripts + ) + +# processed files +set (setup_scripts) + +foreach (file ${setup_scripts}) + configure_file(${file} ${file} @ONLY) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION bin/gcmpy) +endforeach () diff --git a/gcmpy/yaml/CMakeLists.txt b/gcmpy/yaml/CMakeLists.txt new file mode 100644 index 00000000..36e3ed48 --- /dev/null +++ b/gcmpy/yaml/CMakeLists.txt @@ -0,0 +1,16 @@ +set (programs + #fill + ) + +install ( + PROGRAMS ${programs} + DESTINATION bin/gcmpy/yaml + ) + +# processed files +set (setup_scripts) + +foreach (file ${setup_scripts}) + configure_file(${file} ${file} @ONLY) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION bin/gcmpy) +endforeach () From 0e5e3afc3b3184bd5ed2c50884a1a6c0acb46c22 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Tue, 9 Apr 2024 17:48:26 -0400 Subject: [PATCH 03/37] Add scripts via upload --- gcmpy/scripts/atmosphere.py | 333 +++++++++++++++++++ gcmpy/scripts/env.py | 134 ++++++++ gcmpy/scripts/generate_question.py | 59 ++++ gcmpy/scripts/gocart.py | 48 +++ gcmpy/scripts/land.py | 66 ++++ gcmpy/scripts/model.py | 408 ++++++++++++++++++++++++ gcmpy/scripts/ocean.py | 257 +++++++++++++++ gcmpy/scripts/process_questions.py | 232 ++++++++++++++ gcmpy/scripts/test_generate_question.py | 9 + gcmpy/scripts/utility.py | 66 ++++ 10 files changed, 1612 insertions(+) create mode 100644 gcmpy/scripts/atmosphere.py create mode 100644 gcmpy/scripts/env.py create mode 100644 gcmpy/scripts/generate_question.py create mode 100644 gcmpy/scripts/gocart.py create mode 100644 gcmpy/scripts/land.py create mode 100644 gcmpy/scripts/model.py create mode 100644 gcmpy/scripts/ocean.py create mode 100644 gcmpy/scripts/process_questions.py create mode 100644 gcmpy/scripts/test_generate_question.py create mode 100644 gcmpy/scripts/utility.py diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py new file mode 100644 index 00000000..ead977d4 --- /dev/null +++ b/gcmpy/scripts/atmosphere.py @@ -0,0 +1,333 @@ +from env import answerdict +from utility import color + +class atmosphere: + def __init__(self): + self.use_SHMEM = False + self.force_das = "#" + self.force_gcm = "#" + self.num_readers = 1 + self.num_writers = 1 + self.DT = answerdict["heartbeat"].q_answer + self.DT_solar = None + self.DT_irrad = None + self.DT_ocean = None + self.DT_long = None + self.IM = int(answerdict["AM_horizontal_res"].q_answer[1:]) + self.JM = self.IM * 6 + self.NX = None + self.NY = None + self.use_hydrostatic = answerdict["use_hydrostatic"].q_answer + self.microphysics = answerdict["AM_microphysics"].q_answer + self.IM_hist = self.IM * 4 + self.JM_hist = self.JM * 2 + 1 + self.gridfile = f"Gnomonic_c{self.IM}.dat" + self.job_sgmt = None + self.num_sgmt = None + self.res = f"CF{self.IM:04}x6C" + self.post_NDS = None + self.NX_convert = 2 + self.NY_convert = 24 + self.CONUS = "#" + self.stretch_factor = None + self.gridname = f"PE{self.IM}x{self.JM}-CF" + self.res_dateline = f"{self.IM}x{self.JM}" + self.BACM_1M = "#" + self.GFDL_1M = "#" + self.MGB2_2M = "#" + self.GFDL_hydro = ".TRUE." + self.GFDL_prog_ccn = "prog_ccn = .true." + self.GFDL_use_ccn = "use_ccn = .true." + self.MP_turnoff_wsub = None + self.FV_make_NH = None + self.FV_hydro = None + self.schmidt = None + self.target_lon = None + self.target_lat = None + + # for debugging purposes + def print_vars(self): + all_vars = vars(self) + for var_name, var_value in all_vars.items(): + print(f"{color.BLUE}{var_name}: {var_value}{color.RESET}") + + def hres(self, ocean_NX, ocean_NY): + match answerdict["AM_horizontal_res"].q_answer: + case "c12": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_ocean = self.DT_irrad + self.DT_long = self.DT + if answerdict["OM_name"].q_answer == "MOM6": + self.NX = 1 + else: + self.NX = 2 + self.NY = self.NX * 6 + self.job_sgmt = f"{15:08}" + self.num_sgmt = 20 + self.post_NDS = 4 + self.NX_convert = 1 + self.NY_convert = 6 + + case "c24": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_ocean = self.DT_irrad + self.DT_long = self.DT + self.NX = 4 + self.NY = self.NX * 6 + self.job_sgmt = f"{15:08}" + self.num_sgmt = 20 + self.post_NDS = 4 + self.NX_convert = 1 + self.NY_convert = 6 + + case "c48": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_ocean = self.DT_irrad + self.DT_long = self.DT + self.NX = 4 + self.NY = self.NX * 6 + self.IM_hist = 180 + self.JM_hist = 91 + self.job_sgmt = f"{15:08}" + self.num_sgmt = 20 + self.post_NDS = 4 + + case "c90": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_long = self.DT + match answerdict["OM_name"].q_answer: + case "MIT": + self.NX = 10 + self.NY = 36 + self.DT_ocean = self.DT + case "MOM5","MOM6": + self.NX = ocean_NX + self.NY = ocean_NY + self.DT_ocean = self.DT + case _: + self.NX = 3 + self.NY = self.NX * 6 + self.DT_ocean = self.DT_irrad + self.job_sgmt = f"{32:08}" + self.num_sgmt = 4 + self.post_NDS = 8 + + case "c180": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_long = self.DT + if answerdict["OM_coupled"].q_answer == True: + self.NX = ocean_NX + self.NY = ocean_NY + self.DT_ocean = self.DT + else: + self.NX = 6 + self.NY = self.NX * 6 + self.DT_ocean = self.DT_irrad + self.job_sgmt = f"{16:08}" + self.num_sgmt = 1 + self.post_NDS = 8 + self.num_readers = 2 + + case "c360": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_ocean = self.DT_irrad + self.DT_long = self.DT + self.NX = 12 + self.NY = self.NX * 6 + self.num_readers = 4 + self.job_sgmt = f"{5:08}" + self.num_sgmt = 1 + self.post_NDS = 12 + self.NX_convert = 4 + + case "c720": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_ocean = self.DT_irrad + self.DT_long = 450 + self.NX = 24 + self.NY = self.NX * 6 + self.num_readers = 6 + self.job_sgmt = f"{5:08}" + self.num_sgmt = 1 + self.post_NDS = 16 + self.NX_convert = 8 + self.use_SHMEM = True + + case "c1440": + self.DT_solar = 1800 + self.DT_irrad = 1800 + self.DT_ocean = self.DT_irrad + self.DT_long = 300 + self.NX = 48 + self.NY = self.NX * 6 + self.num_readers = 6 + self.job_sgmt = f"{1:08}" + self.num_sgmt = 1 + self.post_NDS = 32 + self.NX_convert = 8 + self.use_SHMEM = True + + case "c2880": + self.DT_solar = 1800 + self.DT_irrad = 1800 + self.DT_ocean = self.DT_irrad + self.DT_long = 300 + self.NX = 96 + self.NY = self.NX * 6 + self.num_readers = 6 + self.job_sgmt = f"{1:08}" + self.num_sgmt = 1 + self.post_NDS = 32 + self.NX_convert = 8 + self.use_SHMEM = True + + case "c5760": + self.DT_solar = 900 + self.DT_irrad = 900 + self.DT_ocean = self.DT_irrad + self.DT_long = 300 + self.NX = 192 + self.NY = self.NX * 6 + self.num_readers = 6 + self.job_sgmt = f"{1:08}" + self.num_sgmt = 1 + self.post_NDS = 32 + self.NX_convert = 8 + self.use_SHMEM = True + + case "c270": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_ocean = self.DT_irrad + self.DT_long = self.DT + self.NX = 18 + self.NY = self.NX * 6 + self.num_readers = 6 + self.job_sgmt = f"{1:08}" + self.num_sgmt = 1 + self.post_NDS = 32 + self.NX_convert = 8 + self.use_SHMEM = True + self.CONUS = "" + self.stretch_factor = 2.5 + + case "c540": + self.DT_solar = 3600 + self.DT_irrad = 3600 + self.DT_ocean = self.DT_irrad + self.DT_long = self.DT + self.NX = 36 + self.NY = self.NX * 6 * 2 + self.num_readers = 6 + self.job_sgmt = f"{1:08}" + self.num_sgmt = 1 + self.post_NDS = 32 + self.NX_convert = 8 + self.use_SHMEM = True + self.CONUS = "" + self.stretch_factor = 2.5 + + case "c1080": + self.DT_solar = 900 + self.DT_irrad = 900 + self.DT_ocean = self.DT_irrad + self.DT_long = 300 + self.NX = 72 + self.NY = self.NX * 6 * 2 + self.num_readers = 6 + self.job_sgmt = f"{1:08}" + self.num_sgmt = 1 + self.post_NDS = 32 + self.NX_convert = 8 + self.use_SHMEM = True + self.CONUS = "" + self.stretch_factor = 2. + + case "c1536": + self.DT_solar = 900 + self.DT_irrad = 900 + self.DT_ocean = self.DT_irrad + self.DT_long = 300 + self.NX = 96 + self.NY = self.NX * 6 + self.num_readers = 6 + self.job_sgmt = f"{5:08}" + self.num_sgmt = 1 + self.post_NDS = 16 + self.NX_convert = 8 + self.use_SHMEM = True + self.CONUS = "" + self.stretch_factor = 3.0 + + case "c2160": + self.DT_solar = 900 + self.DT_irrad = 900 + self.DT_ocean = self.DT_irrad + self.DT_long = 300 + self.NX = 192 + self.NY = self.NX * 6 * 2 + self.num_readers = 6 + self.job_sgmt = f"{5:08}" + self.num_sgmt = 1 + self.post_NDS = 32 + self.NX_convert = 8 + self.use_SHMEM = True + self.CONUS = "" + self.stretch_factor = 2.5 + + if answerdict["OM_name"].q_answer == "MIT": + self.DT_ocean = self.DT + + def set_microphysics(self): + match self.microphysics: + case "BACM_1M": + self.BACM_1M = "" + self.DT_long = 450 + case "GFDL_1M": + self.GFDL_1M = "" + case "MGB2_2M": + self.MGB2_2M = "" + + def set_turnoff_wsub(self): + if self.microphysics == "MGB2_2M": + self.MP_turnoff_wsub = "#DELETE" + else: + self.MP_turnoff_wsub = "" + + # settings for fvcore_layour.rc + def set_fvcore_layout(self): + match self.use_hydrostatic: + case True: + self.FV_make_NH = "Make_NH = .F." + self.FV_hydro = "hydrostatic = .T." + case False: + self.FV_make_NH = "Make_NH = .T." + self.FV_hydro = "hydrostatic = .F." + if self.microphysics == "MGB2_2M": + self.FV_hydro = ".FALSE." + + def set_CONUS(self): + if self.CONUS == "#": + self.schmidt = "do_schmidt = .false." + self.stretch_factor = "stretch_fac = 1.0" + self.target_lon = "target_lon = 0.0" + self.target_lat = "target_lat = 0.0" + else: + self.schmidt = "do_schmidt = .true." + self.stretch_factor = "stretch_fac = $STRETCH_FACTOR" + self.target_lon = "target_lon = -98.35" + self.target_lat = "target_lat = 39.5" + + + def config(self, ocean_NX, ocean_NY): + self.hres(ocean_NX, ocean_NY) + self.set_microphysics() + self.set_fvcore_layout() + self.set_CONUS() diff --git a/gcmpy/scripts/env.py b/gcmpy/scripts/env.py new file mode 100644 index 00000000..1f02b253 --- /dev/null +++ b/gcmpy/scripts/env.py @@ -0,0 +1,134 @@ +import os, sys, platform +import process_questions as pq +from utility import envdict, pathdict, color, exceptions +import questionary + +# PROBABLY WANT TO REMOVE/MODIFY THIS! +''' +# Check if GEOSgcm.x is here, which means you are in the correct directory +if not os.path.exists(os.path.join(pathdict['BIN'], 'GEOSgcm.x')): + exceptions.raise_user_exception( + "You are trying to run " + color.color_file(pathdict['SCRIPTNAME']) + \ + " in the " + color.color_path(pathdict['CWD']) + " directory." + \ + "\nThis is no longer supported.\nPlease run from the " + color.color_path('bin/') + \ + " directory in your installation.") + exit(1) +''' + + +####################################################################### +# Check for Command Line Flags +####################################################################### +# Set default behavior of switches +linkx = False +exe_verb = 'copied' +bool_usingSingularity = False + +# Loop through arguments and mtch to each case +# If argument is not recognized, display usage and exit +for arg in enumerate(sys.argv[1:]): + if (arg[-1] == '--link'): + linkx = True + elif (arg[-1] == '--singularity'): + bool_usingSingularity == True + elif (arg[-1] == '--help' or arg[-1] == '-h'): + exceptions.printusage() + else: + exceptions.raiseuserexception("Command line arguemnt \"" + arg[-1] + "\" not \ + recognized. \nSee usage:\n" ) + exceptions.printusage() + + +####################################################################### +# Determine site +####################################################################### +envdict['node'] = platform.node() +envdict['arch'] = platform.system() +#print(f"{color.RED}{pathdict['bin']}{color.RESET}") +envdict['site'] = open(os.path.join(pathdict['etc'], 'SITE.rc'), 'r').read().split()[-1] + +####################################################################### +# Test for Compiler and MPI Setup +####################################################################### +# Extract BASEDIR tail +basedir = open(os.path.join(pathdict['etc'], 'BASEDIR.rc'), 'r').read().split()[-1] +mpi = os.path.split(basedir)[-1] + +# Map MPI dirname to correct MPI implementation +if any(tag in mpi for tag in ['openmpi','hpcx']): mpi = 'openmpi' +elif any(tag in mpi for tag in ['impi', 'intelmpi']): mpi = 'intelmpi' +elif 'mvapich2' in mpi: mpi = 'mvapich2' +elif 'mpich' in mpi: mpi = 'mpich' +elif 'mpt' in mpi: mpi = 'mpt' +else: mpi = 'intelmpi' +envdict['mpi'] = mpi +#print("MPI implementation is: " + color.GREEN + MPI) + + +answerdict = pq.process() +#for i in answerdict: +# print(answerdict[i].q_answer) + + +####################################################################### +# Set Number of CPUs per Node +####################################################################### +# ----------------------------> PUT IN HANDLE CLASS FROM process_questions.py (MAYBE) <------------------------ +if envdict['site'] == 'NCCS': + if answerdict['processor'].q_answer == 'Haswell': + envdict['n_CPUs'] = 28 + elif answerdict['processor'].q_answer == 'Skylake': + envdict['n_CPUs'] = 40 + elif answerdict['processor'].q_answer == 'Cascade': + ''' + NCCS currently recommends that users do not run with + 48 cores per n_CPUs on SCU16 due to OS issues and + recommends that CPU-intensive works run with 46 or less + cores. As 45 is a multiple of 3, it's the best value + that doesn't waste too much + ''' + envdict['n_CPUs'] = 45 + +elif envdict['site'] == 'NAS': + if answerdict['processor'].q_answer == 'Haswell': + envdict['n_CPUs'] = 24 + elif answerdict['processor'].q_answer == 'Broadwell': + envdict['n_CPUs'] = 28 + elif answerdict['processor'].q_answer == 'Skylake': + envdict['n_CPUs'] = 40 + elif answerdict['processor'].q_answer == 'Cascade': + envdict['n_CPUs'] = 40 + elif answerdict['processor'].q_answer == 'AMD': + envdict['n_CPUs'] = 128 + +elif envdict['site'] == 'AWS' or envdict['site'] == 'AZURE': + # Because we do not know the name of the model or the number of CPUs + # per node. We ask the user to set these variables in the script + print(color.RED + "\nSince you are running on ", envdict['site'], \ + " you must set the processor and # of CPUs yourself.") + # ASK FOR PROCESSOR TYPE <------------------------------------------------------------------------------- + envdict['n_CPUs'] = questionary.text("Enter the number of CPUs per node: ").ask() + +else: + envdict['site'] = 'UNKNOWN' + if envdict['arch'] == 'Linux': + # Get the number of CPU cores on Linux + try: + with open('/proc/cpuinfo') as f: + cpuinfo = f.read() + envdict['n_CPUs'] = cpuinfo.count('processor') + except IOError: + print(color.RED + "ERROR: Unable to retrieve the number of CPUs.") + sys.exit(1) + elif envdict['arch'] == 'Darwin': + # Get the number of CPU cores on macOS + try: + import multiprocessing + envdict['n_CPUs'] = multiprocessing.cpu_count() + except NotImplementedError: + print(color.RED + "ERROR: Unable to retrieve the number of CPUs.") + sys.exit(1) + else: + print(f"ERROR: Unknown architecture", envdict['arch']) + sys.exit(1) + diff --git a/gcmpy/scripts/generate_question.py b/gcmpy/scripts/generate_question.py new file mode 100644 index 00000000..e2efbe20 --- /dev/null +++ b/gcmpy/scripts/generate_question.py @@ -0,0 +1,59 @@ +import os +import questionary +from questionary import Validator, ValidationError + +''' +This class will generate questionary questions based on a set of +parameters specified in a YAML file. It is designed to be as modular +as possible, so keep it that way! (Handle specific cases in +process_questions) +''' +class generateQuestion: + def __init__(self, q_name, q_type, q_prompt, q_choices, q_default, q_follows_up): + self.q_name = q_name + self.q_type = q_type + self.q_prompt = q_prompt + self.q_choices = q_choices + self.q_default = q_default + self.q_follows_up = q_follows_up + self.q_answer = None + + + # Check if a question "follows_up" another and its conditions are met + # to determine whether it should be asked or not + def should_ask(self, answerdict): + if self.q_follows_up: + for prev_question, accepted_answers in self.q_follows_up: + if answerdict[prev_question].q_answer in accepted_answers or ('any' in accepted_answers and answerdict[prev_question].q_answer != None): + return True + return False + return True + + + # loads the questionary api based on yaml configurations + def load_question(self, answerdict): + + # check if the yaml entry should be skipped + if not self.should_ask(answerdict): + return + + # if should_ask() returns true, call correct questionary API + elif self.q_type == 'text': + answer = questionary.text(self.q_prompt, default=self.q_default, validate=qValidator.val_text).ask() + elif self.q_type == 'confirm': + answer = questionary.confirm(self.q_prompt, default=self.q_default).ask() + elif self.q_type == 'select': + answer = questionary.select(self.q_prompt, choices=self.q_choices).ask() + elif self.q_type == 'path': + answer = questionary.path(self.q_prompt, default=self.q_default).ask() + + self.q_answer = answer + +# input validation used for questionary library +class qValidator(): + def val_text(input): + if len(str(input)) == 0 or input.isspace(): + return "please answer the question!" + else: + return True + diff --git a/gcmpy/scripts/gocart.py b/gcmpy/scripts/gocart.py new file mode 100644 index 00000000..d6d9c9db --- /dev/null +++ b/gcmpy/scripts/gocart.py @@ -0,0 +1,48 @@ +from env import answerdict +from utility import color + +class gocart: + def __init__(self): + self.aerosol = answerdict["gocart_aerosols"].q_answer + self.emissions = f"{answerdict['gocart_emission'].q_answer}_EMISSIONS" + self.data_driven = None + self.OPS_species = "#" + self.CMIP_species = "#" + self.MERRA2OX_species = "#" + self.pchem_clim_years = "" + self.gocart = None + self.gocart_hist = None + self.aero_provider = "GOCART2G" + self.RATS_provider = "PCHEM" + + # for debugging purposes + def print_vars(self): + all_vars = vars(self) + for var_name, var_value in all_vars.items(): + print(f"{color.BLUE}{var_name}: {var_value}{color.RESET}") + + def set_gocart(self): + match self.aerosol: + case "Actual": + self.data_driven = False + self.gocart = "" + self.gocart_hist = "" + case "Climatological": + self.data_driven = True + self.gocart = "" + self.gocart_hist = "" + + def set_emissions(self): + match self.emissions.split("_")[0]: + case "AMIP": + self.MERRA2OX_species = "" + self.pchem_clim_years = 1 + case "OPS": + self.OPS_species = "" + self.pchem_clim_years = 39 + + + def config(self): + self.set_gocart() + self.set_emissions() + diff --git a/gcmpy/scripts/land.py b/gcmpy/scripts/land.py new file mode 100644 index 00000000..5bc46d64 --- /dev/null +++ b/gcmpy/scripts/land.py @@ -0,0 +1,66 @@ +from env import answerdict +from utility import color + +class land: + def __init__(self): + self.land_choice = answerdict["LS_model"].q_answer + self.bcs = answerdict["LS_boundary_conditions"].q_answer + self.bound_parameters = None + self.emip_BCS_IN = None + self.emip_oldland = None + self.emip_newland = None + self.emip_MERRA2 = None + self.HIST_catchment = None + self.GCMRUN_catchment = None + + # for debugging purposes + def print_vars(self): + all_vars = vars(self) + for var_name, var_value in all_vars.items(): + print(f"{color.CYAN}{var_name}: {var_value}{color.RESET}") + + def set_bcs(self): + match self.bcs: + case "Icarus": + self.bound_parameters = "#DELETE" + self.emip_BCS_IN = "Ganymed-4_0" + self.emip_oldland = "" + self.emip_newland = "#DELETE" + self.emip_MERRA2 = "MERRA2" + case "Icarus-NLv3": + self.bound_parameters = "" + self.emip_BCS_IN = "Icarus-NLv3" + self.emip_oldland = "#DELETE" + self.emip_newland = "" + self.emip_MERRA2 = "MERRA2_NewLand" + + def set_catchment(self): + if self.bcs == "Icarus-NLv3": + match self.land_choice: + case "Catchment": + self.HIST_catchment = "#DELETE" + self.GCMRUN_catchment = "#DELETE" + case "CatchmentCN-CLM4.0": + self.HIST_catchment = "" + self.GCMRUN_catchment = "" + print(f"{color.RED}IMPORTANT: please set LAND_PARAMS: to CN_CLM40 in RC/GEOS_SurfaceGridComp.rc in the experiment directory.{color.RESET}") + case "CatchmentCN-CLM4.5": + self.HIST_catchment = "" + self.GCMRUN_catchment = "" + print(f"{color.RED}IMPORTANT: please set LAND_PARAMS: to CN_CLM45 in RC/GEOS_SurfaceGridComp.rc in the experiment directory.{color.RESET}") + else: + self.land_choice = "Catchment" + self.HIST_catchment = "#DELETE" + self.GCMRUN_catchment = "#DELETE" + + def config(self): + self.set_bcs() + self.set_catchment() + + + + + + + + diff --git a/gcmpy/scripts/model.py b/gcmpy/scripts/model.py new file mode 100644 index 00000000..8c3209c8 --- /dev/null +++ b/gcmpy/scripts/model.py @@ -0,0 +1,408 @@ +from ocean import ocean +from atmosphere import atmosphere as atmos +from land import land +from gocart import gocart +from env import answerdict, linkx +from utility import envdict, pathdict +import math, os, shutil, tempfile, yaml +from pathlib import Path + + +# combines all models (atmos, ocean, land, gocart) into one big one +class model: + def __init__(self): + self.ocean = ocean() + self.atmos = atmos() + self.land = land() + self.gocart = gocart() + self.is_FCST = False + self.fv_cubed = "" + self.bcs_res = None + self.tile_data = None + self.tile_bin = None + self.interpolate_SST = None + self.job_sgmt = None + self.begin_date = "18910301 000000" + self.end_date = "29990302 210000" + self.n_oserver_nodes = None + self.n_backend_pes = None + self.n_nodes = None + self.exp_dir = answerdict['exp_dir'].q_answer + self.oserver_restart = "NO" + + + def print_all_vars(self): + self.atmos.print_vars() + self.land.print_vars() + self.gocart.print_vars() + + + def config_models(self): + self.ocean.config() + self.atmos.config(self.ocean.NX, self.ocean.NY) + self.land.config() + self.gocart.config() + + + # setup some variables idk + def set_some_stuff(self): + if self.atmos.IM_hist >= self.ocean.IM: + self.interpolate_SST = True + else: + self.interpolate_SST = False + self.bcs_res = f"{self.atmos.res}_{self.ocean.res}" + self.tile_data = f"{self.atmos.res}_{self.ocean.res}_Pfafstetter.til" + self.tile_bin = f"{self.atmos.res}_{self.ocean.res}_Pfafstetter.TIL" + self.job_sgmt = f"{self.atmos.job_sgmt} 000000" + + + # setup experiment nodes + def set_nodes(self): + model_npes = self.atmos.NX * self.atmos.NY + + # Calculate OSERVER nodes based on recommended algorithm + if answerdict["io_server"].q_answer == True: + + # First we calculate the number of model nodes + n_model_nodes = math.ceil(model_NPES / envdict["n_CPUs"]) + + # Next the number of frontend PEs is 10% of the model PEs + n_frontend_pes = math.ceil(model_NPES * 0.1) + + # Now we roughly figure out the number of collections in the HISTORY.rc + n_hist_collections = 0 + with open(answerdict['history_template'].q_answer, 'r') as file: + in_collections = False + for line in file: + if line.split(' ', 1)[0] == "COLLECTIONS:": + in_collections = True + continue + if in_collections and line.split(' ', 1)[0] != "#": + n_hist_collections += 1 + if line.strip() == "::": + break + + # The total number of oserver PEs is frontend PEs plus number of history collections + n_oserver_pes = n_frontend_pes + n_hist_collections + + # calculate the number of oserver nodes + n_oserver_nodes = math.ceil(n_oserver_pes / envdict["n_CPUs"]) + + # The number of backend PEs is the number of history collections divided by the number of oserver nodes + n_backend_pes = math.ceil(n_hist_collections / n_oserver_nodes) + + # multigroup requires at least two backend pes + if (n_backend_pes < 2): n_backend_pes = 2 + + # Calculate the total number of nodes to request from batch + nodes = n_model_nodes + n_oserver_nodes + + else: + self.nodes = math.ceil(model_npes / envdict["n_CPUs"]) + self.n_oserver_nodes = 0 + self.n_backend_pes = 0 + + + + def set_stuff(self): + self.set_nodes() + # Longer job names are now supported with SLURM and PBS. Limits seem to be 1024 characters with SLURM + # and 230 with PBS. To be safe, we will limit to 200 + run_n = f"{answerdict['experiment_id'].q_answer[:200]}_RUN" # RUN Job Name + run_fn = f"{answerdict['experiment_id'].q_answer[:200]}_FCST" # Forecast Job Name + post_n = f"{answerdict['experiment_id'].q_answer[:200]}_POST" # POST Job Name + plot_n = f"{answerdict['experiment_id'].q_answer[:200]}_PLT" # PLOT Job Name + move_n = f"{answerdict['experiment_id'].q_answer[:200]}_PLT" # MOVE Job Name + archive_n = f"{answerdict['experiment_id'].q_answer[:200]}_ARCH" # ARCHIVE Job Name + regress_n = f"{answerdict['experiment_id'].q_answer[:200]}_RGRS" # REGRESS Job Name + + + # Here we need to convert POST_NDS to total tasks. Using 16 cores + # per task as a good default + post_npes = self.atmos.post_NDS * 16 + NPCUS = (post_npes + envdict["n_CPUs"] - 1)/envdict["n_CPUs"] + + ''' + Definition for each variable in the following if-else block: + + batch_cmd - PBS Batch command + batch_group - PBS Syntax for GROUP + batch_time - PBS Syntax for walltime + batch_jobname - PBS Syntax for job name + batch_outputname - PBS Syntax for job output name + batch_joinouterr - PBS Syntax for joining output and error + run_FT - Wallclock Time for gcm_forecast.j + run_FT - Wallclock Time for gcm_run.j + post_T - Wallclock Time for gcm_post.j + plot_T - Wallclock Time for gcm_plot.j + archive_T - Wallclock Time for gcm_archive.j + run_Q - Batch queue name for gcm_run.j + run_P - PE Configuration for gcm_run.j + run_FP - PE Configuration for gcm_forecast.j + post_Q - Batch queue name for gcm_post.j + plot_Q - Batch queue name for gcm_plot.j + move_Q - Batch queue name for gcm_moveplot.j + archive_Q - Batch queue name for gcm_archive.j + post_P - PE Configuration for gcm_post.j + plot_P - PE Configuration for gcm_plot.j + archive_P - PE Configuration for gcm_archive.j + move_P - PE Configuration for gcm_moveplot.j + bcs_dir - Location of Boundary Conditions + replay_ana_expID - Default Analysis Experiment for REPLAY + replay_ana_location - Default Analysis Location for REPLAY + M2_replay_ana_location - Default Analysis Location for M2 REPLAY + sst_dir - Location of SST Boundary Conditions + chem_dir - Locations of Aerosol Chemistry BCs + work_dir - User work directory <----------------- change this later + gwdrs_dir - Location of GWD_RIDGE files + coupled_dir - Coupled Ocean/Atmos Forcing + ''' + + if envdict['site'] == "NAS": + batch_cmd = "qsub" + batch_group = "PBS -W group_list=" + batch_time = "PBS -l walltime=" + batch_jobname = "PBS -N" + batch_outputname = "PBS -o " + batch_joinouterr = "PBS -j oe -k oed" + run_FT = "6:00:00" + run_T = "8:00:00" + post_T = "8:00:00" + plot_T = "8:00:00" + archive_T = "8:00:00" + run_Q = f"PBS -q normal" + run_P = f"PBS -l select={self.nodes}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + run_FP = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + post_Q = "PBS -q normal" + plot_Q = "PBS -q normal" + move_Q = "PBS -q normal" + archive_Q = "PBS -q normal" + post_P = f"PBS -l select={NPCUS}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + plot_P = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs=1:model={answerdict['processor']}" + archive_P = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + move_P = "PBS -l select=1:ncpus=1" + boundary_path = "/nobackup/gmao_SIteam/ModelData" + bcs_dir = f"{boundary_path}/bcs/{self.land.bcs}/{self.land.bcs}_{self.ocean.tag}" + replay_ana_expID = "ONLY_MERRA2_SUPPORTED" + replay_ana_location = "ONLY_MERRA2_SUPPORTED" + M2_replay_ana_location = f"{boundary_path}/merra2/data"# + + # defines location of SST Boundary Conditions + oceanres = f"{self.ocean.IM}x{self.ocean.JM}" + if oceanres == "1440x720": + sst_dir = f"{boundary_path}/fvInput/g5gcm/bcs/SST/{oceanres}" + else: + sst_dir = f"{boundary_path}/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{oceanres}" + if self.ocean.gridtype_abrv == "LL": + sst_dir = "/nobackupp2/estrobac/geos5/SSTDIR" + + chem_dir = f"{boundary_path}/fvInput_nc3" + work_dir = f"/nobackup/{os.environ.get('LOGNAME')}" + gwdrs_dir = f"{boundary_path}/GWD_RIDGE" + + # Coupled Ocean/Atmos Forcing + if self.ocean.name == "MIT": + coupled_dir = "/nobackupp2/estrobac/geos5/GRIDDIR" + else: + coupled_dir = f"{boundary_path}/aogcm" + + + elif envdict['site'] == "NCCS": + batch_cmd = "sbatch" + batch_group = "SBATCH --account=" + batch_time = "SBATCH --time=" + batch_jobname = "SBATCH --job-name=" + batch_outputname = "SBATCH --output=" + batch_joinouterr = "DELETE" + run_FT = "06:00:00" + run_T = "12:00:00" + post_T = "8:00:00" + plot_T = "12:00:00" + archive_T = "2:00:00" + run_Q = f"SBATCH --constraint={answerdict['processor']}" + run_P = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + run_FP = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + post_Q = f"SBATCH --constraint={answerdict['processor']}" + plot_Q = f"SBATCH --constraint={answerdict['processor']}" + move_Q = "SBATCH --partition=datamove" + archive_Q = "SBATCH --partition=datamove" + post_P = f"SBATCH --nodes={NPCUS} --ntasks-per-node={envdict['n_CPUs']}" + plot_P = f"SBATCH --nodes=4 --ntasks=4" + archive_P = "SBATCH --ntasks=1" + move_P = "SBATCH --ntasks=1" + boundary_path = "/discover/nobackup/projects/gmao" + bcs_dir = f"{boundary_path}bcs_shared/fvInput/ExtData/esm/tiles/{self.land.bcs}" + replay_ana_expID = "x0039" + replay_ana_location = f"{boundary_path}/g6dev/ltakacs/x0039" + M2_replay_ana_location = f"{boundary_path}/merra2/data" + + + # define location of SST Boundary Conditions + oceanres = f"{self.ocean.IM}x{self.ocean.JM}" + if oceanres == "1440x720": + sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/SST/{self.ocean.IM}x{self.ocean.JM}" + else: + sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" + if self.ocean.gridtype_abrv == "LL": + sst_dir = "/discover/nobackup/estrobac/geos5/SSTDIR" + + chem_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput_nc3" + work_dir = f"/discover/nobackup/{os.environ.get('LOGNAME')}" + gwdrs_dir = f"{boundary_path}/osse2/stage/BCS_FILES/GWD_RIDGE" + + # Coupled Ocean/Atmos Forcing + if self.ocean.name == "MIT": + coupled_dir = "/gpfsm/dnb32/estrobac/geos5/GRIDDIR" + else: + coupled_dir = f"{boundary_path}/bcs_shared/make_bcs_inputs/ocean" + + + elif envdict['site'] == "AWS" or envdict['SITE'] == "Azure": + batch_cmd = "sbatch" + batch_group = "#DELETE" + batch_time = "SBATCH --time=" + batch_jobname = "SBATCH --job-name=" + batch_outputname = "SBATCH --output=" + batch_joinouterr = "DELETE" + run_FT = "06:00:00" + run_T = "12:00:00" + post_T = "8:00:00" + plot_T = "12:00:00" + archive_T = "1:00:00" + run_Q = f"SBATCH --constraint={answerdict['processor']}" + run_P = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + run_FP = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + post_Q = "NULL" + plot_Q = "NULL" + move_Q = "NULL" + archive_Q = "NULL" + post_P = f"SBATCH --ntasks={post_npes}" + plot_P = f"SBATCH --nodes=4 --ntasks=4" + archive_P = "SBATCH --ntasks=1" + move_P = "SBATCH --ntasks=1" + boundary_path = "/ford1/share/gmao_SIteam/ModelData" + bcs_dir = f"{boundary_path}/bcs/{self.land.bcs}_{self.ocean.tag}" + replay_ana_expID = "REPLAY_UNSUPPORTED" + replay_ana_location = "REPLAY_UNSUPPORTED" + M2_replay_ana_location = "REPLAY_UNSUPPORTED" + sst_dir = f"{boundary_path}/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" + chem_dir = f"{boundary_path}/fvInput_nc3" + work_dir = os.environ.get('HOME') + gwdrs_dir = f"{boundary_path}/GWD_RIDGE" + coupled_dir = f"{boundary_path}/aogcm" + + else: + # These are defaults for the desktop + batch_cmd = "sbatch" + batch_group = "SBATCH --account=" + batch_time = "SBATCH --time=" + batch_jobname = "SBATCH --job-name=" + batch_outputname = "SBATCH --output=" + batch_joinouterr = "DELETE" + run_FT = "06:00:00" + run_T = "12:00:00" + post_T = "8:00:00" + plot_T = "12:00:00" + archive_T = "1:00:00" + run_Q = "NULL" + run_P = "NULL" + run_FP = "NULL" + post_Q = "NULL" + plot_Q = "NULL" + move_Q = "NULL" + archive_Q = "NULL" + post_P = "NULL" + plot_P = "NULL" + archive_P = "NULL" + move_P = "NULL" + boundary_path = "/ford1/share/gmao_SIteam/ModelData" + bcs_dir = f"{boundary_path}/bcs/{self.land.bcs} /{self.land.bcs}_{self.ocean.tag}" + replay_ana_expID = "REPLAY_UNSUPPORTED" + replay_ana_location = "REPLAY_UNSUPPORTED" + M2_replay_ana_location = "REPLAY_UNSUPPORTED" + sst_dir = f"{boundary_path}/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" + chem_dir = f"{boundary_path}/fvInput_nc3" + work_dir = os.environ.get('HOME') + gwdrs_dir = f"{boundary_path}/GWD_RIDGE" + coupled_dir = f"{boundary_path}/aogcm" + + # By default on desktop, just ignore IOSERVER for now + self.atmos.NX = 1 + self.atmos.NY = 6 + answerdict["io_server"] = False + self.n_oserver_nodes = 0 + self.n_backend_pes = 0 + + ''' + def set_hist_temp(self): + tmphist_d, tmphist_path = tempfile.mkstemp() + print(self.ocean.history_template) + shutil.copy(self.ocean.history_template, tmphist_path) + return tmphist_d, tmphist_path + ''' + + ''' + mainly used to create .{*}root files and/or populate them + ''' + def create_dotfile(self, path, content): + try: + path = Path(path) + path.parent.mkdir(parents=True, exist_ok=True) + path.touch() + with open(path, 'w') as file: + file.write(os.path.dirname(content)) + except Exception as e: + print(f"An error occurred while creating directory: {str(e)}") + exit(1) + + + ####################################################################### + # Copy Model Executable and RC Files to Experiment Directory + ####################################################################### + def RC_setup(self): + + # Make the experiment directory and the RC directory inside of it + RC_dir = os.path.join(self.exp_dir, 'RC') + + # Delete the destination directory if it exists + if os.path.exists(RC_dir): + shutil.rmtree(RC_dir) + + # Copy over all files and subdirs in install/etc, keeping symlinks, and ignoring *.tmpl files + shutil.copytree(pathdict['etc'], RC_dir, symlinks=True, ignore=shutil.ignore_patterns('*.tmpl')) + + # Copy or symlink GEOSgcm.x (((IGNORE SINGULARITY/NATIVE BUILDS FOR NOW!!))) + geosgcmx_path = os.path.join(pathdict['bin'], 'GEOSgcm.x') + if linkx == True: + os.symlink(geosgcmx_path, os.path.join(self.exp_dir, 'GEOSgcm.x')) + else: + shutil.copy(geosgcmx_path, self.exp_dir) + + ####################################################################### + # Set Recommended MPI Stack Settings + ####################################################################### + def mpistacksettings(self): + + # load mpi config from YAML + with open('mpi_config.yaml') as file: + mpidict = yaml.load(file, Loader=yaml.FullLoader) + + # retrieve config from correlating mpi setting being used + mpi_config = mpidict.get(envdict['mpi']) + + print(mpi_config) + + + + + +mymodel = model() +mymodel.config_models() +#mymodel.print_all_vars() +mymodel.set_nodes() +mymodel.set_stuff() +mymodel.create_dotfile(f"{os.environ.get('HOME')}/.HOMDIRroot", answerdict['home_dir'].q_answer) +mymodel.create_dotfile(f"{os.environ.get('HOME')}/.EXPDIRroot", answerdict['exp_dir'].q_answer) +mymodel.create_dotfile(f"{os.environ.get('HOME')}/.GROUProot", answerdict['group_root'].q_answer) +mymodel.RC_setup() +mymodel.mpistacksettings() diff --git a/gcmpy/scripts/ocean.py b/gcmpy/scripts/ocean.py new file mode 100644 index 00000000..bf53153f --- /dev/null +++ b/gcmpy/scripts/ocean.py @@ -0,0 +1,257 @@ +from env import answerdict +from utility import color +from datetime import date + +class ocean: + def __init__(self): + self.name = answerdict["OM_name"].q_answer + self.coupled = answerdict["OM_coupled"].q_answer + self.gridtype = "" + self.gridtype_abrv = "" + self.gridname = "" + self.data = "" + self.preload = "" + self.history_template = answerdict["history_template"].q_answer + self.IM = None + self.JM = None + self.LM = answerdict["OM_vertical_res"].q_answer + self.IMO = None + self.JMO = None + self.res = "" + self.tag = "Reynolds" + self.sst_name = "" + self.sst_file = "" + self.ice_file = "" + self.kpar_file = "" + self.ostia = "" + self.out = "" + self.NX = None + self.NY = None + self.NF = None + self.latlon = "" + self.cube = "" + self.n_procs = None + self.MOM5 = "" + self.MOM6 = "" + self.MIT = "" + self.mpt_shepherd = "" + + # for debugging purposes + def print_vars(self): + all_vars = vars(self) + for var_name, var_value in all_vars.items(): + print(f"{color.CYAN}{var_name}: {var_value}{color.RESET}") + + def set_IMO(self): + self.IMO = f"{str(self.IM):04}" + + def set_JMO(self): + self.JMO = f"{str(self.JM):04}" + + def set_res(self): + hres = answerdict["OM_horizontal_res"].q_answer + if self.coupled == False and hres == "CS": + self.res = f"{self.gridtype_abrv}{self.IMO}x6C" + elif self.coupled == False: + self.res = f"{self.gridtype_abrv}{self.IMO}xPE{self.JMO}" + elif self.coupled == True: + self.res = f"{self.gridtype_abrv}{self.IMO}x{self.gridtype_abrv}{self.JMO}" + # Testing at NAS shows that coupled runs *require* MPI_SHEPHERD=true + # to run. We believe this is due to LD_PRELOAD. For now we only set + # this for coupled runs. + self.mpt_shepherd = "setenv MPI_SHEPHERD true" + + def set_gridname(self): + if self.gridtype_abrv == "CF": + self.gridname = f"OC{self.IM}x{self.JM}-{self.gridtype_abrv}" + elif self.name == "MIT": + self.gridname = f"{self.gridtype_abrv}{self.IM}x{self.JM}-{self.gridtype_abrv}" + else: + self.gridname = f"PE{self.IM}x{self.JM}-{self.gridtype_abrv}" + + def set_kpar_file(self): + self.kpar_file = f"SEAWIFS_KPAR_mon_clim.{self.IM}x{self.JM}" + + def coupled_hres(self): + match self.name: + case "MOM5": + self.name = "MOM" + self.preload = "env LD_PRELOAD=$GEOSDIR/lib/libmom.dylib" + mom5_warning = ( + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" + "You have chosen to set up a coupled model experiment with MOM5.\n" + "Be aware that such a set up is _known_ to have problems. See following for more details:\n" + "https://github.com/GEOS-ESM/MOM5/issues/19\n" + "If your intent is to help _fix_ above issue, your help is much appreciated. Thank you and good luck!\n" + "Otherwise, until this above issue is _fixed_ you are on your own with above choice.\n" + "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" + ) + print(color.GREEN + mom5_warning + color.RESET) + case "MOM6": + self.preload = "env LD_PRELOAD=$GEOSDIR/lib/libmom6.dylib" + case "MIT": + self.gridtype_abrv = "llc" + + match self.name: + case "MIT": + match answerdict["OM_MIT_horizontal_res"].q_answer: + case "cs32": + self.JM = 32 + self.IM = self.JM * 6 + self.gridtype_abrv = "CM" + case "llc90": + self.gridtype_abrv = "LL" + if answerdict["AM_horizontal_res"].q_answer == "c48": + self.JM = 30 + self.IM = self.JM * 96 + else: + self.JM = 15 + self.IM = self.JM * 360 + case "llc1080": + self.gridtype_abrv = "LL" + self.JM = 60 + self.IM = self.JM * 2880 + case "llc2160": + self.gridtype_abrv = "LL" + self.JM = 72 + self.IM = self.JM * 7776 + case "MOM", "MOM6": + temp = answerdict["OM_MOM_horizontal_res"].q_answer.split() + self.IM = int(temp[0]) + self.JM = int(temp[1]) + self.gridtype = "TM" + + + def coupled_vres(self): + if answerdict["AM_horizontal_res"].q_answer == "c12": + self.NX = 3 + self.NY = 2 + else: + self.NX = 36 + self.NY = 10 + + self.n_procs = self.NX*self.NY + + match self.name: + case "MOM", "MOM6": + self.gridtype = "Tripolar" + case "MIT": + if self.gridtype_abrv == "CM": + self.NX = 6 + self.NY = 1 + else: + match answerdict["AM_horizontal_res"].q_answer: + case "c48": + self.NX = 96 + self.NY = 1 + case "c90": + self.NX = 360 + self.NY = 1 + case "c720": + self.NX = 2880 + self.NY = 1 + case "c1440": + self.NX = 7776 + self.NY = 1 + + def uncoupled_hres(self): + todays_date = date.today() + match answerdict["OM_horizontal_res"].q_answer: + case "o1": + temp_res = "360 180" + self.IM, self.JM = map(int, temp_res.split()) + self.gridtype = "LatLon" + self.NF = 1 + self.tag = "Reynolds" + self.sst_name = "SST" + self.out = "c" + self.sst_file = f"dataoceanfile_MERRA_sst_1971-current.{self.IM}x{self.JM}.LE" + self.ice_file = f"dataoceanfile_MERRA_fraci_1971-current.{self.IM}x{self.JM}.LE" + self.set_kpar_file() + self.gridtype_abrv = "DE" + self.latlon = "" + self.cube = "#DELETE" + self.ostia = "#DELETE" + self.data = "" + case "o2": + temp_res = "1440 720" + self.IM, self.JM = map(int, temp_res.split()) + self.gridtype = "LatLon" + self.NF = 1 + self.tag = "MERRA-2" + self.sst_name = "MERRA2" + self.out = "e" + self.sst_file = f"dataoceanfile_MERRA2_SST.{self.IM}x{self.JM}.{todays_date.year}.data" + self.ice_file = f"dataoceanfile_MERRA2_ICE.{self.IM}x{self.JM}.{todays_date.year}.data" + self.set_kpar_file() + self.gridtype_abrv = "DE" + self.latlon = "" + self.cube = "#DELETE" + self.ostia = "" + self.data = "" + case "o3": + temp_res = "2880 1440" + self.IM, self.JM = map(int, temp_res.split()) + self.gridtype = "LatLon" + self.NF = 1 + self.tag = "Ostia" + self.sst_name = "OSTIA_REYNOLDS" + self.out = "f" + self.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{OGCM_IM}x{OGCM_JM}.{todays_date.year}.data" + self.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{OGCM_IM}x{OGCM_JM}.{todays_date.year}.data" + self.set_kpar_file() + self.gridtype_abrv = "DE" + self.latlon = "" + self.cube = "#DELETE" + self.ostia = "" + self.data = "" + case "CS": + if int(answerdict["AM_horizontal_res"].q_answer[1:]) >= 90: + self.IM = int(answerdict["AM_horizontal_res"].q_answer[1:]) + self.JM = self.IM * 6 + self.gridtype = "Cubed-Sphere" + self.NF = 6 + self.tag = "Ostia" + self.sst_name = "OSTIA_REYNOLDS" + self.out = "f" + self.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{self.IM}x{self.JM}.{todays_date.year}.data" + self.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{self.IM}x{self.JM}.{todays_date.year}.data" + self.set_kpar_file() + self.gridtype_abrv = "CF" + self.latlon = "#DELETE" + self.cube = "" + self.ostia = "" + self.data = "#DELETE" + else: + print(color.RED + "ERROR: Cubed-Sphere Ocean with " + color.BLUE + \ + answerdict["AM_horizontal_res"].q_answer + color.RED + \ + " is not currently supported. Must be c90 or higher!") + exit(1) + + self.set_IMO() + self.set_JMO() + self.set_res() + self.LM = 34 + self.model = f"Data Ocean ({answerdict['AM_horizontal_res'].q_answer})" + self.coupled = "#DELETE" + self.MOM5 = "#DELETE" + self.MOM6 = "#DELETE" + self.MIT = "#DELETE" + + + + # ocean model driver + def config(self): + match answerdict["OM_coupled"].q_answer: + case True: + self.coupled_hres() + self.coupled_vres() + case False: + self.uncoupled_hres() + + + + + + + diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py new file mode 100644 index 00000000..00411572 --- /dev/null +++ b/gcmpy/scripts/process_questions.py @@ -0,0 +1,232 @@ +import yaml, re, os +from generate_question import generateQuestion +from utility import envdict, pathdict, color + +""" +This class handles special cases where a question"s properties need to be checked/dynamically +changed at runtime based on certain conditions (e.g. input validation) +""" +class handle: + + @staticmethod + def select_type(answerdict, i): + if answerdict[i].q_type == "select" and answerdict[i].q_answer != None: + # as of right now, we only want the first word of every select-type question. + # If that changes it's probably best to delete this function. + answerdict[i].q_answer = answerdict[i].q_answer.split(None, 1)[0] + + @staticmethod + def experiment_desc(answerdict, i): + if i == "experiment_description" and answerdict[i].q_answer != None: + while answerdict["experiment_description"].q_answer == answerdict["experiment_id"].q_answer: + print(color.RED + "The experiment description must be different from the ID!") + answerdict[i].load_question(answerdict) + + @staticmethod + def processor_choices(answerdict, i): + if i == "processor": + if envdict["site"] == "NCCS": + answerdict[i].q_choices = ["Skylake", "Cascade Lake"] + elif envdict["site"] == "NAS": + answerdict[i].q_choices = ["Skylake", "Haswell", "Broadwell", "Cascade Lake", "AMD Rome"] + else: + exit(1) + + print(color.GREEN + "NOTE Due to how FV3 is compiled by default, Sandy Bridge\n" + \ + "and Ivy Bridge are not supported by current GEOS" + color.RESET) + + @staticmethod + def MIT_hres_choices(answerdict, i): + # This is a dumb case, but these are the only known ocean resolutions that work + # with these atmosphere resolutions, so we will only give the users these choices + if i == "OM_MIT_horizontal_res": + if answerdict["AM_horizontal_res"].q_answer == "c720": + answerdict[i].q_choices = ["llc1080 (1/12-deg, Lat-Lon-Cube)"] + elif answerdict["AM_horizontal_res"].q_answer == "c1440": + answerdict[i].q_choices = ["llc2160 (1/24-deg, Lat-Lon-Cube)"] + + @staticmethod + def MOM_hres_default(answerdict, i): + if i == "OM_MOM_horizontal_res" and \ + answerdict["OM_name"].q_answer == "MOM6" and \ + answerdict["AM_horizontal_res"].q_answer == "c12": + answerdict[i].q_default = "72 36" + + @staticmethod + def OM_hres_valid(answerdict, i): + if i == "OM_MOM_horizontal_res" and answerdict[i].q_answer != None: + #input validation using regex + while not re.match(r"^\d+\s\d+$", answerdict[i].q_answer): + print(color.RED + "please enter exactly 2 numbers separated by a space! (int int)\n") + answerdict[i].load_question(answerdict) + + @staticmethod + def heartbeat_default(answerdict, i): + if i == "heartbeat": + ''' + Default heartbeat is determined by atmospheric resolution. + Of course, this just the recommended value. The user can + enter whatever value they like + ''' + heartbeat = "" + match answerdict["AM_horizontal_res"].q_answer: + case "c12" | "c24" | "c48" | "c90": + heartbeat = "1800" + case "c180": + heartbeat = "900" + case "c360": + heartbeat = "450" + case "c720": + heartbeat = "225" + case "c1440": + heartbeat = "75" + case "c5760": + heartbeat = "30" + case "c270" | "c540": + heartbeat = "600" + case "c1080": + heartbeat = "150" + case "c1536": + heartbeat = "75" + case "c2160": + heartbeat = "60" + + + # Per W. Putman recommendation, set heartbeat to 450s anytime BACM_1M is selected + # ((IMPORTANT: default must be type string)) + if answerdict["AM_microphysics"].q_answer == "BACM_1M": + heartbeat = "450" + + answerdict[i].q_default = heartbeat + + + @staticmethod + def heartbeat_valid(answerdict, i): + if i == "heartbeat": + # input validation using regex + while not re.match(r"^\d+$", answerdict[i].q_answer): + print(f"{color.RED}please enter exactly 1 number!{color.RESET}") + answerdict[i].load_question(answerdict) + + @staticmethod + def history_template_default(answerdict, i): + if i == "history_template": + + match answerdict["OM_name"]: + case "MOM5": + answerdict[i].q_default = f"{pathdict['etc']}/HISTORY.AOGCM-MOM5.rc.tmpl" + case "MOM6": + answerdict[i].q_default = f"{pathdict['etc']}/HISTORY.AOGCM.rc.tmpl" + case "MIT": + answerdict[i].q_default = f"{pathdict['etc']}/HISTORY.AOGCM_MITgcm.rc.tmpl" + case _: + answerdict[i].q_default = f"{pathdict['etc']}/HISTORY.AGCM.rc.tmpl" + + + @staticmethod + def history_template_valid(answerdict, i): + if i == "history_template": + while not os.path.exists(answerdict[i].q_answer): + print(f"Error: Could not find {color.RED}{answerdict[i]}{color.RESET}") + answerdict[i].load_question(answerdict) + + + @staticmethod + def exp_dir_default(answerdict, i): + if i == "home_dir" or i == "exp_dir": + root = f"{os.environ.get('HOME')}/.{i[:3].upper()}DIRroot" + if os.path.exists(root): + try: + print("here") + with open(root, "r") as file: + answerdict[i].q_default = f"{file.read()}/{answerdict['experiment_id'].q_answer}" + except Exception as e: + print(f"An error occurred while reading {color.BLUE}.HOMDIRroot{color.RESET}: {str(e)}") + elif envdict['site'] in ['NAS','NCCS']: + answerdict[i].q_default = f"/{'discover/' if envdict['site'] == 'NCCS' else ''}nobackup/{os.environ.get('LOGNAME')}/{answerdict['experiment_id'].q_answer}" + else: + answerdict[i].q_default = f"{os.environ.get('HOME')}/{answerdict['experiment_id']}" + + + @staticmethod + def exp_dir_valid(answerdict, i): + if i == "home_dir" or i == "exp_dir": + while os.path.basename(answerdict[i].q_answer) != answerdict['experiment_id'].q_answer: + print(f"{color.RED}This directory MUST point to the experiment ID: {color.BLUE}{answerdict['experiment_id'].q_answer}{color.RED}!{color.RESET}") + answerdict[i].load_question(answerdict) + + + @staticmethod + def group_root_default(answerdict, i): + if i == "group_root": + groups = subprocess.check_output('groups', shell=True).decode('utf-8').strip() + answerdict[i].q_default = groups.split()[0] + + + + + +# open yaml file and create dictionary from it's contents +def load_yamls(): + + # list of question files (*MAKE SURE THEY ARE IN THE ORDER YOU WANT THEM TO BE ASKED*) + file_list = ["exp_setup.yaml", \ + "atmospheric_model.yaml", \ + "ocean_model.yaml", \ + "land_model.yaml", \ + "gocart.yaml", \ + "directory_setup.yaml"] + all_yaml_questions = {} + + for filename in file_list: + try: + with open(filename, "r") as file: + yaml_questions = yaml.safe_load(file) + all_yaml_questions.update(yaml_questions) + except IOError: + print(f"{color.RED}YAML file '{filename}' could not be located. Exiting.") + exit(1) + + return all_yaml_questions + +# actual driver for questionary questions +def process(): + answerdict = {} + yaml_questions = load_yamls() + + # creates a dictionary of question:answer pairs + for i in yaml_questions: + temp = generateQuestion(i, yaml_questions[i]["type"], \ + yaml_questions[i]["prompt"], \ + yaml_questions[i]["choices"], \ + yaml_questions[i]["default_answer"],\ + yaml_questions[i]["follows_up"]) + + answerdict[i] = temp + + + # if the question properties need to dynamically change at + # runtime call handle function BEFORE load_question() + handle.processor_choices(answerdict,i) + handle.MIT_hres_choices(answerdict, i) + handle.MOM_hres_default(answerdict, i) + handle.heartbeat_default(answerdict, i) + handle.history_template_default(answerdict, i) + handle.exp_dir_default(answerdict, i) + + # prompts the user with the question + answerdict[i].load_question(answerdict) + + # input validation and other post processing goes here, + # AFTER load_question() call + handle.experiment_desc(answerdict, i) + handle.OM_hres_valid(answerdict, i) + handle.heartbeat_valid(answerdict, i) + handle.history_template_valid(answerdict, i) + handle.exp_dir_valid(answerdict, i) + + # strips the first word from every select type question + handle.select_type(answerdict, i) + + return answerdict + diff --git a/gcmpy/scripts/test_generate_question.py b/gcmpy/scripts/test_generate_question.py new file mode 100644 index 00000000..b4a4219d --- /dev/null +++ b/gcmpy/scripts/test_generate_question.py @@ -0,0 +1,9 @@ +import unittest +import generate_question as gq + +class testGenereateQuestion(unittest.TestCase): + def test_should_ask(self): + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/gcmpy/scripts/utility.py b/gcmpy/scripts/utility.py new file mode 100644 index 00000000..9ce7295d --- /dev/null +++ b/gcmpy/scripts/utility.py @@ -0,0 +1,66 @@ +import os, sys, platform + +# pretty font +class color: + PURPLE = '\033[95m' + CYAN = '\033[96m' + DARKCYAN = '\033[36m' + BLUE = '\033[94m' + GREEN = '\033[92m' + YELLOW = '\033[93m' + RED = '\033[91m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + END = '\033[0m' + RESET = '\033[0m' + + # accepts any string and styles it + def color_path(path): + return color.BLUE + color.BOLD + path + color.RESET + + def color_file(file): + return color.GREEN + color.BOLD + file + color.RESET + +# raises expections +class exceptions: + # Displays usage information to user + def print_usage(): + print(color.GREEN + pathdict['SCRIPTNAME'] + ", a setup script for the GEOS GCM\n\n" + \ + "\tUsage: " + pathdict['SCRIPTNAME'] + " [optional flag]\n\n" + \ + "\t --link Link GEOSgcm.x into experiment directory\n" + \ + "\t --singularity Set up Singularity experiment\n" + \ + "\t -h --help Show usage" + \ + "\n\nIf invoked alone, the script runs as normal." + \ + "\nFor more information, please contact Matt Thompson, Scott Rabenhorst, or Shayon Shakoorzadeh.\n") + exit(1) + + # Display misconfiguration messages to the user + def raise_user_exception(msg): + print(msg) + exit(1) + + def raise_fatal_exception(msg): + exceptions.raiseuserexception(msg) + exit(1) + + # This function will clean output files if script is interrupted + def cleanup(): + pass + + + +####################################################################### +# Directory and Environment Variable Locations Dictionaries +####################################################################### +# set up envirnoment dictionary for later +envdict = {} +pathdict = {} # Start empty - cannot reference self before initialization +pathdict['cwd'] = os.getcwd() +pathdict['bin'] = os.path.dirname(pathdict['cwd']) +pathdict['install'] = os.path.dirname(pathdict['bin']) +pathdict['etc'] = os.path.join(pathdict['install'], 'etc') +pathdict['GEOSgcm'] = os.path.dirname(pathdict['install']) +pathdict['build'] = os.path.join(pathdict['GEOSgcm'], 'build') +#pathdict['SCRIPT'] = os.path.realpath(__file__) +#pathdict['SCRIPTNAME'] = os.path.split(pathdict['SCRIPT'])[-1] +#pathdict['PY_METHOD'] = os.path.join(pathdict['BIN'], 'py_method') From 6361d50d09d4ad40858b97a0590645498a257c94 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Tue, 9 Apr 2024 17:49:53 -0400 Subject: [PATCH 04/37] Add yaml files via upload --- gcmpy/yaml/atmospheric_model.yaml | 50 ++++++++++++++++++ gcmpy/yaml/directory_setup.yaml | 30 +++++++++++ gcmpy/yaml/exp_setup.yaml | 32 ++++++++++++ gcmpy/yaml/gocart.yaml | 13 +++++ gcmpy/yaml/land_model.yaml | 14 +++++ gcmpy/yaml/mpi_config.yaml | 85 +++++++++++++++++++++++++++++++ gcmpy/yaml/ocean_model.yaml | 66 ++++++++++++++++++++++++ 7 files changed, 290 insertions(+) create mode 100644 gcmpy/yaml/atmospheric_model.yaml create mode 100644 gcmpy/yaml/directory_setup.yaml create mode 100644 gcmpy/yaml/exp_setup.yaml create mode 100644 gcmpy/yaml/gocart.yaml create mode 100644 gcmpy/yaml/land_model.yaml create mode 100644 gcmpy/yaml/mpi_config.yaml create mode 100644 gcmpy/yaml/ocean_model.yaml diff --git a/gcmpy/yaml/atmospheric_model.yaml b/gcmpy/yaml/atmospheric_model.yaml new file mode 100644 index 00000000..9769d35f --- /dev/null +++ b/gcmpy/yaml/atmospheric_model.yaml @@ -0,0 +1,50 @@ +AM_horizontal_res: + type: 'select' + prompt: 'Select the atmospheric models HORIZONTAL resolution:' + choices: ['c12 -- 8 deg (750.0 km)', 'c24 -- 4 deg (375.0 km)', 'c48 -- 2 deg (187.5 km)', 'c90 -- 1 deg (100.0 km)', 'c180 -- 1/2 deg ( 50.0 km)', 'c360 -- 1/4 deg ( 25.0 km)', 'c720 -- 1/8 deg ( 12.5 km)', 'c1440 - 1/16 deg ( 6.25 km)', 'c2880 - 1/32 deg ( 3.125 km)', 'c5760 - 1/64 deg ( 1.5625 km)','c270 -- (16.0 -100 km)', 'c540 -- ( 8.0 - 50 km)', 'c1080 - ( 4.0 - 25 km)', 'c1536 - ( 2.0 - 20 km)', 'c2160 - ( 2.0 - 12 km)'] + default_answer: '' + follows_up: '' + +AM_vertical_res: + type: 'select' + prompt: 'Enter the atmospheric models VERTICAL resolution:' + choices: ['72', '91', '137', '181'] + default_answer: '' + follows_up: '' + +AM_microphysics: + type: 'select' + prompt: 'Select the Atmospheric Model Microphysics:' + choices: ['BACM_1M -- 3-phase 1-moment Bacmeister et al', 'GFDL_1M -- 6-phase 1-moment Geophysical Fluid Dynamics Laboratory', 'MGB2_2M -- 5 or 6-phase 2-moment Morrison & Gettleman'] + default_answer: '' + follows_up: '' + +heartbeat: + type: 'text' + prompt: 'Enter a number (in seconds) for HEARTBEAT_DT (press ENTER for recommended value):' + choices: '' + default_answer: '' + follows_up: '' + +use_hydrostatic: + type: 'confirm' + prompt: 'Use Hydrostatic Amtosphere?' + choices: '' + default_answer: True + follows_up: '' + +io_server: + type: 'confirm' + prompt: 'Would you like to IOSERVER?' + choices: '' + default_answer: 'True' + follows_up: '' + + +#combine these two questions and just change "choices:" based on site +processor: + type: 'select' + prompt: 'Enter the Processor Type you wish to run on:' + choices: '' + default_answer: '' + follows_up: '' diff --git a/gcmpy/yaml/directory_setup.yaml b/gcmpy/yaml/directory_setup.yaml new file mode 100644 index 00000000..c4e7456e --- /dev/null +++ b/gcmpy/yaml/directory_setup.yaml @@ -0,0 +1,30 @@ +history_template: + type: 'path' + prompt: 'Enter the location of HISTORY template to use (press ENTER for recommended template):' + choices: '' + default_answer: '' + follows_up: '' + +home_dir: + type: 'path' + prompt: 'Enter Desired Location for the HOME Directory (to contain scripts and RC files):' + choices: '' + default_answer: '' + follows_up: '' + +exp_dir: + type: 'path' + prompt: 'Enter Desired Location for the EXPERIMENT Directory (to contain model output and restart files):' + choices: '' + default_answer: '' + follows_up: '' + +group_root: + type: 'text' + prompt: 'Enter your GROUP ID for Current EXP:' + choices: '' + default_answer: '' + follows_up: '' + + + diff --git a/gcmpy/yaml/exp_setup.yaml b/gcmpy/yaml/exp_setup.yaml new file mode 100644 index 00000000..82404a5d --- /dev/null +++ b/gcmpy/yaml/exp_setup.yaml @@ -0,0 +1,32 @@ +experiment_id: + type: 'text' + prompt: 'Enter the experiment ID:' + choices: '' + default_answer: '' + follows_up: '' + +experiment_description: + type: 'text' + prompt: 'Enter a 1-line Experiment Description:' + choices: '' + default_answer: '' + follows_up: '' + +clone_experiment: + type: 'confirm' + prompt: 'Would you like to CLONE an old experiment?' + choices: '' + default_answer: False + follows_up: '' + +clone_experiment_path: + type: 'path' + prompt: 'Enter the location of the experiment you wish to clone (where gcm_run.j is located):' + choices: '' + default_answer: '' + follows_up: + - ['clone_experiment', [True]] + + + + diff --git a/gcmpy/yaml/gocart.yaml b/gcmpy/yaml/gocart.yaml new file mode 100644 index 00000000..f7c681ff --- /dev/null +++ b/gcmpy/yaml/gocart.yaml @@ -0,0 +1,13 @@ +gocart_aerosols: + type: 'select' + prompt: 'Do you wish to run GOCART with Actual or Climatological Aersols?' + choices: ['Actual', 'Climatological'] + default_answer: '' + follows_up: '' + +gocart_emission: + type: 'select' + prompt: 'Select the GOCART Emission Files to use:' + choices: ['AMIP', 'OPS'] + default_answer: '' + follows_up: '' diff --git a/gcmpy/yaml/land_model.yaml b/gcmpy/yaml/land_model.yaml new file mode 100644 index 00000000..86353a87 --- /dev/null +++ b/gcmpy/yaml/land_model.yaml @@ -0,0 +1,14 @@ +LS_boundary_conditions: + type: 'select' + prompt: 'Select the Land Surface Boundary Conditions:' + choices: ['Icarus', 'Icarus-NLv3'] + default_answer: '' + follows_up: '' + +LS_model: + type: 'select' + prompt: 'Select the Land Surface Model:' + choices: ['Catchment', 'CatchmentCN-CLM4.0 (CN_CLM40)', 'CatchmentCN-CLM4.5 (CN_CLM45)'] + default_answer: '' + follows_up: + - ['LS_boundary_conditions', 'Icarus-NLv3'] diff --git a/gcmpy/yaml/mpi_config.yaml b/gcmpy/yaml/mpi_config.yaml new file mode 100644 index 00000000..df537070 --- /dev/null +++ b/gcmpy/yaml/mpi_config.yaml @@ -0,0 +1,85 @@ +openmpi: | + # Turn off warning about TMPDIR on NFS + setenv OMPI_MCA_shmem_mmap_enable_nfs_warning 0 + setenv OMPI_MCA_mpi_preconnect_all 1 + setenv OMPI_MCA_coll_tuned_bcast_algorithm 7 + setenv OMPI_MCA_coll_tuned_scatter_algorithm 2 + setenv OMPI_MCA_coll_tuned_reduce_scatter_algorithm 3 + setenv OMPI_MCA_coll_tuned_allreduce_algorithm 3 + setenv OMPI_MCA_coll_tuned_allgather_algorithm 4 + setenv OMPI_MCA_coll_tuned_allgatherv_algorithm 3 + setenv OMPI_MCA_coll_tuned_gather_algorithm 1 + setenv OMPI_MCA_coll_tuned_barrier_algorithm 0 + # required for a tuned flag to be effective + setenv OMPI_MCA_coll_tuned_use_dynamic_rules 1 + # disable file locks + setenv OMPI_MCA_sharedfp "^lockedfile,individual" + +mvapich: | + # MVAPICH and GEOS has issues with restart writing. Having the + # oserver write them seems to...work + setenv MV2_ENABLE_AFFINITY 0 + setenv SLURM_DISTRIBUTION block + setenv MV2_MPIRUN_TIMEOUT 100 + setenv MV2_GATHERV_SSEND_THRESHOLD 256 + +mpt: | + setenv MPI_COLL_REPRODUCIBLE + setenv SLURM_DISTRIBUTION block + #setenv MPI_DISPLAY_SETTINGS 1 + #setenv MPI_VERBOSE 1 + setenv MPI_MEMMAP_OFF + unsetenv MPI_NUM_MEMORY_REGIONS + setenv MPI_XPMEM_ENABLED yes + unsetenv SUPPRESS_XPMEM_TRIM_THRESH + setenv MPI_LAUNCH_TIMEOUT 40 + setenv MPI_COMM_MAX 1024 + setenv MPI_GROUP_MAX 1024 + setenv MPI_BUFS_PER_PROC 256 + # For some reason, PMI_RANK is randomly set and interferes + # with binarytile.x and other executables. + unsetenv PMI_RANK + # Often when debugging on MPT, the traceback from Intel Fortran + # is "absorbed" and only MPT's errors are displayed. To allow the + # compiler's traceback to be displayed, uncomment this environment + # variable + #setenv FOR_IGNORE_EXCEPTIONS false + +intelmpi: | + setenv I_MPI_ADJUST_ALLREDUCE 12 + setenv I_MPI_ADJUST_GATHERV 3 + # This flag prints out the Intel MPI state. Uncomment if needed + #setenv I_MPI_DEBUG 9 + +NCCS: | + # These are options determined to be useful at NCCS + # Not setting generally as they are more fabric/cluster + # specific compared to the above adjustments + setenv I_MPI_SHM_HEAP_VSIZE 512 + setenv PSM2_MEMORY large + +BUILT_ON_SLE15: | + # Testing by Bill Putman found these to be + # useful flags with Intel MPI on SLES15 on the + # Milan nodes. + # Note 1: Testing by NCCS shows the PSM3 provider + # runs on the Infiniband fabric. Tests show it runs + # up to C720. + # Note 2: When the Cascade Lakes are moved to + # SLES15, these will need to be Milan-only flags + # as Intel MPI will probably work just fine with + # Intel chips. + setenv I_MPI_FALLBACK 0 + setenv I_MPI_FABRICS ofi + setenv I_MPI_OFI_PROVIDER psm3 + setenv I_MPI_ADJUST_SCATTER 2 + setenv I_MPI_ADJUST_SCATTERV 2 + setenv I_MPI_ADJUST_GATHER 2 + setenv I_MPI_ADJUST_GATHERV 3 + setenv I_MPI_ADJUST_ALLGATHER 3 + setenv I_MPI_ADJUST_ALLGATHERV 3 + setenv I_MPI_ADJUST_ALLREDUCE 12 + setenv I_MPI_ADJUST_REDUCE 10 + setenv I_MPI_ADJUST_BCAST 11 + setenv I_MPI_ADJUST_REDUCE_SCATTER 4 + setenv I_MPI_ADJUST_BARRIER 9 diff --git a/gcmpy/yaml/ocean_model.yaml b/gcmpy/yaml/ocean_model.yaml new file mode 100644 index 00000000..57e321dc --- /dev/null +++ b/gcmpy/yaml/ocean_model.yaml @@ -0,0 +1,66 @@ +# format - loads the questionary API +# +# question name: +# question type: 'text/confirm/select/path' +# question prompt: 'ask your question' +# choices: ['list', 'of', 'choices'] <----------(only for select type, otherwise leave blank) +# default answer: 'default' <----------(optional/can be left blank) +# follows_up: <----------(optional/can be left blank. If you want to +# -['prev question', ['answer1', 'answer2']] conditionally skip a question, add a list of +# -['or other prev question', ['any']] tuples containing the question(s) it will follow up +# and the answer the user has to give in order for +# this question to be asked. Multiple answers can be +# an ask condition, or you can set the answer to 'any' +# which will allow any answer given to show the question.) + +OM_coupled: + type: 'confirm' + prompt: 'Do you wish to run the COUPLED Ocean/Sea-Ice Model?' + choices: '' + default_answer: False + follows_up: '' + +# ------------------------------------- coupled == False -------------------------------------- +OM_horizontal_res: + type: 'select' + prompt: 'Select the Data_Ocean HORIZONTAL resolution:' + choices: ['o1 (1 -deg, 360x180 Reynolds)', 'o2 (1/4-deg, 1440x720 MERRA-2)', 'o3 (1/8-deg, 2880x1440 OSTIA)', 'CS (Cubed-Sphere OSTIA)'] + default_answer: '' + follows_up: + - ['OM_coupled', [False]] +# --------------------------------------------------------------------------------------------- + +# ------------------------------------- coupled == True --------------------------------------- +OM_name: + type: 'select' + prompt: 'Choose an Ocean Model:' + choices: ['MOM5', 'MOM6', 'MIT'] + default_answer: '' + follows_up: + - ['OM_coupled', [True]] + +OM_MOM_horizontal_res: + type: 'text' + prompt: 'Enter the Ocean Lat/Lon Horizontal Resolution (IM JM):' + choices: '' + default_answer: '360 200' + follows_up: + - ['OM_name', ['MOM5', 'MOM6']] + +OM_MIT_horizontal_res: + type: 'select' + prompt: 'Select the Data_Ocean HORIZONTAL resolution:' + choices: ['llc90 (1-deg, Lat-Lon-Cube)', 'llc270 (1/3-deg, Lat-Lon-Cube)', 'cs32 (5-deg, cubed-sphere)'] + default_answer: '' + follows_up: + - ['OM_name', ['MIT']] + +OM_vertical_res: + type: 'text' + prompt: 'Enter the Ocean Model VERTICAL resolution (LM):' + choices: '' + default_answer: '50' + follows_up: + - ['OM_MOM_horizontal_res', ['any']] + - ['OM_MIT_horizontal_res', ['any']] +# ---------------------------------------------------------------------------------------------- \ No newline at end of file From e13a1f5b1facfc44014af5aa1b59d9b46035f006 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 10 Apr 2024 11:54:12 -0400 Subject: [PATCH 05/37] Update gcmpy/CMakeLists.txt Co-authored-by: Matthew Thompson --- gcmpy/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcmpy/CMakeLists.txt b/gcmpy/CMakeLists.txt index 8846312e..f90cd199 100644 --- a/gcmpy/CMakeLists.txt +++ b/gcmpy/CMakeLists.txt @@ -1,6 +1,6 @@ # cp (makes exe) add_subdirectory(scripts) -add_subdirectory(yamls) +add_subdirectory(yaml) set (programs) From 6f84181fe02a73622e4621669478f160fc78c4b5 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 10 Apr 2024 15:17:31 -0400 Subject: [PATCH 06/37] CMakeLists changes --- gcmpy/CMakeLists.txt | 2 +- gcmpy/scripts/CMakeLists.txt | 10 +++++++++- gcmpy/yaml/CMakeLists.txt | 8 +++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/gcmpy/CMakeLists.txt b/gcmpy/CMakeLists.txt index 8846312e..f90cd199 100644 --- a/gcmpy/CMakeLists.txt +++ b/gcmpy/CMakeLists.txt @@ -1,6 +1,6 @@ # cp (makes exe) add_subdirectory(scripts) -add_subdirectory(yamls) +add_subdirectory(yaml) set (programs) diff --git a/gcmpy/scripts/CMakeLists.txt b/gcmpy/scripts/CMakeLists.txt index 43be2a33..440db4ac 100644 --- a/gcmpy/scripts/CMakeLists.txt +++ b/gcmpy/scripts/CMakeLists.txt @@ -1,5 +1,13 @@ set (programs - #fill + atmosphere.py + env.py + generate_question.py + gocart.py + land.py + model.py + ocean.py + process_questions.py + utility.py ) install ( diff --git a/gcmpy/yaml/CMakeLists.txt b/gcmpy/yaml/CMakeLists.txt index 36e3ed48..92e417d7 100644 --- a/gcmpy/yaml/CMakeLists.txt +++ b/gcmpy/yaml/CMakeLists.txt @@ -1,5 +1,11 @@ set (programs - #fill + atmospheric_model.yaml + directory_setup.yaml + exp_setup.yaml + gocart.yaml + land_model.yaml + mpi_config.yaml + ocean_model.yaml ) install ( From bd64abf0f74aa70e78c7bbb84f6ba024486be874 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 24 Apr 2024 12:11:26 -0400 Subject: [PATCH 07/37] storing to switch branches --- gcmpy/scripts/model.py | 25 +++++++++++++++++++++---- gcmpy/scripts/process_questions.py | 12 ++++++------ gcmpy/scripts/utility.py | 19 +++++++++---------- gcmpy/sync.sh | 8 ++++++++ 4 files changed, 44 insertions(+), 20 deletions(-) create mode 100755 gcmpy/sync.sh diff --git a/gcmpy/scripts/model.py b/gcmpy/scripts/model.py index 8c3209c8..86970dec 100644 --- a/gcmpy/scripts/model.py +++ b/gcmpy/scripts/model.py @@ -369,7 +369,7 @@ def RC_setup(self): shutil.rmtree(RC_dir) # Copy over all files and subdirs in install/etc, keeping symlinks, and ignoring *.tmpl files - shutil.copytree(pathdict['etc'], RC_dir, symlinks=True, ignore=shutil.ignore_patterns('*.tmpl')) + shutil.copytree(pathdict['etc'], RC_dir, symlinks=True, ignore=shutil.ignore_patterns('*.tmpl', 'fvcore.layout.rc')) # Copy or symlink GEOSgcm.x (((IGNORE SINGULARITY/NATIVE BUILDS FOR NOW!!))) geosgcmx_path = os.path.join(pathdict['bin'], 'GEOSgcm.x') @@ -384,7 +384,7 @@ def RC_setup(self): def mpistacksettings(self): # load mpi config from YAML - with open('mpi_config.yaml') as file: + with open('../yaml/mpi_config.yaml') as file: mpidict = yaml.load(file, Loader=yaml.FullLoader) # retrieve config from correlating mpi setting being used @@ -392,8 +392,25 @@ def mpistacksettings(self): print(mpi_config) - - + ####################################################################### + # Create directories and copy files over + ####################################################################### + def copy_files_into_exp(self): + file_list = ['gcm_run.j', \ + 'gcm_post.j', \ + 'gcm_archive.j', \ + 'gcm_regress.j', \ + 'gcm_plot.tmpl', \ + 'gcm_quickplot.csh', \ + 'gcm_moveplot.j', \ + 'gcm_forecast.tmpl', \ + 'gcm_forecast.setup', \ + 'gcm_emip.setup', \ + 'CAP.rc.tmpl', \ + 'AGCM.rc.tmpl', \ + 'HISTORY.rc.tmpl', \ + 'logging.yaml', \ + 'fvcore_layout.rc'] mymodel = model() diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index 00411572..0e09cb97 100644 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -170,12 +170,12 @@ def group_root_default(answerdict, i): def load_yamls(): # list of question files (*MAKE SURE THEY ARE IN THE ORDER YOU WANT THEM TO BE ASKED*) - file_list = ["exp_setup.yaml", \ - "atmospheric_model.yaml", \ - "ocean_model.yaml", \ - "land_model.yaml", \ - "gocart.yaml", \ - "directory_setup.yaml"] + file_list = ["../yaml/exp_setup.yaml", \ + "../yaml/atmospheric_model.yaml", \ + "../yaml/ocean_model.yaml", \ + "../yaml/land_model.yaml", \ + "../yaml/gocart.yaml", \ + "../yaml/directory_setup.yaml"] all_yaml_questions = {} for filename in file_list: diff --git a/gcmpy/scripts/utility.py b/gcmpy/scripts/utility.py index 9ce7295d..7e2fc1c5 100644 --- a/gcmpy/scripts/utility.py +++ b/gcmpy/scripts/utility.py @@ -54,13 +54,12 @@ def cleanup(): ####################################################################### # set up envirnoment dictionary for later envdict = {} -pathdict = {} # Start empty - cannot reference self before initialization -pathdict['cwd'] = os.getcwd() -pathdict['bin'] = os.path.dirname(pathdict['cwd']) -pathdict['install'] = os.path.dirname(pathdict['bin']) -pathdict['etc'] = os.path.join(pathdict['install'], 'etc') -pathdict['GEOSgcm'] = os.path.dirname(pathdict['install']) -pathdict['build'] = os.path.join(pathdict['GEOSgcm'], 'build') -#pathdict['SCRIPT'] = os.path.realpath(__file__) -#pathdict['SCRIPTNAME'] = os.path.split(pathdict['SCRIPT'])[-1] -#pathdict['PY_METHOD'] = os.path.join(pathdict['BIN'], 'py_method') +pathdict = {} # Start empty - cannot reference self before initialization (<--what are you yapping about??) +pathdict['scripts'] = os.getcwd() +pathdict['gcmpy'] = os.path.dirname(pathdict['scripts']) +pathdict['yaml'] = os.path.join(pathdict['gcmpy'], 'yaml') +pathdict['bin'] = os.path.dirname(pathdict['gcmpy']) +pathdict['install'] = os.path.dirname(pathdict['bin']) +pathdict['etc'] = os.path.join(pathdict['install'], 'etc') +pathdict['GEOSgcm'] = os.path.dirname(pathdict['install']) +pathdict['build'] = os.path.join(pathdict['GEOSgcm'], 'build') diff --git a/gcmpy/sync.sh b/gcmpy/sync.sh new file mode 100755 index 00000000..5225d453 --- /dev/null +++ b/gcmpy/sync.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# Source and destination directories +source_dir="/discover/nobackup/sshakoor/GEOSgcm/src/Applications/@GEOSgcm_App/gcmpy" +destination_dir="/discover/nobackup/sshakoor/GEOSgcm/install/bin/gcmpy" + +# Synchronize scripts +rsync -av --exclude='sync.sh' --exclude='**/CMakeLists.txt' "$source_dir/" "$destination_dir/" From 51e200226075f6abc864251548ceebd14fc84950 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 24 Apr 2024 15:30:18 -0400 Subject: [PATCH 08/37] commit to switch branches --- gcmpy/scripts/model.py | 43 ++++++++++++++++++++++++---------------- gcmpy/scripts/utility.py | 17 ++++++++-------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/gcmpy/scripts/model.py b/gcmpy/scripts/model.py index 86970dec..bfa2fa3f 100644 --- a/gcmpy/scripts/model.py +++ b/gcmpy/scripts/model.py @@ -6,6 +6,7 @@ from utility import envdict, pathdict import math, os, shutil, tempfile, yaml from pathlib import Path +from jinja2 import Environment, FileSystemLoader, StrictUndefined # combines all models (atmos, ocean, land, gocart) into one big one @@ -395,23 +396,12 @@ def mpistacksettings(self): ####################################################################### # Create directories and copy files over ####################################################################### - def copy_files_into_exp(self): - file_list = ['gcm_run.j', \ - 'gcm_post.j', \ - 'gcm_archive.j', \ - 'gcm_regress.j', \ - 'gcm_plot.tmpl', \ - 'gcm_quickplot.csh', \ - 'gcm_moveplot.j', \ - 'gcm_forecast.tmpl', \ - 'gcm_forecast.setup', \ - 'gcm_emip.setup', \ - 'CAP.rc.tmpl', \ - 'AGCM.rc.tmpl', \ - 'HISTORY.rc.tmpl', \ - 'logging.yaml', \ - 'fvcore_layout.rc'] - + def copy_files_into_exp(self, file_list[]): + for file in file_list: + if file[-5:] == '.tmpl': + shutil.copy(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file[:-5]}") + else: + shutil.copy(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file}") mymodel = model() mymodel.config_models() @@ -423,3 +413,22 @@ def copy_files_into_exp(self): mymodel.create_dotfile(f"{os.environ.get('HOME')}/.GROUProot", answerdict['group_root'].q_answer) mymodel.RC_setup() mymodel.mpistacksettings() +file_list['gcm_run.j', \ + 'gcm_post.j', \ + 'gcm_archive.j', \ + 'gcm_regress.j', \ + 'gcm_plot.tmpl', \ + 'gcm_quickplot.csh', \ + 'gcm_moveplot.j', \ + 'gcm_forecast.tmpl', \ + 'gcm_forecast.setup', \ + 'gcm_emip.setup', \ + 'CAP.rc.tmpl', \ + 'AGCM.rc.tmpl', \ + 'HISTORY.rc.tmpl', \ + 'logging.yaml', \ + 'fvcore_layout.rc'] + +mymodel.copy_files_into_exp(file_list) + + diff --git a/gcmpy/scripts/utility.py b/gcmpy/scripts/utility.py index 7e2fc1c5..9d60c84a 100644 --- a/gcmpy/scripts/utility.py +++ b/gcmpy/scripts/utility.py @@ -55,11 +55,12 @@ def cleanup(): # set up envirnoment dictionary for later envdict = {} pathdict = {} # Start empty - cannot reference self before initialization (<--what are you yapping about??) -pathdict['scripts'] = os.getcwd() -pathdict['gcmpy'] = os.path.dirname(pathdict['scripts']) -pathdict['yaml'] = os.path.join(pathdict['gcmpy'], 'yaml') -pathdict['bin'] = os.path.dirname(pathdict['gcmpy']) -pathdict['install'] = os.path.dirname(pathdict['bin']) -pathdict['etc'] = os.path.join(pathdict['install'], 'etc') -pathdict['GEOSgcm'] = os.path.dirname(pathdict['install']) -pathdict['build'] = os.path.join(pathdict['GEOSgcm'], 'build') +pathdict['scripts'] = os.getcwd() +pathdict['gcmpy'] = os.path.dirname(pathdict['scripts']) +pathdict['yaml'] = os.path.join(pathdict['gcmpy'], 'yaml') +pathdict['bin'] = os.path.dirname(pathdict['gcmpy']) +pathdict['install'] = os.path.dirname(pathdict['bin']) +pathdict['etc'] = os.path.join(pathdict['install'], 'etc') +pathdict['GEOSgcm'] = os.path.dirname(pathdict['install']) +pathdict['build'] = os.path.join(pathdict['GEOSgcm'], 'build') +pathdict['GEOSgcm_App'] = os.path.join(pathdict['GEOSgcm'], 'src/Applications/@GEOSgcm_App') From 4a95c497731f0ccd8defbbbe54ceb7616565e691 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 12 Jun 2024 13:17:01 -0400 Subject: [PATCH 09/37] dir setup --- gcmpy/scripts/.model.py.swp | Bin 0 -> 20480 bytes .../__pycache__/atmosphere.cpython-312.pyc | Bin 0 -> 11467 bytes gcmpy/scripts/__pycache__/env.cpython-312.pyc | Bin 0 -> 4668 bytes .../generate_question.cpython-312.pyc | Bin 0 -> 2995 bytes .../__pycache__/gocart.cpython-312.pyc | Bin 0 -> 2472 bytes .../scripts/__pycache__/land.cpython-312.pyc | Bin 0 -> 3150 bytes .../scripts/__pycache__/ocean.cpython-312.pyc | Bin 0 -> 12294 bytes .../process_questions.cpython-312.pyc | Bin 0 -> 12394 bytes .../__pycache__/utility.cpython-312.pyc | Bin 0 -> 3732 bytes gcmpy/scripts/model.py | 106 ++++++++++++++---- gcmpy/scripts/ocean.py | 1 + gcmpy/yaml/directory_setup.yaml | 7 -- gcmpy/yaml/ocean_model.yaml | 10 +- 13 files changed, 94 insertions(+), 30 deletions(-) create mode 100644 gcmpy/scripts/.model.py.swp create mode 100644 gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/env.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/gocart.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/land.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/ocean.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/utility.cpython-312.pyc diff --git a/gcmpy/scripts/.model.py.swp b/gcmpy/scripts/.model.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..9828119ed456ce9298323498d949b7ee20b6c8d8 GIT binary patch literal 20480 zcmeHPU5p!76`oSk(9!~G_z{2YjjiHc>e#zU6E%yr>elh@x?QhVwv$b?O{e4W*q&rO z`TdApt56s4e9?cjkJ= zv$LBtN_l`8>9cq4J#+54XYM)oo^$WIF?FO=W(RXq60Ubi(o_FfYNdaC>CR7nP?8*{ zqnxxXo2s_En!2M}>zX~icRMOc%C~zhr<-q@jeYy_f_Z+SSgEzuZeBMXS22uyLpSrd z?+x;fYU@4M$#<=$X5@NRloc?UjQM;Tm5pu|L#crrGEX5{`W(XdcQdNN;HsYAkjdg zfkXp|1`-V<8b~ydXdux*qJcyM|Cbt2nv!$?JwHS7GWP#P{Qu%RCFwEXo4{v*lfX^D zdx6*9AxVz_4+9SYeV_xZ03QKfy-Jdv0UiME1=fHYfUAH%UMWdG1ik_^fhpi};OyJM z6W9P&fZKpufh=$(@YgFO=}F)T;0*8}@CD!)a1*c_V8FG21f0EGlD-3c2Dlrj0q+JL zf14z&10MrsfP=t?fJ=d=cS_RFfzJWQfTO^Nf#)uhq-TN81FOIh;1b|>J0Js~0}H@T z-~}Wqz7O<(n}J=xKarex8Tb-V1FFC^z%xj?`~tWGxEk02(0ll)pSyTt1CoWVH0$;a zS8v-^zsGFtuD)(-4pUraXo}-9cf(>0MLnsRP1e&KDfA>8yD?>-Oa>X7WnIPX;Vh&Z|duMQ){xuAVTan%6Ov~2B9k=QKSn(TIyV$Y36!USKYOgDHm1_JE`MQ z`BlYG`-b9b7t+3`KvQnnmgz$AT%*@RWl=qj$?qx6wQw>fq&m@IUv+{dqx+uGcS58w ziX7KaNLj35Ys$&7_C>AUVuo&NImgA3oQX*`JIhitGpU(aVtQzEzu5J&Y&w=6%yn~Y zC@C12UVA-5cPBC|lV#JBYg5PBZZw?Urd<`<)y=*Z+YkvBX=#?#?JcNBeU8dNoi9|D zmWqXXsj^&)Q$x$Lc?ZxOYw3ozSy7whm{$x(8#liV-R&@|r1=2=AD$WimCCNx z?a^q=9M9b)djwgQu``oQabg;cc_XuIYD`aQwrp*%4UNHXv^&NCT-tqGV^$wNW6VCo zc8M-hN@f! zBmw6}Mi6b^YlgdrF%J-G{yfZoUbo>pp`ES#fY*M+3t<$6US3MKWY0yWg11K2M58bm zBxzO{`I<_tSUpm#dfp9Q(}4@LOn7zG>UQBsaH|+?%f?vg1|9di?0FqWGg>*t?OIN5 z`6x6UzCXrCKvQd>)b;%K1l3P^(xj;vlZbYzr`bB%bA_87jU3MHgw>FpcGrc4&9YYN zbf^hYHDpu#N(FuIRls#USswrlU7p%0Dmg8!!tJ%4FX(=@>31`<- zTxGK)=Vph8BkUTgBh%!0zS0Gc(<8itIvl>;v&dHETCENRaa)&&fG!P&AG~`i+2XM= zSA~HUQgW%xClYqktXJx(t5o**ir4E{T}^h}eybJtj;WTdE4HpQ4D?uUp2P}-#G#9~ z)wWc{c5`sD@C*}ywem^>UVDowZ|wPxabi!t<)hiKxXZ^PEIq2R=BO)Pfy~FaBYF}q zYR`uDWpv7k6?f}uPvlMY)Vx=Sv#K6n>JO|%A}#R``ors_zZ$~$aiKRV$JDW03C0K~ zgKf!8-KJ`B&4!&u#wQ3ldeBLNmh&(@(-md(JqvGc1{0xA7GBVC>Uc7-H1eG07TjnV z15495AMXSG+k5cf!Kr;ydl`-z;)-;(p|vsfjXi~Drf)nrjc2BXi;x6MF17F=q7dJ4 zQb+A<3$l>E5e(zFh5X2NWFh~s9a(E#R{IV3>fl1RBf8NYdArD4Hc zczie+SdmxiunFE;mT^{DE@am4)g;zYu7zn&V-3Ac-|$RW33S;B-8`Y}WqP+~!N7{< zx{mcVO;cGmk9nmwz(mnqvXrJ~XITxaSJgd?IkSbvn;wTAVj4ql2o@{2m3(#-?m!*~ zPO8(#c*rtZbJ2P(%LYo<@EA~y?hXV4Ka9vSVoWQxEJZOmMbG6$tso4R1?a49o;>AI z_%GKN!MpQn=(UN5>2I%;YpvJOuuk)z36)?a$nQK-@6GvC{6?bq|F?*7e}(v$;(xJ! z{wU)7uL1+$2rvy?0h~pA{{ld@P1$ia6jVx0x$)<2Y3bX{PVzffiD6Uumns3mjQo3T>m5BKH%fPDsTg^ z3%DA134MDWcn)|LpuYYRNUlT!i3So4BpOIGkZ9n4O9R~jj}9qeK%o~cVnvZ^^#(F6 z;vB3|T}wuEH9@zsfu!?f5JvJPZl<-aS~lvG0kU97Ze@;3V{6}xVYLy_v~#o|M4FOc z5t1M^mUEG_<5UrnxrIU*+=F`XiI5cLR-zP968zt!tabHXjwfwAX(C*R1ldVV#YTW2 z+m6H+IEJK)|M~10mYX}VWkc9_P)~9i)#-pLh6}G9X=PKVNnBfN<25>>oj5Lvt#e@?k2FQ*idlz!ZBG42e3^a+&RzN>_8%@aS=#@(YLm;>mz7 zNtB{?kN|ZDylMRCzWuh3U3)Tx9M4j1}9?eO~)DoZm8@7b+hB7g#PO0-I% zdh~~{Cy2C`DJ|EF)#bUROg2+0uT-k_s8{!%&eZDFxq4x-SkBCNIosigo#2n}%tE;o zCd$SV73QktIl(8Mq&zojC?N314dgzZS=?J0aR}UCn(evJi^u;6-K7s)f)B+1;(YxR zi1p6^p8ytsS3vX|;Mc(SfO~;kfH~lG#Q9GFj{^hXX5eMS@!tSCz%9Vf5XV0Wd>!~S z@F}1JP@GS({ZD{9fmPt|h}q8oMc@aB(;oxA4D0|53Yrb2gbx?H;1LsVdPjW~scD^tPEn=TaIx=g>vV&k|>oLrIm)Y$!hMLMpGtwa-* zTrTe>5K1$~jfK`X+(>As!$yR8ypeIZKi}3YXa6}ZIy~ZI%sN!!3qJt~v6W!%-nEj(9{_93AqRVbM6-Km8-?%}{D09Q=A)q&NW5 z8%#L1nq@cvipKdu*n2~xp7^UQuLn_DuTLc5=m^pr_D5Y8O7k9Mt-i_6oN}S5LFyxE z0=u19Z{qjJ5Cif;Iu@qGsA&+>-!!ZxQqjd)g>qi>Aug_S4Kg6bh9j)HFB3`Wi%3(m zXBZb#2x?yvLLhNPSri=7LD+~J+J@#SD1UQ$ErY^L=zwb)R*f`=wvN+n-gA7n8mUiP zLpV+P#S@eq;D0wXDuFVwdo0?dZ@(!tO4-nyfxw(+3bH&#*X&tdJl{7AZ%aO~+#n^8 z$>s7ymIpJx6JBmLl*e8#hQH15RMx;U>uB7xFED*wBN uOiDF$O0T?9!U+VV6B%kqjTbo{3O64%Mq1n;yLn2ckj6i6<;NnE(tiL>oMEj1 literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc b/gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2b48271bf2b4f467fcfa465a730cd402a9551c6 GIT binary patch literal 11467 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 LTQSEVBn|%u?;q7K literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/env.cpython-312.pyc b/gcmpy/scripts/__pycache__/env.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e52fa08ecff323f9113d7f65f0e2a68ceda3adf0 GIT binary patch literal 4668 zcmcgvTWlN06`kdBxerk<>P73hvR-CviH@bjkGOVhNtSF!lq*_|%{mn*?ua5q?lQYe zJqQ<-iU6Tdx2DjdQqYge{izJ2fb-|i^shi36-gIjCLc-BepG*S93YMJ(atQnQWDv& z+ooMXvorUex%bSSJ9n1vmX-4&oAOb{ z*y6JoZ`xtmywkBjm?o+{u4pTGl&_LWFhpB=wTEdZ85D%@;3+kH!n zMAd^kR6#NTUJC)>tAG`fZ66j%?92fGR9fPEB{#};q`V=u!BUAMJqp}t+|da{qH#Op z5(DeN4EXT=UB71UPO*b+oH8)&re^mo*-dK+ER;$~Yci(5GgzLn5|ky}xogwxnf{?o zDm#gV1`e;_o6lEpt`PsKm?e_4}Fde#^mEb=+D%l|78=q6fRjm(Jj7-&*yM978DK4#C{q`K_j58t5+ z7^BVz;ep4@c;3v=@X%hZnZ>*8q$9*S$p-u`H*%@hV0DZq)u%@4GwrC8DTEfb#(u(?g1^okO;O5(`0T zn_S4-|G-be*4-Tm$upM|rQO|HNDjs$el?^o5cxEW#1fY7=|o+>5{>$0NyJDf`qf|@ zMrB>xpE$Q)loefk)<=Z_B`AjyQ0fr{FN9)T^9SJx0a;~5g2?Ju1Jj6xdLY4i&tD$w zQ3HrlkyQ)nFd>{h;~gA0KZb>Y;^&01{p0|(;s1x^uDpmhc@qWI{NI~beNqHal^?Co`H z+O&U0QB?QP;HWnkh`Kd3;64+JMM43;5m@)jMa=}3x-lZQ;MM|aD5h&}yfHnog-86! zAe7;JOg*L6VISlc(5i9sH}LmGkg*+31s1g%fj1Iq+u<)BTCw8Cj%vzfL97ykGA4C8F7-$@Q(#$*Nz_H|o<|-xsPAYcWM@ zi16b=vJNA-r#4|R;-a(uSST=k1Tk1f_B9&QRR>X7J^lS&#K%-605uJ#C_C)e=3peU z-AL3nd7}T)xQ1Bo%tFLJ1GmZd5@P%PTEH*C?QSxnJ!ibz#69BAs)}DCvk`q}WMF&I zP@j3#idFG!%DOi6r6M zL}f}OYzR=*U}UN%(Kd(|sv2N99-YKp6BEOIlF27T#EyF|dPZOMAm){j9G_2=x`|YBefF4(&>kzUi8ltrY4HtokU!PLcD5@;3XX5oZ)Qnt3me}ivjq9NZKISSpJ}OB! zl_3rJnSe@6tY2L~45<$Dh=cQRViu~CsAf`8A`@{^D{x@VdVzR|Nki4I8|OGUi)dUY zkPuUGS{TP1IaGg0gK-V2I~7SKKUk0rQ`TV=SxKrRD=A>e8dgHMuR_0s7!98^9kG*s z4N4)kkVLd!UO;Sdbx82bID^ze1$=#?FhY#s9noWh1IVhwc^#9|W)L-n*y2VYTqNT% zwtaqdP*rg%TH!o)RUVB;^ia__UL@i%exd-a@+kWGXeq#q^CQswF*ue5$36m%yp5-Ins0}j}0Qr^`oD_7S1Ym=#K*^>RA0)Y}2`*U1L^6WC3I+o!YauwCfOin0GPA+$) zCNe^Mj%!-4&T<{5>`F#xTCZ9kyH&R_@S7H_O$u9FQ<`h~6W8(y*Fi=dX|7|l^W}GX z-%)>mG~Ib24=4{cKs^9d*8ueyp!jptCtsVFufaSpgwFe-0Jm}>+8cCey1wy7~FDPNINcM9j|OT#?p?l ztmE?L_^WBhmBQ2qc2H8DRBz5L&)vMfe0^mrw=c(6r7osRTIjtSyf^i>lB;{=Gn!&N6rQ-xwN|p_Jdk!C*mQZa&e1KWH|_Lho#Tr` z$>EH(21DvZ+&{N8nq$k7vr9i(>&mdLd8>_gepp$PQnHnud0;6$z0sPhZ}@fRTb;i; zkYaP~2Y)+qYvk_1Z2PGcyT+v}T0dtn=mA0I?LeqZ)h@TJ4QKfFyp`ddAKCZk#N+Gb zTjKGwcswh=Ca zcTaL20N%59jP%j(xs3ivr{@TGzmFOD4*ULb7HdBMhdgfjgC2^sM-Gj)(ti{w-2M~a CXhu{3 literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc b/gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4d5b6bbefaa6fbaaabb988d15eaacaf38caba86 GIT binary patch literal 2995 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 Dej({3 literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc b/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3c2d8d18617d8d070e247a01f4f3c0ad7040e28 GIT binary patch literal 12394 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 literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/model.py b/gcmpy/scripts/model.py index bfa2fa3f..7f373228 100644 --- a/gcmpy/scripts/model.py +++ b/gcmpy/scripts/model.py @@ -3,7 +3,7 @@ from land import land from gocart import gocart from env import answerdict, linkx -from utility import envdict, pathdict +from utility import envdict, pathdict, color import math, os, shutil, tempfile, yaml from pathlib import Path from jinja2 import Environment, FileSystemLoader, StrictUndefined @@ -391,44 +391,106 @@ def mpistacksettings(self): # retrieve config from correlating mpi setting being used mpi_config = mpidict.get(envdict['mpi']) - print(mpi_config) - ####################################################################### # Create directories and copy files over ####################################################################### - def copy_files_into_exp(self, file_list[]): + # A little helper function for copying files and displaying the info to the user + def copy_helper(self, src, destination, filename): + shutil.copy(src, destination) + print(f"Creating {color.RED}{filename}{color.RESET} for Experiment: {answerdict['experiment_id'].q_answer}") + + def copy_files_into_exp(self, file_list): + print("\n\n\n") + for file in file_list: if file[-5:] == '.tmpl': - shutil.copy(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file[:-5]}") + self.copy_helper(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file[:-5]}", file) else: - shutil.copy(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file}") + self.copy_helper(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file}", file) + + # These files will be added if user chose to run coupled, regardless of ocean model selected. + if self.ocean.coupled == True: + self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/plotcon.j", f"{self.exp_dir}/plotcon.j", "plotcon.j") + self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/confon.py", f"{self.exp_dir}/__init__.py", "confon.py") + + if self.ocean.name == 'MOM5': + self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.IM}x{self.ocean.JM}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") + self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.IM}x{self.ocean.JM}/diag_table", f"{self.exp_dir}/diag_table.nml", "diag_table") + self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.IM}x{self.ocean.JM}/field_table", f"{self.exp_dir}/field_table.nml", "field_table") + elif self.ocean.name == 'MOM6': + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/MOM_input", f"{self.exp_dir}/MOM_input", "MOM_input") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/MOM_override", f"{self.exp_dir}/MOM_override", "MOM_override") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/diag_table", f"{self.exp_dir}/diag_table", "diag_table") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/field_table", f"{self.exp_dir}/field_table", "field_table") + + if self.ocean.seaice_model == 'CICE6': + self.copy_helper(f"{pathdict['ect']}/CICE6/cice6_app/{self.ocean.IM}x{self.ocean.JM}/ice_in", f"{self.exp_dir}/ice_in") + + print(f"{color.GREEN}Done!{color.RESET}\n") + + + ####################################################################### + # Produce Final script and .rc files + ####################################################################### + + # THIS WHOLE SECTION IS WILDLY OUT OF DATE, HOWEVER I KEPT IT AS IT WAS + # IN THE ORIGINAL SCRIPT FOR NOW + def restarts(self): + # comment or un-comment restarts based on exp configuration + # --------------------------------------------------------- + rsnames = {'H2O': False, + 'MAM': False, + 'CARMA': False, + 'GMICHEM': False, + 'STRATCHEM': False} + rstypes = ['INTERNAL','IMPORT'] + + # Load Jinja2 template + with open(f"{answerdict['exp_dir'].q_answer}/AGCM.rc", "r") as file: + file_content = file.read() + #file = Template(file_content) + + # Template in a "#" if restart is set to false + for rst in rsnames: + for typ in rstypes: + rst_string = f"{rst}_{typ}" + comment = "#" if not rsnames[rst] else "" + file_content = file_content.replace(rst_string, f"{comment}{rst_string}") + + with open(f"{answerdict['exp_dir'].q_answer}/AGCM.rc", "w") as file: + file.write(file_content) + + + mymodel = model() mymodel.config_models() #mymodel.print_all_vars() mymodel.set_nodes() mymodel.set_stuff() -mymodel.create_dotfile(f"{os.environ.get('HOME')}/.HOMDIRroot", answerdict['home_dir'].q_answer) mymodel.create_dotfile(f"{os.environ.get('HOME')}/.EXPDIRroot", answerdict['exp_dir'].q_answer) mymodel.create_dotfile(f"{os.environ.get('HOME')}/.GROUProot", answerdict['group_root'].q_answer) mymodel.RC_setup() mymodel.mpistacksettings() -file_list['gcm_run.j', \ - 'gcm_post.j', \ - 'gcm_archive.j', \ - 'gcm_regress.j', \ - 'gcm_plot.tmpl', \ - 'gcm_quickplot.csh', \ - 'gcm_moveplot.j', \ - 'gcm_forecast.tmpl', \ - 'gcm_forecast.setup', \ - 'gcm_emip.setup', \ - 'CAP.rc.tmpl', \ - 'AGCM.rc.tmpl', \ - 'HISTORY.rc.tmpl', \ - 'logging.yaml', \ - 'fvcore_layout.rc'] +file_list = ['gcm_run.j', + 'gcm_post.j', + 'gcm_archive.j', + 'gcm_regress.j', + 'gcm_plot.tmpl', + 'gcm_quickplot.csh', + 'gcm_moveplot.j', + 'gcm_forecast.tmpl', + 'gcm_forecast.setup', + 'gcm_emip.setup', + 'CAP.rc.tmpl', + 'AGCM.rc.tmpl', + 'HISTORY.rc.tmpl', + 'logging.yaml', + 'fvcore_layout.rc'] mymodel.copy_files_into_exp(file_list) +mymodel.restarts() + diff --git a/gcmpy/scripts/ocean.py b/gcmpy/scripts/ocean.py index bf53153f..2f832bce 100644 --- a/gcmpy/scripts/ocean.py +++ b/gcmpy/scripts/ocean.py @@ -6,6 +6,7 @@ class ocean: def __init__(self): self.name = answerdict["OM_name"].q_answer self.coupled = answerdict["OM_coupled"].q_answer + self.seaice_model = answerdict["OM_seaice_model"].q_answer self.gridtype = "" self.gridtype_abrv = "" self.gridname = "" diff --git a/gcmpy/yaml/directory_setup.yaml b/gcmpy/yaml/directory_setup.yaml index c4e7456e..4edbcfe2 100644 --- a/gcmpy/yaml/directory_setup.yaml +++ b/gcmpy/yaml/directory_setup.yaml @@ -5,13 +5,6 @@ history_template: default_answer: '' follows_up: '' -home_dir: - type: 'path' - prompt: 'Enter Desired Location for the HOME Directory (to contain scripts and RC files):' - choices: '' - default_answer: '' - follows_up: '' - exp_dir: type: 'path' prompt: 'Enter Desired Location for the EXPERIMENT Directory (to contain model output and restart files):' diff --git a/gcmpy/yaml/ocean_model.yaml b/gcmpy/yaml/ocean_model.yaml index 57e321dc..91c69f32 100644 --- a/gcmpy/yaml/ocean_model.yaml +++ b/gcmpy/yaml/ocean_model.yaml @@ -63,4 +63,12 @@ OM_vertical_res: follows_up: - ['OM_MOM_horizontal_res', ['any']] - ['OM_MIT_horizontal_res', ['any']] -# ---------------------------------------------------------------------------------------------- \ No newline at end of file + +OM_seaice_model: + type: 'select' + prompt: 'Choose a seaice model:' + choices: ['CICE4', 'CICE6'] + default_answer: '' + follows_up: + - ['OM_coupled', ['True']] +# ---------------------------------------------------------------------------------------------- From 230641bc44e92aac8dc6a160674d251c476412e9 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Tue, 9 Jul 2024 10:55:04 -0400 Subject: [PATCH 10/37] stashing for a moment --- AGCM.rc.tmpl | 388 +++++++++++++------------- CAP.rc.tmpl | 12 +- HISTORY.rc.tmpl | 136 +++++----- fvcore_layout.rc | 14 +- gcm_archive.j | 22 +- gcm_emip.setup | 2 +- gcm_forecast.setup | 12 +- gcm_forecast.tmpl | 92 +++---- gcm_moveplot.j | 30 +-- gcm_plot.tmpl | 32 +-- gcm_post.j | 34 +-- gcm_regress.j | 232 ++++++++-------- gcm_run.j | 658 ++++++++++++++++++++++----------------------- gcmpy/jinjafy.py | 250 +++++++++++++++++ gcmpy/sync.sh | 5 + 15 files changed, 1087 insertions(+), 832 deletions(-) create mode 100755 gcmpy/jinjafy.py diff --git a/AGCM.rc.tmpl b/AGCM.rc.tmpl index 162aa713..49e1a345 100644 --- a/AGCM.rc.tmpl +++ b/AGCM.rc.tmpl @@ -1,54 +1,54 @@ # Atmospheric Model Configuration Parameters # ------------------------------------------ -NX: @NX -NY: @NY +NX: {{ NX }} +NY: {{ NY }} -IOSERVER_NODES: @NUM_OSERVER_NODES -NUM_BACKEND_PES: @NUM_BACKEND_PES +IOSERVER_NODES: {{ NUM_OSERVER_NODES }} +NUM_BACKEND_PES: {{ NUM_BACKEND_PES }} -AGCM_IM: @AGCM_IM -AGCM_JM: @AGCM_JM -AGCM_LM: @AGCM_LM -AGCM_GRIDNAME: @AGCM_GRIDNAME +AGCM_IM: {{ AGCM_IM }} +AGCM_JM: {{ AGCM_JM }} +AGCM_LM: {{ AGCM_LM }} +AGCM_GRIDNAME: {{ AGCM_GRIDNAME }} -AGCM.GRID_TYPE: @GRID_TYPE -AGCM.GRIDNAME: @AGCM_GRIDNAME -@CUBE_AGCM AGCM.NF: @AGCM_NF -AGCM.LM: @AGCM_LM -AGCM.IM_WORLD: @AGCM_IM -@LATLON_AGCM AGCM.JM_WORLD: @AGCM_JM +AGCM.GRID_TYPE: {{ GRID_TYPE }} +AGCM.GRIDNAME: {{ AGCM_GRIDNAME }} +{{ CUBE_AGCM }} AGCM.NF: {{ AGCM_NF }} +AGCM.LM: {{ AGCM_LM }} +AGCM.IM_WORLD: {{ AGCM_IM }} +{{ LATLON_AGCM }} AGCM.JM_WORLD: {{ AGCM_JM }} -@CONUS AGCM.STRETCH_FACTOR: @STRETCH_FACTOR -@CONUS AGCM.TARGET_LAT: 39.5 -@CONUS AGCM.TARGET_LON: -98.35 +{{ CONUS }} AGCM.STRETCH_FACTOR: {{ STRETCH_FACTOR }} +{{ CONUS }} AGCM.TARGET_LAT: 39.5 +{{ CONUS }} AGCM.TARGET_LON: -98.35 ########################################################### # long physics DT options # ---------------------------------------- ADJUST_DT: .FALSE. CHEMISTRY_RUN_AT_INTERVAL_START: .TRUE. -CHEMISTRY_DT: @LONG_DT -GOCART_DT: @LONG_DT -HEMCO_DT: @LONG_DT -GF_DT: @LONG_DT -UW_DT: @LONG_DT +CHEMISTRY_DT: {{ LONG_DT }} +GOCART_DT: {{ LONG_DT }} +HEMCO_DT: {{ LONG_DT }} +GF_DT: {{ LONG_DT }} +UW_DT: {{ LONG_DT }} ########################################################### ########################################################### # dynamics options # ---------------------------------------- -DYCORE: @DYCORE -@FV_HWT FV3_CONFIG: HWT +DYCORE: {{ DYCORE }} +{{ FV_HWT }} FV3_CONFIG: HWT AdvCore_Advection: 0 ########################################################### ########################################################### # radiation options # ---------------------------------------- - SOLAR_DT: @SOLAR_DT - IRRAD_DT: @IRRAD_DT -SATSIM_DT: @IRRAD_DT + SOLAR_DT: {{ SOLAR_DT }} + IRRAD_DT: {{ IRRAD_DT }} +SATSIM_DT: {{ IRRAD_DT }} SOLARAvrg: 0 IRRADAvrg: 0 EOT: .TRUE. @@ -58,21 +58,21 @@ ORBIT_ANAL2B: .TRUE. ########################################################### # BACM_1M microphysics options # ---------------------------------------- -@BACM_1M_CLDMICR_OPTION: BACM_1M +{{ BACM_1M_ }}CLDMICR_OPTION: BACM_1M ########################################################### ########################################################### # GFDL_1M microphysics options # ---------------------------------------- -@GFDL_1M_CLDMICR_OPTION: GFDL_1M -@GFDL_1M_HYDROSTATIC: @GFDL_HYDRO +{{ GFDL_1M_ }}CLDMICR_OPTION: GFDL_1M +{{ GFDL_1M_ }}HYDROSTATIC: {{ GFDL_HYDRO }} ########################################################### ########################################################### # MGB2_2M microphysics options # ---------------------------------------- -@MGB2_2M_CLDMICR_OPTION: MGB2_2M -@MGB2_2M_MGVERSION: @MGVERSION +{{ MGB2_2M_ }}CLDMICR_OPTION: MGB2_2M +{{ MGB2_2M_ }}MGVERSION: @MGVERSION ########################################################### ########################################################### @@ -84,7 +84,7 @@ SHALLOW_OPTION: UW ########################################################### # convection scheme options # ---------------------------------------- -CONVPAR_OPTION: @CONVPAR_OPTION +CONVPAR_OPTION: {{ CONVPAR_OPTION }} #USE_GF2020: 1 # Convective plumes to be activated (1 true, 0 false) DEEP: 1 @@ -102,42 +102,42 @@ CLOSURE_CONGESTUS: 3 ########################################################### # TRB/GWD Parameterization # ------------------------ -@FV_HWT RAYLEIGH_TAU1: 0.0 +{{ FV_HWT }} RAYLEIGH_TAU1: 0.0 ########################################################### -@HIST_GOCART########################################################### -@HIST_GOCART# Enable wet scavenging -@HIST_GOCART# NOTE: this section should be commented out when running gocart.data -@HIST_GOCARTMCHEMTRI_increments:: -@HIST_GOCARTDU::DU default -@HIST_GOCARTSS::SS default -@HIST_GOCARTSU::SO4 default -@HIST_GOCARTCA.bc::CA.bcphilic default -@HIST_GOCARTCA.br::CA.brphilic default -@HIST_GOCARTCA.oc::CA.ocphilic default -@HIST_GOCARTNI::NO3an1 "NI::NO3an2,NI::NO3an3" -@HIST_GOCARTPCHEM::OX default -@HIST_GOCART:: -@HIST_GOCART########################################################### + {{ HIST_GOCART }}########################################################### + {{ HIST_GOCART }}# Enable wet scavenging + {{ HIST_GOCART }}# NOTE: this section should be commented out when running gocart.data + {{ HIST_GOCART }}MCHEMTRI_increments:: + {{ HIST_GOCART }}DU::DU default + {{ HIST_GOCART }}SS::SS default + {{ HIST_GOCART }}SU::SO4 default + {{ HIST_GOCART }}CA.bc::CA.bcphilic default + {{ HIST_GOCART }}CA.br::CA.brphilic default + {{ HIST_GOCART }}CA.oc::CA.ocphilic default + {{ HIST_GOCART }}NI::NO3an1 "NI::NO3an2,NI::NO3an3" + {{ HIST_GOCART }}PCHEM::OX default + {{ HIST_GOCART }}:: + {{ HIST_GOCART }}########################################################### ########################################################### # Ocean Model Configuration Parameters # ------------------------------------ -OGCM.GRID_TYPE: @OGCM_GRID_TYPE -OGCM.GRIDNAME: @OGCM_GRIDNAME -OGCM.IM_WORLD: @OGCM_IM -OGCM.JM_WORLD: @OGCM_JM -OGCM.LM: @OGCM_LM -@COUPLED OGCM.NX: @OGCM_NX -@COUPLED OGCM.NY: @OGCM_NY -@MOM5 OGCM.GRIDSPEC: MAPL_Tripolar.nc -@MOM6 OGCM.GRIDSPEC: MAPL_Tripolar.nc -@MIT OGCM.GRIDSPEC: mit.ascii -@MIT OCEAN_DIR: mitocean_run -@DATAOCEAN @LATLON_OGCM OGCM.POLE: 'PE' -@DATAOCEAN @LATLON_OGCM OGCM.DATELINE: 'DE' -@DATAOCEAN @CUBE_OGCM OGCM.NF: @OGCM_NF -OGCM_RUN_DT: @OCEAN_DT +OGCM.GRID_TYPE: {{ OGCM_GRID_TYPE }} +OGCM.GRIDNAME: {{ OGCM_GRIDNAME }} +OGCM.IM_WORLD: {{ OGCM_IM }} +OGCM.JM_WORLD: {{ OGCM_JM }} +OGCM.LM: {{ OGCM_LM }} +{{ COUPLED }} OGCM.NX: {{ OGCM_NX }} +{{ COUPLED }} OGCM.NY: {{ OGCM_NY }} +{{ MOM5 }} OGCM.GRIDSPEC: MAPL_Tripolar.nc +{{ MOM6 }} OGCM.GRIDSPEC: MAPL_Tripolar.nc +{{ MIT }} OGCM.GRIDSPEC: mit.ascii +{{ MIT }} OCEAN_DIR: mitocean_run +{{ DATAOCEAN }} {{ LATLON_OGCM }} OGCM.POLE: 'PE' +{{ DATAOCEAN }} {{ LATLON_OGCM }} OGCM.DATELINE: 'DE' +{{ DATAOCEAN }} {{ CUBE_OGCM }} OGCM.NF: {{ OGCM_NF }} +OGCM_RUN_DT: {{ OCEAN_DT }} ########################################################### ############################################################################################## #### #### @@ -165,7 +165,7 @@ PRINTRC: 1 #--------------------------------------------------------------- PARALLEL_READFORCING: 0 # The num_readers should be set to multiple of 6 if READ_RESTART_BY_FACE is set to YES -NUM_READERS: @NUM_READERS +NUM_READERS: {{ NUM_READERS }} # The num_writers should be set to multiple of 6 if WRITE_RESTART_BY_FACE is set to YES NUM_WRITERS: 1 @@ -176,16 +176,16 @@ READ_RESTART_BY_FACE: NO WRITE_RESTART_BY_FACE: NO # Write restarts by oserver (Default: NO) -WRITE_RESTART_BY_OSERVER: @RESTART_BY_OSERVER +WRITE_RESTART_BY_OSERVER: {{ RESTART_BY_OSERVER }} # Active observer when desired # ---------------------------- -BKG_FREQUENCY: @OBSERVER_FRQ +BKG_FREQUENCY: {{ OBSERVER_FRQ }} # Resolution of state passed to atmos analysis # -------------------------------------------- -ANA_GRIDNAME: PC@AGCM_IMx@AGCM_JM-DC -ANA_LM: @AGCM_LM +ANA_GRIDNAME: PC{{ AGCM_IM }}x{{ AGCM_JM }}-DC +ANA_LM: {{ AGCM_LM }} # Restart Record Parameters # ------------------------- @@ -317,7 +317,7 @@ RECORD_REF_TIME: >>>REFTIME<<< >>>FCSTIME<<< # Typical MERRA-2 Regular REPLAY Configuration # -------------------------------------------- #M2 REPLAY_ANA_EXPID: MERRA-2 -#M2 REPLAY_ANA_LOCATION: @M2_REPLAY_ANA_LOCATION +#M2 REPLAY_ANA_LOCATION: {{ M2_REPLAY_ANA_LOCATION }} #M2 REPLAY_MODE: Regular #M2 REPLAY_FILE: ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4 # ----------------------------------------------------------------- @@ -345,23 +345,23 @@ RECORD_REF_TIME: >>>REFTIME<<< >>>FCSTIME<<< # Typical Exact REPLAY Configuration # ---------------------------------- # REPLAY_MODE: Exact -# REPLAY_FILE: rs/Y%y4/M%m2/@REPLAY_ANA_EXPID.agcm_import_rst.%y4%m2%d2_%h2z.bin -# REPLAY_FILE09: rs/Y%y4/M%m2/@REPLAY_ANA_EXPID.agcm09_import_rst.%y4%m2%d2_%h2z.bin +# REPLAY_FILE: rs/Y%y4/M%m2/{{ REPLAY_ANA_EXPID }}.agcm_import_rst.%y4%m2%d2_%h2z.bin +# REPLAY_FILE09: rs/Y%y4/M%m2/{{ REPLAY_ANA_EXPID }}.agcm09_import_rst.%y4%m2%d2_%h2z.bin # REPLAY_FILE_FREQUENCY: 10800 # REPLAY_FILE_REFERENCE_TIME: 000000 # Typical Regular REPLAY Configuration # ------------------------------------ # REPLAY_MODE: Regular -# REPLAY_FILE: ana/Y%y4/M%m2/@REPLAY_ANA_EXPID.ana.eta.%y4%m2%d2_%h2z.nc4 -# REPLAY_FILE09: ana/Y%y4/M%m2/@REPLAY_ANA_EXPID.ana09.eta.%y4%m2%d2_%h2z.nc4 +# REPLAY_FILE: ana/Y%y4/M%m2/{{ REPLAY_ANA_EXPID }}.ana.eta.%y4%m2%d2_%h2z.nc4 +# REPLAY_FILE09: ana/Y%y4/M%m2/{{ REPLAY_ANA_EXPID }}.ana09.eta.%y4%m2%d2_%h2z.nc4 # REPLAY_FILE_FREQUENCY: 10800 # REPLAY_FILE_REFERENCE_TIME: 000000 # 4DIAU (recreate analysis tendency on the fly) # --------------------------------------------- -#>>>4DIAUDAS<<< AINC_FILE: @EXPID.ana.eta.%y4%m2%d2_%h2%n2z.nc4 +#>>>4DIAUDAS<<< AINC_FILE: {{ EXPID }}.ana.eta.%y4%m2%d2_%h2%n2z.nc4 #>>>4DIAUDAS<<< NUDGE_STATE: YES ##>>>4DIAUDAS<<< TAUANL: 3600 #>>>4DIAUDAS<<< AGCM_IMPORT_RESTART_FILE: agcm_import_rst.>>>ANA0YYYYMMDDHHMN<<>>REFTIME<<< >>>FCSTIME<<< # 1 : Catchment # 2 : CatchmentCNCLM40 # ------------------------------------------------------------ -LSM_CHOICE: @LSM_CHOICE +LSM_CHOICE: {{ LSM_CHOICE }} # Apply increments from LDAS? # 0 : no (default) @@ -570,227 +570,227 @@ LSM_CHOICE: @LSM_CHOICE >>>FORCEGCM<<>>FORCEGCM<<>>FORCEGCM<<>>FORCEGCM<<>>FORCEGCM<<>>FORCEGCM<<>>NCSUFFIX<<<' , inst3_3d_asm_Np-.mode: 'instantaneous' , - inst3_3d_asm_Np-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_3d_asm_Np-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_3d_asm_Np-.frequency: 030000 , inst3_3d_asm_Np-.duration: 030000 , inst3_3d_asm_Np-.end_date: >>>IOEDATE<<< , @@ -209,7 +209,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_3d_asm_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , inst3_3d_asm_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst3_3d_asm_Nv-.mode: 'instantaneous' , - inst3_3d_asm_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_3d_asm_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_3d_asm_Nv-.frequency: 030000 , inst3_3d_asm_Nv-.duration: 030000 , inst3_3d_asm_Nv-.end_date: >>>IOEDATE<<< , @@ -240,7 +240,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst1_2d_asm_Nx-.regrid_method: 'BILINEAR_MONOTONIC' , inst1_2d_asm_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst1_2d_asm_Nx-.mode: 'instantaneous' , - inst1_2d_asm_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst1_2d_asm_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst1_2d_asm_Nx-.frequency: 010000 , inst1_2d_asm_Nx-.duration: 010000 , inst1_2d_asm_Nx-.end_date: >>>IOEDATE<<< , @@ -283,7 +283,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_cld_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_cld_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_cld_Nv-.mode: 'time-averaged' , - tavg3_3d_cld_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_cld_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_cld_Nv-.frequency: 030000 , tavg3_3d_cld_Nv-.duration: 030000 , tavg3_3d_cld_Nv-.end_date: >>>IOEDATE<<< , @@ -340,7 +340,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_mst_Ne-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_mst_Ne-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_mst_Ne-.mode: 'time-averaged' , - tavg3_3d_mst_Ne-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_mst_Ne-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_mst_Ne-.frequency: 030000 , tavg3_3d_mst_Ne-.duration: 030000 , tavg3_3d_mst_Ne-.end_date: >>>IOEDATE<<< , @@ -361,7 +361,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_mst_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_mst_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_mst_Nv-.mode: 'time-averaged' , - tavg3_3d_mst_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_mst_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_mst_Nv-.frequency: 030000 , tavg3_3d_mst_Nv-.duration: 030000 , tavg3_3d_mst_Nv-.end_date: >>>IOEDATE<<< , @@ -419,7 +419,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_rad_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_rad_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_rad_Nv-.mode: 'time-averaged' , - tavg3_3d_rad_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_rad_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_rad_Nv-.frequency: 030000 , tavg3_3d_rad_Nv-.duration: 030000 , tavg3_3d_rad_Nv-.end_date: >>>IOEDATE<<< , @@ -463,7 +463,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_trb_Ne-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_trb_Ne-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_trb_Ne-.mode: 'time-averaged' , - tavg3_3d_trb_Ne-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_trb_Ne-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_trb_Ne-.frequency: 030000 , tavg3_3d_trb_Ne-.duration: 030000 , tavg3_3d_trb_Ne-.end_date: >>>IOEDATE<<< , @@ -519,7 +519,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_tdt_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_tdt_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_tdt_Nv-.mode: 'time-averaged' , - tavg3_3d_tdt_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_tdt_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_tdt_Nv-.frequency: 030000 , tavg3_3d_tdt_Nv-.duration: 030000 , tavg3_3d_tdt_Nv-.end_date: >>>IOEDATE<<< , @@ -573,7 +573,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_udt_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_udt_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_udt_Nv-.mode: 'time-averaged' , - tavg3_3d_udt_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_udt_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_udt_Nv-.frequency: 030000 , tavg3_3d_udt_Nv-.duration: 030000 , tavg3_3d_udt_Nv-.end_date: >>>IOEDATE<<< , @@ -621,7 +621,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_qdt_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_qdt_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_qdt_Nv-.mode: 'time-averaged' , - tavg3_3d_qdt_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_qdt_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_qdt_Nv-.frequency: 030000 , tavg3_3d_qdt_Nv-.duration: 030000 , tavg3_3d_qdt_Nv-.end_date: >>>IOEDATE<<< , @@ -679,7 +679,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_odt_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_odt_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_odt_Nv-.mode: 'time-averaged' , - tavg3_3d_odt_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_odt_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_odt_Nv-.frequency: 030000 , tavg3_3d_odt_Nv-.duration: 030000 , tavg3_3d_odt_Nv-.end_date: >>>IOEDATE<<< , @@ -725,7 +725,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_lsf_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_lsf_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_lsf_Nv-.mode: 'time-averaged' , - tavg3_3d_lsf_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_lsf_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_lsf_Nv-.frequency: 030000 , tavg3_3d_lsf_Nv-.duration: 030000 , tavg3_3d_lsf_Nv-.end_date: >>>IOEDATE<<< , @@ -743,7 +743,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_lsf_Ne-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_lsf_Ne-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_lsf_Ne-.mode: 'time-averaged' , - tavg3_3d_lsf_Ne-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_lsf_Ne-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_lsf_Ne-.frequency: 030000 , tavg3_3d_lsf_Ne-.duration: 030000 , tavg3_3d_lsf_Ne-.end_date: >>>IOEDATE<<< , @@ -759,7 +759,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_slv_Nx-.regrid_method: 'BILINEAR_MONOTONIC' , tavg1_2d_slv_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_slv_Nx-.mode: 'time-averaged' , - tavg1_2d_slv_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_slv_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_slv_Nx-.frequency: 010000 , tavg1_2d_slv_Nx-.duration: 010000 , tavg1_2d_slv_Nx-.end_date: >>>IOEDATE<<< , @@ -811,7 +811,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_flx_Nx-.regrid_method: 'BILINEAR_MONOTONIC' , tavg1_2d_flx_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_flx_Nx-.mode: 'time-averaged' , - tavg1_2d_flx_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_flx_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_flx_Nx-.frequency: 010000 , tavg1_2d_flx_Nx-.duration: 010000 , tavg1_2d_flx_Nx-.end_date: >>>IOEDATE<<< , @@ -869,7 +869,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_rad_Nx-.regrid_method: 'BILINEAR_MONOTONIC' , tavg1_2d_rad_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_rad_Nx-.mode: 'time-averaged' , - tavg1_2d_rad_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_rad_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_rad_Nx-.frequency: 010000 , tavg1_2d_rad_Nx-.duration: 010000 , tavg1_2d_rad_Nx-.end_date: >>>IOEDATE<<< , @@ -918,7 +918,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_lnd_Nx-.descr: '2d,1-Hourly,Time-Averaged,Single-Level,Assimilation,Land Surface Diagnostics' , tavg1_2d_lnd_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_lnd_Nx-.mode: 'time-averaged' , - tavg1_2d_lnd_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_lnd_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_lnd_Nx-.frequency: 010000 , tavg1_2d_lnd_Nx-.duration: 010000 , tavg1_2d_lnd_Nx-.end_date: >>>IOEDATE<<< , @@ -980,7 +980,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' # tavg1_2d_lfo_Nx-.nbits: 10, tavg1_2d_lfo_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_lfo_Nx-.mode: 'time-averaged' , - tavg1_2d_lfo_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_lfo_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_lfo_Nx-.frequency: 010000 , tavg1_2d_lfo_Nx-.duration: 010000 , tavg1_2d_lfo_Nx-.end_date: >>>IOEDATE<<< , @@ -1000,7 +1000,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' # inst1_2d_lfo_Nx-.nbits: 10, inst1_2d_lfo_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst1_2d_lfo_Nx-.mode: 'instantaneous' , - inst1_2d_lfo_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst1_2d_lfo_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst1_2d_lfo_Nx-.frequency: 010000 , inst1_2d_lfo_Nx-.duration: 010000 , inst1_2d_lfo_Nx-.end_date: >>>IOEDATE<<< , @@ -1019,7 +1019,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_ocn_Nx-.regrid_method: 'BILINEAR_MONOTONIC' , tavg1_2d_ocn_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_ocn_Nx-.mode: 'time-averaged' , - tavg1_2d_ocn_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_ocn_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_ocn_Nx-.frequency: 010000 , tavg1_2d_ocn_Nx-.duration: 010000 , tavg1_2d_ocn_Nx-.end_date: >>>IOEDATE<<< , @@ -1077,7 +1077,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst1_2d_ocn_Nx-.regrid_method: 'BILINEAR_MONOTONIC' , inst1_2d_ocn_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst1_2d_ocn_Nx-.mode: 'instantaneous' , - inst1_2d_ocn_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst1_2d_ocn_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst1_2d_ocn_Nx-.frequency: 010000 , inst1_2d_ocn_Nx-.duration: 010000 , inst1_2d_ocn_Nx-.end_date: >>>IOEDATE<<< , @@ -1298,7 +1298,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' gaas_bkg.sfc.frequency: 030000 , gaas_bkg.sfc.duration: 030000 , gaas_bkg.sfc.mode: 'instantaneous' , - gaas_bkg.sfc.grid_label: PC@HIST_IMx@HIST_JM-DC , + gaas_bkg.sfc.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , gaas_bkg.sfc.fields: 'U10M;V10M' , 'SURFACE' , 'DUEXTTAU' , 'DU' , 'SSEXTTAU' , 'SS' , @@ -1320,7 +1320,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_2d_gas_Nx-.frequency: 030000 , inst3_2d_gas_Nx-.duration: 030000 , inst3_2d_gas_Nx-.mode: 'instantaneous' , - inst3_2d_gas_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_2d_gas_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_2d_gas_Nx-.fields: 'AODANA' , 'GAAS' , 'AODINC' , 'GAAS' , :: @@ -1338,7 +1338,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_3d_gas_Nv-.frequency: 030000 , inst3_3d_gas_Nv-.duration: 030000 , inst3_3d_gas_Nv-.mode: 'instantaneous' , - inst3_3d_gas_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_3d_gas_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_3d_gas_Nv-.fields: 'DELP' , 'DYN' , 'delp' , 'AIRDENS' , 'CHEMENV' , 'DUINC' , 'GAAS' , @@ -1354,7 +1354,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst1_2d_aer_Nx-.descr: '2d,1-Hourly,Instantaneous,Single-Level,Analysis,Aerosol Diagnostics' , inst1_2d_aer_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst1_2d_aer_Nx-.mode: 'instantaneous' , - inst1_2d_aer_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst1_2d_aer_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst1_2d_aer_Nx-.conservative: 1 , inst1_2d_aer_Nx-.splitField: 1 , inst1_2d_aer_Nx-.frequency: 010000 , @@ -1467,7 +1467,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_adg_Nx-.descr: '2d,1-Hourly,Time-Averaged,Single-Level,Analysis,Aerosol Diagnostics (extended)' , tavg1_2d_adg_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_adg_Nx-.mode: 'time-averaged' , - tavg1_2d_adg_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_adg_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_adg_Nx-.frequency: 010000 , tavg1_2d_adg_Nx-.duration: 010000 , tavg1_2d_adg_Nx-.end_date: >>>IOEDATE<<< , @@ -1557,7 +1557,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_2d_chm_Nx-.descr: '2d,3-Hourly,Time-Averaged,Single-Level,Analysis,Constituent Diagnostics' , tavg3_2d_chm_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_2d_chm_Nx-.mode: 'time-averaged' , - tavg3_2d_chm_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_2d_chm_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_2d_chm_Nx-.frequency: 030000 , tavg3_2d_chm_Nx-.duration: 030000 , tavg3_2d_chm_Nx-.end_date: >>>IOEDATE<<< , @@ -1584,7 +1584,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst1_2d_hwl_Nx-.descr: '2d,1-Hourly,Instantaneous,Single-Level,Analysis,Hyperwall' , inst1_2d_hwl_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst1_2d_hwl_Nx-.mode: 'instantaneous' , - inst1_2d_hwl_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst1_2d_hwl_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst1_2d_hwl_Nx-.splitField: 1 , inst1_2d_hwl_Nx-.frequency: 010000 , inst1_2d_hwl_Nx-.duration: 010000 , @@ -1602,7 +1602,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_3d_aer_Nv-.descr: '3d,3-Hourly,Instantaneous,Model-Level,Analysis,Aerosol Concentrations' , inst3_3d_aer_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst3_3d_aer_Nv-.mode: 'instantaneous' , - inst3_3d_aer_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_3d_aer_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_3d_aer_Nv-.frequency: 030000 , inst3_3d_aer_Nv-.duration: 030000 , inst3_3d_aer_Nv-.ref_time: 000000 , @@ -1655,7 +1655,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_3d_chm_Nv-.descr: '3d,3-Hourly,Instantaneous,Model-Level,Analysis,Chemistry' , inst3_3d_chm_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst3_3d_chm_Nv-.mode: 'instantaneous' , - inst3_3d_chm_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_3d_chm_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_3d_chm_Nv-.frequency: 030000 , inst3_3d_chm_Nv-.duration: 030000 , inst3_3d_chm_Nv-.ref_time: 000000 , @@ -1675,7 +1675,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_3d_tag_Nv-.descr: '3d,3-Hourly,Instantaneous,Model-Level,Analysis,Tag Tracers' , inst3_3d_tag_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst3_3d_tag_Nv-.mode: 'instantaneous' , - inst3_3d_tag_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_3d_tag_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_3d_tag_Nv-.frequency: 030000 , inst3_3d_tag_Nv-.duration: 030000 , inst3_3d_tag_Nv-.ref_time: 000000 , @@ -1704,7 +1704,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_2d_tag_Nx-.descr: '2d,3-Hourly,Time-Averaged,Single-Level,Analysis,Constituent Diagnostics' , tavg3_2d_tag_Nx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_2d_tag_Nx-.mode: 'time-averaged' , - tavg3_2d_tag_Nx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_2d_tag_Nx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_2d_tag_Nx-.frequency: 030000 , tavg3_2d_tag_Nx-.duration: 030000 , tavg3_2d_tag_Nx-.end_date: >>>IOEDATE<<< , @@ -1773,7 +1773,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_ctm_Cv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_ctm_Cv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_ctm_Cv-.mode: 'time-averaged' , - tavg3_3d_ctm_Cv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_ctm_Cv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_ctm_Cv-.frequency: 030000 , tavg3_3d_ctm_Cv-.duration: 030000 , tavg3_3d_ctm_Cv-.end_date: >>>IOEDATE<<< , @@ -1804,7 +1804,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_ctm_Ce-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_ctm_Ce-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_ctm_Ce-.mode: 'time-averaged' , - tavg3_3d_ctm_Ce-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_ctm_Ce-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_ctm_Ce-.frequency: 030000 , tavg3_3d_ctm_Ce-.duration: 030000 , tavg3_3d_ctm_Ce-.end_date: >>>IOEDATE<<< , @@ -1825,7 +1825,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_2d_ctm_Cx-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_2d_ctm_Cx-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_2d_ctm_Cx-.mode: 'time-averaged' , - tavg3_2d_ctm_Cx-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_2d_ctm_Cx-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_2d_ctm_Cx-.frequency: 030000 , tavg3_2d_ctm_Cx-.duration: 030000 , tavg3_2d_ctm_Cx-.end_date: >>>IOEDATE<<< , @@ -1869,7 +1869,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_nav_Nv-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_nav_Nv-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_nav_Nv-.mode: 'time-averaged' , - tavg3_3d_nav_Nv-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_nav_Nv-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_nav_Nv-.frequency: 030000 , tavg3_3d_nav_Nv-.duration: 030000 , tavg3_3d_nav_Nv-.end_date: >>>IOEDATE<<< , @@ -1885,7 +1885,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_nav_Ne-.regrid_method: 'BILINEAR_MONOTONIC' , tavg3_3d_nav_Ne-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg3_3d_nav_Ne-.mode: 'time-averaged' , - tavg3_3d_nav_Ne-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_nav_Ne-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_nav_Ne-.frequency: 030000 , tavg3_3d_nav_Ne-.duration: 030000 , tavg3_3d_nav_Ne-.end_date: >>>IOEDATE<<< , @@ -1900,7 +1900,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_trc_Np-.frequency: 030000 , tavg3_3d_trc_Np-.duration: 030000 , tavg3_3d_trc_Np-.mode: 'time-averaged' , - tavg3_3d_trc_Np-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_trc_Np-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_trc_Np-.vscale: 100.0 , tavg3_3d_trc_Np-.vunit: 'hPa' , tavg3_3d_trc_Np-.vvars: 'log(PLE)' , 'DYN' , @@ -1926,7 +1926,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' vtx.mix.end_date: >>>IOEBKGD<<< , vtx.mix.end_time: >>>IOEBKGT<<< , vtx.mix.mode: 'instantaneous' , - vtx.mix.grid_label: PC@HIST_IMx@HIST_JM-DC , + vtx.mix.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , vtx.mix.fields: 'PHIS' , 'AGCM' , 'SLP' , 'DYN' , 'PS' , 'DYN' , @@ -1953,7 +1953,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' vtx.prs.end_date: >>>IOEBKGD<<< , vtx.prs.end_time: >>>IOEBKGT<<< , vtx.prs.mode: 'instantaneous' , - vtx.prs.grid_label: PC@HIST_IMx@HIST_JM-DC , + vtx.prs.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , vtx.prs.vscale: 100.0 , vtx.prs.vunit: 'hPa' , vtx.prs.vvars: 'log(PLE)' , 'DYN' , @@ -2032,7 +2032,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg2_3d_aiau_Np+-.regrid_method: 'BILINEAR_MONOTONIC' , tavg2_3d_aiau_Np+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg2_3d_aiau_Np+-.mode: 'time-averaged' , - tavg2_3d_aiau_Np+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg2_3d_aiau_Np+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg2_3d_aiau_Np+-.frequency: 020000 , tavg2_3d_aiau_Np+-.duration: 020000 , tavg2_3d_aiau_Np+-.reftime: 010000 , @@ -2069,7 +2069,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_3d_asm_Np+-.regrid_method: 'BILINEAR_MONOTONIC' , inst3_3d_asm_Np+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst3_3d_asm_Np+-.mode: 'instantaneous' , - inst3_3d_asm_Np+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_3d_asm_Np+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_3d_asm_Np+-.frequency: 030000 , inst3_3d_asm_Np+-.duration: 030000 , inst3_3d_asm_Np+-.ref_date: >>>IOBBKGD<<< , @@ -2104,7 +2104,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_3d_asm_Nv+-.regrid_method: 'BILINEAR_MONOTONIC' , inst3_3d_asm_Nv+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst3_3d_asm_Nv+-.mode: 'instantaneous' , - inst3_3d_asm_Nv+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_3d_asm_Nv+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_3d_asm_Nv+-.frequency: 030000 , inst3_3d_asm_Nv+-.duration: 030000 , inst3_3d_asm_Nv+-.ref_date: >>>IOBBKGD<<< , @@ -2135,7 +2135,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_slv_Nx+-.regrid_method: 'BILINEAR_MONOTONIC' , tavg1_2d_slv_Nx+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_slv_Nx+-.mode: 'time-averaged' , - tavg1_2d_slv_Nx+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_slv_Nx+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_slv_Nx+-.frequency: 010000 , tavg1_2d_slv_Nx+-.duration: 010000 , tavg1_2d_slv_Nx+-.ref_date: >>>IOBBKGD<<< , @@ -2185,7 +2185,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_flx_Nx+-.regrid_method: 'BILINEAR_MONOTONIC' , tavg1_2d_flx_Nx+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_flx_Nx+-.mode: 'time-averaged' , - tavg1_2d_flx_Nx+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_flx_Nx+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_flx_Nx+-.frequency: 010000 , tavg1_2d_flx_Nx+-.duration: 010000 , tavg1_2d_flx_Nx+-.ref_date: >>>IOBBKGD<<< , @@ -2235,7 +2235,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_lnd_Nx+-.descr: '2d,1-Hourly,Time-Averaged,Single-Level,Forecast,Land Surface Diagnostics' , tavg1_2d_lnd_Nx+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_lnd_Nx+-.mode: 'time-averaged' , - tavg1_2d_lnd_Nx+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_lnd_Nx+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_lnd_Nx+-.frequency: 010000 , tavg1_2d_lnd_Nx+-.duration: 010000 , tavg1_2d_lnd_Nx+-.ref_date: >>>IOBBKGD<<< , @@ -2299,7 +2299,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg1_2d_rad_Nx+-.regrid_method: 'BILINEAR_MONOTONIC' , tavg1_2d_rad_Nx+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , tavg1_2d_rad_Nx+-.mode: 'time-averaged' , - tavg1_2d_rad_Nx+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg1_2d_rad_Nx+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg1_2d_rad_Nx+-.frequency: 010000 , tavg1_2d_rad_Nx+-.duration: 010000 , tavg1_2d_rad_Nx+-.ref_date: >>>IOBBKGD<<< , @@ -2351,7 +2351,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst3_2d_met_Nx+-.regrid_method: 'BILINEAR_MONOTONIC' , inst3_2d_met_Nx+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , inst3_2d_met_Nx+-.mode: 'instantaneous' , - inst3_2d_met_Nx+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst3_2d_met_Nx+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst3_2d_met_Nx+-.frequency: 030000 , inst3_2d_met_Nx+-.duration: 030000 , inst3_2d_met_Nx+-.ref_date: >>>IOBBKGD<<< , @@ -2492,7 +2492,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_ext_Np+-.frequency: 030000 , tavg3_3d_ext_Np+-.duration: 030000 , tavg3_3d_ext_Np+-.mode: 'time-averaged' , - tavg3_3d_ext_Np+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_ext_Np+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_ext_Np+-.splitField: 1 , tavg3_3d_ext_Np+-.conservative: 1 , tavg3_3d_ext_Np+-.vscale: 100.0 , @@ -2527,7 +2527,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_aer_Np+-.frequency: 030000 , tavg3_3d_aer_Np+-.duration: 030000 , tavg3_3d_aer_Np+-.mode: 'time-averaged' , - tavg3_3d_aer_Np+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_aer_Np+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_aer_Np+-.splitField: 1 , tavg3_3d_aer_Np+-.conservative: 1 , tavg3_3d_aer_Np+-.vscale: 100.0 , @@ -2552,7 +2552,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_chm_Np+-.frequency: 030000 , tavg3_3d_chm_Np+-.duration: 030000 , tavg3_3d_chm_Np+-.mode: 'time-averaged' , - tavg3_3d_chm_Np+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_chm_Np+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_chm_Np+-.vscale: 100.0 , tavg3_3d_chm_Np+-.vunit: 'hPa' , tavg3_3d_chm_Np+-.vvars: 'log(PLE)' , 'DYN' , @@ -2574,7 +2574,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' tavg3_3d_tag_Np+-.frequency: 030000 , tavg3_3d_tag_Np+-.duration: 030000 , tavg3_3d_tag_Np+-.mode: 'time-averaged' , - tavg3_3d_tag_Np+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + tavg3_3d_tag_Np+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , tavg3_3d_tag_Np+-.vscale: 100.0 , tavg3_3d_tag_Np+-.vunit: 'hPa' , tavg3_3d_tag_Np+-.vvars: 'log(PLE)' , 'DYN' , @@ -2606,7 +2606,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' inst1_2d_hwl_Nx+-.deflate: 2 , inst1_2d_hwl_Nx+-.regrid_method: 'BILINEAR_MONOTONIC' , inst1_2d_hwl_Nx+-.mode: 'instantaneous' , - inst1_2d_hwl_Nx+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + inst1_2d_hwl_Nx+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , inst1_2d_hwl_Nx+-.splitField: 1 , inst1_2d_hwl_Nx+-.frequency: 010000 , inst1_2d_hwl_Nx+-.duration: 010000 , @@ -2638,7 +2638,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' prog.eta+-.frequency: 060000 , prog.eta+-.duration: 060000 , prog.eta+-.mode: 'instantaneous' , - prog.eta+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + prog.eta+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , prog.eta+-.fields: 'PHIS' , 'AGCM' , 'phis' , 'SGH' , 'AGCM' , 'hs_stdv' , 'PS' , 'DYN' , 'ps' , @@ -2666,7 +2666,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' prog.sfc+-.frequency: 060000 , prog.sfc+-.duration: 060000 , prog.sfc+-.mode: 'instantaneous' , - prog.sfc+-.grid_label: PC@HIST_IMx@HIST_JM-DC , + prog.sfc+-.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , prog.sfc+-.fields: 'PHIS' , 'AGCM' , 'US;VS' , 'DYN' , 'UA;VA' , 'TA' , 'DYN' , @@ -2716,7 +2716,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' const_2d_asm_Nx.format: 'CFIO' , const_2d_asm_Nx.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , const_2d_asm_Nx.mode: 'instantaneous' , - const_2d_asm_Nx.grid_label: PC@HIST_IMx@HIST_JM-DC , + const_2d_asm_Nx.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , const_2d_asm_Nx.frequency: 240000 , const_2d_asm_Nx.duration: 240000 , const_2d_asm_Nx.ref_time: >>>IOBBKGT<<< , @@ -2744,7 +2744,7 @@ COLLECTIONS: 'inst3_3d_asm_Np-' asm.eta.frequency: @ASYNFRQ , asm.eta.duration: @ASYNFRQ , asm.eta.mode: 'instantaneous' , - asm.eta.grid_label: PC@HIST_IMx@HIST_JM-DC , + asm.eta.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , asm.eta.fields: 'PHIS' , 'AGCM' , 'phis' , 'SGH' , 'AGCM' , 'hs_stdv' , 'TS' , 'SURFACE' , 'ts' , diff --git a/fvcore_layout.rc b/fvcore_layout.rc index fec5a2e9..398dd8b5 100644 --- a/fvcore_layout.rc +++ b/fvcore_layout.rc @@ -1,11 +1,11 @@ &fv_core_nml - @FV_HYDRO + {{ FV_HYDRO }} range_warn = .T. fv_debug = .F. - @FV_SCHMIDT - @FV_STRETCH_FAC - @FV_TARGET_LON - @FV_TARGET_LAT + {{ FV_SCHMIDT }} + {{ FV_STRETCH_FAC }} + {{ FV_TARGET_LON }} + {{ FV_TARGET_LAT }} compute_coords_locally = .false. / @@ -47,8 +47,8 @@ c_pgacs = 0.01 c_paut = 1.0 c_cracw = 1.0 - @GFDL_PROG_CCN - @GFDL_USE_CCN + {{ GFDL_PROG_CCN }} + {{ GFDL_USE_CCN }} ccn_l = 300. ccn_o = 100. z_slope_liq = .true. diff --git a/gcm_archive.j b/gcm_archive.j index a4a8ffcb..d48272dd 100644 --- a/gcm_archive.j +++ b/gcm_archive.j @@ -4,12 +4,12 @@ # Batch Parameters for Archive Job ####################################################################### -#@BATCH_TIME@ARCHIVE_T -#@ARCHIVE_P -#@BATCH_JOBNAME@ARCHIVE_N -#@ARCHIVE_Q -#@BATCH_GROUP -#@BATCH_OUTPUTNAMEOUTPUT +#{{ BATCH_TIME }}{{ ARCHIVE_T }} +#{{ ARCHIVE_P }} +#{{ BATCH_JOBNAME }}{{ ARCHIVE_N }} +#{{ ARCHIVE_Q }} +#{{ BATCH_GROUP }} +#{{ BATCH_OUTPUTNAME }}OUTPUT ####################################################################### # System Environment Variables @@ -21,7 +21,7 @@ limit stacksize unlimited @SETENVS -@MPT_SHEPHERD +{{ MPT_SHEPHERD }} ####################################################################### # Architecture Specific Environment Variables @@ -29,13 +29,13 @@ limit stacksize unlimited setenv ARCH `uname` -setenv SITE @SITE -setenv GEOSBIN @GEOSBIN +setenv SITE {{ SITE }} +setenv GEOSBIN {{ GEOSBIN }} source $GEOSBIN/g5_modules -setenv @LD_LIBRARY_PATH_CMD ${LD_LIBRARY_PATH} +setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH} if ( $?BASEDIR ) then - setenv @LD_LIBRARY_PATH_CMD ${@LD_LIBRARY_PATH_CMD}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib endif ####################################################################### diff --git a/gcm_emip.setup b/gcm_emip.setup index 53f75c14..6b5d7275 100755 --- a/gcm_emip.setup +++ b/gcm_emip.setup @@ -30,6 +30,6 @@ sed -f sedfile gcm_run.tmp > gcm_run.j$RSTDATE /bin/rm -f sedfile /bin/rm -f gcm_run.tmp -echo @BATCH_CMD gcm_run.j$RSTDATE +echo {{ BATCH_CMD }} gcm_run.j$RSTDATE end diff --git a/gcm_forecast.setup b/gcm_forecast.setup index bce27a19..88417308 100755 --- a/gcm_forecast.setup +++ b/gcm_forecast.setup @@ -5,12 +5,12 @@ ####################################################################### setenv ARCH `uname` -setenv SITE @SITE +setenv SITE {{ SITE }} -setenv EXPID @EXPID -setenv EXPDIR @EXPDIR -setenv HOMDIR @HOMDIR -setenv GEOSUTIL @GEOSUTIL +setenv EXPID {{ EXPID }} +setenv EXPDIR {{ EXPDIR }} +setenv HOMDIR {{ HOMDIR }} +setenv GEOSUTIL {{ GEOSUTIL }} ####################################################################### # Parameters for Forecasts @@ -107,7 +107,7 @@ s?&FHRS?$FHRS?g EOF sed -f sedfile $EXPDIR/forecasts/gcm_forecast.tmp > $EXPDIR/forecasts/gcm_forecast_${FCST_LABL}.j${date}-${nymde} -if( $QSUB != 'FALSE' ) @BATCH_CMD $EXPDIR/forecasts/gcm_forecast_${FCST_LABL}.j${date}-${nymde} +if( $QSUB != 'FALSE' ) {{ BATCH_CMD }} $EXPDIR/forecasts/gcm_forecast_${FCST_LABL}.j${date}-${nymde} set date = $test end diff --git a/gcm_forecast.tmpl b/gcm_forecast.tmpl index fd958308..86552531 100755 --- a/gcm_forecast.tmpl +++ b/gcm_forecast.tmpl @@ -4,12 +4,12 @@ # Batch Parameters for Run Job ####################################################################### -#@BATCH_TIME@RUN_FT -#@RUN_FP -#@BATCH_JOBNAME@RUN_FN_&DATE -#@RUN_Q -#@BATCH_GROUP -#@BATCH_OUTPUTNAMEFCSTOUT +#{{ BATCH_TIME }}{{ RUN_FT }} +#{{ RUN_FP }} +#{{ BATCH_JOBNAME }}{{ RUN_FN }}_&DATE +#{{ RUN_Q }} +#{{ BATCH_GROUP }} +#{{ BATCH_OUTPUTNAME }}FCSTOUT ####################################################################### # System Settings @@ -25,19 +25,19 @@ limit stacksize unlimited setenv ARCH `uname` -setenv SITE @SITE -setenv GEOSDIR @GEOSDIR -setenv GEOSBIN @GEOSBIN -setenv GEOSETC @GEOSETC -setenv GEOSUTIL @GEOSSRC +setenv SITE {{ SITE }} +setenv GEOSDIR {{ GEOSDIR }} +setenv GEOSBIN {{ GEOSBIN }} +setenv GEOSETC {{ GEOSETC }} +setenv GEOSUTIL {{ GEOSSRC }} source $GEOSBIN/g5_modules -setenv @LD_LIBRARY_PATH_CMD ${LD_LIBRARY_PATH}:${GEOSDIR}/lib +setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH}:${GEOSDIR}/lib if ( $?BASEDIR ) then - setenv @LD_LIBRARY_PATH_CMD ${@LD_LIBRARY_PATH_CMD}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib endif -setenv RUN_CMD "@RUN_CMD" +setenv RUN_CMD "{{ RUN_CMD }}" setenv GCMVER `cat $GEOSETC/.AGCM_VERSION` echo VERSION: $GCMVER @@ -47,9 +47,9 @@ echo VERSION: $GCMVER ####################################################################### -setenv EXPID @EXPID -setenv EXPDIR @EXPDIR -setenv HOMDIR @HOMDIR +setenv EXPID {{ EXPID }} +setenv EXPDIR {{ EXPDIR }} +setenv HOMDIR {{ HOMDIR }} ####################################################################### # Set Forecast Run Parameters @@ -104,14 +104,14 @@ set AGCM_LM = `grep '^\s*AGCM_LM:' $HOMDIR/AGCM.rc | cut -d: -f2` set OGCM_IM = `grep '^\s*OGCM\.IM_WORLD:' $HOMDIR/AGCM.rc | cut -d: -f2` set OGCM_JM = `grep '^\s*OGCM\.JM_WORLD:' $HOMDIR/AGCM.rc | cut -d: -f2` -@COUPLED set OGCM_LM = `grep '^\s*OGCM\.LM:' $HOMDIR/AGCM.rc | cut -d: -f2` -@COUPLED set NX = `grep '^\s*OGCM\.NX:' $HOMDIR/AGCM.rc | cut -d: -f2` -@COUPLED set NY = `grep '^\s*OGCM\.NY:' $HOMDIR/AGCM.rc | cut -d: -f2` +{{ COUPLED }} set OGCM_LM = `grep '^\s*OGCM\.LM:' $HOMDIR/AGCM.rc | cut -d: -f2` +{{ COUPLED }} set NX = `grep '^\s*OGCM\.NX:' $HOMDIR/AGCM.rc | cut -d: -f2` +{{ COUPLED }} set NY = `grep '^\s*OGCM\.NY:' $HOMDIR/AGCM.rc | cut -d: -f2` # Calculate number of cores/nodes for IOSERVER # -------------------------------------------- -set USE_IOSERVER = @USE_IOSERVER +set USE_IOSERVER = {{ USE_IOSERVER }} set NUM_OSERVER_NODES = `grep '^\s*IOSERVER_NODES:' $HOMDIR/AGCM.rc | cut -d: -f2` set NUM_BACKEND_PES = `grep '^\s*NUM_BACKEND_PES:' $HOMDIR/AGCM.rc | cut -d: -f2` @@ -127,7 +127,7 @@ endif @ MODEL_NPES = $NX * $NY -set NCPUS_PER_NODE = @NCPUS_PER_NODE +set NCPUS_PER_NODE = {{ NCPUS_PER_NODE }} set NUM_MODEL_NODES=`echo "scale=6;($MODEL_NPES / $NCPUS_PER_NODE)" | bc | awk 'function ceil(x, y){y=int(x); return(x>y?y+1:y)} {print ceil($1)}'` if ( $NCPUS != NULL ) then @@ -347,16 +347,16 @@ done: # Link Boundary Datasets ####################################################################### -setenv BCSDIR @BCSDIR -@DATAOCEANsetenv SSTDIR @SSTDIR -setenv BCRSLV @ATMOStag_@OCEANtag -@MOM5setenv SSTDIR @COUPLEDIR/SST/MERRA2/${OGCM_IM}x${OGCM_JM}/v1 -@MOM6setenv SSTDIR @COUPLEDIR/SST/MERRA2/${OGCM_IM}x${OGCM_JM}/v1 +setenv BCSDIR {{ BCSDIR }} +{{ DATAOCEAN }}setenv SSTDIR {{ SSTDIR }} +setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} +{{ MOM5 }}setenv SSTDIR {{ COUPLEDIR }}/SST/MERRA2/${OGCM_IM}x${OGCM_JM}/v1 +{{ MOM6 }}setenv SSTDIR {{ COUPLEDIR }}/SST/MERRA2/${OGCM_IM}x${OGCM_JM}/v1 #this is hard-wired for NAS for now - should make it more general -@DATAOCEANsetenv BCTAG `basename $BCSDIR` -@COUPLEDsetenv BCTAG `basename @COUPLEDIR/@OCNMODEL/${OGCM_IM}x${OGCM_JM}` -setenv EMISSIONS @EMISSIONS +{{ DATAOCEAN }}setenv BCTAG `basename $BCSDIR` +{{ COUPLED }}setenv BCTAG `basename {{ COUPLEDIR }}/{{ OCNMODEL }}/${OGCM_IM}x${OGCM_JM}` +setenv EMISSIONS {{ EMISSIONS }} chmod +x linkbcs >>>GCMRUN_CATCHCN<< WSUB_ExtData.rc + {{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/mv WSUB_ExtData.rc WSUB_ExtData.tmp + {{ MP_TURN_OFF_WSUB_EXTDATA }}cat WSUB_ExtData.tmp | sed -e '/^WSUB_CLIM/ s#ExtData.*#/dev/null#' > WSUB_ExtData.rc else - @MP_TURN_OFF_WSUB_EXTDATA/bin/mv WSUB_ExtData.yaml WSUB_ExtData.tmp - @MP_TURN_OFF_WSUB_EXTDATAcat WSUB_ExtData.tmp | sed -e '/collection:/ s#WSUB_SWclim.*#/dev/null#' > WSUB_ExtData.yaml + {{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/mv WSUB_ExtData.yaml WSUB_ExtData.tmp + {{ MP_TURN_OFF_WSUB_EXTDATA }}cat WSUB_ExtData.tmp | sed -e '/collection:/ s#WSUB_SWclim.*#/dev/null#' > WSUB_ExtData.yaml endif -@MP_TURN_OFF_WSUB_EXTDATA/bin/rm WSUB_ExtData.tmp +{{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/rm WSUB_ExtData.tmp # Generate the complete ExtData.rc # -------------------------------- @@ -604,7 +604,7 @@ setenv YEAR $yearc if (! -e tile.bin) then $GEOSBIN/binarytile.x tile.data tile.bin -@MOM5 $GEOSBIN/binarytile.x tile_hist.data tile_hist.bin +{{ MOM5 }} $GEOSBIN/binarytile.x tile_hist.data tile_hist.bin endif # If running in dual ocean mode, link sst and fraci data here @@ -634,8 +634,8 @@ else # Run the script # -------------- - @SINGULARITY_BUILD $RUN_CMD 1 $SINGULARITY_RUN $GEOSBIN/SaltIntSplitter tile.data $SCRDIR/saltwater_internal_rst - @NATIVE_BUILD $RUN_CMD 1 $GEOSBIN/SaltIntSplitter tile.data $SCRDIR/saltwater_internal_rst + {{ SINGULARITY_BUILD }} $RUN_CMD 1 $SINGULARITY_RUN $GEOSBIN/SaltIntSplitter tile.data $SCRDIR/saltwater_internal_rst + {{ NATIVE_BUILD }} $RUN_CMD 1 $GEOSBIN/SaltIntSplitter tile.data $SCRDIR/saltwater_internal_rst # Move restarts # ------------- @@ -673,8 +673,8 @@ endif if ( -x $GEOSBIN/rs_numtiles.x ) then set N_OPENW_TILES_EXPECTED = `grep '^\s*0' tile.data | wc -l` - @SINGULARITY_BUILD set N_OPENW_TILES_FOUND = `$RUN_CMD 1 $SINGULARITY_RUN $GEOSBIN/rs_numtiles.x openwater_internal_rst | grep Total | awk '{print $NF}'` - @NATIVE_BUILD set N_OPENW_TILES_FOUND = `$RUN_CMD 1 $GEOSBIN/rs_numtiles.x openwater_internal_rst | grep Total | awk '{print $NF}'` + {{ SINGULARITY_BUILD }} set N_OPENW_TILES_FOUND = `$RUN_CMD 1 $SINGULARITY_RUN $GEOSBIN/rs_numtiles.x openwater_internal_rst | grep Total | awk '{print $NF}'` + {{ NATIVE_BUILD }} set N_OPENW_TILES_FOUND = `$RUN_CMD 1 $GEOSBIN/rs_numtiles.x openwater_internal_rst | grep Total | awk '{print $NF}'` if ( $N_OPENW_TILES_EXPECTED != $N_OPENW_TILES_FOUND ) then echo "Error! Found $N_OPENW_TILES_FOUND tiles in openwater. Expect to find $N_OPENW_TILES_EXPECTED tiles." @@ -720,7 +720,7 @@ endif @SETENVS -@MPT_SHEPHERD +{{ MPT_SHEPHERD }} # Run bundleParser.py #--------------------- @@ -765,8 +765,8 @@ else set IOSERVER_EXTRA = "" endif -@SINGULARITY_BUILD @OCEAN_PRELOAD $RUN_CMD $TOTAL_PES $SINGULARITY_RUN $GEOSEXE $IOSERVER_OPTIONS $IOSERVER_EXTRA --logging_config 'logging.yaml' -@NATIVE_BUILD @OCEAN_PRELOAD $RUN_CMD $TOTAL_PES $GEOSEXE $IOSERVER_OPTIONS $IOSERVER_EXTRA --logging_config 'logging.yaml' +{{ SINGULARITY_BUILD }} {{ OCEAN_PRELOAD }} $RUN_CMD $TOTAL_PES $SINGULARITY_RUN $GEOSEXE $IOSERVER_OPTIONS $IOSERVER_EXTRA --logging_config 'logging.yaml' +{{ NATIVE_BUILD }} {{ OCEAN_PRELOAD }} $RUN_CMD $TOTAL_PES $GEOSEXE $IOSERVER_OPTIONS $IOSERVER_EXTRA --logging_config 'logging.yaml' if( $USE_SHMEM == 1 ) $GEOSBIN/RmShmKeys_sshmpi.csh >& /dev/null diff --git a/gcm_moveplot.j b/gcm_moveplot.j index cfe19f21..f473fd45 100755 --- a/gcm_moveplot.j +++ b/gcm_moveplot.j @@ -4,12 +4,12 @@ # Batch Parameters for Plot Job ####################################################################### -#@BATCH_TIME1:00:00 -#@MOVE_P -#@BATCH_JOBNAME@MOVE_N -#@MOVE_Q -#@BATCH_GROUP -#@BATCH_OUTPUTNAMEgcm_moveplot.o +#{{ BATCH_TIME }}1:00:00 +#{{ MOVE_P }} +#{{ BATCH_JOBNAME }}{{ MOVE_N }} +#{{ MOVE_Q }} +#{{ BATCH_GROUP }} +#{{ BATCH_OUTPUTNAME }}gcm_moveplot.o ####################################################################### # System Environment Variables @@ -21,7 +21,7 @@ limit stacksize unlimited @SETENVS -@MPT_SHEPHERD +{{ MPT_SHEPHERD }} ####################################################################### # Architecture Specific Environment Variables @@ -29,23 +29,23 @@ limit stacksize unlimited setenv ARCH `uname` -setenv SITE @SITE -setenv GEOSBIN @GEOSBIN -setenv GEOSUTIL @GEOSSRC +setenv SITE {{ SITE }} +setenv GEOSBIN {{ GEOSBIN }} +setenv GEOSUTIL {{ GEOSSRC }} source $GEOSBIN/g5_modules -setenv @LD_LIBRARY_PATH_CMD ${LD_LIBRARY_PATH} +setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH} if ( $?BASEDIR ) then - setenv @LD_LIBRARY_PATH_CMD ${@LD_LIBRARY_PATH_CMD}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib endif ####################################################################### # Experiment Specific Environment Variables ####################################################################### -setenv EXPID @EXPID -setenv EXPDIR @EXPDIR -setenv HOMDIR @HOMDIR +setenv EXPID {{ EXPID }} +setenv EXPDIR {{ EXPDIR }} +setenv HOMDIR {{ HOMDIR }} ####################################################################### # MOVE Commands diff --git a/gcm_plot.tmpl b/gcm_plot.tmpl index e202c413..f68ca271 100755 --- a/gcm_plot.tmpl +++ b/gcm_plot.tmpl @@ -4,12 +4,12 @@ # Batch Parameters for Plot Job ####################################################################### -#@BATCH_TIME@PLOT_T -#@PLOT_P -#@BATCH_JOBNAME@NAME -#@PLOT_Q -#@BATCH_GROUP -#@BATCH_OUTPUTNAMEOUTPUT +#{{ BATCH_TIME }}{{ PLOT_T }} +#{{ PLOT_P }} +#{{ BATCH_JOBNAME }}@NAME +#{{ PLOT_Q }} +#{{ BATCH_GROUP }} +#{{ BATCH_OUTPUTNAME }}OUTPUT ####################################################################### # System Environment Variables @@ -21,7 +21,7 @@ limit stacksize unlimited @SETENVS -@MPT_SHEPHERD +{{ MPT_SHEPHERD }} ####################################################################### # Architecture Specific Environment Variables @@ -29,23 +29,23 @@ limit stacksize unlimited setenv ARCH `uname` -setenv SITE @SITE -setenv GEOSBIN @GEOSBIN -setenv GEOSUTIL @GEOSSRC +setenv SITE {{ SITE }} +setenv GEOSBIN {{ GEOSBIN }} +setenv GEOSUTIL {{ GEOSSRC }} source $GEOSBIN/g5_modules -setenv @LD_LIBRARY_PATH_CMD ${LD_LIBRARY_PATH} +setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH} if ( $?BASEDIR ) then - setenv @LD_LIBRARY_PATH_CMD ${@LD_LIBRARY_PATH_CMD}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib endif ####################################################################### # Experiment Specific Environment Variables ####################################################################### -setenv EXPID @EXPID -setenv EXPDIR @EXPDIR -setenv HOMDIR @HOMDIR +setenv EXPID {{ EXPID }} +setenv EXPDIR {{ EXPDIR }} +setenv HOMDIR {{ HOMDIR }} ####################################################################### # Quickplot Commands @@ -64,5 +64,5 @@ endif ####################################################################### set MOVE = `grep PLOT_MOVE: $EXPDIR/plot/plot.rc | cut -d'#' -f1 | cut -d':' -f2` -if( $MOVE[1] == 'ON' ) @BATCH_CMD $EXPDIR/plot/gcm_moveplot.j +if( $MOVE[1] == 'ON' ) {{ BATCH_CMD }} $EXPDIR/plot/gcm_moveplot.j diff --git a/gcm_post.j b/gcm_post.j index 7cc0be91..177996ef 100755 --- a/gcm_post.j +++ b/gcm_post.j @@ -4,13 +4,13 @@ # Batch Parameters for Post-Processing Job ####################################################################### -#@BATCH_TIME@POST_T -#@POST_P -#@BATCH_JOBNAME@POST_N_@COLLECTION.@YYYYMM -#@POST_Q -#@BATCH_GROUP -#@BATCH_OUTPUTNAME@POST_O -#@BATCH_JOINOUTERR +#{{ BATCH_TIME }}{{ POST_T }} +#{{ POST_P }} +#{{ BATCH_JOBNAME }}{{ POST_N }}_@COLLECTION.@YYYYMM +#{{ POST_Q }} +#{{ BATCH_GROUP }} +#{{ BATCH_OUTPUTNAME }}@POST_O +#{{ BATCH_JOINOUTERR }} ####################################################################### # System Environment Variables @@ -22,7 +22,7 @@ limit stacksize unlimited @SETENVS -@MPT_SHEPHERD +{{ MPT_SHEPHERD }} ####################################################################### # Architecture Specific Environment Variables @@ -30,22 +30,22 @@ limit stacksize unlimited setenv ARCH `uname` -setenv SITE @SITE -setenv GEOSBIN @GEOSBIN -setenv GEOSUTIL @GEOSSRC -setenv BATCHNAME "@POST_N" +setenv SITE {{ SITE }} +setenv GEOSBIN {{ GEOSBIN }} +setenv GEOSUTIL {{ GEOSSRC }} +setenv BATCHNAME "{{ POST_N }}" source $GEOSBIN/g5_modules -setenv @LD_LIBRARY_PATH_CMD ${LD_LIBRARY_PATH} +setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH} if ( $?BASEDIR ) then - setenv @LD_LIBRARY_PATH_CMD ${@LD_LIBRARY_PATH_CMD}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib endif if( $?SLURM_NTASKS ) then - setenv RUN_CMD "@RUN_CMD" + setenv RUN_CMD "{{ RUN_CMD }}" set NCPUS = $SLURM_NTASKS else if( $?PBS_NODEFILE ) then - setenv RUN_CMD "@RUN_CMD" + setenv RUN_CMD "{{ RUN_CMD }}" set NCPUS = `cat $PBS_NODEFILE | wc -l` else set NCPUS = NULL @@ -55,6 +55,6 @@ endif # Perform Post Processing ####################################################################### -$GEOSUTIL/post/gcmpost.script -source @EXPDIR -ncpus $NCPUS -collections @COLLECTION -rec_plt @YYYYMM +$GEOSUTIL/post/gcmpost.script -source {{ EXPDIR }} -ncpus $NCPUS -collections @COLLECTION -rec_plt @YYYYMM exit diff --git a/gcm_regress.j b/gcm_regress.j index ee8a6c4f..5ba8d717 100755 --- a/gcm_regress.j +++ b/gcm_regress.j @@ -4,11 +4,11 @@ # Batch Parameters for Regress Job ####################################################################### -#@BATCH_TIME@RUN_T -#@RUN_P -#@BATCH_JOBNAME@REGRESS_N -#@RUN_Q -#@BATCH_GROUP +#{{ BATCH_TIME }}{{ RUN_T }} +#{{ RUN_P }} +#{{ BATCH_JOBNAME }}{{ REGRESS_N }} +#{{ RUN_Q }} +#{{ BATCH_GROUP }} ####################################################################### # System Environment Variables @@ -20,7 +20,7 @@ limit stacksize unlimited @SETENVS -@MPT_SHEPHERD +{{ MPT_SHEPHERD }} # Establish safe default number of OpenMP threads # ----------------------------------------------- @@ -85,26 +85,26 @@ set argv = () setenv ARCH `uname` -setenv SITE @SITE -setenv GEOSDIR @GEOSDIR -setenv GEOSBIN @GEOSBIN +setenv SITE {{ SITE }} +setenv GEOSDIR {{ GEOSDIR }} +setenv GEOSBIN {{ GEOSBIN }} source $GEOSBIN/g5_modules -setenv @LD_LIBRARY_PATH_CMD ${LD_LIBRARY_PATH}:${GEOSDIR}/lib -# We only add BASEDIR to the @LD_LIBRARY_PATH_CMD if BASEDIR is defined (i.e., not running with Spack) +setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH}:${GEOSDIR}/lib +# We only add BASEDIR to the {{ LD_LIBRARY_PATH_CMD }} if BASEDIR is defined (i.e., not running with Spack) if ( $?BASEDIR ) then - setenv @LD_LIBRARY_PATH_CMD ${@LD_LIBRARY_PATH_CMD}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib endif -setenv RUN_CMD "@RUN_CMD" +setenv RUN_CMD "{{ RUN_CMD }}" ####################################################################### # Experiment Specific Environment Variables ####################################################################### -setenv EXPID @EXPID -setenv EXPDIR @EXPDIR -setenv HOMDIR @HOMDIR +setenv EXPID {{ EXPID }} +setenv EXPDIR {{ EXPDIR }} +setenv HOMDIR {{ HOMDIR }} setenv SCRDIR $EXPDIR/scratch ####################################################################### @@ -130,9 +130,9 @@ cp $EXPDIR/RC/*.yaml $EXPDIR/regress cp $EXPDIR/GEOSgcm.x $EXPDIR/regress cp $EXPDIR/linkbcs $EXPDIR/regress cp $HOMDIR/*.yaml $EXPDIR/regress -@COUPLED cp $HOMDIR/*.nml $EXPDIR/regress -@MOM6cp $HOMDIR/MOM_input $EXPDIR/regress -@MOM6cp $HOMDIR/MOM_override $EXPDIR/regress +{{ COUPLED }} cp $HOMDIR/*.nml $EXPDIR/regress +{{ MOM6 }}cp $HOMDIR/MOM_input $EXPDIR/regress +{{ MOM6 }}cp $HOMDIR/MOM_override $EXPDIR/regress cat fvcore_layout.rc >> input.nml @@ -172,10 +172,10 @@ cp $EXPDIR/cap_restart $EXPDIR/regress # Get proper ridge scheme GWD internal restart # -------------------------------------------- /bin/rm gwd_internal_rst -/bin/cp @GWDRSDIR/gwd_internal_c${IM} gwd_internal_rst +/bin/cp {{ GWDRSDIR }}/gwd_internal_c${IM} gwd_internal_rst -@COUPLED /bin/mkdir INPUT -@COUPLED cp $EXPDIR/RESTART/* INPUT +{{ COUPLED }} /bin/mkdir INPUT +{{ COUPLED }} cp $EXPDIR/RESTART/* INPUT setenv YEAR `cat cap_restart | cut -c1-4` ./linkbcs @@ -228,23 +228,23 @@ COLLECTIONS: test_collection test_collection.format: 'CFIO' , test_collection.deflate: 1 , test_collection.frequency: 060000 , -@DATAOCEAN test_collection.fields: 'PHIS', 'AGCM' , -@DATAOCEAN 'SLP' , 'DYN' , -@DATAOCEAN 'T' , 'DYN' , -@DATAOCEAN 'U;V' , 'DYN' , -@DATAOCEAN 'Q' , 'MOIST', 'QV', -@MOM5 test_collection.fields: 'UW' ,'MOM' , 'US', -@MOM5 'VW' ,'MOM' , 'VS', -@MOM5 'TW' ,'MOM' , 'TS', -@MOM5 'SW' ,'MOM' , 'SS', -@MOM5 'SLV' ,'MOM' , -@MOM5 'QFLUX','OCEAN' , -@MOM6 test_collection.fields: 'UW' ,'MOM6' , 'US', -@MOM6 'VW' ,'MOM6' , 'VS', -@MOM6 'TW' ,'MOM6' , 'TS', -@MOM6 'SW' ,'MOM6' , 'SS', -@MOM6 'SLV' ,'MOM6' , -@MOM6 'QFLUX','OCEAN' , +{{ DATAOCEAN }} test_collection.fields: 'PHIS', 'AGCM' , +{{ DATAOCEAN }} 'SLP' , 'DYN' , +{{ DATAOCEAN }} 'T' , 'DYN' , +{{ DATAOCEAN }} 'U;V' , 'DYN' , +{{ DATAOCEAN }} 'Q' , 'MOIST', 'QV', +{{ MOM5 }} test_collection.fields: 'UW' ,'MOM' , 'US', +{{ MOM5 }} 'VW' ,'MOM' , 'VS', +{{ MOM5 }} 'TW' ,'MOM' , 'TS', +{{ MOM5 }} 'SW' ,'MOM' , 'SS', +{{ MOM5 }} 'SLV' ,'MOM' , +{{ MOM5 }} 'QFLUX','OCEAN' , +{{ MOM6 }} test_collection.fields: 'UW' ,'MOM6' , 'US', +{{ MOM6 }} 'VW' ,'MOM6' , 'VS', +{{ MOM6 }} 'TW' ,'MOM6' , 'TS', +{{ MOM6 }} 'SW' ,'MOM6' , 'SS', +{{ MOM6 }} 'SLV' ,'MOM6' , +{{ MOM6 }} 'QFLUX','OCEAN' , :: _EOF_ @@ -293,8 +293,8 @@ set EXTDATA2G_TRUE = `grep -i '^\s*USE_EXTDATA2G:\s*\.TRUE\.' CAP.rc | wc -l # Select proper AMIP GOCART Emission RC Files # ------------------------------------------- -setenv EMISSIONS @EMISSIONS -if( @EMISSIONS == AMIP_EMISSIONS ) then +setenv EMISSIONS {{ EMISSIONS }} +if( {{ EMISSIONS }} == AMIP_EMISSIONS ) then if( $EXTDATA2G_TRUE == 0 ) then set AMIP_Transition_Date = 20000301 @@ -321,16 +321,16 @@ if( @EMISSIONS == AMIP_EMISSIONS ) then endif endif -@MP_TURN_OFF_WSUB_EXTDATA# 1MOM and GFDL microphysics do not use WSUB_CLIM -@MP_TURN_OFF_WSUB_EXTDATA# ------------------------------------------------- +{{ MP_TURN_OFF_WSUB_EXTDATA }}# 1MOM and GFDL microphysics do not use WSUB_CLIM +{{ MP_TURN_OFF_WSUB_EXTDATA }}# ------------------------------------------------- if ($EXTDATA2G_TRUE == 0 ) then - @MP_TURN_OFF_WSUB_EXTDATA/bin/mv WSUB_ExtData.rc WSUB_ExtData.tmp - @MP_TURN_OFF_WSUB_EXTDATAcat WSUB_ExtData.tmp | sed -e '/^WSUB_CLIM/ s#ExtData.*#/dev/null#' > WSUB_ExtData.rc + {{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/mv WSUB_ExtData.rc WSUB_ExtData.tmp + {{ MP_TURN_OFF_WSUB_EXTDATA }}cat WSUB_ExtData.tmp | sed -e '/^WSUB_CLIM/ s#ExtData.*#/dev/null#' > WSUB_ExtData.rc else - @MP_TURN_OFF_WSUB_EXTDATA/bin/mv WSUB_ExtData.yaml WSUB_ExtData.tmp - @MP_TURN_OFF_WSUB_EXTDATAcat WSUB_ExtData.tmp | sed -e '/collection:/ s#WSUB_SWclim.*#/dev/null#' > WSUB_ExtData.yaml + {{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/mv WSUB_ExtData.yaml WSUB_ExtData.tmp + {{ MP_TURN_OFF_WSUB_EXTDATA }}cat WSUB_ExtData.tmp | sed -e '/collection:/ s#WSUB_SWclim.*#/dev/null#' > WSUB_ExtData.yaml endif -@MP_TURN_OFF_WSUB_EXTDATA/bin/rm WSUB_ExtData.tmp +{{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/rm WSUB_ExtData.tmp # Generate the complete ExtData.rc # -------------------------------- @@ -451,7 +451,7 @@ if( $RUN_STARTSTOP == TRUE ) then echo "=== Running test of duration ${test_duration_step1} with NX = $NX and NY = $NY starting at $nymd0 $nhms0 ===" - @OCEAN_PRELOAD $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' + {{ OCEAN_PRELOAD }} $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' set date = `cat cap_restart` set nymde1 = $date[1] @@ -470,7 +470,7 @@ if( $RUN_STARTSTOP == TRUE ) then /bin/mv -v $chk ${chk}.${nymde1}_${nhmse1}.1 end - @MOM6/bin/mv -v RESTART/MOM.res.nc MOM.res.nc.1 + {{ MOM6 }}/bin/mv -v RESTART/MOM.res.nc MOM.res.nc.1 # Move history as well set hist_file_names = `ls -1 ${EXPID}.test_collection.*.nc4` @@ -499,9 +499,9 @@ cp CAP.rc.orig CAP.rc cp AGCM.rc.orig AGCM.rc cp HISTORY.rc0 HISTORY.rc -@COUPLED /bin/rm -rf INPUT -@COUPLED /bin/mkdir INPUT -@COUPLED cp $EXPDIR/RESTART/* INPUT +{{ COUPLED }} /bin/rm -rf INPUT +{{ COUPLED }} /bin/mkdir INPUT +{{ COUPLED }} cp $EXPDIR/RESTART/* INPUT ./strip CAP.rc set oldstring = `cat CAP.rc | grep JOB_SGMT:` @@ -517,7 +517,7 @@ set NY = `grep "^ *NY": AGCM.rc | cut -d':' -f2` echo "=== Running test of duration ${test_duration_step2} with NX = $NX and NY = $NY starting at $nymd0 $nhms0 ===" -@OCEAN_PRELOAD $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' +{{ OCEAN_PRELOAD }} $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' set date = `cat cap_restart` set nymde2 = $date[1] @@ -544,7 +544,7 @@ foreach chk ( $replay_chk_file_names ) $MOVE_OR_COPY $chk ${chk}.${nymde1}_${nhmse1}.2 end -@MOM6 $MOVE_OR_COPY RESTART/MOM.res.nc MOM.res.nc.2 +{{ MOM6 }} $MOVE_OR_COPY RESTART/MOM.res.nc MOM.res.nc.2 # *Copy* history as well set hist_file_names = `ls -1 ${EXPID}.test_collection.*.nc4` @@ -585,7 +585,7 @@ while ( $n <= $numchk ) @ n = $n + 1 end -@COUPLED cp RESTART/* INPUT +{{ COUPLED }} cp RESTART/* INPUT ################################################################## ###### @@ -600,10 +600,10 @@ if ($RUN_STARTSTOP == TRUE) then cp HISTORY.rc0 HISTORY.rc - @MOM6# When you restart in MOM6 mode, you must change input_filename - @MOM6# in the input.nml file from 'n' to 'r' - @MOM6 /bin/cp input.nml input.nml.orig - @MOM6 sed -i -e "s/input_filename = 'n'/input_filename = 'r'/g" input.nml + {{ MOM6 }}# When you restart in MOM6 mode, you must change input_filename + {{ MOM6 }}# in the input.nml file from 'n' to 'r' + {{ MOM6 }} /bin/cp input.nml input.nml.orig + {{ MOM6 }} sed -i -e "s/input_filename = 'n'/input_filename = 'r'/g" input.nml ./strip CAP.rc set oldstring = `cat CAP.rc | grep JOB_SGMT:` @@ -623,7 +623,7 @@ if ($RUN_STARTSTOP == TRUE) then echo "=== Running test of duration ${test_duration_step3} with NX = $NX and NY = $NY starting at $nymdb $nhmsb ===" - @OCEAN_PRELOAD $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' + {{ OCEAN_PRELOAD }} $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' set date = `cat cap_restart` set nymde3 = $date[1] @@ -639,7 +639,7 @@ if ($RUN_STARTSTOP == TRUE) then foreach chk ( $replay_chk_file_names ) /bin/mv -v $chk ${chk}.${nymde1}_${nhmse1}.3 end - @MOM6/bin/mv -v RESTART/MOM.res.nc MOM.res.nc.3 + {{ MOM6 }}/bin/mv -v RESTART/MOM.res.nc MOM.res.nc.3 # Move history as well set hist_file_names = `ls -1 ${EXPID}.test_collection.*.nc4` @@ -674,14 +674,14 @@ if ( $RUN_LAYOUT == TRUE) then # Get proper ridge scheme GWD internal restart # -------------------------------------------- /bin/rm gwd_internal_rst - /bin/cp @GWDRSDIR/gwd_internal_c${IM} gwd_internal_rst + /bin/cp {{ GWDRSDIR }}/gwd_internal_c${IM} gwd_internal_rst - @COUPLED /bin/rm -rf INPUT - @COUPLED /bin/mkdir INPUT - @COUPLED cp $EXPDIR/RESTART/* INPUT + {{ COUPLED }} /bin/rm -rf INPUT + {{ COUPLED }} /bin/mkdir INPUT + {{ COUPLED }} cp $EXPDIR/RESTART/* INPUT - @COUPLED # restore original input.nml - @COUPLED /bin/mv input.nml.orig input.nml + {{ COUPLED }} # restore original input.nml + {{ COUPLED }} /bin/mv input.nml.orig input.nml /bin/rm cap_restart echo $nymd0 $nhms0 > cap_restart @@ -717,17 +717,17 @@ if ( $RUN_LAYOUT == TRUE) then /bin/mv AGCM.rc AGCM.tmp cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc - @COUPLED set oldstring = `cat AGCM.rc | grep "^ *OGCM.NX:"` - @COUPLED set newstring = "OGCM.NX: ${test_NY}" - @COUPLED /bin/mv AGCM.rc AGCM.tmp - @COUPLED cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc - @COUPLED set oldstring = `cat AGCM.rc | grep "^ *OGCM.NY:"` - @COUPLED set newstring = "OGCM.NY: ${test_NX}" - @COUPLED /bin/mv AGCM.rc AGCM.tmp - @COUPLED cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc + {{ COUPLED }} set oldstring = `cat AGCM.rc | grep "^ *OGCM.NX:"` + {{ COUPLED }} set newstring = "OGCM.NX: ${test_NY}" + {{ COUPLED }} /bin/mv AGCM.rc AGCM.tmp + {{ COUPLED }} cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc + {{ COUPLED }} set oldstring = `cat AGCM.rc | grep "^ *OGCM.NY:"` + {{ COUPLED }} set newstring = "OGCM.NY: ${test_NX}" + {{ COUPLED }} /bin/mv AGCM.rc AGCM.tmp + {{ COUPLED }} cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc - @MOM5sed -r -i -e "/^ *layout/ s#= ([0-9]+),*([0-9]+)#= ${test_NY},${test_NX}#" input.nml - @MOM6sed -r -i -e "s/#override LAYOUT = 3, 2/#override LAYOUT = ${test_NY}, ${test_NX}/g" MOM_override + {{ MOM5 }}sed -r -i -e "/^ *layout/ s#= ([0-9]+),*([0-9]+)#= ${test_NY},${test_NX}#" input.nml + {{ MOM6 }}sed -r -i -e "s/#override LAYOUT = 3, 2/#override LAYOUT = ${test_NY}, ${test_NX}/g" MOM_override setenv YEAR `cat cap_restart | cut -c1-4` ./linkbcs @@ -737,7 +737,7 @@ if ( $RUN_LAYOUT == TRUE) then echo "=== Running test of duration ${test_duration_step4} with NX = $test_NX and NY = $test_NY starting at $nymd0 $nhms0 ===" - @OCEAN_PRELOAD $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' + {{ OCEAN_PRELOAD }} $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' set date = `cat cap_restart` set nymde4 = $date[1] @@ -754,7 +754,7 @@ if ( $RUN_LAYOUT == TRUE) then /bin/mv -v $chk ${chk}.${nymde1}_${nhmse1}.4 end - @MOM6/bin/mv -v RESTART/MOM.res.nc MOM.res.nc.4 + {{ MOM6 }}/bin/mv -v RESTART/MOM.res.nc MOM.res.nc.4 # Move history as well set hist_file_names = `ls -1 ${EXPID}.test_collection.*.nc4` @@ -809,24 +809,24 @@ if ($RUN_STARTSTOP == TRUE) then endif end - @MOM6# check MOM.res.nc (MOM6 restart) - @MOM6set file1 = MOM.res.nc.1 - @MOM6set file2 = MOM.res.nc.3 - @MOM6if( -e $file1 && -e $file2 ) then - @MOM6 set check = true - @MOM6 if( $check == true ) then - @MOM6 echo Comparing "MOM6 restarts" - @MOM6 cmp $file1 $file2 - @MOM6 if( $status == 0 ) then - @MOM6 echo Start-Stop Success! - @MOM6 echo " " - @MOM6 else - @MOM6 echo Start-Stop Failed! - @MOM6 echo " " - @MOM6 set pass = false - @MOM6 endif - @MOM6 endif - @MOM6endif + {{ MOM6 }}# check MOM.res.nc (MOM6 restart) + {{ MOM6 }}set file1 = MOM.res.nc.1 + {{ MOM6 }}set file2 = MOM.res.nc.3 + {{ MOM6 }}if( -e $file1 && -e $file2 ) then + {{ MOM6 }} set check = true + {{ MOM6 }} if( $check == true ) then + {{ MOM6 }} echo Comparing "MOM6 restarts" + {{ MOM6 }} cmp $file1 $file2 + {{ MOM6 }} if( $status == 0 ) then + {{ MOM6 }} echo Start-Stop Success! + {{ MOM6 }} echo " " + {{ MOM6 }} else + {{ MOM6 }} echo Start-Stop Failed! + {{ MOM6 }} echo " " + {{ MOM6 }} set pass = false + {{ MOM6 }} endif + {{ MOM6 }} endif + {{ MOM6 }}endif echo "=== Comparing replay checkpoint files from ${NX0}x${NY0} run of duration ${test_duration_step1} with restarts from ${test_duration_step2} + ${test_duration_step3} ${NX0}x${NY0} runs ===" @@ -934,24 +934,24 @@ if ($RUN_LAYOUT == TRUE) then endif end - @MOM6# check MOM.res.nc (MOM6 restart) - @MOM6set file1 = MOM.res.nc.2 - @MOM6set file2 = MOM.res.nc.4 - @MOM6if( -e $file1 && -e $file2 ) then - @MOM6 set check = true - @MOM6 if( $check == true ) then - @MOM6 echo Comparing "MOM6 restarts" - @MOM6 cmp $file1 $file2 - @MOM6 if( $status == 0 ) then - @MOM6 echo Layout Success! - @MOM6 echo " " - @MOM6 else - @MOM6 echo Layout Failed! - @MOM6 echo " " - @MOM6 set pass = false - @MOM6 endif - @MOM6 endif - @MOM6endif + {{ MOM6 }}# check MOM.res.nc (MOM6 restart) + {{ MOM6 }}set file1 = MOM.res.nc.2 + {{ MOM6 }}set file2 = MOM.res.nc.4 + {{ MOM6 }}if( -e $file1 && -e $file2 ) then + {{ MOM6 }} set check = true + {{ MOM6 }} if( $check == true ) then + {{ MOM6 }} echo Comparing "MOM6 restarts" + {{ MOM6 }} cmp $file1 $file2 + {{ MOM6 }} if( $status == 0 ) then + {{ MOM6 }} echo Layout Success! + {{ MOM6 }} echo " " + {{ MOM6 }} else + {{ MOM6 }} echo Layout Failed! + {{ MOM6 }} echo " " + {{ MOM6 }} set pass = false + {{ MOM6 }} endif + {{ MOM6 }} endif + {{ MOM6 }}endif echo "=== Comparing replay checkpoint files from 6-hour ${NX0}x${NY0} run with restarts from 6-hour ${test_NX}x${test_NY} run ===" diff --git a/gcm_run.j b/gcm_run.j index d7946e8d..b4df0e73 100755 --- a/gcm_run.j +++ b/gcm_run.j @@ -4,12 +4,12 @@ # Batch Parameters for Run Job ####################################################################### -#@BATCH_TIME@RUN_T -#@RUN_P -#@BATCH_JOBNAME@RUN_N -#@RUN_Q -#@BATCH_GROUP -#@BATCH_JOINOUTERR +#{{ BATCH_TIME }}{{ RUN_T }} +#{{ RUN_P }} +#{{ BATCH_JOBNAME }}{{ RUN_N }} +#{{ RUN_Q }} +#{{ BATCH_GROUP }} +#{{ BATCH_JOINOUTERR }} #@BATCH_NAME -o gcm_run.o@RSTDATE ####################################################################### @@ -26,20 +26,20 @@ limit stacksize unlimited setenv ARCH `uname` -setenv SITE @SITE -setenv GEOSDIR @GEOSDIR -setenv GEOSBIN @GEOSBIN -setenv GEOSETC @GEOSETC -setenv GEOSUTIL @GEOSSRC +setenv SITE {{ SITE }} +setenv GEOSDIR {{ GEOSDIR }} +setenv GEOSBIN {{ GEOSBIN }} +setenv GEOSETC {{ GEOSETC }} +setenv GEOSUTIL {{ GEOSSRC }} source $GEOSBIN/g5_modules -setenv @LD_LIBRARY_PATH_CMD ${LD_LIBRARY_PATH}:${GEOSDIR}/lib -# We only add BASEDIR to the @LD_LIBRARY_PATH_CMD if BASEDIR is defined (i.e., not running with Spack) +setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH}:${GEOSDIR}/lib +# We only add BASEDIR to the {{ LD_LIBRARY_PATH_CMD }} if BASEDIR is defined (i.e., not running with Spack) if ( $?BASEDIR ) then - setenv @LD_LIBRARY_PATH_CMD ${@LD_LIBRARY_PATH_CMD}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib endif -setenv RUN_CMD "@RUN_CMD" +setenv RUN_CMD "{{ RUN_CMD }}" setenv GCMVER `cat $GEOSETC/.AGCM_VERSION` echo VERSION: $GCMVER @@ -49,9 +49,9 @@ echo VERSION: $GCMVER ####################################################################### -setenv EXPID @EXPID -setenv EXPDIR @EXPDIR -setenv HOMDIR @HOMDIR +setenv EXPID {{ EXPID }} +setenv EXPDIR {{ EXPDIR }} +setenv HOMDIR {{ HOMDIR }} setenv RSTDATE @RSTDATE setenv GCMEMIP @GCMEMIP @@ -87,14 +87,14 @@ set AGCM_LM = `grep '^\s*AGCM_LM:' $HOMDIR/AGCM.rc | cut -d: -f2` set OGCM_IM = `grep '^\s*OGCM\.IM_WORLD:' $HOMDIR/AGCM.rc | cut -d: -f2` set OGCM_JM = `grep '^\s*OGCM\.JM_WORLD:' $HOMDIR/AGCM.rc | cut -d: -f2` -@COUPLED set OGCM_LM = `grep '^\s*OGCM\.LM:' $HOMDIR/AGCM.rc | cut -d: -f2` -@COUPLED set NX = `grep '^\s*OGCM\.NX:' $HOMDIR/AGCM.rc | cut -d: -f2` -@COUPLED set NY = `grep '^\s*OGCM\.NY:' $HOMDIR/AGCM.rc | cut -d: -f2` +{{ COUPLED }} set OGCM_LM = `grep '^\s*OGCM\.LM:' $HOMDIR/AGCM.rc | cut -d: -f2` +{{ COUPLED }} set NX = `grep '^\s*OGCM\.NX:' $HOMDIR/AGCM.rc | cut -d: -f2` +{{ COUPLED }} set NY = `grep '^\s*OGCM\.NY:' $HOMDIR/AGCM.rc | cut -d: -f2` # Calculate number of cores/nodes for IOSERVER # -------------------------------------------- -set USE_IOSERVER = @USE_IOSERVER +set USE_IOSERVER = {{ USE_IOSERVER }} set NUM_OSERVER_NODES = `grep '^\s*IOSERVER_NODES:' $HOMDIR/AGCM.rc | cut -d: -f2` set NUM_BACKEND_PES = `grep '^\s*NUM_BACKEND_PES:' $HOMDIR/AGCM.rc | cut -d: -f2` @@ -110,7 +110,7 @@ endif @ MODEL_NPES = $NX * $NY -set NCPUS_PER_NODE = @NCPUS_PER_NODE +set NCPUS_PER_NODE = {{ NCPUS_PER_NODE }} set NUM_MODEL_NODES=`echo "scale=6;($MODEL_NPES / $NCPUS_PER_NODE)" | bc | awk 'function ceil(x, y){y=int(x); return(x>y?y+1:y)} {print ceil($1)}'` if ( $NCPUS != NULL ) then @@ -180,7 +180,7 @@ set month = `echo $RSTDATE | cut -d_ -f1 | cut -b5-6` >>>EMIP_OLDLAND<<<# --------------------- >>>EMIP_NEWLAND<<<# Copy Jason-3_4 REPLAY MERRA-2 NewLand Restarts >>>EMIP_NEWLAND<<<# ---------------------------------------------- -cp /discover/nobackup/projects/gmao/g6dev/ltakacs/@EMIP_MERRA2/restarts/AMIP/M${month}/restarts.${year}${month}.tar . +cp /discover/nobackup/projects/gmao/g6dev/ltakacs/{{ EMIP_MERRA2 }}/restarts/AMIP/M${month}/restarts.${year}${month}.tar . tar xf restarts.${year}${month}.tar /bin/rm restarts.${year}${month}.tar >>>EMIP_OLDLAND<<>>EMIP_NEWLAND<<<# ------------------------------------------------ set RSTID = `/bin/ls *catch* | cut -d. -f1` set day = `/bin/ls *catch* | cut -d. -f3 | awk 'match($0,/[0-9]{8}/) {print substr($0,RSTART+6,2)}'` -$GEOSBIN/remap_restarts.py command_line -np -ymdh ${year}${month}${day}21 -grout C${AGCM_IM} -levsout ${AGCM_LM} -out_dir . -rst_dir . -expid $RSTID -bcvin @EMIP_BCS_IN -oceanin 1440x720 -nobkg -lbl -nolcv -bcvout @LSMBCS -rs 3 -oceanout @OCEANOUT -in_bc_base @BC_BASE -out_bc_base @BC_BASE +$GEOSBIN/remap_restarts.py command_line -np -ymdh ${year}${month}${day}21 -grout C${AGCM_IM} -levsout ${AGCM_LM} -out_dir . -rst_dir . -expid $RSTID -bcvin {{ EMIP_BCS_IN }} -oceanin 1440x720 -nobkg -lbl -nolcv -bcvout {{ LSMBCS }} -rs 3 -oceanout {{ OCEANOUT }} -in_bc_base @BC_BASE -out_bc_base @BC_BASE >>>EMIP_OLDLAND<<>>EMIP_OLDLAND<<>>EMIP_OLDLAND<<<$GEOSBIN/gogo.x -s $RSTID.Chem_Registry.rc.${year}${month}${day}_21z -t $EXPDIR/RC/Chem_Registry.rc -i gocart_internal_rst.merra2 -o gocart_internal_rst -r C${AGCM_IM} -l ${AGCM_LM} @@ -269,9 +269,9 @@ if (-z input.nml) then exit 0 endif -@MOM6cp -f $HOMDIR/MOM_input . -@MOM6cp -f $HOMDIR/MOM_override . -@CICE6cp -f $HOMDIR/ice_in . +{{ MOM6 }}cp -f $HOMDIR/MOM_input . +{{ MOM6 }}cp -f $HOMDIR/MOM_override . +{{ CICE6 }}cp -f $HOMDIR/ice_in . if( $GCMEMIP == TRUE ) then cp -f $EXPDIR/restarts/$RSTDATE/cap_restart . @@ -315,16 +315,16 @@ done: ####################################################################### # Link Boundary Datasets ####################################################################### -setenv BCSDIR @BCSDIR -@DATAOCEANsetenv SSTDIR @SSTDIR -setenv BCRSLV @ATMOStag_@OCEANtag -@MOM5setenv SSTDIR @COUPLEDIR/SST/MERRA2/${OGCM_IM}x${OGCM_JM}/v1 -@MOM6setenv SSTDIR @COUPLEDIR/SST/MERRA2/${OGCM_IM}x${OGCM_JM}/v1 +setenv BCSDIR {{ BCSDIR }} +{{ DATAOCEAN }}setenv SSTDIR {{ SSTDIR }} +setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} +{{ MOM5 }}setenv SSTDIR {{ COUPLEDIR }}/SST/MERRA2/${OGCM_IM}x${OGCM_JM}/v1 +{{ MOM6 }}setenv SSTDIR {{ COUPLEDIR }}/SST/MERRA2/${OGCM_IM}x${OGCM_JM}/v1 #this is hard-wired for NAS for now - should make it more general -@DATAOCEANsetenv BCTAG `basename $BCSDIR` -@COUPLEDsetenv BCTAG `basename @COUPLEDIR/@OCNMODEL/${OGCM_IM}x${OGCM_JM}` -setenv EMISSIONS @EMISSIONS +{{ DATAOCEAN }}setenv BCTAG `basename $BCSDIR` +{{ COUPLED }}setenv BCTAG `basename {{ COUPLEDIR }}/{{ OCNMODEL }}/${OGCM_IM}x${OGCM_JM}` +setenv EMISSIONS {{ EMISSIONS }} chmod +x linkbcs >>>GCMRUN_CATCHCN<< $yearc ) then @ yearf = $yearc + 1 @ nymdf = $yearf * 10000 + 0101 @@ -773,16 +773,16 @@ if ( $DNA_TRUE == 0 && -e DNA_ExtData.rc ) /bin/mv set ACHEM_TRUE = `grep -i '^\s*ENABLE_ACHEM:\s*\.TRUE\.' GEOS_ChemGridComp.rc | wc -l` if ( $ACHEM_TRUE == 0 && -e GEOSachem_ExtData.rc ) /bin/mv GEOSachem_ExtData.rc GEOSachem_ExtData.rc.NOT_USED -@MP_TURN_OFF_WSUB_EXTDATA# 1MOM and GFDL microphysics do not use WSUB_CLIM -@MP_TURN_OFF_WSUB_EXTDATA# ------------------------------------------------- +{{ MP_TURN_OFF_WSUB_EXTDATA }}# 1MOM and GFDL microphysics do not use WSUB_CLIM +{{ MP_TURN_OFF_WSUB_EXTDATA }}# ------------------------------------------------- if ($EXTDATA2G_TRUE == 0 ) then - @MP_TURN_OFF_WSUB_EXTDATA/bin/mv WSUB_ExtData.rc WSUB_ExtData.tmp - @MP_TURN_OFF_WSUB_EXTDATAcat WSUB_ExtData.tmp | sed -e '/^WSUB_CLIM/ s#ExtData.*#/dev/null#' > WSUB_ExtData.rc + {{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/mv WSUB_ExtData.rc WSUB_ExtData.tmp + {{ MP_TURN_OFF_WSUB_EXTDATA }}cat WSUB_ExtData.tmp | sed -e '/^WSUB_CLIM/ s#ExtData.*#/dev/null#' > WSUB_ExtData.rc else - @MP_TURN_OFF_WSUB_EXTDATA/bin/mv WSUB_ExtData.yaml WSUB_ExtData.tmp - @MP_TURN_OFF_WSUB_EXTDATAcat WSUB_ExtData.tmp | sed -e '/collection:/ s#WSUB_SWclim.*#/dev/null#' > WSUB_ExtData.yaml + {{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/mv WSUB_ExtData.yaml WSUB_ExtData.tmp + {{ MP_TURN_OFF_WSUB_EXTDATA }}cat WSUB_ExtData.tmp | sed -e '/collection:/ s#WSUB_SWclim.*#/dev/null#' > WSUB_ExtData.yaml endif -@MP_TURN_OFF_WSUB_EXTDATA/bin/rm WSUB_ExtData.tmp +{{ MP_TURN_OFF_WSUB_EXTDATA }}/bin/rm WSUB_ExtData.tmp # Generate the complete ExtData.rc # -------------------------------- @@ -853,8 +853,8 @@ else # Run the script # -------------- - @SINGULARITY_BUILD $RUN_CMD 1 $SINGULARITY_RUN $GEOSBIN/SaltIntSplitter tile.data $SCRDIR/saltwater_internal_rst - @NATIVE_BUILD $RUN_CMD 1 $GEOSBIN/SaltIntSplitter tile.data $SCRDIR/saltwater_internal_rst + {{ SINGULARITY_BUILD }} $RUN_CMD 1 $SINGULARITY_RUN $GEOSBIN/SaltIntSplitter tile.data $SCRDIR/saltwater_internal_rst + {{ NATIVE_BUILD }} $RUN_CMD 1 $GEOSBIN/SaltIntSplitter tile.data $SCRDIR/saltwater_internal_rst # Move restarts # ------------- @@ -892,8 +892,8 @@ endif if ( -x $GEOSBIN/rs_numtiles.x ) then set N_OPENW_TILES_EXPECTED = `grep '^\s*0' tile.data | wc -l` - @SINGULARITY_BUILD set N_OPENW_TILES_FOUND = `$RUN_CMD 1 $SINGULARITY_RUN $GEOSBIN/rs_numtiles.x openwater_internal_rst | grep Total | awk '{print $NF}'` - @NATIVE_BUILD set N_OPENW_TILES_FOUND = `$RUN_CMD 1 $GEOSBIN/rs_numtiles.x openwater_internal_rst | grep Total | awk '{print $NF}'` + {{ SINGULARITY_BUILD }} set N_OPENW_TILES_FOUND = `$RUN_CMD 1 $SINGULARITY_RUN $GEOSBIN/rs_numtiles.x openwater_internal_rst | grep Total | awk '{print $NF}'` + {{ NATIVE_BUILD }} set N_OPENW_TILES_FOUND = `$RUN_CMD 1 $GEOSBIN/rs_numtiles.x openwater_internal_rst | grep Total | awk '{print $NF}'` if ( $N_OPENW_TILES_EXPECTED != $N_OPENW_TILES_FOUND ) then echo "Error! Found $N_OPENW_TILES_FOUND tiles in openwater. Expect to find $N_OPENW_TILES_EXPECTED tiles." @@ -933,7 +933,7 @@ endif @SETENVS -@MPT_SHEPHERD +{{ MPT_SHEPHERD }} # Run bundleParser.py #--------------------- @@ -968,75 +968,75 @@ endif # Establish safe default number of OpenMP threads # ----------------------------------------------- -@MIT # --------------------------------------------------- -@MIT # For MITgcm restarts - before running GEOSgcm.x -@MIT # --------------------------------------------------- -@MIT -@MIT # set time interval for segment in seconds -@MIT -@MIT set yearc = `echo $nymdc | cut -c1-4` -@MIT set monthc = `echo $nymdc | cut -c5-6` -@MIT set dayc = `echo $nymdc | cut -c7-8` -@MIT set hourc = `echo $nhmsc | cut -c1-2` -@MIT set minutec = `echo $nhmsc | cut -c3-4` -@MIT set secondc = `echo $nhmsc | cut -c5-6` -@MIT -@MIT set yearf = `echo $nymdf | cut -c1-4` -@MIT set monthf = `echo $nymdf | cut -c5-6` -@MIT set dayf = `echo $nymdf | cut -c7-8` -@MIT set hourf = `echo $nhmsf | cut -c1-2` -@MIT set minutef = `echo $nhmsf | cut -c3-4` -@MIT set secondf = `echo $nhmsf | cut -c5-6` -@MIT -@MIT set yearf = `echo $nymdf | cut -c1-4` -@MIT -@MIT set time1 = `date -u -d "${yearc}-${monthc}-${dayc}T${hourc}:${minutec}:${secondc}" "+%s"` -@MIT set time2 = `date -u -d "${yearf}-${monthf}-${dayf}T${hourf}:${minutef}:${secondf}" "+%s"` -@MIT -@MIT @ mitdt = $time2 - $time1 -@MIT echo "Segment time: $mitdt" -@MIT -@MIT -@MIT # Set-up MITgcm run directory -@MIT if (! -e mitocean_run) mkdir -p mitocean_run -@MIT cd mitocean_run -@MIT -@MIT # link mit configuration and initialization files -@MIT ln -sf $EXPDIR/mit_input/* . -@MIT # link mitgcm restarts if exist -@MIT /bin/ln -sf $EXPDIR/restarts/pic* . -@MIT # make an archive folder for mitgcm run -@MIT mkdir $EXPDIR/mit_output -@MIT -@MIT # Calculate segment time steps -@MIT set mit_nTimeSteps = `cat ${SCRDIR}/AGCM.rc | grep OGCM_RUN_DT: | cut -d: -f2 | tr -s " " | cut -d" " -f2` -@MIT @ mit_nTimeSteps = ${mitdt} / $mit_nTimeSteps -@MIT -@MIT #change namelist variables in data - nTimeSteps, chkptFreq and monitorFreq -@MIT sed -i "s/nTimeSteps.*/nTimeSteps = ${mit_nTimeSteps},/" data -@MIT sed -i "s/chkptFreq.*/chkptFreq = ${mitdt}.0,/" data -@MIT sed -i "s/pChkptFreq.*/pChkptFreq = ${mitdt}.0,/" data -@MIT # get nIter0 -@MIT -@MIT if (! -e ${EXPDIR}/restarts/MITgcm_restart_dates.txt ) then -@MIT set nIter0 = `grep nIter0 data | tr -s " " | cut -d"=" -f2 | cut -d"," -f1 | awk '{$1=$1;print}'` -@MIT else -@MIT set nIter0 = `grep "$nymdc $nhmsc" ${EXPDIR}/restarts/MITgcm_restart_dates.txt | cut -d" " -f5` -@MIT if ( $nIter0 == "" ) then -@MIT echo "No ocean restart file for $nymdc $nhmsc, exiting" -@MIT echo "If this is a new initialized experiment, delete:" -@MIT echo "${EXPDIR}/restarts/MITgcm_restart_dates.txt" -@MIT echo "and restart" -@MIT exit -@MIT else -@MIT sed -i "s/nIter0.*/ nIter0 = ${nIter0},/" data -@MIT endif -@MIT endif -@MIT -@MIT cd .. -@MIT # --------------------------------------------------- -@MIT # End MITgcm restarts - before running GEOSgcm.x -@MIT # --------------------------------------------------- +{{ MIT }} # --------------------------------------------------- +{{ MIT }} # For MITgcm restarts - before running GEOSgcm.x +{{ MIT }} # --------------------------------------------------- +{{ MIT }} +{{ MIT }} # set time interval for segment in seconds +{{ MIT }} +{{ MIT }} set yearc = `echo $nymdc | cut -c1-4` +{{ MIT }} set monthc = `echo $nymdc | cut -c5-6` +{{ MIT }} set dayc = `echo $nymdc | cut -c7-8` +{{ MIT }} set hourc = `echo $nhmsc | cut -c1-2` +{{ MIT }} set minutec = `echo $nhmsc | cut -c3-4` +{{ MIT }} set secondc = `echo $nhmsc | cut -c5-6` +{{ MIT }} +{{ MIT }} set yearf = `echo $nymdf | cut -c1-4` +{{ MIT }} set monthf = `echo $nymdf | cut -c5-6` +{{ MIT }} set dayf = `echo $nymdf | cut -c7-8` +{{ MIT }} set hourf = `echo $nhmsf | cut -c1-2` +{{ MIT }} set minutef = `echo $nhmsf | cut -c3-4` +{{ MIT }} set secondf = `echo $nhmsf | cut -c5-6` +{{ MIT }} +{{ MIT }} set yearf = `echo $nymdf | cut -c1-4` +{{ MIT }} +{{ MIT }} set time1 = `date -u -d "${yearc}-${monthc}-${dayc}T${hourc}:${minutec}:${secondc}" "+%s"` +{{ MIT }} set time2 = `date -u -d "${yearf}-${monthf}-${dayf}T${hourf}:${minutef}:${secondf}" "+%s"` +{{ MIT }} +{{ MIT }} @ mitdt = $time2 - $time1 +{{ MIT }} echo "Segment time: $mitdt" +{{ MIT }} +{{ MIT }} +{{ MIT }} # Set-up MITgcm run directory +{{ MIT }} if (! -e mitocean_run) mkdir -p mitocean_run +{{ MIT }} cd mitocean_run +{{ MIT }} +{{ MIT }} # link mit configuration and initialization files +{{ MIT }} ln -sf $EXPDIR/mit_input/* . +{{ MIT }} # link mitgcm restarts if exist +{{ MIT }} /bin/ln -sf $EXPDIR/restarts/pic* . +{{ MIT }} # make an archive folder for mitgcm run +{{ MIT }} mkdir $EXPDIR/mit_output +{{ MIT }} +{{ MIT }} # Calculate segment time steps +{{ MIT }} set mit_nTimeSteps = `cat ${SCRDIR}/AGCM.rc | grep OGCM_RUN_DT: | cut -d: -f2 | tr -s " " | cut -d" " -f2` +{{ MIT }} @ mit_nTimeSteps = ${mitdt} / $mit_nTimeSteps +{{ MIT }} +{{ MIT }} #change namelist variables in data - nTimeSteps, chkptFreq and monitorFreq +{{ MIT }} sed -i "s/nTimeSteps.*/nTimeSteps = ${mit_nTimeSteps},/" data +{{ MIT }} sed -i "s/chkptFreq.*/chkptFreq = ${mitdt}.0,/" data +{{ MIT }} sed -i "s/pChkptFreq.*/pChkptFreq = ${mitdt}.0,/" data +{{ MIT }} # get nIter0 +{{ MIT }} +{{ MIT }} if (! -e ${EXPDIR}/restarts/MITgcm_restart_dates.txt ) then +{{ MIT }} set nIter0 = `grep nIter0 data | tr -s " " | cut -d"=" -f2 | cut -d"," -f1 | awk '{$1=$1;print}'` +{{ MIT }} else +{{ MIT }} set nIter0 = `grep "$nymdc $nhmsc" ${EXPDIR}/restarts/MITgcm_restart_dates.txt | cut -d" " -f5` +{{ MIT }} if ( $nIter0 == "" ) then +{{ MIT }} echo "No ocean restart file for $nymdc $nhmsc, exiting" +{{ MIT }} echo "If this is a new initialized experiment, delete:" +{{ MIT }} echo "${EXPDIR}/restarts/MITgcm_restart_dates.txt" +{{ MIT }} echo "and restart" +{{ MIT }} exit +{{ MIT }} else +{{ MIT }} sed -i "s/nIter0.*/ nIter0 = ${nIter0},/" data +{{ MIT }} endif +{{ MIT }} endif +{{ MIT }} +{{ MIT }} cd .. +{{ MIT }} # --------------------------------------------------- +{{ MIT }} # End MITgcm restarts - before running GEOSgcm.x +{{ MIT }} # --------------------------------------------------- # Set OMP_NUM_THREADS # ------------------- @@ -1054,8 +1054,8 @@ else set IOSERVER_EXTRA = "" endif -@SINGULARITY_BUILD @OCEAN_PRELOAD $RUN_CMD $TOTAL_PES $SINGULARITY_RUN $GEOSEXE $IOSERVER_OPTIONS $IOSERVER_EXTRA --logging_config 'logging.yaml' -@NATIVE_BUILD @OCEAN_PRELOAD $RUN_CMD $TOTAL_PES $GEOSEXE $IOSERVER_OPTIONS $IOSERVER_EXTRA --logging_config 'logging.yaml' +{{ SINGULARITY_BUILD }} {{ OCEAN_PRELOAD }} $RUN_CMD $TOTAL_PES $SINGULARITY_RUN $GEOSEXE $IOSERVER_OPTIONS $IOSERVER_EXTRA --logging_config 'logging.yaml' +{{ NATIVE_BUILD }} {{ OCEAN_PRELOAD }} $RUN_CMD $TOTAL_PES $GEOSEXE $IOSERVER_OPTIONS $IOSERVER_EXTRA --logging_config 'logging.yaml' if( $USE_SHMEM == 1 ) $GEOSBIN/RmShmKeys_sshmpi.csh >& /dev/null @@ -1066,86 +1066,86 @@ else endif echo GEOSgcm Run Status: $rc -@MIT # --------------------------------------------------- -@MIT # For MITgcm restarts - after running GEOSgcm.x -@MIT # --------------------------------------------------- -@MIT -@MIT set STEADY_STATE_OCEAN=`grep STEADY_STATE_OCEAN AGCM.rc | cut -d':' -f2 | tr -d " "` -@MIT -@MIT # update ocean only if activated. Otherwize use the same pickups (passive ocean). -@MIT if ( ${STEADY_STATE_OCEAN} != 0 ) then -@MIT -@MIT if ( ${rc} == 0 ) then -@MIT -@MIT # Update nIter0 for next segment -@MIT set znIter00 = `echo $nIter0 | awk '{printf("%010d",$1)}'` -@MIT @ nIter0 = $nIter0 + $mit_nTimeSteps -@MIT set znIter0 = `echo $nIter0 | awk '{printf("%010d",$1)}'` -@MIT -@MIT # to update MITgcm restart list file -@MIT sed -i "/${nIter0}/d" ${EXPDIR}/restarts/MITgcm_restart_dates.txt -@MIT echo "Date_GEOS5 $nymdf $nhmsf NITER0_MITgcm ${nIter0}" >> ${EXPDIR}/restarts/MITgcm_restart_dates.txt -@MIT -@MIT /bin/mv $SCRDIR/mitocean_run/STDOUT.0000 $EXPDIR/mit_output/STDOUT.${znIter00} -@MIT -@MIT endif -@MIT -@MIT cd $SCRDIR/mitocean_run -@MIT -@MIT # Check existance of roling pickups -@MIT set nonomatch rp = ( pickup*ckptA* ) -@MIT echo $rp -@MIT # Rename and move them if exist -@MIT if ( -e $rp[1] ) then -@MIT set timeStepNumber=`cat pickup.ckptA.meta | grep timeStepNumber | tr -s " " | cut -d" " -f5 | awk '{printf("%010d",$1)}'` -@MIT foreach fname ( pickup*ckptA* ) -@MIT set bname = `echo ${fname} | cut -d "." -f1 | cut -d "/" -f2` -@MIT set aname = `echo ${fname} | cut -d "." -f3` -@MIT echo $EXPDIR/restarts/${bname}.${timeStepNumber}.${aname} -@MIT /bin/mv ${fname} $EXPDIR/restarts/${bname}.${timeStepNumber}.${aname} -@MIT end -@MIT endif -@MIT -@MIT # Check existance of permanent pickups -@MIT set nonomatch pp = ( pickup* ) -@MIT echo $pp -@MIT # Move them if exist -@MIT if ( -e $pp[1] ) then -@MIT foreach fname ( pickup* ) -@MIT if ( ! -e $EXPDIR/restarts/${fname} ) /bin/mv ${fname} $EXPDIR/restarts/${fname} -@MIT end -@MIT endif -@MIT -@MIT /bin/mv T.* $EXPDIR/mit_output/ -@MIT /bin/mv S.* $EXPDIR/mit_output/ -@MIT /bin/mv U.* $EXPDIR/mit_output/ -@MIT /bin/mv V.* $EXPDIR/mit_output/ -@MIT /bin/mv W.* $EXPDIR/mit_output/ -@MIT /bin/mv PH* $EXPDIR/mit_output/ -@MIT /bin/mv Eta.* $EXPDIR/mit_output/ -@MIT -@MIT /bin/mv AREA.* $EXPDIR/mit_output/ -@MIT /bin/mv HEFF.* $EXPDIR/mit_output/ -@MIT /bin/mv HSNOW.* $EXPDIR/mit_output/ -@MIT /bin/mv UICE.* $EXPDIR/mit_output/ -@MIT /bin/mv VICE.* $EXPDIR/mit_output/ -@MIT -@MIT #copy mit output to mit_output -@MIT foreach i (`grep -i filename data.diagnostics | grep "^ " | cut -d"=" -f2 | cut -d"'" -f2 | awk '{$1=$1;print}'`) -@MIT /bin/mv ${i}* $EXPDIR/mit_output/ -@MIT end -@MIT -@MIT foreach i (`grep -i stat_fName data.diagnostics | grep "^ " | cut -d"=" -f2 | cut -d"'" -f2 | awk '{$1=$1;print}'`) -@MIT /bin/mv ${i}* $EXPDIR/mit_output/ -@MIT end -@MIT -@MIT cd $SCRDIR -@MIT -@MIT endif -@MIT -@MIT # --------------------------------------------------- -@MIT # End MITgcm restarts - after running GEOSgcm.x -@MIT # --------------------------------------------------- +{{ MIT }} # --------------------------------------------------- +{{ MIT }} # For MITgcm restarts - after running GEOSgcm.x +{{ MIT }} # --------------------------------------------------- +{{ MIT }} +{{ MIT }} set STEADY_STATE_OCEAN=`grep STEADY_STATE_OCEAN AGCM.rc | cut -d':' -f2 | tr -d " "` +{{ MIT }} +{{ MIT }} # update ocean only if activated. Otherwize use the same pickups (passive ocean). +{{ MIT }} if ( ${STEADY_STATE_OCEAN} != 0 ) then +{{ MIT }} +{{ MIT }} if ( ${rc} == 0 ) then +{{ MIT }} +{{ MIT }} # Update nIter0 for next segment +{{ MIT }} set znIter00 = `echo $nIter0 | awk '{printf("%010d",$1)}'` +{{ MIT }} @ nIter0 = $nIter0 + $mit_nTimeSteps +{{ MIT }} set znIter0 = `echo $nIter0 | awk '{printf("%010d",$1)}'` +{{ MIT }} +{{ MIT }} # to update MITgcm restart list file +{{ MIT }} sed -i "/${nIter0}/d" ${EXPDIR}/restarts/MITgcm_restart_dates.txt +{{ MIT }} echo "Date_GEOS5 $nymdf $nhmsf NITER0_MITgcm ${nIter0}" >> ${EXPDIR}/restarts/MITgcm_restart_dates.txt +{{ MIT }} +{{ MIT }} /bin/mv $SCRDIR/mitocean_run/STDOUT.0000 $EXPDIR/mit_output/STDOUT.${znIter00} +{{ MIT }} +{{ MIT }} endif +{{ MIT }} +{{ MIT }} cd $SCRDIR/mitocean_run +{{ MIT }} +{{ MIT }} # Check existance of roling pickups +{{ MIT }} set nonomatch rp = ( pickup*ckptA* ) +{{ MIT }} echo $rp +{{ MIT }} # Rename and move them if exist +{{ MIT }} if ( -e $rp[1] ) then +{{ MIT }} set timeStepNumber=`cat pickup.ckptA.meta | grep timeStepNumber | tr -s " " | cut -d" " -f5 | awk '{printf("%010d",$1)}'` +{{ MIT }} foreach fname ( pickup*ckptA* ) +{{ MIT }} set bname = `echo ${fname} | cut -d "." -f1 | cut -d "/" -f2` +{{ MIT }} set aname = `echo ${fname} | cut -d "." -f3` +{{ MIT }} echo $EXPDIR/restarts/${bname}.${timeStepNumber}.${aname} +{{ MIT }} /bin/mv ${fname} $EXPDIR/restarts/${bname}.${timeStepNumber}.${aname} +{{ MIT }} end +{{ MIT }} endif +{{ MIT }} +{{ MIT }} # Check existance of permanent pickups +{{ MIT }} set nonomatch pp = ( pickup* ) +{{ MIT }} echo $pp +{{ MIT }} # Move them if exist +{{ MIT }} if ( -e $pp[1] ) then +{{ MIT }} foreach fname ( pickup* ) +{{ MIT }} if ( ! -e $EXPDIR/restarts/${fname} ) /bin/mv ${fname} $EXPDIR/restarts/${fname} +{{ MIT }} end +{{ MIT }} endif +{{ MIT }} +{{ MIT }} /bin/mv T.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv S.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv U.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv V.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv W.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv PH* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv Eta.* $EXPDIR/mit_output/ +{{ MIT }} +{{ MIT }} /bin/mv AREA.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv HEFF.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv HSNOW.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv UICE.* $EXPDIR/mit_output/ +{{ MIT }} /bin/mv VICE.* $EXPDIR/mit_output/ +{{ MIT }} +{{ MIT }} #copy mit output to mit_output +{{ MIT }} foreach i (`grep -i filename data.diagnostics | grep "^ " | cut -d"=" -f2 | cut -d"'" -f2 | awk '{$1=$1;print}'`) +{{ MIT }} /bin/mv ${i}* $EXPDIR/mit_output/ +{{ MIT }} end +{{ MIT }} +{{ MIT }} foreach i (`grep -i stat_fName data.diagnostics | grep "^ " | cut -d"=" -f2 | cut -d"'" -f2 | awk '{$1=$1;print}'`) +{{ MIT }} /bin/mv ${i}* $EXPDIR/mit_output/ +{{ MIT }} end +{{ MIT }} +{{ MIT }} cd $SCRDIR +{{ MIT }} +{{ MIT }} endif +{{ MIT }} +{{ MIT }} # --------------------------------------------------- +{{ MIT }} # End MITgcm restarts - after running GEOSgcm.x +{{ MIT }} # --------------------------------------------------- ####################################################################### @@ -1155,8 +1155,8 @@ echo GEOSgcm Run Status: $rc set edate = e`awk '{print $1}' cap_restart`_`awk '{print $2}' cap_restart | cut -c1-2`z -@COUPLED cp -r RESTART ${EXPDIR}/restarts/RESTART.${edate} -@COUPLED cp RESTART/* INPUT +{{ COUPLED }} cp -r RESTART ${EXPDIR}/restarts/RESTART.${edate} +{{ COUPLED }} cp RESTART/* INPUT # Move Intermediate Checkpoints to RESTARTS directory # --------------------------------------------------- @@ -1224,10 +1224,10 @@ endif # --------------------- cd $EXPDIR/restarts if( $FSEGMENT == 00000000 ) then - @DATAOCEAN tar cf restarts.${edate}.tar $EXPID.*.${edate}.${GCMVER}.${BCTAG}_${BCRSLV}.* - @COUPLED tar cvf restarts.${edate}.tar $EXPID.*.${edate}.${GCMVER}.${BCTAG}_${BCRSLV}.* RESTART.${edate} + {{ DATAOCEAN }} tar cf restarts.${edate}.tar $EXPID.*.${edate}.${GCMVER}.${BCTAG}_${BCRSLV}.* + {{ COUPLED }} tar cvf restarts.${edate}.tar $EXPID.*.${edate}.${GCMVER}.${BCTAG}_${BCRSLV}.* RESTART.${edate} /bin/rm -rf `/bin/ls -d -1 $EXPID.*.${edate}.${GCMVER}.${BCTAG}_${BCRSLV}.*` - @COUPLED /bin/rm -rf RESTART.${edate} + {{ COUPLED }} /bin/rm -rf RESTART.${edate} endif @@ -1242,36 +1242,36 @@ foreach collection ( $collections ) /bin/mv `/bin/ls -1 *.${collection}.*` $EXPDIR/holding/$collection end -@COUPLED # MOM-Specific Output Files -@COUPLED # ------------------------- -@MOM5 set dsets="ocean_month" -@MOM6 set dsets="ocean_state prog_z sfc_ave forcing" -@MOM5 foreach dset ( $dsets ) -@MOM5 set num = `/bin/ls -1 $dset.nc | wc -l` -@MOM5 if($num != 0) then -@MOM5 if(! -e $EXPDIR/MOM_Output) mkdir -p $EXPDIR/MOM_Output -@MOM5 /bin/mv $SCRDIR/$dset.nc $EXPDIR/MOM_Output/$dset.${edate}.nc -@MOM5 endif -@MOM5 end -@MOM6 foreach dset ( $dsets ) -@MOM6 set num = `/bin/ls -1 $dset.nc | wc -l` -@MOM6 if($num != 0) then -@MOM6 if(! -e $EXPDIR/MOM_Output) mkdir -p $EXPDIR/MOM_Output -@MOM6 /bin/mv $SCRDIR/$dset.nc $EXPDIR/MOM_Output/$dset.${edate}.nc -@MOM6 endif -@MOM6 end - -@CICE6 # CICE6-Specific Output Files -@CICE6 # ------------------------- -@CICE6 set dsets="iceh" -@CICE6 foreach dset ( $dsets ) -@CICE6 set num = `/bin/ls -1 $dset.*.nc | wc -l` -@CICE6 if($num != 0) then -@CICE6 if(! -e $EXPDIR/CICE_Output) mkdir -p $EXPDIR/CICE_Output -@CICE6 /bin/mv $SCRDIR/$dset.*.nc $EXPDIR/CICE_Output/ -@CICE6 endif -@CICE6 end -@CICE6 +{{ COUPLED }} # MOM-Specific Output Files +{{ COUPLED }} # ------------------------- +{{ MOM5 }} set dsets="ocean_month" +{{ MOM6 }} set dsets="ocean_state prog_z sfc_ave forcing" +{{ MOM5 }} foreach dset ( $dsets ) +{{ MOM5 }} set num = `/bin/ls -1 $dset.nc | wc -l` +{{ MOM5 }} if($num != 0) then +{{ MOM5 }} if(! -e $EXPDIR/MOM_Output) mkdir -p $EXPDIR/MOM_Output +{{ MOM5 }} /bin/mv $SCRDIR/$dset.nc $EXPDIR/MOM_Output/$dset.${edate}.nc +{{ MOM5 }} endif +{{ MOM5 }} end +{{ MOM6 }} foreach dset ( $dsets ) +{{ MOM6 }} set num = `/bin/ls -1 $dset.nc | wc -l` +{{ MOM6 }} if($num != 0) then +{{ MOM6 }} if(! -e $EXPDIR/MOM_Output) mkdir -p $EXPDIR/MOM_Output +{{ MOM6 }} /bin/mv $SCRDIR/$dset.nc $EXPDIR/MOM_Output/$dset.${edate}.nc +{{ MOM6 }} endif +{{ MOM6 }} end + +{{ CICE6 }} # CICE6-Specific Output Files +{{ CICE6 }} # ------------------------- +{{ CICE6 }} set dsets="iceh" +{{ CICE6 }} foreach dset ( $dsets ) +{{ CICE6 }} set num = `/bin/ls -1 $dset.*.nc | wc -l` +{{ CICE6 }} if($num != 0) then +{{ CICE6 }} if(! -e $EXPDIR/CICE_Output) mkdir -p $EXPDIR/CICE_Output +{{ CICE6 }} /bin/mv $SCRDIR/$dset.*.nc $EXPDIR/CICE_Output/ +{{ CICE6 }} endif +{{ CICE6 }} end +{{ CICE6 }} ####################################################################### # Run Post-Processing and Forecasts ####################################################################### @@ -1342,13 +1342,13 @@ else endif endif -@COUPLED cp -rf RESTART $EXPDIR +{{ COUPLED }} cp -rf RESTART $EXPDIR if ( $rc == 0 ) then cd $HOMDIR if ( $GCMEMIP == TRUE ) then - if( $capdate < $enddate ) @BATCH_CMD $HOMDIR/gcm_run.j$RSTDATE + if( $capdate < $enddate ) {{ BATCH_CMD }} $HOMDIR/gcm_run.j$RSTDATE else - if( $capdate < $enddate ) @BATCH_CMD $HOMDIR/gcm_run.j + if( $capdate < $enddate ) {{ BATCH_CMD }} $HOMDIR/gcm_run.j endif endif diff --git a/gcmpy/jinjafy.py b/gcmpy/jinjafy.py new file mode 100755 index 00000000..1dd0efef --- /dev/null +++ b/gcmpy/jinjafy.py @@ -0,0 +1,250 @@ +''' +The purpose of this script is to "jinja-fy" the template files affected by gcm_setup. + +Jinja can't process items unless they are enclosed on both sides with an +identifier. The old/current way to identify template items is "@ITEM_NAME". +This script will replace all these instances with "{{ ITEM_NAME }}". + +Variables templated at run time (identified with ">>>ITEM<<<") are kept +the same but included in case someone wants this changed. + +This script only needs to be run once. +''' + +import os + +def replace_strings_in_file(file_path, replacements): + # Read the content of the file + with open(file_path, 'r') as file: + content = file.read() + + # Replace all occurrences of the keys with their corresponding values + for key, value in replacements.items(): + content = content.replace(key, value) + + # Write the modified content back to the file + with open(file_path, 'w') as file: + file.write(content) + +def main(file_list, replacements): + for file_path in file_list: + file_path = f"{os.path.dirname(os.getcwd())}/{file_path}" + if os.path.isfile(file_path): + replace_strings_in_file(file_path, replacements) + else: + print(f"File {file_path} not found.") + +if __name__ == "__main__": + # List of files to process + file_list = [ + 'gcm_run.j', + 'gcm_post.j', + 'gcm_archive.j', + 'gcm_regress.j', + 'gcm_plot.tmpl', + 'gcm_quickplot.csh', + 'gcm_moveplot.j', + 'gcm_forecast.tmpl', + 'gcm_forecast.setup', + 'gcm_emip.setup', + 'CAP.rc.tmpl', + 'AGCM.rc.tmpl', + 'HISTORY.rc.tmpl', + 'logging.yaml', + 'fvcore_layout.rc' + ] + + # Dictionary with keys to find and values to replace + replacements = { + '@GCMVER': '{{ GCMVER }}', + '@EXPSRC': '{{ EXPSRC }}', + '@EXPID': '{{ EXPID }}', + '@RUN_N': '{{ RUN_N }}', + '@RUN_FN': '{{ RUN_FN }}', + '@RUN_FT': '{{ RUN_FT }}', + '@RUN_T': '{{ RUN_T }}', + '@RUN_P': '{{ RUN_P }}', + '@RUN_FP': '{{ RUN_FP }}', + '@RUN_Q': '{{ RUN_Q }}', + '@POST_N': '{{ POST_N }}', + '@POST_T': '{{ POST_T }}', + '@POST_P': '{{ POST_P }}', + '@POST_Q': '{{ POST_Q }}', + '@MOVE_N': '{{ MOVE_N }}', + '@PLOT_N': '{{ PLOT_N }}', + '@PLOT_T': '{{ PLOT_T }}', + '@PLOT_P': '{{ PLOT_P }}', + '@PLOT_Q': '{{ PLOT_Q }}', + '@MOVE_Q': '{{ MOVE_Q }}', + '@MOVE_P': '{{ MOVE_P }}', + '@ARCHIVE_N': '{{ ARCHIVE_N }}', + '@ARCHIVE_T': '{{ ARCHIVE_T }}', + '@ARCHIVE_P': '{{ ARCHIVE_P }}', + '@ARCHIVE_Q': '{{ ARCHIVE_Q }}', + '@REGRESS_N': '{{ REGRESS_N }}', + '@BCSDIR': '{{ BCSDIR }}', + '@SSTDIR': '{{ SSTDIR }}', + '@SSTNAME': '{{ SSTNAME }}', + '@OCEANOUT': '{{ OCEANOUT }}', + '@LSMBCS': '{{ LSMBCS }}', + '@EMIP_BCS_IN': '{{ EMIP_BCS_IN }}', + '@EMIP_MERRA2': '{{ EMIP_MERRA2 }}', + '@BCSTAG': '{{ BCSTAG }}', + '@SSTFILE': '{{ SSTFILE }}', + '@ICEFILE': '{{ ICEFILE }}', + '@KPARFILE': '{{ KPARFILE }}', + '@CHMDIR': '{{ CHMDIR }}', + '@COUPLEDIR': '{{ COUPLEDIR }}', + '@shared_COUPLED': '{{ shared_COUPLED }}', + '@GWDRSDIR': '{{ GWDRSDIR }}', + '@EXPDIR': '{{ EXPDIR }}', + '@EXPDSC': '{{ EXPDSC }}', + '@HOMDIR': '{{ HOMDIR }}', + '@BATCH_GROUP': '{{ BATCH_GROUP }}', + '@BATCH_TIME': '{{ BATCH_TIME }}', + '@BATCH_CMD': '{{ BATCH_CMD }}', + '@BATCH_JOBNAME': '{{ BATCH_JOBNAME }}', + '@BATCH_OUTPUTNAME': '{{ BATCH_OUTPUTNAME }}', + '@BATCH_JOINOUTERR': '{{ BATCH_JOINOUTERR }}', + '@SITE': '{{ SITE }}', + '@GEOSDIR': '{{ GEOSDIR }}', + '@GEOSSRC': '{{ GEOSSRC }}', + '@GEOSBIN': '{{ GEOSBIN }}', + '@GEOSETC': '{{ GEOSETC }}', + '@GEOSUTIL': '{{ GEOSUTIL }}', + '@SINGULARITY_BUILD': '{{ SINGULARITY_BUILD }}', + '@NATIVE_BUILD': '{{ NATIVE_BUILD }}', + '@MPT_SHEPHERD': '{{ MPT_SHEPHERD }}', + '@SINGULARITY_SANDBOX': '{{ SINGULARITY_SANDBOX }}', + '@REAL_BIND_PATH': '{{ REAL_BIND_PATH }}', + '@BASE_BIND_PATH': '{{ BASE_BIND_PATH }}', + '@BOUNDARY_DIR': '{{ BOUNDARY_DIR }}', + '@CHECKPOINT_TYPE': '{{ CHECKPOINT_TYPE }}', + '@OGCM_NX': '{{ OGCM_NX }}', + '@OGCM_NY': '{{ OGCM_NY }}', + '@OGCM_NPROCS': '{{ OGCM_NPROCS }}', + '@OBSERVER_FRQ': '{{ OBSERVER_FRQ }}', + '@DASTUNING': '{{ DASTUNING }}', + '>>>FORCEDAS<<<': '>>>FORCEDAS<<<', + '>>>FORCEGCM<<<': '>>>FORCEGCM<<<', + '@COUPLED': '{{ COUPLED }}', + '@CLDMICRO': '{{ CLDMICRO }}', + '@MOM5': '{{ MOM5 }}', + '@MOM6': '{{ MOM6 }}', + '@OCNMODEL': '{{ OCNMODEL }}', + '@CICE4': '{{ CICE4 }}', + '@CICE6': '{{ CICE6 }}', + '>>>HIST_CICE4<<<': '{{ >>>HIST_CICE4<<< }}', + '@MIT': '{{ MIT }}', + '@DATAOCEAN': '{{ DATAOCEAN }}', + '>>>GOCART<<<': '>>>GOCART<<<', + '@OPS_SPECIES': '{{ OPS_SPECIES }}', + '@CMIP_SPECIES': '{{ CMIP_SPECIES }}', + '@MERRA2OX_SPECIES': '{{ MERRA2OX_SPECIES }}', + '>>>FVCUBED<<<': '>>>FVCUBED<<<', + '@HIST_GOCART': ' {{ HIST_GOCART }}', + '>>>OSTIA<<<': '>>>OSTIA<<<', + '>>>HIST_CATCHCN<<<': '>>>HIST_CATCHCN<<<', + '>>>GCMRUN_CATCHCN<<<': '>>>GCMRUN_CATCHCN<<<', + '>>>EMIP_OLDLAND<<<': '>>>EMIP_OLDLAND<<<', + '>>>EMIP_NEWLAND<<<': '>>>EMIP_NEWLAND<<<', + '@LSM_PARMS': '{{ LSM_PARMS }}', + '@OCEAN_NAME': '{{ OCEAN_NAME }}', + '@OCEAN_PRELOAD': '{{ OCEAN_PRELOAD }}', + '>>>4DIAUDAS<<<': '>>>4DIAUDAS<<<', + '>>>REGULAR_REPLAY<<<': '>>>REGULAR_REPLAY<<<', + '>>>REGULAR_REPLAY_GMAO<<<': '>>>REGULAR_REPLAY_GMAO<<<', + '>>>REGULAR_REPLAY_NCEP<<<': '>>>REGULAR_REPLAY_NCEP<<<', + '>>>REGULAR_REPLAY_ECMWF<<<': '>>>REGULAR_REPLAY_ECMWF<<<', +'ana4replay.eta.%y4%m2%d2_%h2z.nc4': '{{ ana4replay.eta.%y4%m2%d2_%h2z.nc4 }}', + '@REPLAY_ANA_EXPID': '{{ REPLAY_ANA_EXPID }}', + '@REPLAY_ANA_LOCATION': '{{ REPLAY_ANA_LOCATION }}', + '@M2_REPLAY_ANA_LOCATION': '{{ M2_REPLAY_ANA_LOCATION }}', + '@OX_RELAXTIME': '{{ OX_RELAXTIME }}', + '@PCHEM_CLIM_YEARS': '{{ PCHEM_CLIM_YEARS }}', + '@RATS_PROVIDER': '{{ RATS_PROVIDER }}', + '@AERO_PROVIDER': '{{ AERO_PROVIDER }}', + '@OANA_PROVIDER': '{{ OANA_PROVIDER }}', + '@EMISSIONS': '{{ EMISSIONS }}', + '@DYCORE': '{{ DYCORE }}', + '@AGCM_GRIDNAME': '{{ AGCM_GRIDNAME }}', + '@OGCM_GRIDNAME': '{{ OGCM_GRIDNAME }}', + '@OGCM_IS_FCST': '{{ OGCM_IS_FCST }}', + '@BOOT': '{{ BOOT }}', + '@BCSRES': '{{ BCSRES }}', + '@OCEANtag': '{{ OCEANtag }}', + '@ATMOStag': '{{ ATMOStag }}', + '@RES_DATELINE': '{{ RES_DATELINE }}', + '@TILEDATA': '{{ TILEDATA }}', + '@TILEBIN': '{{ TILEBIN }}', + '@DT': '{{ DT }}', + '@SOLAR_DT': '{{ SOLAR_DT }}', + '@IRRAD_DT': '{{ IRRAD_DT }}', + '@OCEAN_DT': '{{ OCEAN_DT }}', + '@LONG_DT': '{{ LONG_DT }}', + '@NX': '{{ NX }}', + '@NY': '{{ NY }}', + '@USE_SHMEM': '{{ USE_SHMEM }}', + '@USE_IOSERVER': '{{ USE_IOSERVER }}', + '@NUM_OSERVER_NODES': '{{ NUM_OSERVER_NODES }}', + '@NUM_BACKEND_PES': '{{ NUM_BACKEND_PES }}', + '@RESTART_BY_OSERVER': '{{ RESTART_BY_OSERVER }}', + '@NCPUS_PER_NODE': '{{ NCPUS_PER_NODE }}', + '@NUM_READERS': '{{ NUM_READERS }}', + '@NUM_WRITERS': '{{ NUM_WRITERS }}', + '@LATLON_AGCM': '{{ LATLON_AGCM }}', + '@LATLON_OGCM': '{{ LATLON_OGCM }}', + '@CUBE_AGCM': '{{ CUBE_AGCM }}', + '@CUBE_OGCM': '{{ CUBE_OGCM }}', + '@GRID_TYPE': '{{ GRID_TYPE }}', + '@AGCM_NF': '{{ AGCM_NF }}', + '@AGCM_IM': '{{ AGCM_IM }}', + '@AGCM_JM': '{{ AGCM_JM }}', + '@AGCM_LM': '{{ AGCM_LM }}', + '@OGCM_IM': '{{ OGCM_IM }}', + '@OGCM_JM': '{{ OGCM_JM }}', + '@OGCM_LM': '{{ OGCM_LM }}', + '@OGCM_NF': '{{ OGCM_NF }}', + '@OGCM_GRID_TYPE': '{{ OGCM_GRID_TYPE }}', + '@BEG_DATE': '{{ BEG_DATE }}', + '@END_DATE': '{{ END_DATE }}', + '@JOB_SGMT': '{{ JOB_SGMT }}', + '@NUM_SGMT': '{{ NUM_SGMT }}', + '@CONUS': '{{ CONUS }}', + '@FV_HWT': '{{ FV_HWT }}', + '@CONVPAR_OPTION': '{{ CONVPAR_OPTION }}', + '@STRETCH_FACTOR': '{{ STRETCH_FACTOR }}', + '@INTERPOLATE_SST': '{{ INTERPOLATE_SST }}', + '@HIST_IM': '{{ HIST_IM }}', + '@HIST_JM': '{{ HIST_JM }}', + '@ISCCP_SATSIM': '{{ ISCCP_SATSIM }}', + '@MODIS_SATSIM': '{{ MODIS_SATSIM }}', + '@RADAR_SATSIM': '{{ RADAR_SATSIM }}', + '@LIDAR_SATSIM': '{{ LIDAR_SATSIM }}', + '@MISR_SATSIM': '{{ MISR_SATSIM }}', + '@SATSIM': '{{ SATSIM }}', + '@USE_SKIN_LAYER': '{{ USE_SKIN_LAYER }}', + '@ANALYZE_TS': '{{ ANALYZE_TS }}', + '@LSM_CHOICE': '{{ LSM_CHOICE }}', + '@MP_TURN_OFF_WSUB_EXTDATA': '{{ MP_TURN_OFF_WSUB_EXTDATA }}', + '@BACM_1M_': '{{ BACM_1M_ }}', + '@GFDL_1M_': '{{ GFDL_1M_ }}', + '@MGB2_2M_': '{{ MGB2_2M_ }}', + '@PRELOAD_COMMAND': '{{ PRELOAD_COMMAND }}', + '@LD_LIBRARY_PATH_CMD': '{{ LD_LIBRARY_PATH_CMD }}', + '@RUN_CMD': '{{ RUN_CMD }}', + '@HYDROSTATIC': '{{ HYDROSTATIC }}', + '@FV_SCHMIDT': '{{ FV_SCHMIDT }}', + '@FV_STRETCH_FAC': '{{ FV_STRETCH_FAC }}', + '@FV_TARGET_LON': '{{ FV_TARGET_LON }}', + '@FV_TARGET_LAT': '{{ FV_TARGET_LAT }}', + '@FV_MAKENH': '{{ FV_MAKENH }}', + '@FV_HYDRO': '{{ FV_HYDRO }}', + '@GFDL_PROG_CCN': '{{ GFDL_PROG_CCN }}', + '@GFDL_USE_CCN': '{{ GFDL_USE_CCN }}', + '@GFDL_HYDRO': '{{ GFDL_HYDRO }}' + + } + + main(file_list, replacements) + diff --git a/gcmpy/sync.sh b/gcmpy/sync.sh index 5225d453..4e48f1f7 100755 --- a/gcmpy/sync.sh +++ b/gcmpy/sync.sh @@ -1,5 +1,10 @@ #!/bin/bash +''' +The purpose of this script to sync up the gcmpy directories between the @GEOSgcm_App dir and bin dir without having to make install +''' + + # Source and destination directories source_dir="/discover/nobackup/sshakoor/GEOSgcm/src/Applications/@GEOSgcm_App/gcmpy" destination_dir="/discover/nobackup/sshakoor/GEOSgcm/install/bin/gcmpy" From 824e8f54c10c808cd5cc44c62f3f0ae9f6b1f523 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 16 Oct 2024 10:04:27 -0400 Subject: [PATCH 11/37] template files were modified to be compatible with jinja2. AMIP experiments are trivial zero diff --- AGCM.rc.tmpl | 22 +- gcm_archive.j | 2 +- gcm_forecast.tmpl | 2 +- gcm_moveplot.j | 2 +- gcm_plot.tmpl | 2 +- gcm_post.j | 2 +- gcm_regress.j | 2 +- gcm_run.j | 2 +- gcmpy/jinjafy.py | 3 +- gcmpy/scripts/.model.py.swp | Bin 20480 -> 0 bytes .../__pycache__/atmosphere.cpython-312.pyc | Bin 11467 -> 12201 bytes gcmpy/scripts/__pycache__/env.cpython-312.pyc | Bin 4668 -> 4887 bytes .../__pycache__/gocart.cpython-312.pyc | Bin 2472 -> 2697 bytes .../scripts/__pycache__/land.cpython-312.pyc | Bin 3150 -> 2669 bytes .../scripts/__pycache__/ocean.cpython-312.pyc | Bin 12294 -> 12802 bytes .../process_questions.cpython-312.pyc | Bin 12394 -> 12295 bytes .../__pycache__/utility.cpython-312.pyc | Bin 3732 -> 3860 bytes gcmpy/scripts/atmosphere.py | 331 ++++--- gcmpy/scripts/env.py | 22 +- gcmpy/scripts/gcm_setup.py | 919 ++++++++++++++++++ gcmpy/scripts/generate_question.py | 0 gcmpy/scripts/gocart.py | 47 +- gcmpy/scripts/land.py | 59 +- gcmpy/scripts/model.py | 496 ---------- gcmpy/scripts/ocean.py | 256 +++-- gcmpy/scripts/process_questions.py | 9 +- gcmpy/scripts/utility.py | 1 + gcmpy/yaml/atmospheric_model.yaml | 2 +- gcmpy/yaml/directory_setup.yaml | 0 gcmpy/yaml/exp_setup.yaml | 0 gcmpy/yaml/gocart.yaml | 0 gcmpy/yaml/land_model.yaml | 5 +- gcmpy/yaml/mpi_config.yaml | 0 gcmpy/yaml/ocean_model.yaml | 0 linkbcs.tmpl | 88 +- 35 files changed, 1362 insertions(+), 912 deletions(-) delete mode 100644 gcmpy/scripts/.model.py.swp mode change 100644 => 100755 gcmpy/scripts/atmosphere.py mode change 100644 => 100755 gcmpy/scripts/env.py create mode 100755 gcmpy/scripts/gcm_setup.py mode change 100644 => 100755 gcmpy/scripts/generate_question.py mode change 100644 => 100755 gcmpy/scripts/gocart.py mode change 100644 => 100755 gcmpy/scripts/land.py delete mode 100644 gcmpy/scripts/model.py mode change 100644 => 100755 gcmpy/scripts/ocean.py mode change 100644 => 100755 gcmpy/scripts/process_questions.py mode change 100644 => 100755 gcmpy/scripts/utility.py mode change 100644 => 100755 gcmpy/yaml/atmospheric_model.yaml mode change 100644 => 100755 gcmpy/yaml/directory_setup.yaml mode change 100644 => 100755 gcmpy/yaml/exp_setup.yaml mode change 100644 => 100755 gcmpy/yaml/gocart.yaml mode change 100644 => 100755 gcmpy/yaml/land_model.yaml mode change 100644 => 100755 gcmpy/yaml/mpi_config.yaml mode change 100644 => 100755 gcmpy/yaml/ocean_model.yaml diff --git a/AGCM.rc.tmpl b/AGCM.rc.tmpl index 49e1a345..d522d393 100644 --- a/AGCM.rc.tmpl +++ b/AGCM.rc.tmpl @@ -361,21 +361,21 @@ RECORD_REF_TIME: >>>REFTIME<<< >>>FCSTIME<<< # 4DIAU (recreate analysis tendency on the fly) # --------------------------------------------- -#>>>4DIAUDAS<<< AINC_FILE: {{ EXPID }}.ana.eta.%y4%m2%d2_%h2%n2z.nc4 -#>>>4DIAUDAS<<< NUDGE_STATE: YES -##>>>4DIAUDAS<<< TAUANL: 3600 -#>>>4DIAUDAS<<< AGCM_IMPORT_RESTART_FILE: agcm_import_rst.>>>ANA0YYYYMMDDHHMN<<>>4DIAUDAS<<< AGCM_IMPORT_RESTART_TYPE: binary +#>>>_4DIAUDAS<<< AINC_FILE: {{ EXPID }}.ana.eta.%y4%m2%d2_%h2%n2z.nc4 +#>>>_4DIAUDAS<<< NUDGE_STATE: YES +##>>>_4DIAUDAS<<< TAUANL: 3600 +#>>>_4DIAUDAS<<< AGCM_IMPORT_RESTART_FILE: agcm_import_rst.>>>ANA0YYYYMMDDHHMN<<>>_4DIAUDAS<<< AGCM_IMPORT_RESTART_TYPE: binary # Exact REPLAY Mode for 4D-IAU # ---------------------------- ->>>4DIAUDAS<<< REPLAY_MODE: Exact ->>>4DIAUDAS<<< REPLAY_FILE: agcm_import_rst.%y4%m2%d2_%h2%n2z.nc4 ->>>4DIAUDAS<<< REPLAY_FILE_FREQUENCY: 7200 ->>>4DIAUDAS<<< REPLAY_SHUTOFF: 21600.0 # ShutOff Replay after 6-hours for G5NCEP and G5ECMWF Forecasts +>>>_4DIAUDAS<<< REPLAY_MODE: Exact +>>>_4DIAUDAS<<< REPLAY_FILE: agcm_import_rst.%y4%m2%d2_%h2%n2z.nc4 +>>>_4DIAUDAS<<< REPLAY_FILE_FREQUENCY: 7200 +>>>_4DIAUDAS<<< REPLAY_SHUTOFF: 21600.0 # ShutOff Replay after 6-hours for G5NCEP and G5ECMWF Forecasts -#>>>4DIAUDAS<<< REPLAY_INTERVAL: 3600.0 -#>>>4DIAUDAS<<< PREDICTOR_OFFSET: 3600.0 +#>>>_4DIAUDAS<<< REPLAY_INTERVAL: 3600.0 +#>>>_4DIAUDAS<<< PREDICTOR_OFFSET: 3600.0 #################################################################################################### #### Miscellaneous Exact/Regular REPLAY Parameters #### diff --git a/gcm_archive.j b/gcm_archive.j index d48272dd..722f5a1c 100644 --- a/gcm_archive.j +++ b/gcm_archive.j @@ -35,7 +35,7 @@ setenv GEOSBIN {{ GEOSBIN }} source $GEOSBIN/g5_modules setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH} if ( $?BASEDIR ) then - setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib endif ####################################################################### diff --git a/gcm_forecast.tmpl b/gcm_forecast.tmpl index 86552531..2a26a7ba 100755 --- a/gcm_forecast.tmpl +++ b/gcm_forecast.tmpl @@ -34,7 +34,7 @@ setenv GEOSUTIL {{ GEOSSRC }} source $GEOSBIN/g5_modules setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH}:${GEOSDIR}/lib if ( $?BASEDIR ) then - setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib endif setenv RUN_CMD "{{ RUN_CMD }}" diff --git a/gcm_moveplot.j b/gcm_moveplot.j index f473fd45..cc293ee3 100755 --- a/gcm_moveplot.j +++ b/gcm_moveplot.j @@ -36,7 +36,7 @@ setenv GEOSUTIL {{ GEOSSRC }} source $GEOSBIN/g5_modules setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH} if ( $?BASEDIR ) then - setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib endif ####################################################################### diff --git a/gcm_plot.tmpl b/gcm_plot.tmpl index f68ca271..e9f26a7c 100755 --- a/gcm_plot.tmpl +++ b/gcm_plot.tmpl @@ -36,7 +36,7 @@ setenv GEOSUTIL {{ GEOSSRC }} source $GEOSBIN/g5_modules setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH} if ( $?BASEDIR ) then - setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib endif ####################################################################### diff --git a/gcm_post.j b/gcm_post.j index 177996ef..8a589028 100755 --- a/gcm_post.j +++ b/gcm_post.j @@ -38,7 +38,7 @@ setenv BATCHNAME "{{ POST_N }}" source $GEOSBIN/g5_modules setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH} if ( $?BASEDIR ) then - setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib endif if( $?SLURM_NTASKS ) then diff --git a/gcm_regress.j b/gcm_regress.j index 5ba8d717..99f70287 100755 --- a/gcm_regress.j +++ b/gcm_regress.j @@ -93,7 +93,7 @@ source $GEOSBIN/g5_modules setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH}:${GEOSDIR}/lib # We only add BASEDIR to the {{ LD_LIBRARY_PATH_CMD }} if BASEDIR is defined (i.e., not running with Spack) if ( $?BASEDIR ) then - setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib endif setenv RUN_CMD "{{ RUN_CMD }}" diff --git a/gcm_run.j b/gcm_run.j index b4df0e73..7e56e855 100755 --- a/gcm_run.j +++ b/gcm_run.j @@ -36,7 +36,7 @@ source $GEOSBIN/g5_modules setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH}:${GEOSDIR}/lib # We only add BASEDIR to the {{ LD_LIBRARY_PATH_CMD }} if BASEDIR is defined (i.e., not running with Spack) if ( $?BASEDIR ) then - setenv {{ LD_LIBRARY_PATH_CMD }} ${{{ LD_LIBRARY_PATH_CMD }}}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib endif setenv RUN_CMD "{{ RUN_CMD }}" diff --git a/gcmpy/jinjafy.py b/gcmpy/jinjafy.py index 1dd0efef..263541ed 100755 --- a/gcmpy/jinjafy.py +++ b/gcmpy/jinjafy.py @@ -51,7 +51,8 @@ def main(file_list, replacements): 'AGCM.rc.tmpl', 'HISTORY.rc.tmpl', 'logging.yaml', - 'fvcore_layout.rc' + 'fvcore_layout.rc', + 'linkbcs.tmpl' ] # Dictionary with keys to find and values to replace diff --git a/gcmpy/scripts/.model.py.swp b/gcmpy/scripts/.model.py.swp deleted file mode 100644 index 9828119ed456ce9298323498d949b7ee20b6c8d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 zcmeHPU5p!76`oSk(9!~G_z{2YjjiHc>e#zU6E%yr>elh@x?QhVwv$b?O{e4W*q&rO z`TdApt56s4e9?cjkJ= zv$LBtN_l`8>9cq4J#+54XYM)oo^$WIF?FO=W(RXq60Ubi(o_FfYNdaC>CR7nP?8*{ zqnxxXo2s_En!2M}>zX~icRMOc%C~zhr<-q@jeYy_f_Z+SSgEzuZeBMXS22uyLpSrd z?+x;fYU@4M$#<=$X5@NRloc?UjQM;Tm5pu|L#crrGEX5{`W(XdcQdNN;HsYAkjdg zfkXp|1`-V<8b~ydXdux*qJcyM|Cbt2nv!$?JwHS7GWP#P{Qu%RCFwEXo4{v*lfX^D zdx6*9AxVz_4+9SYeV_xZ03QKfy-Jdv0UiME1=fHYfUAH%UMWdG1ik_^fhpi};OyJM z6W9P&fZKpufh=$(@YgFO=}F)T;0*8}@CD!)a1*c_V8FG21f0EGlD-3c2Dlrj0q+JL zf14z&10MrsfP=t?fJ=d=cS_RFfzJWQfTO^Nf#)uhq-TN81FOIh;1b|>J0Js~0}H@T z-~}Wqz7O<(n}J=xKarex8Tb-V1FFC^z%xj?`~tWGxEk02(0ll)pSyTt1CoWVH0$;a zS8v-^zsGFtuD)(-4pUraXo}-9cf(>0MLnsRP1e&KDfA>8yD?>-Oa>X7WnIPX;Vh&Z|duMQ){xuAVTan%6Ov~2B9k=QKSn(TIyV$Y36!USKYOgDHm1_JE`MQ z`BlYG`-b9b7t+3`KvQnnmgz$AT%*@RWl=qj$?qx6wQw>fq&m@IUv+{dqx+uGcS58w ziX7KaNLj35Ys$&7_C>AUVuo&NImgA3oQX*`JIhitGpU(aVtQzEzu5J&Y&w=6%yn~Y zC@C12UVA-5cPBC|lV#JBYg5PBZZw?Urd<`<)y=*Z+YkvBX=#?#?JcNBeU8dNoi9|D zmWqXXsj^&)Q$x$Lc?ZxOYw3ozSy7whm{$x(8#liV-R&@|r1=2=AD$WimCCNx z?a^q=9M9b)djwgQu``oQabg;cc_XuIYD`aQwrp*%4UNHXv^&NCT-tqGV^$wNW6VCo zc8M-hN@f! zBmw6}Mi6b^YlgdrF%J-G{yfZoUbo>pp`ES#fY*M+3t<$6US3MKWY0yWg11K2M58bm zBxzO{`I<_tSUpm#dfp9Q(}4@LOn7zG>UQBsaH|+?%f?vg1|9di?0FqWGg>*t?OIN5 z`6x6UzCXrCKvQd>)b;%K1l3P^(xj;vlZbYzr`bB%bA_87jU3MHgw>FpcGrc4&9YYN zbf^hYHDpu#N(FuIRls#USswrlU7p%0Dmg8!!tJ%4FX(=@>31`<- zTxGK)=Vph8BkUTgBh%!0zS0Gc(<8itIvl>;v&dHETCENRaa)&&fG!P&AG~`i+2XM= zSA~HUQgW%xClYqktXJx(t5o**ir4E{T}^h}eybJtj;WTdE4HpQ4D?uUp2P}-#G#9~ z)wWc{c5`sD@C*}ywem^>UVDowZ|wPxabi!t<)hiKxXZ^PEIq2R=BO)Pfy~FaBYF}q zYR`uDWpv7k6?f}uPvlMY)Vx=Sv#K6n>JO|%A}#R``ors_zZ$~$aiKRV$JDW03C0K~ zgKf!8-KJ`B&4!&u#wQ3ldeBLNmh&(@(-md(JqvGc1{0xA7GBVC>Uc7-H1eG07TjnV z15495AMXSG+k5cf!Kr;ydl`-z;)-;(p|vsfjXi~Drf)nrjc2BXi;x6MF17F=q7dJ4 zQb+A<3$l>E5e(zFh5X2NWFh~s9a(E#R{IV3>fl1RBf8NYdArD4Hc zczie+SdmxiunFE;mT^{DE@am4)g;zYu7zn&V-3Ac-|$RW33S;B-8`Y}WqP+~!N7{< zx{mcVO;cGmk9nmwz(mnqvXrJ~XITxaSJgd?IkSbvn;wTAVj4ql2o@{2m3(#-?m!*~ zPO8(#c*rtZbJ2P(%LYo<@EA~y?hXV4Ka9vSVoWQxEJZOmMbG6$tso4R1?a49o;>AI z_%GKN!MpQn=(UN5>2I%;YpvJOuuk)z36)?a$nQK-@6GvC{6?bq|F?*7e}(v$;(xJ! z{wU)7uL1+$2rvy?0h~pA{{ld@P1$ia6jVx0x$)<2Y3bX{PVzffiD6Uumns3mjQo3T>m5BKH%fPDsTg^ z3%DA134MDWcn)|LpuYYRNUlT!i3So4BpOIGkZ9n4O9R~jj}9qeK%o~cVnvZ^^#(F6 z;vB3|T}wuEH9@zsfu!?f5JvJPZl<-aS~lvG0kU97Ze@;3V{6}xVYLy_v~#o|M4FOc z5t1M^mUEG_<5UrnxrIU*+=F`XiI5cLR-zP968zt!tabHXjwfwAX(C*R1ldVV#YTW2 z+m6H+IEJK)|M~10mYX}VWkc9_P)~9i)#-pLh6}G9X=PKVNnBfN<25>>oj5Lvt#e@?k2FQ*idlz!ZBG42e3^a+&RzN>_8%@aS=#@(YLm;>mz7 zNtB{?kN|ZDylMRCzWuh3U3)Tx9M4j1}9?eO~)DoZm8@7b+hB7g#PO0-I% zdh~~{Cy2C`DJ|EF)#bUROg2+0uT-k_s8{!%&eZDFxq4x-SkBCNIosigo#2n}%tE;o zCd$SV73QktIl(8Mq&zojC?N314dgzZS=?J0aR}UCn(evJi^u;6-K7s)f)B+1;(YxR zi1p6^p8ytsS3vX|;Mc(SfO~;kfH~lG#Q9GFj{^hXX5eMS@!tSCz%9Vf5XV0Wd>!~S z@F}1JP@GS({ZD{9fmPt|h}q8oMc@aB(;oxA4D0|53Yrb2gbx?H;1LsVdPjW~scD^tPEn=TaIx=g>vV&k|>oLrIm)Y$!hMLMpGtwa-* zTrTe>5K1$~jfK`X+(>As!$yR8ypeIZKi}3YXa6}ZIy~ZI%sN!!3qJt~v6W!%-nEj(9{_93AqRVbM6-Km8-?%}{D09Q=A)q&NW5 z8%#L1nq@cvipKdu*n2~xp7^UQuLn_DuTLc5=m^pr_D5Y8O7k9Mt-i_6oN}S5LFyxE z0=u19Z{qjJ5Cif;Iu@qGsA&+>-!!ZxQqjd)g>qi>Aug_S4Kg6bh9j)HFB3`Wi%3(m zXBZb#2x?yvLLhNPSri=7LD+~J+J@#SD1UQ$ErY^L=zwb)R*f`=wvN+n-gA7n8mUiP zLpV+P#S@eq;D0wXDuFVwdo0?dZ@(!tO4-nyfxw(+3bH&#*X&tdJl{7AZ%aO~+#n^8 z$>s7ymIpJx6JBmLl*e8#hQH15RMx;U>uB7xFED*wBN uOiDF$O0T?9!U+VV6B%kqjTbo{3O64%Mq1n;yLn2ckj6i6<;NnE(tiL>oMEj1 diff --git a/gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc b/gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc index d2b48271bf2b4f467fcfa465a730cd402a9551c6..d97f50573188cdca56fab4774fce29ab835dbe8a 100644 GIT binary patch delta 2858 zcmZ`*eQZy62pG@43GB{GEjTp3P?A;P*SlIQ#d5>-Ja4@%0-=EwcFv_ky)xiCEX~ z2Y5wT|L3EIcL^$T+$AnyV>d|$F|uL4jXfkTv%MnWIQCzIdr&s5h?<(C#+K2@S%+LY zGJ&j-y}<8lX{zz^T1<#!Gc4jYH`gS%0K3l{onX{bV_xFsI@w>XO&%*QEE`rp0CIOt zE;oQ#Tcd1y(*W#Noz1aHgO}LR=kv1TmxAon6xw$bK;5e&DF@9iZaWuavg4AEr#mIKV&Ch8Obl0RZ`VG{fU>(|{qZZKY(UBWaNJp)# zD2&W#yAaix7-Xyt#dXvMvVA&2&HXy^0P5FKJD`CYDsT}myDzw%j$;#v@1wbvJ_Fwze9A@m3h>QPJc4S&LMBDCi{}fuOe&|EG7E|GnOt5q%~dDT zEX~L>nfbIT&1KIeaIl{tbzfn7NwxiMPM%F*bj|wn2aZ%OPpWMGq4VenO zjc30#z2rK+89K2Q8s7|!|0yt06t0<=Svq1U1%eyLq&{-US_*`K+fW%CyN8F8w-k;R zg@;nl6C)Rd*)`DKQxvY7+4s$#lS#I0iIOSyjwM9C%I;aF$yw&NddMpq&se7kSztFB z9+Q8uRoi27c_VATL&)t7k8_L|M1`Ltj6QFo&=>a4MksLxYgaj`>#rsaNhf!>K z^jRc_k$eTn9Rr<&L6x){nt*EvGbdcugi^?15PrX(POU$$C>Pzh+|egk->{cL z(KX@E&fv%Ff5AcK=V9uJvg{|I%hYNa*9ZeTa8zCs*V z;9#c=bu#_X6*yVYB$8%>A!)w?SVhE1dIS*GjiX1A36#HLAq;u&6$CUuZ}J-e|MzCg}sXYC{gfd`JBLUJ0(?r;FB=3F|D9eXLa(wxjMWOIw>(=;8|xu@Ca z-m}$8zf`TXkr zNP%*K#kDKq z3hPA-bC?zT23j9VZ6&E;OX}E^IzE)Tv`{7^4eSqnJ*!_wzb_)$S@kCfpIVv$?+&M# z(kYZ1YXtMiVUN1PmH7d&r#uhu)G1Q7%o)TzS;V1on;;H- zY8OR6g-!o%G;;js=nN~Q`Tk5gvXGUR=F`LU7r?_k&*4A9Ck8^uM_l_yoaf)dw?*PF Jb4WGA{{t~7kmLXW delta 2334 zcmaJ?Z%kWN6o2>iJ^H_l{s9W5lu{_=Pk}OEW^8T_m>|^6u{gerus$5!MvJ$d8R%r_ z)W!V+57X$}hxtYM;0Gl!(NDU>7_(#s6SuC>WFL%%#JE`!W9ApndC(T3^EL1H?(dv) z&pG$pb8i<%ZVp>+n#~3QpU$7#p0l>iTh6eq`O7<`DSf~&f7>gjH1iMdflDkho5_lv zmxNHlQLc`noR2E%C>|Lbjit4yJrR!`O>3gDWLoSSOpE>ah7aL8%&9Zdrio~T z$0x_9646K^t?e5e8ILBCX>I=?{8_NIB7A5h5|6zw#*=A7csMtf_dFdwcmVcl7d+ZT zWPBp3pguXukB%iNV1A4VZ`VzU-!S-0cNiM=?Mvf&KPxn)ytU_~3x(?EVj+BO_?zv4 zuZ)eX8-6#|vQ}`IhRS;}!H6bX8T`_i-qj;ZXH7$ljlf;=efBGSYq`(jOP?1mGUI!v znBqKMCkXrlh?i6?T`KZ0jTBpjPptRZi*Vhx!V2KLeMO!}LqA-$AB0_aqdglI{WHKFLD97JO)Ty_;(P+5k`7S+#r z%pd~4l`iBBJaa7eCK|M=2D6U{6oN`y9W=SBz);e^UG<(zr43`*vJAaR=xwX&?eu?o zn}wbBz7A!xllF~HVy`G2s)LswvFf#Cj^|eaPIC>UTtTTb%#C2E@H)3(M%;w3QizZi zTehvxeZUK$ry{0Zxq)5G9q>g(txJxycXqTy&*DC=d`Y%aB-GimLf1?hWcQ94JEtw? zbaXi#G43I#BB0~Ry##b#xSybrpoyTFpoO57AV5%0KsN+0B?u9;AuMY69{i+r>OmR7 z6OkPmhZ7XvxVrr4MFaaj(Tr*PwiX>H}$Bm;agv`}vN>F4~qf_NlUXJ%dL6}oY zJV|hzpp#%5LO|x&`NEoBty50LpFl-|62x^O!Y{SWRUYJtc4TLSl*M|-Qn_rY{Hdrc zRarGBEtpc3UTF5aSuc1Rop99uWCO*R)>e1-4D<~3s0jqbwTNA)*%Sh9`$McA^mPHN zdW<)f2I}j52CB$Ofv?v?hijIQ*24RBF1Twgb}QQT66mlrxuZBG&@Z5ezv}8Rvzmav zWi6{<@9u#EJ;8va-fMgZCA5=3t;ojJ!|Q>q&$iOi2T;Ghbnmjo`(u$K`q*x3#8xO>^B>1|Mhyd+32yu$FMOR7;`yXIQ`5YL8O_ z)Ngzj!ES<$sUT156L@K=_vy5KG&vDZOpcH7v0zTx1-BaZ`~GzoQd6k?bq)vb;D5+5 z2G<=nm~5J;#{#i1R^l|pn<03W;57pJx8Bg7gn62=cyWiRK-?fpk$&XQ`dV3rJ5uDJFslXN8Oyko}oMOe61Q8N;|n_GN~&I@z1C zOLA?-qL+i2VuRedS|-WPHCN;y411eBW#@5}cmGh=H4#@%o*3K7FTrfHv#?KQ&Wu2) G8vO&v3-RIr diff --git a/gcmpy/scripts/__pycache__/env.cpython-312.pyc b/gcmpy/scripts/__pycache__/env.cpython-312.pyc index e52fa08ecff323f9113d7f65f0e2a68ceda3adf0..857deed04a32a112bf630b96a7ba5159043101db 100644 GIT binary patch delta 934 zcmZvY&rjN57{}k2LQ5$KYKXc4qJYTMxv6pfz#pIl$rKD|G7bwXmQ7}<1YA&e&?U>p zfdgAjmMlwlTH;|@vT)shpwWR#Bt3cAL9+wNmTbum?kx&(SeriY_kF&f=STX*{HCLB zPo+`-^!z08N8g)X)iuK(pRFG;IKZzF>}j)@BAtmD2I-x9Rb!P)7M#~X0@7ecchr{CfCxB`MYo`|pr z4lS+5Vl>AH^=0k?2!`ez3o}9!%Y@iyI6)^iLUDR+xx#Kzv3NA`gfsSVaic&XRdECb znl`&v=&Tbq4SaDdCaYT|$*Q0Aba+Xt~j0L3Wn_Vr_jeGtWe(;N&1 delta 621 zcmbQPwnv5UG%qg~0}z-$F-|KIoyaG_cw(da8fHeX$s1UddD&8wQrS|JZGZ|Y8G$0Q zlmD}DaI2zk0%4E$WDoWPusnMbPbFhHLj`jrLph_S#bybP2u8+$$%UM9vc*No`i=z! zIho0cC7Jno#rh8JuKvO4$+_`B(ap0sjTx0Z5{t`Ib8=qF0KI>UEic|VAhh@vdvJDT zPGWZIOJHa*On%5EEbvkSB+uzol%JRaQa@RU`~T+cJd+u@Vt^8iKwKQNIfU;Oqks?t z3wMWEqy2=mOUyDi*aasC2#7OYn*3fsZ;~L3^amz3PM!~Z46^ba>=QUHaY%j;WZ*LY zAi}`LJ9(mjvK&z42B+`@?~9xY*EuyWa%!%KzQk#9Lq-m)9Ab(#*9T?>F5?euAWeFL zOIbfMF!9em!e)`Pk^cX>;k&eG2^LYhEAPE3R1fs(L diff --git a/gcmpy/scripts/__pycache__/gocart.cpython-312.pyc b/gcmpy/scripts/__pycache__/gocart.cpython-312.pyc index 1a7f17b4b5bb6349e346bc40b068d8c8f02a4605..065a559f75a2ceaa227597b8a472d08fbfdc3861 100644 GIT binary patch delta 977 zcmZ8gOH30%7~bhVy0G11|#gd^Jkx{Ezv+nO$!!w9B7lxtReo zedgkLRsMp0uI_v|#V;^3>N4F@7+?~eQBwq9y80ZL7MM)lp<75#44Qx;oypE*GqGqQ zmaXcdsYHf^H6DFcm!6x!v1DW}mq^9PlE%s5NG?lWYVv52IN1Bbrf94~GGtaoi$*M3O&CN!VmoV+Rs=t^_q$0U=G96DuBgrtP%H*}q z(8RTg@PwPgwqvk>k5dpRoS_N8fU2 zQ)dP(mP603s>2pg*|0KInEGn*mSu0n(cAFpsrw8phrnl7%jkXBO3w2}^bJ%Q6BV|h z%5TBkqISwbLDlBT8)0Nv(Ka;UKofp{PZ5C~sGu|fJB*{6G?Q_y@k*Za`~3bYd;P}k zAAJy;*9L~p1^j-WTfhe3RX&?ZCUUqP=D34GCxuoD|H$!N>s?I4YF&w7A-FABOOmz7 zZb+`;&63o&ex@u9R$OY=_KFL--qhJEHsD)23zcTNFug6?OR~M_+>m>VPfD_T{Z3g9 zG-AvLu{O6FL!~;6k31^UBHkPH(vuDSe>~t-A)0>tAQ8{Y@pLqTbG|zDkr$#JS;>2G zz}`*6+!PM8oCW%dQOm%kOHEx}I=;Ww&GMH~ty$zfwKkFO-|Nuu7Pz&sCijIA8c$D! oEdYPS(NtQQO~!&a2$VjaEY)(CMF{OMT|12N7yV6Y41gN;7umkw&Hw-a delta 766 zcmZ`$O=uHA6rS1L+5B$ICg%UgO-j>jk_uW;5v^7WMMW)b@3Cgn5R6HgRJ29JlaPz1 zj7O24q#itZ^&ogukfOyUCE&q>0S_TP2qNm6jUb9Xm~Y&hGaX}$X*g>Ipu73N2V49vwnZiWq*o4v+!SYi8wgX*Q(`C@aqT&k9v9ru|F zXJ^?Jp}-yrBhuW|!aRE^tl=AMQoQ`^u^7NO#-2+B9A`Z#js46`7Gg;#TEbTCA&9W? zwR@L+mt*dm*uYn_2+=7xj4TYBKKwr#Jrqo&ME?q4T;8}g;;|GT~i zU7tJ(U5i%NUW^P0Bop9W%M1dH&u7^x$ZO^8v9cugjU>RG4a+jwu!eqxvm;A zv(}`eW>#-Y+uqR~HTWx}Sv!RK1o=WV$ree3{jgs=P~Z<8`ujED9l6w~FI6jRN~KX+ zq$~S}be!FGq;QgLIP$3kzXm^w=5CZSE{b+hn@m7TIG%qg~0}$Ll#gcxBeIwslMitiF{FKz3Tg*wx#kaT$5{nXZQ%h2dif?hJ z=4KYe14ZLA^CojM?U0BA>T6)QqolJU>Y|dxbtT7(N{$^YJzSITFi9}=@NfRkbf0nZ zJ}yosGsejeS)@2p7_&7P7>ZOT%W=p~R$n&z?Uz1x5x7d7LgMu85ZZZ4$7~kT9aN_+^%Y72_Qf@Jq85&J~$?8+T z0PLU}-2D9(ofZ>HFLBGl>G8jzrrqIkg$Kyh0MW8wVKA-N;c^uy&MVj-(HSvA z^b)TeSPilkpb225Fs){|w5TGi!LH{6Hv^yi`MY(N$>&|6?o$xz9l$?kWH(>bvuIU_eUujC~oP-1c{hotIDCLpUw z9Y|=h6mbKoTiiLoz===J$j?kpEfNCB3Qz9gG>gy%GK>9zL<0jTsH{4zW=LP+R=J_3 z4h*Q!x5+k7$`tBAJ`fA41gZXWYYoJV>DTs zTZ7SbvI}<@H$(s=YBG5#w;`7htNAA_4pz<2B9k9*>oHnP=I4=6w+70Cd{Qh5Bt9@R aGBVy}kh;qt`JKg>QT7u9kSLM>$^ZZ&RnTAn delta 1326 zcmb_bO-vI(6rSB~e-|ngN?Lzlt@6_bN(B^xdZ=xK#IisE4JNwO-8HRR+DsP}qN(2S zqL?|TQDeNBcrsp0OgworYA_{i78+vW#e-TwW5NYzwxA@Qj83xO_vU+V-g~n%^Qroc z%l@jo+y?OI{Lp@S+WN%)nhLPz;^UGaCele!)(oe_tX6R=)J#&xY99O`ir}@$GSx?uzCphZ~PBVFn3%#XXhP-9R(~tBLWi#L~@~yl; zgXV2z7b%H4+XMitrvUoS9Hu1`dTt!-vGAIySB%4n?5cTJI1-HvN2b`G`1oW>mRdT5 zfCe;EUnCX_wymCubJ@9bsclt3^P~3EmYR7yEcXDOL54?l5Rb;$O1*F`(|Isz6bTD`Fxgk1J@+?9RakEKVhR`v&@B!$E$yo6DS&<5`)@$_f_^@?l{h7z_3db#qFZ z3-LlI+Sd`_lH*(~)Y=p29}4u3YHz{mRsDf=NoVh3wfo-4 zgV8&qw~rJ7Xd0xy0T82)(LV^Cpud&~y9Vi#G^T9={T%@37@b@AkI9N=P~$7wKx5l< zIA6A1ZD=K2r}JFd&OaX-4bYNh#N;DC#*ezKO;i^Wtw-6CK-2(wY29NhH|}4qtuzK! p8qk{6Pjw)_&DGe6{p1m3ofwJ+ilPc&YXP`_F#D(-%K(F3@FyRPP&NPn diff --git a/gcmpy/scripts/__pycache__/ocean.cpython-312.pyc b/gcmpy/scripts/__pycache__/ocean.cpython-312.pyc index aea87ddfe0755e1d3558ec146a1fca3f9d2039fc..83d662d19ed58579ab51062aaf63f96da3c938bd 100644 GIT binary patch delta 1545 zcma)6ZA@EL7(VB=_x8KDx7XJ7wzSmJ^8KL*6NZC9KNxPqWr9L*I=#pkrMPx15?GkV zm}0gJaz+57*tx}J#zahiNaDv|qx;i)b?HsTi2l&bABNTaP=6TDy#)hvA>QP?=e+Ox zocHTIxo^=vYp5 zYIF=eqduUIy^IGYU zQhh<6j+4CvtUzCBeuH&rRr?97Prs}iBVc2C-S8O!JJ37kkhXuOf3ZO{6{mkS`yqS+ zSu6*rvuXeq06Jl^qwkFxxF1beCSkR#@8QXjG63RQo|*#BLAe+Ci`f-0!>`jRI&w z2bmH*uU8ZwZ$NWaA6jO-GHweqB4f0?S;6$6o6HB>y-EZvZ!bhZuUf3YZ*st-xfx z>|dyyt4tXMYt@J2A5Gqv6s*m+jQb=Lb4ea`qiFI<&Tuk#@z9n@p1$M_B!k}?-Rqlq zY@)$EeXTiD6B2yktgl<}b!U$CiM~F`z6WQGNOo>vXl^J4=SCFO>rV!68Qt4MUhB`) zMFf9m)_+v+AIdP95bH7`Jr%s(b){=1AeKC~ z#ujDV4FcPkWm^TdHOqzsHuMb}Ne0*Kj>VG2(@Ui&Do^VkRdN;Mq7HB9fWImJD1P%7 z3%s@zctPMzh1c(AQIX?wU4h>TdJ1JMHV3a&=&9v(m`GIN0>CsGXRdT)JO2rB#KGZ0=Fr6+Q-acoEX0xBdYm^bgFI18dh(r6MMhxW2+6WMr3eGLFV9hA7tC8A8HRbPlJw>Wpp$gv pThO`MAordeOeT&J`!8(^{-uvc2lvO{N8i=D=(q|7@<5gf=pQH_-UI*u delta 1370 zcmZ`%TWlLe6rI_J9Xqk>$96Yfd)JTHiQ}Y6TotKlppEk~cJqQt6_yYo%7!T9RoSI# z0Feq1YEcneO`^DJ1F?#f!WWg1TBL&b;ExZop_R8utQ3I|@PUk>^beTbBvp#U?9S}W zx#!-Qopaul-g(jbjm2UHxP86U_R{gX8`kehnwlP-8buGtK_=0+P9$;f?OP`keFN)c zvTp#TsF=C`xpksHg?kVBi0X#VqF*Ud$fQS_W2a6{j*kqV9-o=cG`GjQ2TqKQObuZa zIq9eDjF_EOnEC>9P+<<9r!JcE!}Li4)}vd--(VA3skjNF`61H`0T1QBt-MXZ7`kZf zu1H--WkYKgZ~mS&1YrXGvoB^iPXe$A(4d8_ItwK@5e6WA3<4zCUK3mxp>@Orfn<0c z3_)1unT`WfSsKmU7WZyvD~Y$EuTGcv+YKk!XCYAJErA%lQOkXwP9z~P(-Hg z*aG)=YqFcHZ`FTTVOtAqhr)IgU0yX1%+66)jcTBFr7l-@J(g?8YRd!BEOoa!Qgr$B z>7DAxraQD++p4&a6x^MPyYs78*4({nZ8+O?HLli1R>pE;pAxyrY}Zo!{^KZ_o6^vt zE3jKi+jP&Kb6vTnEVX3Z_+Q2jp=1Pn&BF@d@X7+(f5ouL`Bww23U{Qybt+tEflDY{ z;ydoROl|T)R$7i;9=p_qSfK_Iy~ zjGD|wbeVsz{Vc?msK%C{bQ?HzOKe-tB30;^89U8{MK|Ddy=kKFxbQ7h^0P>GCpBYk zJJ5!M`%sg|qj}J#SHKWz^oSbAu?t8}je~A^o+Q#!=r2zc&Y-aHuJH}LMP>`2&xNPw zwpHG;iT08U^_Uuf-|HzL)V!#=K)pp%3bqu{j(7Nkq@qh4l8_X zf$vcGj-n8FByF88o(9x!YrO;1VAb~k8@v#F94XO243)gV!R7CXVEDU(&4f}A1dj#GH;-huxx{L4=fv+=}=jMA||v$G#l-L*U*>I>c$mZ fMN>Y*@ATr diff --git a/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc b/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc index a3c2d8d18617d8d070e247a01f4f3c0ad7040e28..32776d843a9266e04b39f6c58a40d0835faa9dd4 100644 GIT binary patch delta 898 zcmYjPUr1A76#u^aM|Zb7b#v;Rb5m2-CEYYzsbGI_GtECqgk(i(-I<%ZyFM>rF~NK& zp@)n^sfgjDAw9?*0w1DefzZoD!5Ti~YxLkBNQfS~pJsR-ew_0==lst34&RUNXWhmx zMx!2Swpo#Ke{9jX#NZZKVH}2Fcu4IT81UQ;hGQ(-lWqRRAT)`hSjPP)5t_in3ZuDI znal#F?Fh{vnVn@u7!|=K&d!7cz+5IcZTiA?0jY+=B7~xh%q?hA)Vyefjj|ylblYsO zY_>pou`W&1;iE`S$<+!%88B{hVgcrDE{~ovvf&{jEi$hbXu*NWhrCF)B8+SdW0`8C z)9rFHj%{~bwK0#X_T|-`IKKb?iWxM^Mzy!niCqG$6|5G*j{W92(ya-R z9u1P55($Kp90~NuNq$Hr!3Z(ZO## z4HTBd4JsubQFsE|CBID~FXKHHrI@!F>TWw=wKO+oaqVN=3!+qu`{A+_zy#h&9)3dW zdmG!5c3C_D>*X%2!k_Yd^MPEZmXo-{sW0G^yOf{On2)gzcR$ACuu!PPs6;_gM>f*pJAQk+fbhx!YfrRntm delta 1030 zcmZuuO-xf+6u$SpK1yGCErnA0Lt8DiP_;aj2;#(`w%|{!B$`a3ld&|sH_$5W^R}a8 zQeZZd85xb5LqZK2Su$fxO1i)>$pj4=5?x@%WF{RJvv8ve1G2!lntN$#T=*6z-~G<{ zzVpsGKli`wm!3A3oO8cXn`K zI7ZpxIv2M!`FMn;P!22jVk<(KDvCIUZebFHMQ6K}e}I`aLeogm(JWE~C(JjyJ@j35 zPdCbC%V`>u)t?}OzFltk*CBRB4Ja#Bctu}v!zgR6usKete!!Jq`_U+$GFuVq6JPO+r0Qb&F2*)WaP zO8YN3dtJC~#tK9#(koJ!qJ&3yfrZTCt;X!cA27kq`i1!3MeXDmvyU)2Q zteP!1uU@-)bL`q!UU_A1UgHGIFkZDf@`1_ds>7XEX2R3nHG~_IcsBCS{;v6RbLWcR z6rzik#e>V~m%i|Yzr%ws!-FeFhgS9_^5V?iJJKt=yvZ}gI@5vdSui`0H?%1-Zp#Zk zc%p5-#vTqm?%EaU;Gg)bDPHOjBHj9>uk;i@#V7A&6qDwW1j?ldtY!kKVPHsQ zOA)jI(v^&wLYsFmB{4EOO_pYnKe#pw=XPX5D_%;g9)m=TDJoi=CkDl;-)WDuWRz$YS*a9Jv` PfulqE5`$B+hAK+(+|EXz11$MPm~IRH&!1ma@l&8K*k896R7h!^n! F`2c?N9f$w` diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py old mode 100644 new mode 100755 index ead977d4..ab853446 --- a/gcmpy/scripts/atmosphere.py +++ b/gcmpy/scripts/atmosphere.py @@ -8,30 +8,32 @@ def __init__(self): self.force_gcm = "#" self.num_readers = 1 self.num_writers = 1 - self.DT = answerdict["heartbeat"].q_answer - self.DT_solar = None - self.DT_irrad = None - self.DT_ocean = None - self.DT_long = None - self.IM = int(answerdict["AM_horizontal_res"].q_answer[1:]) - self.JM = self.IM * 6 - self.NX = None - self.NY = None + self.dt = answerdict["heartbeat"].q_answer + self.dt_solar = None + self.dt_irrad = None + self.dt_ocean = None + self.dt_long = None + self.lm = int(answerdict['AM_vertical_res'].q_answer) + self.im = int(answerdict['AM_horizontal_res'].q_answer[1:]) + self.jm = self.im * 6 + self.nx = None + self.ny = None + self.nf = 6 self.use_hydrostatic = answerdict["use_hydrostatic"].q_answer self.microphysics = answerdict["AM_microphysics"].q_answer - self.IM_hist = self.IM * 4 - self.JM_hist = self.JM * 2 + 1 - self.gridfile = f"Gnomonic_c{self.IM}.dat" + self.im_hist = self.im * 4 + self.jm_hist = self.jm * 2 + 1 + self.gridfile = f"Gnomonic_c{self.im}.dat" self.job_sgmt = None self.num_sgmt = None - self.res = f"CF{self.IM:04}x6C" + self.res = f"CF{self.im:04}x6C" self.post_NDS = None - self.NX_convert = 2 - self.NY_convert = 24 - self.CONUS = "#" + self.nx_convert = 2 + self.ny_convert = 24 + self.conus = "#" self.stretch_factor = None - self.gridname = f"PE{self.IM}x{self.JM}-CF" - self.res_dateline = f"{self.IM}x{self.JM}" + self.gridname = f"PE{self.im}x{self.jm}-CF" + self.res_dateline = f"{self.im}x{self.jm}" self.BACM_1M = "#" self.GFDL_1M = "#" self.MGB2_2M = "#" @@ -41,9 +43,17 @@ def __init__(self): self.MP_turnoff_wsub = None self.FV_make_NH = None self.FV_hydro = None + self.FV_hwt = None self.schmidt = None self.target_lon = None self.target_lat = None + self.convpar_option = 'GF' + self.mp_turn_off_wsub_extdata = None + + # These are superfluous for GCM, but are needed SCM (considered latlon) + self.latlon = '#DELETE' + self.cube = '' + # for debugging purposes def print_vars(self): @@ -51,245 +61,246 @@ def print_vars(self): for var_name, var_value in all_vars.items(): print(f"{color.BLUE}{var_name}: {var_value}{color.RESET}") - def hres(self, ocean_NX, ocean_NY): + def hres(self, ocean_nx, ocean_ny): match answerdict["AM_horizontal_res"].q_answer: case "c12": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_ocean = self.DT_irrad - self.DT_long = self.DT + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_ocean = self.dt_irrad + self.dt_long = self.dt if answerdict["OM_name"].q_answer == "MOM6": - self.NX = 1 + self.nx = 1 else: - self.NX = 2 - self.NY = self.NX * 6 + self.nx = 2 + self.ny = self.nx * 6 self.job_sgmt = f"{15:08}" self.num_sgmt = 20 self.post_NDS = 4 - self.NX_convert = 1 - self.NY_convert = 6 + self.nx_convert = 1 + self.ny_convert = 6 case "c24": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_ocean = self.DT_irrad - self.DT_long = self.DT - self.NX = 4 - self.NY = self.NX * 6 + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_ocean = self.dt_irrad + self.dt_long = self.dt + self.nx = 4 + self.ny = self.nx * 6 self.job_sgmt = f"{15:08}" self.num_sgmt = 20 self.post_NDS = 4 - self.NX_convert = 1 - self.NY_convert = 6 + self.nx_convert = 1 + self.ny_convert = 6 case "c48": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_ocean = self.DT_irrad - self.DT_long = self.DT - self.NX = 4 - self.NY = self.NX * 6 - self.IM_hist = 180 - self.JM_hist = 91 + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_ocean = self.dt_irrad + self.dt_long = self.dt + self.nx = 4 + self.ny = self.nx * 6 + self.im_hist = 180 + self.jm_hist = 91 self.job_sgmt = f"{15:08}" self.num_sgmt = 20 self.post_NDS = 4 case "c90": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_long = self.DT + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_long = self.dt match answerdict["OM_name"].q_answer: case "MIT": - self.NX = 10 - self.NY = 36 - self.DT_ocean = self.DT + self.nx = 10 + self.ny = 36 + self.dt_ocean = self.dt case "MOM5","MOM6": - self.NX = ocean_NX - self.NY = ocean_NY - self.DT_ocean = self.DT + self.nx = ocean_nx + self.ny = ocean_ny + self.dt_ocean = self.dt case _: - self.NX = 3 - self.NY = self.NX * 6 - self.DT_ocean = self.DT_irrad + self.nx = 3 + self.ny = self.nx * 6 + self.dt_ocean = self.dt_irrad self.job_sgmt = f"{32:08}" self.num_sgmt = 4 self.post_NDS = 8 case "c180": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_long = self.DT + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_long = self.dt if answerdict["OM_coupled"].q_answer == True: - self.NX = ocean_NX - self.NY = ocean_NY - self.DT_ocean = self.DT + self.nx = ocean_nx + self.ny = ocean_ny + self.dt_ocean = self.dt else: - self.NX = 6 - self.NY = self.NX * 6 - self.DT_ocean = self.DT_irrad + self.nx = 6 + self.ny = self.nx * 6 + self.dt_ocean = self.dt_irrad self.job_sgmt = f"{16:08}" self.num_sgmt = 1 self.post_NDS = 8 self.num_readers = 2 case "c360": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_ocean = self.DT_irrad - self.DT_long = self.DT - self.NX = 12 - self.NY = self.NX * 6 + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_ocean = self.dt_irrad + self.dt_long = self.dt + self.nx = 12 + self.ny = self.nx * 6 self.num_readers = 4 self.job_sgmt = f"{5:08}" self.num_sgmt = 1 self.post_NDS = 12 - self.NX_convert = 4 + self.nx_convert = 4 case "c720": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_ocean = self.DT_irrad - self.DT_long = 450 - self.NX = 24 - self.NY = self.NX * 6 + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_ocean = self.dt_irrad + self.dt_long = 450 + self.nx = 24 + self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{5:08}" self.num_sgmt = 1 self.post_NDS = 16 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True case "c1440": - self.DT_solar = 1800 - self.DT_irrad = 1800 - self.DT_ocean = self.DT_irrad - self.DT_long = 300 - self.NX = 48 - self.NY = self.NX * 6 + self.dt_solar = 1800 + self.dt_irrad = 1800 + self.dt_ocean = self.dt_irrad + self.dt_long = 300 + self.nx = 48 + self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True case "c2880": - self.DT_solar = 1800 - self.DT_irrad = 1800 - self.DT_ocean = self.DT_irrad - self.DT_long = 300 - self.NX = 96 - self.NY = self.NX * 6 + self.dt_solar = 1800 + self.dt_irrad = 1800 + self.dt_ocean = self.dt_irrad + self.dt_long = 300 + self.nx = 96 + self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True + self.convpar_option = 'NONE' case "c5760": - self.DT_solar = 900 - self.DT_irrad = 900 - self.DT_ocean = self.DT_irrad - self.DT_long = 300 - self.NX = 192 - self.NY = self.NX * 6 + self.dt_solar = 900 + self.dt_irrad = 900 + self.dt_ocean = self.dt_irrad + self.dt_long = 300 + self.nx = 192 + self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True + self.convpar_option = 'NONE' case "c270": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_ocean = self.DT_irrad - self.DT_long = self.DT - self.NX = 18 - self.NY = self.NX * 6 + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_ocean = self.dt_irrad + self.dt_long = self.dt + self.nx = 18 + self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True - self.CONUS = "" + self.conus = "" self.stretch_factor = 2.5 case "c540": - self.DT_solar = 3600 - self.DT_irrad = 3600 - self.DT_ocean = self.DT_irrad - self.DT_long = self.DT - self.NX = 36 - self.NY = self.NX * 6 * 2 + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_ocean = self.dt_irrad + self.dt_long = self.dt + self.nx = 36 + self.ny = self.nx * 6 * 2 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True - self.CONUS = "" + self.conus = "" self.stretch_factor = 2.5 case "c1080": - self.DT_solar = 900 - self.DT_irrad = 900 - self.DT_ocean = self.DT_irrad - self.DT_long = 300 - self.NX = 72 - self.NY = self.NX * 6 * 2 + self.dt_solar = 900 + self.dt_irrad = 900 + self.dt_ocean = self.dt_irrad + self.dt_long = 300 + self.nx = 72 + self.ny = self.nx * 6 * 2 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True - self.CONUS = "" + self.conus = "" self.stretch_factor = 2. case "c1536": - self.DT_solar = 900 - self.DT_irrad = 900 - self.DT_ocean = self.DT_irrad - self.DT_long = 300 - self.NX = 96 - self.NY = self.NX * 6 + self.dt_solar = 900 + self.dt_irrad = 900 + self.dt_ocean = self.dt_irrad + self.dt_long = 300 + self.nx = 96 + self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{5:08}" self.num_sgmt = 1 self.post_NDS = 16 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True - self.CONUS = "" + self.conus = "" self.stretch_factor = 3.0 case "c2160": - self.DT_solar = 900 - self.DT_irrad = 900 - self.DT_ocean = self.DT_irrad - self.DT_long = 300 - self.NX = 192 - self.NY = self.NX * 6 * 2 + self.dt_solar = 900 + self.dt_irrad = 900 + self.dt_ocean = self.dt_irrad + self.dt_long = 300 + self.nx = 192 + self.ny = self.nx * 6 * 2 self.num_readers = 6 self.job_sgmt = f"{5:08}" self.num_sgmt = 1 self.post_NDS = 32 - self.NX_convert = 8 + self.nx_convert = 8 self.use_SHMEM = True - self.CONUS = "" + self.conus = "" self.stretch_factor = 2.5 if answerdict["OM_name"].q_answer == "MIT": - self.DT_ocean = self.DT + self.dt_ocean = self.dt def set_microphysics(self): match self.microphysics: case "BACM_1M": self.BACM_1M = "" - self.DT_long = 450 case "GFDL_1M": self.GFDL_1M = "" case "MGB2_2M": @@ -303,18 +314,19 @@ def set_turnoff_wsub(self): # settings for fvcore_layour.rc def set_fvcore_layout(self): - match self.use_hydrostatic: - case True: - self.FV_make_NH = "Make_NH = .F." - self.FV_hydro = "hydrostatic = .T." - case False: - self.FV_make_NH = "Make_NH = .T." - self.FV_hydro = "hydrostatic = .F." - if self.microphysics == "MGB2_2M": - self.FV_hydro = ".FALSE." + if self.use_hydrostatic == True: + self.FV_make_NH = "Make_NH = .F." + self.FV_hydro = "hydrostatic = .T." + self.FV_hwt = '#' + else: + self.FV_make_NH = "Make_NH = .T." + self.FV_hydro = "hydrostatic = .F." + self.FV_hwt = '' + if self.microphysics == "MGB2_2M": + self.FV_hydro = ".FALSE." - def set_CONUS(self): - if self.CONUS == "#": + def set_conus(self): + if self.conus == "#": self.schmidt = "do_schmidt = .false." self.stretch_factor = "stretch_fac = 1.0" self.target_lon = "target_lon = 0.0" @@ -325,9 +337,16 @@ def set_CONUS(self): self.target_lon = "target_lon = -98.35" self.target_lat = "target_lat = 39.5" + def set_wsub_extdata(self): + if self.microphysics == 'BACM_1M' or self.microphysics == 'GFDL_1M': + self.mp_turn_off_wsub_extdata = '' + else: + self.mp_turn_off_wsub_extdata = '#DELETE#' + - def config(self, ocean_NX, ocean_NY): - self.hres(ocean_NX, ocean_NY) + def config(self, ocean_nx, ocean_ny): + self.hres(ocean_nx, ocean_ny) self.set_microphysics() self.set_fvcore_layout() - self.set_CONUS() + self.set_conus() + self.set_wsub_extdata() diff --git a/gcmpy/scripts/env.py b/gcmpy/scripts/env.py old mode 100644 new mode 100755 index 1f02b253..a4be198d --- a/gcmpy/scripts/env.py +++ b/gcmpy/scripts/env.py @@ -73,11 +73,10 @@ ####################################################################### # Set Number of CPUs per Node ####################################################################### -# ----------------------------> PUT IN HANDLE CLASS FROM process_questions.py (MAYBE) <------------------------ if envdict['site'] == 'NCCS': - if answerdict['processor'].q_answer == 'Haswell': - envdict['n_CPUs'] = 28 - elif answerdict['processor'].q_answer == 'Skylake': + # NOTE: in the current version of gcm_setup, we never build on + # SLES15, so milan nodes are not an option for NCCS. + if answerdict['processor'].q_answer == 'Skylake': envdict['n_CPUs'] = 40 elif answerdict['processor'].q_answer == 'Cascade': ''' @@ -132,3 +131,18 @@ print(f"ERROR: Unknown architecture", envdict['arch']) sys.exit(1) +####################################################################### +# Build Directory Locations +####################################################################### +if envdict['arch'] == 'Darwin': + envdict['preload_command'] = 'DYLD_INSERT_LIBRARIES' + envdict['ld_library_path_command'] = 'DYLD_LIBRARY_PATH' + # On macOS we seem to need to call mpirun directly and not use esma_mpirun + # For some reason SIP does not let the libraries be preloaded + envdict['run_command'] = 'mpirun -np ' +else: + envdict['preload_command'] = 'LD_PRELOAD' + envdict['ld_library_path_command'] = 'LD_LIBRARY_PATH' + envdict['run_command'] = '$GEOSBIN/esma_mpirun -np ' + + diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py new file mode 100755 index 00000000..c1602591 --- /dev/null +++ b/gcmpy/scripts/gcm_setup.py @@ -0,0 +1,919 @@ +from ocean import ocean +from atmosphere import atmosphere as atmos +from land import land +from gocart import gocart +from env import answerdict, linkx +from utility import envdict, pathdict, color +import math, os, shutil, tempfile, yaml, re +from pathlib import Path +from jinja2 import Environment, FileSystemLoader, Undefined + + +# combines all models (atmos, ocean, land, gocart) into one big one +class setup: + def __init__(self): + self.ocean = ocean() + self.atmos = atmos() + self.land = land() + self.gocart = gocart() + self.is_FCST = False + self.fv_cubed = '' + self.bcs_res = None + self.tile_data = None + self.tile_bin = None + self.interpolate_sst = None + self.job_sgmt = None + self.begin_date = '18910301 000000' + self.end_date = '29990302 210000' + self.n_oserver_nodes = None + self.n_backend_pes = None + self.n_nodes = None + self.exp_dir = answerdict['exp_dir'].q_answer + self.restart_by_oserver = 'NO' + self.gcm_version = Path(f"{pathdict['etc']}/.AGCM_VERSION").read_text() + self.file_list = ['gcm_run.j', + 'gcm_post.j', + 'gcm_archive.j', + 'gcm_regress.j', + 'gcm_plot.tmpl', + 'gcm_quickplot.csh', + 'gcm_moveplot.j', + 'gcm_forecast.tmpl', + 'gcm_forecast.setup', + 'gcm_emip.setup', + 'CAP.rc.tmpl', + 'AGCM.rc.tmpl', + 'HISTORY.rc.tmpl', + 'logging.yaml', + 'fvcore_layout.rc', + 'linkbcs.tmpl'] + + def config_models(self): + self.ocean.config() + self.atmos.config(self.ocean.nx, self.ocean.ny) + self.land.config() + self.gocart.config() + + + # setup some variables idk + def set_some_stuff(self): + if self.atmos.im_hist >= self.ocean.im: + self.interpolate_sst = True + else: + self.interpolate_sst = False + self.bcs_res = f"{self.atmos.res}_{self.ocean.res}" + self.tile_data = f"{self.atmos.res}_{self.ocean.res}_Pfafstetter.til" + self.tile_bin = f"{self.atmos.res}_{self.ocean.res}_Pfafstetter.TIL" + self.job_sgmt = f"{self.atmos.job_sgmt} 000000" + + + # setup experiment nodes + def set_nodes(self): + model_npes = self.atmos.nx * self.atmos.ny + + # Calculate OSERVER nodes based on recommended algorithm + if answerdict['io_server'].q_answer == True: + + # First we calculate the number of model nodes + n_model_nodes = math.ceil(model_npes / envdict["n_CPUs"]) + + # Next the number of frontend PEs is 10% of the model PEs + n_frontend_pes = math.ceil(model_npes * 0.1) + + # Now we roughly figure out the number of collections in the HISTORY.rc + n_hist_collections = 0 + with open(answerdict['history_template'].q_answer, 'r') as file: + in_collections = False + for line in file: + if line.split(' ', 1)[0] == "COLLECTIONS:": + in_collections = True + continue + if in_collections and line.split(' ', 1)[0] != "#": + n_hist_collections += 1 + if line.strip() == "::": + break + + # The total number of oserver PEs is frontend PEs plus number of history collections + n_oserver_pes = n_frontend_pes + n_hist_collections + + # calculate the number of oserver nodes + n_oserver_nodes = math.ceil(n_oserver_pes / envdict["n_CPUs"]) + + # The number of backend PEs is the number of history collections divided by the number of oserver nodes + n_backend_pes = math.ceil(n_hist_collections / n_oserver_nodes) + + # multigroup requires at least two backend pes + if (n_backend_pes < 2): n_backend_pes = 2 + + # Calculate the total number of nodes to request from batch + self.nodes = n_model_nodes + n_oserver_nodes + + else: + self.nodes = math.ceil(model_npes / envdict["n_CPUs"]) + self.n_oserver_nodes = 0 + self.n_backend_pes = 0 + + + + def set_stuff(self): + self.set_nodes() + # Longer job names are now supported with SLURM and PBS. Limits seem to be 1024 characters with SLURM + # and 230 with PBS. To be safe, we will limit to 200 + self.run_n = f"{answerdict['experiment_id'].q_answer[:200]}_RUN" # RUN Job Name + self.run_fn = f"{answerdict['experiment_id'].q_answer[:200]}_FCST" # Forecast Job Name + self.post_n = f"{answerdict['experiment_id'].q_answer[:200]}_POST" # POST Job Name + self.plot_n = f"{answerdict['experiment_id'].q_answer[:200]}_PLT" # PLOT Job Name + self.move_n = f"{answerdict['experiment_id'].q_answer[:200]}_PLT" # MOVE Job Name + self.archive_n = f"{answerdict['experiment_id'].q_answer[:200]}_ARCH" # ARCHIVE Job Name + self.regress_n = f"{answerdict['experiment_id'].q_answer[:200]}_RGRS" # REGRESS Job Name + + + # Here we need to convert POST_NDS to total tasks. Using 16 cores + # per task as a good default + post_npes = self.atmos.post_NDS * 16 + NPCUS = (post_npes + envdict["n_CPUs"] - 1)/envdict["n_CPUs"] + + ''' + Definition for each variable in the following if-else block: + + batch_cmd - PBS Batch command + batch_group - PBS Syntax for GROUP + batch_time - PBS Syntax for walltime + batch_jobname - PBS Syntax for job name + batch_outputname - PBS Syntax for job output name + batch_joinouterr - PBS Syntax for joining output and error + run_ft - Wallclock Time for gcm_forecast.j + run_ft - Wallclock Time for gcm_run.j + post_t - Wallclock Time for gcm_post.j + plot_t - Wallclock Time for gcm_plot.j + archive_t - Wallclock Time for gcm_archive.j + run_q - Batch queue name for gcm_run.j + run_p - PE Configuration for gcm_run.j + run_fp - PE Configuration for gcm_forecast.j + post_q - Batch queue name for gcm_post.j + plot_q - Batch queue name for gcm_plot.j + move_q - Batch queue name for gcm_moveplot.j + archive_q - Batch queue name for gcm_archive.j + post_p - PE Configuration for gcm_post.j + plot_p - PE Configuration for gcm_plot.j + archive_p - PE Configuration for gcm_archive.j + move_p - PE Configuration for gcm_moveplot.j + bcs_dir - Location of Boundary Conditions + replay_ana_expID - Default Analysis Experiment for REPLAY + replay_ana_location - Default Analysis Location for REPLAY + M2_replay_ana_location - Default Analysis Location for M2 REPLAY + sst_dir - Location of SST Boundary Conditions + chem_dir - Locations of Aerosol Chemistry BCs + work_dir - User work directory <----------------- change this later + gwdrs_dir - Location of GWD_RIDGE files + coupled_dir - Coupled Ocean/Atmos Forcing + ''' + + if envdict['site'] == "NAS": + self.batch_cmd = "qsub" + self.batch_group = "PBS -W group_list=" + self.batch_time = "PBS -l walltime=" + self.batch_jobname = "PBS -N" + self.batch_outputname = "PBS -o " + self.batch_joinouterr = "PBS -j oe -k oed" + self.run_ft = "6:00:00" + self.run_t = "8:00:00" + self.post_t = "8:00:00" + self.plot_t = "8:00:00" + self.archive_t = "8:00:00" + self.run_q = f"PBS -q normal" + self.run_p = f"PBS -l select={self.nodes}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + self.run_fp = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + self.post_q = "PBS -q normal" + self.plot_q = "PBS -q normal" + self.move_q = "PBS -q normal" + self.archive_q = "PBS -q normal" + self.post_p = f"PBS -l select={NPCUS}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + self.plot_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs=1:model={answerdict['processor']}" + self.archive_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + self.move_p = "PBS -l select=1:ncpus=1" + self.boundary_path = "/nobackup/gmao_SIteam/ModelData" + self.bcs_dir = f"{self.boundary_path}/bcs/{self.land.bcs}/{self.land.bcs}_{self.ocean.tag}" + self.replay_ana_expID = "ONLY_MERRA2_SUPPORTED" + self.replay_ana_location = "ONLY_MERRA2_SUPPORTED" + self.M2_replay_ana_location = f"{self.boundary_path}/merra2/data" + + # defines location of SST Boundary Conditions + oceanres = f"{self.ocean.im}x{self.ocean.jm}" + if oceanres == "1440x720": + self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/SST/{oceanres}" + else: + self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{oceanres}" + if self.ocean.gridtype_abrv == "LL": + self.sst_dir = "/nobackupp2/estrobac/geos5/SSTDIR" + + self.chem_dir = f"{self.boundary_path}/fvInput_nc3" + self.work_dir = f"/nobackup/{os.environ.get('LOGNAME')}" + self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" + + # Coupled Ocean/Atmos Forcing + if self.ocean.model == "MIT": + self.coupled_dir = "/nobackupp2/estrobac/geos5/GRIDDIR" + else: + self.coupled_dir = f"{boundary_path}/aogcm" + + + elif envdict['site'] == "NCCS": + self.batch_cmd = "sbatch" + self.batch_group = "SBATCH --account=" + self.batch_time = "SBATCH --time=" + self.batch_jobname = "SBATCH --job-name=" + self.batch_outputname = "SBATCH --output=" + self.batch_joinouterr = "DELETE" + self.run_ft = "06:00:00" + self.run_t = "12:00:00" + self.post_t = "8:00:00" + self.plot_t = "12:00:00" + self.archive_t = "2:00:00" + self.run_q = f"SBATCH --constraint={answerdict['processor']}" + self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + self.run_fp = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + self.post_q = f"SBATCH --constraint={answerdict['processor']}" + self.plot_q = f"SBATCH --constraint={answerdict['processor']}" + self.move_q = "SBATCH --partition=datamove" + self.archive_q = "SBATCH --partition=datamove" + self.post_p = f"SBATCH --nodes={NPCUS} --ntasks-per-node={envdict['n_CPUs']}" + self.plot_p = f"SBATCH --nodes=4 --ntasks=4" + self.archive_p = "SBATCH --ntasks=1" + self.move_p = "SBATCH --ntasks=1" + self.boundary_path = "/discover/nobackup/projects/gmao" + self.bcs_dir = f"{self.boundary_path}bcs_shared/fvInput/ExtData/esm/tiles/{self.land.bcs}" + self.replay_ana_expID = "x0039" + self.replay_ana_location = f"{self.boundary_path}/g6dev/ltakacs/x0039" + self.M2_replay_ana_location = f"{self.boundary_path}/merra2/data" + + + # define location of SST Boundary Conditions + oceanres = f"{self.ocean.im}x{self.ocean.jm}" + if oceanres == "1440x720": + self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/SST/{oceanres}" + else: + self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{oceanres}" + if self.ocean.gridtype_abrv == "LL": + self.sst_dir = "/discover/nobackup/estrobac/geos5/SSTDIR" + + self.chem_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput_nc3" + self.work_dir = f"/discover/nobackup/{os.environ.get('LOGNAME')}" + self.gwdrs_dir = f"{self.boundary_path}/osse2/stage/BCS_FILES/GWD_RIDGE" + + # Coupled Ocean/Atmos Forcing + if self.ocean.model == "MIT": + self.coupled_dir = "/gpfsm/dnb32/estrobac/geos5/GRIDDIR" + else: + self.coupled_dir = f"{self.boundary_path}/bcs_shared/make_bcs_inputs/ocean" + + + elif envdict['site'] == "AWS" or envdict['SITE'] == "Azure": + self.batch_cmd = "sbatch" + self.batch_group = "#DELETE" + self.batch_time = "SBATCH --time=" + self.batch_jobname = "SBATCH --job-name=" + self.batch_outputname = "SBATCH --output=" + self.batch_joinouterr = "DELETE" + self.run_ft = "06:00:00" + self.run_t = "12:00:00" + self.post_t = "8:00:00" + self.plot_t = "12:00:00" + self.archive_t = "1:00:00" + self.run_q = f"SBATCH --constraint={answerdict['processor']}" + self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + self.run_fp = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + self.post_q = "NULL" + self.plot_q = "NULL" + self.move_q = "NULL" + self.archive_q = "NULL" + self.post_p = f"SBATCH --ntasks={post_npes}" + self.plot_p = f"SBATCH --nodes=4 --ntasks=4" + self.archive_p = "SBATCH --ntasks=1" + self.move_p = "SBATCH --ntasks=1" + self.boundary_path = "/ford1/share/gmao_SIteam/ModelData" + self.bcs_dir = f"{self.boundary_path}/bcs/{self.land.bcs}_{self.ocean.tag}" + self.replay_ana_expID = "REPLAY_UNSUPPORTED" + self.replay_ana_location = "REPLAY_UNSUPPORTED" + self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" + self.sst_dir = f"{self.boundary_path}/{self.ocean.sst_name}/{self.ocean.im}x{self.ocean.jm}" + self.chem_dir = f"{self.boundary_path}/fvInput_nc3" + self.work_dir = os.environ.get('HOME') + self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" + self.coupled_dir = f"{self.boundary_path}/aogcm" + + else: + # These are defaults for the desktop + self.batch_cmd = "sbatch" + self.batch_group = "SBATCH --account=" + self.batch_time = "SBATCH --time=" + self.batch_jobname = "SBATCH --job-name=" + self.batch_outputname = "SBATCH --output=" + self.batch_joinouterr = "DELETE" + self.run_ft = "06:00:00" + self.run_t = "12:00:00" + self.post_t = "8:00:00" + self.plot_t = "12:00:00" + self.archive_t = "1:00:00" + self.run_q = "NULL" + self.run_p = "NULL" + self.run_fp = "NULL" + self.post_q = "NULL" + self.plot_q = "NULL" + self.move_q = "NULL" + self.archive_q = "NULL" + self.post_p = "NULL" + self.plot_p = "NULL" + self.archive_p = "NULL" + self.move_p = "NULL" + self.boundary_path = "/ford1/share/gmao_SIteam/ModelData" + self.bcs_dir = f"{self.boundary_path}/bcs/{self.land.bcs} /{self.land.bcs}_{self.ocean.tag}" + self.replay_ana_expID = "REPLAY_UNSUPPORTED" + self.replay_ana_location = "REPLAY_UNSUPPORTED" + self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" + self.sst_dir = f"{self.boundary_path}/{self.ocean.sst_name}/{self.ocean.im}x{self.ocean.jm}" + self.chem_dir = f"{self.boundary_path}/fvInput_nc3" + self.work_dir = os.environ.get('HOME') + self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" + self.coupled_dir = f"{self.boundary_path}/aogcm" + + # By default on desktop, just ignore IOSERVER for now + self.atmos.NX = 1 + self.atmos.NY = 6 + answerdict["io_server"] = False + self.n_oserver_nodes = 0 + self.n_backend_pes = 0 + + ''' + def set_hist_temp(self): + tmphist_d, tmphist_path = tempfile.mkstemp() + print(self.ocean.history_template) + shutil.copy(self.ocean.history_template, tmphist_path) + return tmphist_d, tmphist_path + ''' + + ''' + mainly used to create .{*}root files and/or populate them + ''' + def create_dotfile(self, path, content): + try: + path = Path(path) + path.parent.mkdir(parents=True, exist_ok=True) + path.touch() + with open(path, 'w') as file: + file.write(os.path.dirname(content)) + except Exception as e: + print(f"An error occurred while creating directory: {str(e)}") + exit(1) + + + ####################################################################### + # Copy Model Executable and RC Files to Experiment Directory + ####################################################################### + def RC_setup(self): + + # Make the experiment directory and the RC directory inside of it + RC_dir = os.path.join(self.exp_dir, 'RC') + + # Delete the destination directory if it exists + if os.path.exists(RC_dir): + shutil.rmtree(RC_dir) + + # Copy over all files and subdirs in install/etc, keeping symlinks, and ignoring *.tmpl files + shutil.copytree(pathdict['etc'], RC_dir, symlinks=True, ignore=shutil.ignore_patterns('*.tmpl', 'fvcore.layout.rc')) + + # Copy or symlink GEOSgcm.x (((IGNORE SINGULARITY/NATIVE BUILDS FOR NOW!!))) + geosgcmx_path = os.path.join(pathdict['bin'], 'GEOSgcm.x') + if linkx == True: + os.symlink(geosgcmx_path, os.path.join(self.exp_dir, 'GEOSgcm.x')) + else: + shutil.copy(geosgcmx_path, self.exp_dir) + + + ####################################################################### + # Set Recommended MPI Stack Settings + ####################################################################### + def mpistacksettings(self): + + # load mpi config from YAML + with open('../yaml/mpi_config.yaml') as file: + mpidict = yaml.load(file, Loader=yaml.FullLoader) + + # retrieve config from correlating mpi setting being used + mpi_config = mpidict.get(envdict['mpi']) + + # restart by oserver if using openmpi or mvapich + if envdict['mpi'] == 'openmpi' or envdict['mpi'] == 'mvapich': + self.restart_by_oserver = 'YES' + + + + ####################################################################### + # Create directories and copy files over + ####################################################################### + # A little helper function for copying files and displaying the info to the user + def copy_helper(self, src, destination, filename): + shutil.copy(src, destination) + print(f"Creating {color.RED}{filename}{color.RESET} for Experiment: {answerdict['experiment_id'].q_answer}") + + def copy_files_into_exp(self): + print("\n\n\n") + + for file in self.file_list: + self.copy_helper(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file}", file) + + self.copy_helper(f"{pathdict['install']}/post/plot.rc", f"{self.exp_dir}/plot.rc", "plot.rc") + self.copy_helper(f"{pathdict['install']}/post/post.rc", f"{self.exp_dir}/post.rc", "post.rc") + + # These files will be added if user chose to run coupled, regardless of ocean model selected. + if self.ocean.coupled == True: + self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/plotcon.j", f"{self.exp_dir}/plotcon.j", "plotocn.j") + self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/confon.py", f"{self.exp_dir}/__init__.py", "confocn.py") + self.file_list.extend(['input.nml', 'diag_table', 'plotocn.j', '__init__.py']) + + if self.ocean.model == 'MOM5': + self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.im}x{self.ocean.jm}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") + self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.im}x{self.ocean.jm}/diag_table", f"{self.exp_dir}/diag_table.nml", "diag_table") + self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.im}x{self.ocean.jm}/field_table", f"{self.exp_dir}/field_table.nml", "field_table") + self.file_list.append('field_table') + elif self.ocean.model == 'MOM6': + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/MOM_input", f"{self.exp_dir}/MOM_input", "MOM_input") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/MOM_override", f"{self.exp_dir}/MOM_override", "MOM_override") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/diag_table", f"{self.exp_dir}/diag_table", "diag_table") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/field_table", f"{self.exp_dir}/field_table", "field_table") + self.file_list.extend(['MOM_input', 'MOM_override', 'data_table']) + + if self.ocean.seaice_model == 'CICE6': + self.copy_helper(f"{pathdict['etc']}/CICE6/cice6_app/{self.ocean.im}x{self.ocean.jm}/ice_in", f"{self.exp_dir}/ice_in") + self.file_list.append('ice_in') + + print(f"{color.GREEN}Done!{color.RESET}\n") + + + ####################################################################### + # Produce Final script and .rc files + ####################################################################### + + # THIS WHOLE SECTION IS WILDLY OUT OF DATE, HOWEVER I KEPT IT AS IT WAS + # IN THE ORIGINAL SCRIPT FOR NOW + def restarts(self): + # comment or un-comment restarts based on exp configuration + # --------------------------------------------------------- + rsnames = {'H2O': False, + 'MAM': False, + 'CARMA': False, + 'GMICHEM': False, + 'STRATCHEM': False} + rstypes = ['INTERNAL','IMPORT'] + + with open(f"{answerdict['exp_dir'].q_answer}/AGCM.rc.tmpl", 'r') as file: + file_content = file.read() + + # Template in a "#" if restart is set to false + for rst in rsnames: + for typ in rstypes: + rst_string = f"{rst}_{typ}" + comment = "" if rsnames[rst] else "#" + file_content = file_content.replace(rst_string, f"{comment}{rst_string}") + + with open(f"{answerdict['exp_dir'].q_answer}/AGCM.rc.tmpl", 'w') as file: + file.write(file_content) + + ####################################################################### + # Modify RC Directory for LM and GOCART.data/GOCART Options + ####################################################################### + def mod_RC_dir_for_pchem(self): + if self.atmos.lm == 72: + return + + rc_dir = f"{answerdict['exp_dir'].q_answer}/RC" + + # if atmospheric vertical resolution != 72, we loop through every + # file in the RC dir and modify the atmos.lm values + for file_name in os.listdir(rc_dir): + file_path = os.path.join(rc_dir, file_name) + + with open(file_path, 'r') as file: + file_content = file.read() + + file_content = file_content.replace("/L72/", f"/L{self.atmos.lm}/") + file_content = file_content.replace("z72", f"z{self.atmos.lm}") + file_content = file_content.replace("_72_", f"_{self.atmos.lm}_") + + with open(file_path, 'w') as file: + file.write(file_content) + + # configure pchem and TR in GEOS_ChemGridComp.rc + def config_chemGridComp(self): + if self.gocart.rats_provider == 'PCHEM': + pchem = 'TRUE' + else: + pchem = 'FALSE' + + chemgridcomp = f"{answerdict['exp_dir'].q_answer}/RC/GEOS_ChemGridComp.rc" + with open(chemgridcomp, 'r') as file: + file_content = file.read() + + # we always enable TR and gocart + file_content = re.sub(r'(ENABLE_PCHEM:\s*\.).*(\.)', r'\1'+pchem+r'\2', file_content) + file_content = re.sub(r'(ENABLE_TR:\s*\.).*(\.)', r'\1TRUE\2', file_content) + file_content = re.sub(r'(ENABLE_GOCART_DATA:\s*\.).*(\.)', r'\1TRUE\2', file_content) + + with open(chemgridcomp, 'w') as file: + file.write(file_content) + + # update LAND_PARAMS choices + def config_surfaceGridComp(self): + surfacegridcomp = f"{answerdict['exp_dir'].q_answer}/RC/GEOS_SurfaceGridComp.rc" + with open(surfacegridcomp, 'r') as file: + file_content = file.read() + + if self.land.model == 'CatchmentCN-CLM4.0': + file_content = re.sub(r'(LAND_PARAMS:\s*).*', r'\1CN_CLM40', file_content) + + if self.land.bcs == 'ICA': + file_content = re.sub(r'(LAND_PARAMS:\s*).*', r'\1Icarus', file_content) + file_content = re.sub(r'(Z0_FORMULATION:\s*).*', r'\1 2', file_content) + + with open(surfacegridcomp, 'w') as file: + file.write(file_content) + + # enable DATA_DRIVEN gocart2G + def config_gocartGridComp(self): + gocartgridcomp = f"{answerdict['exp_dir'].q_answer}/RC/GOCART2G_GridComp.rc" + with open(gocartgridcomp, 'r') as file: + file_content = file.read() + + if self.gocart.data_driven == True: + file_content = re.sub(r'(ACTIVE_INSTANCES_DU:\s*)DU', r'\1DU.data', file_content) + file_content = re.sub(r'(ACTIVE_INSTANCES_SS:\s*)SS', r'\1SS.data', file_content) + file_content = re.sub(r'(ACTIVE_INSTANCES_SU:\s*)SU', r'\1SU.data', file_content) + file_content = re.sub(r'(ACTIVE_INSTANCES_NI:\s*)NI', r'\1NI.data', file_content) + file_content = re.sub(r'(ACTIVE_INSTANCES_CA:\s*)CA.oc', r'\1CA.oc.data', file_content) + file_content = re.sub(r'(ACTIVE_INSTANCES_CA:\s*)CA.bc', r'\1CA.bc.data', file_content) + file_content = re.sub(r'(ACTIVE_INSTANCES_CA:\s*)CA.br', r'\1CA.br.data', file_content) + + with open(gocartgridcomp, 'w') as file: + file.write(file_content) + + + def config_heartbeat(self): + + # With MOM5 we need to change dt lines in input.nml to + # use $OCEAN_DT instead. NOTE: This regex assumes integer followed by comma + if self.ocean.model == 'MOM5': + with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'r') as file: + file_content = file.read() + + file_content = re.sub(r'(dt_cpld\s*=\s*)[0-9]+(\,)', r'\1'+self.atmos.DT_ocean+r'\2', file_content) + file_content = re.sub(r'(dt_atmos\s*=\s*)[0-9]+(\,)', r'\1'+self.atmos.DT_ocean+r'\2', file_content) + + with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'r') as file: + file.write(file_content) + + # We also must change the MOM_override file to + # have consistent DTs with the AGCM. So we use OCEAN_DT + # and change MOM_override to match. NOTE: This sed + # assumes floating point number with a decimal + if self.ocean.model == 'MOM6': + with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'r') as file: + file_content = file.read() + + file_content = re.sub(r'(DT\s*=\s*).*(\,)', r'\1'+self.atmos.DT_ocean+r'\2', file_content) + file_content = re.sub(r'(DT_THERM\s*=\s*).*(\,)', r'\1'+self.atmos.DT_ocean+r'\2', file_content) + + with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'r') as file: + file.write(file_content) + + ''' + This is a helper function that extends jinja's Undefined class to ignore + template variables that aren't detemplated by this script + ''' + def get_undefined_handler(variable_start_string, variable_end_string, self): + class PreserveUndefined(Undefined): + __slots__ = () + + def __init__(self, *args, **kwargs): + super(PreserveUndefined, self).__init__(**kwargs) + + def __str__(self): + return f"{variable_start_string}{self._undefined_name}{variable_end_string}" + return PreserveUndefined + + + # another templating helper function that removes lines from a file that begin with #DELETE + def cleanup(self, file_path): + with open(file_path, 'r') as file: + content = file.read() + + content = re.sub(r'^\s*#DELETE.*\n', r'', content, flags=re.MULTILINE) + + with open(file_path, 'w') as file: + file.write(content) + + + + def template(self): + # this dictionary holds template values for the default jinja2 delimiter "{{ val }}" + jinja_dict = { + 'GCMVER': self.gcm_version, + 'EXPSRC': self.gcm_version, + 'EXPID': answerdict['experiment_id'].q_answer, + 'RUN_N': self.run_n, + 'RUN_FN': self.run_fn, + 'RUN_FT': self.run_ft, + 'RUN_T': self.run_t, + 'RUN_P': self.run_p, + 'RUN_FP': self.run_fp, + 'RUN_Q': self.run_q, + 'POST_N': self.post_n, + 'POST_T': self.post_t, + 'POST_P': self.post_p, + 'POST_Q': self.post_q, + 'MOVE_N': self.move_n, + 'PLOT_N': self.plot_n, + 'PLOT_T': self.plot_t, + 'PLOT_P': self.plot_p, + 'PLOT_Q': self.plot_q, + 'MOVE_Q': self.move_q, + 'MOVE_P': self.move_p, + 'ARCHIVE_N': self.archive_n, + 'ARCHIVE_T': self.archive_t, + 'ARCHIVE_P': self.archive_p, + 'ARCHIVE_Q': self.archive_q, + 'REGRESS_N': self.regress_n, + 'BCSDIR': self.bcs_dir, + 'SSTDIR': self.sst_dir, + 'SSTNAME': self.ocean.sst_name, + 'OCEANOUT': self.ocean.out, + 'LSMBCS': self.land.bcs, + 'EMIP_BCS_IN': self.land.emip_bcs_in, + 'EMIP_MERRA2': self.land.emip_MERRA2, + 'BCSTAG': self.ocean.tag, + 'SSTFILE': self.ocean.sst_file, + 'ICEFILE': self.ocean.ice_file, + 'KPARFILE': self.ocean.kpar_file, + 'CHMDIR': self.chem_dir, + 'COUPLEDIR': self.coupled_dir, + 'GWDRSDIR': self.gwdrs_dir, + 'EXPDIR': self.exp_dir, + 'EXPDSC': answerdict['experiment_description'].q_answer, + 'HOMDIR': self.exp_dir, + 'BATCH_GROUP': self.batch_group, + 'BATCH_TIME': self.batch_time, + 'BATCH_CMD': self.batch_cmd, + 'BATCH_JOBNAME': self.batch_jobname, + 'BATCH_OUTPUTNAME': self.batch_outputname, + 'BATCH_JOINOUTERR': self.batch_joinouterr, + 'SITE': envdict['site'], + 'GEOSDIR': pathdict['install'], + 'GEOSSRC': pathdict['install'], + 'GEOSBIN': pathdict['bin'], + 'GEOSETC': pathdict['etc'], + 'GEOSUTIL': pathdict['install'], + 'SINGULARITY_BUILD': '#DELETE', + 'NATIVE_BUILD': '', + 'MPT_SHEPHERD': self.ocean.mpt_shepherd, + 'SINGULARITY_SANDBOX': '', + 'REAL_BIND_PATH': '', + 'BASE_BIND_PATH': '', + 'BOUNDARY_DIR': self.boundary_path, + 'CHECKPOINT_TYPE': 'default', + 'OGCM_NX': self.ocean.nx, + 'OGCM_NY': self.ocean.ny, + 'OGCM_NPROCS': self.ocean.n_procs, + 'OBSERVER_FRQ': 0, + 'DASTUNING': '#', + 'COUPLED': self.ocean.coupled, + 'CLDMICRO': self.atmos.microphysics, + 'MOM5': self.ocean.MOM5, + 'MOM6': self.ocean.MOM6, + 'OCNMODEL': self.ocean.model, + 'CICE4': '#DELETE', + 'CICE6': '#DELETE', + 'MIT': self.ocean.MIT, + 'DATAOCEAN': self.ocean.data, + 'OPS_SPECIES': self.gocart.ops_species, + 'CMIP_SPECIES': self.gocart.cmip_species, + 'MERRA2OX_SPECIES': self.gocart.MERRA2OX_species, + 'HIST_GOCART': self.gocart.gocart_hist, + 'LSM_PARMS': self.land.parameters, + 'OCEAN_NAME': self.ocean.model, + 'OCEAN_PRELOAD': self.ocean.preload, + #'ana4replay.eta.%y4%m2%d2_%h2z.nc4': '/discover/nobackup/projects/gmao/merra2/data/ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4?g', + 'REPLAY_ANA_EXPID': self.replay_ana_expID, + 'REPLAY_ANA_LOCATION': self.replay_ana_location, + 'M2_REPLAY_ANA_LOCATION': self.M2_replay_ana_location, + 'OX_RELAXTIME': self.gocart.ox_relaxtime, + 'PCHEM_CLIM_YEARS': self.gocart.pchem_clim_years, + 'RATS_PROVIDER': self.gocart.rats_provider, + 'AERO_PROVIDER': self.gocart.aero_provider, + 'OANA_PROVIDER': 'PCHEM', + 'EMISSIONS': self.gocart.emissions, + 'DYCORE': 'FV3', + 'AGCM_GRIDNAME': self.atmos.gridname, + 'OGCM_GRIDNAME': self.ocean.gridname, + 'OGCM_IS_FCST': '0', + 'BOOT': 'YES', + 'BCSRES': self.bcs_res, + 'OCEANtag': self.ocean.res, + 'ATMOStag': self.atmos.res, + 'RES_DATELINE': self.atmos.res_dateline, + 'TILEDATA': self.tile_data, + 'TILEBIN': self.tile_bin, + 'DT': self.atmos.dt, + 'SOLAR_DT': self.atmos.dt_solar, + 'IRRAD_DT': self.atmos.dt_irrad, + 'OCEAN_DT': self.atmos.dt_ocean, + 'LONG_DT': self.atmos.dt_long, + 'NX': self.atmos.nx, + 'NY': self.atmos.ny, + 'USE_SHMEM': int(self.atmos.use_SHMEM), + 'USE_IOSERVER': int(answerdict['io_server'].q_answer), + 'NUM_OSERVER_NODES': self.n_oserver_nodes, + 'NUM_BACKEND_PES': self.n_backend_pes, + 'RESTART_BY_OSERVER': self.restart_by_oserver, + 'NCPUS_PER_NODE': envdict['n_CPUs'], + 'NUM_READERS': self.atmos.num_readers, + 'NUM_WRITERS': self.atmos.num_writers, + 'LATLON_AGCM': self.atmos.latlon, + 'LATLON_OGCM': self.ocean.latlon, + 'CUBE_AGCM': self.atmos.cube, + 'CUBE_OGCM': self.ocean.cube, + 'GRID_TYPE': 'Cubed-Sphere', + 'AGCM_NF': self.atmos.nf, + 'AGCM_IM': self.atmos.im, + 'AGCM_JM': self.atmos.jm, + 'AGCM_LM': self.atmos.lm, + 'OGCM_IM': self.ocean.im, + 'OGCM_JM': self.ocean.jm, + 'OGCM_LM': self.ocean.lm, + 'OGCM_NF': self.ocean.nf, + 'OGCM_GRID_TYPE': self.ocean.gridtype, + 'BEG_DATE': self.begin_date, + 'END_DATE': self.end_date, + 'JOB_SGMT': self.job_sgmt, + 'NUM_SGMT': self.atmos.num_sgmt, + 'CONUS': self.atmos.conus, + 'FV_HWT': self.atmos.FV_hwt, + 'CONVPAR_OPTION': self.atmos.convpar_option, + 'STRETCH_FACTOR': self.atmos.stretch_factor, + 'INTERPOLATE_SST': self.interpolate_sst, + 'HIST_IM': self.atmos.im_hist, + 'HIST_JM': self.atmos.jm_hist, + 'ISCCP_SATSIM': 1, + 'MODIS_SATSIM': 0, + 'RADAR_SATSIM': 0, + 'LIDAR_SATSIM': 0, + 'MISR_SATSIM': 0, + 'SATSIM': 0, + 'USE_SKIN_LAYER': 1, + 'ANALYZE_TS': 0, + 'LSM_CHOICE': self.land.model, + 'MP_TURN_OFF_WSUB_EXTDATA': self.atmos.mp_turn_off_wsub_extdata, + 'BACM_1M_': self.atmos.BACM_1M, + 'GFDL_1M_': self.atmos.GFDL_1M, + 'MGB2_2M_': self.atmos.MGB2_2M, + 'PRELOAD_COMMAND': envdict['preload_command'], + 'LD_LIBRARY_PATH_CMD': envdict['ld_library_path_command'], + 'RUN_CMD': envdict['run_command'], + 'HYDROSTATIC': self.atmos.use_hydrostatic, + 'FV_SCHMIDT': self.atmos.schmidt, + 'FV_STRETCH_FAC': self.atmos.stretch_factor, + 'FV_TARGET_LON': self.atmos.target_lon, + 'FV_TARGET_LAT': self.atmos.target_lat, + 'FV_MAKENH': self.atmos.FV_make_NH, + 'FV_HYDRO': self.atmos.FV_hydro, + 'GFDL_PROG_CCN': self.atmos.GFDL_prog_ccn, + 'GFDL_USE_CCN': self.atmos.GFDL_use_ccn, + 'GFDL_HYDRO': self.atmos.GFDL_hydro + } + + # this dictionary holds values that use the ">>>val<<<" delimiter + jinja_dict_special_delimiter = { + 'FORCEDAS': self.atmos.force_das, + 'FORCEGCM': self.atmos.force_gcm, + 'HIST_CICE4': '#DELETE', + 'GOCART': self.gocart.gocart, + 'FVCUBED': '', + 'OSTIA': self.ocean.ostia, + 'HIST_CATCHCN': self.land.HIST_catchment, + 'GCMRUN_CATCHCN': self.land.GCMRUN_catchment, + 'EMIP_OLDLAND': self.land.emip_oldland, + 'EMIP_NEWLAND': self.land.emip_newland, + '_4DIAUDAS': '#DELETE', + 'REGULAR_REPLAY': '#', + 'REGULAR_REPLAY_GMAO': '#', + 'REGULAR_REPLAY_NCEP': '#DELETE', + 'REGULAR_REPLAY_ECMWF': '#DELETE' + } + + + exp_dir = answerdict['exp_dir'].q_answer + + # this is an edge-case that can't be handled with jinja2 + # original csh line: s?^[ \t]*RECORD_?#RECORD_?g + for file in self.file_list: + with open(f"{exp_dir}/{file}", 'r') as tmpl: + file_content = tmpl.read() + + file_content = re.sub(r'^[ \t]*(RECORD_.*)', r'#\1', file_content) + + with open(f"{exp_dir}/{file}", 'w') as tmpl: + tmpl.write(file_content) + + # this block handles the default case for jinja templating + default_env = Environment( + loader=FileSystemLoader(exp_dir) + ) + for file in self.file_list: + template = default_env.get_template(file) + content = template.render(jinja_dict) + with open(f"{exp_dir}/{file}", 'w') as tmpl: + tmpl.write(content) + + # this block handles the special case for jinja templating + PreserveUndefined = self.get_undefined_handler('>>>', '<<<') + special_env = Environment( + loader=FileSystemLoader(exp_dir), + undefined=PreserveUndefined, + variable_start_string=">>>", + variable_end_string="<<<" + ) + for file in self.file_list: + template = special_env.get_template(file) + content = template.render(jinja_dict_special_delimiter) + with open(f"{exp_dir}/{file}", 'w') as tmpl: + tmpl.write(content) + + # remove #DELETE lines + for file in self.file_list: + file_path = f"{exp_dir}/{file}" + self.cleanup(file_path) + + + # organize files into sub directories and update file permissions + def organize_exp_dir(self): + exp_dir = answerdict['exp_dir'].q_answer + + # make sub dirs + sub_dirs = ['archive', 'forecasts', 'plot', 'post' , 'regress'] + for i in sub_dirs: + os.makedirs(os.path.join(exp_dir, i), exist_ok=True) + + # archive dir + shutil.move(f"{exp_dir}/gcm_archive.j", f"{exp_dir}/archive/gcm_archive.j") + + # forecasts dir + shutil.move(f"{exp_dir}/gcm_forecast.setup", f"{exp_dir}/forecasts/gcm_forecast.setup") + shutil.move(f"{exp_dir}/gcm_forecast.tmpl", f"{exp_dir}/forecasts/gcm_forecast.tmpl") + + # plot dir + shutil.move(f"{exp_dir}/gcm_moveplot.j", f"{exp_dir}/plot/gcm_moveplot.j") + shutil.move(f"{exp_dir}/gcm_plot.tmpl", f"{exp_dir}/plot/gcm_plot.tmpl") + shutil.move(f"{exp_dir}/gcm_quickplot.csh", f"{exp_dir}/plot/gcm_quickplot.csh") + shutil.move(f"{exp_dir}/plot.rc", f"{exp_dir}/plot/plot.rc") + + # post dir + shutil.move(f"{exp_dir}/gcm_post.j", f"{exp_dir}/post/gcm_post.j") + shutil.move(f"{exp_dir}/post.rc", f"{exp_dir}/post/post.rc") + + # regress dir + shutil.move(f"{exp_dir}/gcm_regress.j", f"{exp_dir}/regress/gcm_regress.j") + + # rename tmpl files + os.rename(f"{exp_dir}/CAP.rc.tmpl", f"{exp_dir}/CAP.rc") + os.rename(f"{exp_dir}/AGCM.rc.tmpl", f"{exp_dir}/AGCM.rc") + os.rename(f"{exp_dir}/HISTORY.rc.tmpl", f"{exp_dir}/HISTORY.rc") + os.rename(f"{exp_dir}/linkbcs.tmpl", f"{exp_dir}/linkbcs") + + # update file permissions + os.chmod(f"{exp_dir}/CAP.rc", 0o755) + os.chmod(f"{exp_dir}/fvcore_layout.rc", 0o755) + os.chmod(f"{exp_dir}/archive/gcm_archive.j", 0o755) + os.chmod(f"{exp_dir}/linkbcs", 0o755) + os.chmod(f"{exp_dir}/logging.yaml", 0o755) + os.chmod(f"{exp_dir}/forecasts/gcm_forecast.tmpl", 0o644) + os.chmod(f"{exp_dir}/plot/gcm_plot.tmpl", 0o644) + + +my_exp = setup() +my_exp.config_models() +#my_exp.print_all_vars() +my_exp.set_some_stuff() +my_exp.set_nodes() +my_exp.set_stuff() +my_exp.create_dotfile(f"{os.environ.get('HOME')}/.EXPDIRroot", answerdict['exp_dir'].q_answer) +my_exp.create_dotfile(f"{os.environ.get('HOME')}/.GROUProot", answerdict['group_root'].q_answer) +my_exp.RC_setup() +my_exp.mpistacksettings() +my_exp.copy_files_into_exp() +my_exp.restarts() +my_exp.mod_RC_dir_for_pchem() +my_exp.config_chemGridComp() +my_exp.config_surfaceGridComp() +my_exp.config_gocartGridComp() +my_exp.config_heartbeat() +my_exp.template() +my_exp.organize_exp_dir() diff --git a/gcmpy/scripts/generate_question.py b/gcmpy/scripts/generate_question.py old mode 100644 new mode 100755 diff --git a/gcmpy/scripts/gocart.py b/gcmpy/scripts/gocart.py old mode 100644 new mode 100755 index d6d9c9db..309109a1 --- a/gcmpy/scripts/gocart.py +++ b/gcmpy/scripts/gocart.py @@ -6,14 +6,15 @@ def __init__(self): self.aerosol = answerdict["gocart_aerosols"].q_answer self.emissions = f"{answerdict['gocart_emission'].q_answer}_EMISSIONS" self.data_driven = None - self.OPS_species = "#" - self.CMIP_species = "#" - self.MERRA2OX_species = "#" - self.pchem_clim_years = "" - self.gocart = None + self.ops_species = '#' + self.cmip_species = '#' + self.MERRA2OX_species = '#' + self.pchem_clim_years = '' + self.ox_relaxtime = None + self.gocart = '' self.gocart_hist = None - self.aero_provider = "GOCART2G" - self.RATS_provider = "PCHEM" + self.aero_provider = 'GOCART2G' + self.rats_provider = 'PCHEM' # for debugging purposes def print_vars(self): @@ -22,24 +23,24 @@ def print_vars(self): print(f"{color.BLUE}{var_name}: {var_value}{color.RESET}") def set_gocart(self): - match self.aerosol: - case "Actual": - self.data_driven = False - self.gocart = "" - self.gocart_hist = "" - case "Climatological": - self.data_driven = True - self.gocart = "" - self.gocart_hist = "" + if self.aerosol == 'Actual': + self.data_driven = False + self.gocart = '' + self.gocart_hist = '' + elif self.aerosol == 'Climatological': + self.data_driven = True + self.gocart = '#' + self.gocart_hist = '#DELETE' def set_emissions(self): - match self.emissions.split("_")[0]: - case "AMIP": - self.MERRA2OX_species = "" - self.pchem_clim_years = 1 - case "OPS": - self.OPS_species = "" - self.pchem_clim_years = 39 + if self.emissions.split('_')[0] == 'AMIP': + self.MERRA2OX_species = '' + self.pchem_clim_years = 1 + self.ox_relaxtime = '0.00' + elif self.emissions.split('_')[0] == 'OPS': + self.ops_species = '' + self.pchem_clim_years = 39 + self.ox_relaxtime = '259200.' def config(self): diff --git a/gcmpy/scripts/land.py b/gcmpy/scripts/land.py old mode 100644 new mode 100755 index 5bc46d64..0cc2d664 --- a/gcmpy/scripts/land.py +++ b/gcmpy/scripts/land.py @@ -3,10 +3,10 @@ class land: def __init__(self): - self.land_choice = answerdict["LS_model"].q_answer + self.model = answerdict["LS_model"].q_answer self.bcs = answerdict["LS_boundary_conditions"].q_answer - self.bound_parameters = None - self.emip_BCS_IN = None + self.parameters = None + self.emip_bcs_in = None self.emip_oldland = None self.emip_newland = None self.emip_MERRA2 = None @@ -20,38 +20,35 @@ def print_vars(self): print(f"{color.CYAN}{var_name}: {var_value}{color.RESET}") def set_bcs(self): - match self.bcs: - case "Icarus": - self.bound_parameters = "#DELETE" - self.emip_BCS_IN = "Ganymed-4_0" - self.emip_oldland = "" - self.emip_newland = "#DELETE" - self.emip_MERRA2 = "MERRA2" - case "Icarus-NLv3": - self.bound_parameters = "" - self.emip_BCS_IN = "Icarus-NLv3" - self.emip_oldland = "#DELETE" - self.emip_newland = "" - self.emip_MERRA2 = "MERRA2_NewLand" + if self.bcs == "ICA": + self.parameters = "#DELETE" + self.emip_bcs_in = "GM4" + self.emip_oldland = "" + self.emip_newland = "#DELETE" + self.emip_MERRA2 = "MERRA2" + elif self.bcs == "NL3": + self.parameters = "" + self.emip_bcs_in = "NL3" + self.emip_oldland = "#DELETE" + self.emip_newland = "" + self.emip_MERRA2 = "MERRA2_NewLand" + elif self.bcs == "v12": + self.parameters = "" + self.emip_bcs_in = "NL3" + self.emip_oldland = "#DELETE" + self.emip_newland = "" + self.emip_MERRA2 = "MERRA2_NewLand" + def set_catchment(self): - if self.bcs == "Icarus-NLv3": - match self.land_choice: - case "Catchment": - self.HIST_catchment = "#DELETE" - self.GCMRUN_catchment = "#DELETE" - case "CatchmentCN-CLM4.0": - self.HIST_catchment = "" - self.GCMRUN_catchment = "" - print(f"{color.RED}IMPORTANT: please set LAND_PARAMS: to CN_CLM40 in RC/GEOS_SurfaceGridComp.rc in the experiment directory.{color.RESET}") - case "CatchmentCN-CLM4.5": - self.HIST_catchment = "" - self.GCMRUN_catchment = "" - print(f"{color.RED}IMPORTANT: please set LAND_PARAMS: to CN_CLM45 in RC/GEOS_SurfaceGridComp.rc in the experiment directory.{color.RESET}") - else: - self.land_choice = "Catchment" + if self.model == "Catchment": + self.land_choice = 1 self.HIST_catchment = "#DELETE" self.GCMRUN_catchment = "#DELETE" + elif self.model == "CatchmentCN-CLM4.0": + self.model = 2 + self.HIST_catchment = "" + self.GCMRUN_catchment = "" def config(self): self.set_bcs() diff --git a/gcmpy/scripts/model.py b/gcmpy/scripts/model.py deleted file mode 100644 index 7f373228..00000000 --- a/gcmpy/scripts/model.py +++ /dev/null @@ -1,496 +0,0 @@ -from ocean import ocean -from atmosphere import atmosphere as atmos -from land import land -from gocart import gocart -from env import answerdict, linkx -from utility import envdict, pathdict, color -import math, os, shutil, tempfile, yaml -from pathlib import Path -from jinja2 import Environment, FileSystemLoader, StrictUndefined - - -# combines all models (atmos, ocean, land, gocart) into one big one -class model: - def __init__(self): - self.ocean = ocean() - self.atmos = atmos() - self.land = land() - self.gocart = gocart() - self.is_FCST = False - self.fv_cubed = "" - self.bcs_res = None - self.tile_data = None - self.tile_bin = None - self.interpolate_SST = None - self.job_sgmt = None - self.begin_date = "18910301 000000" - self.end_date = "29990302 210000" - self.n_oserver_nodes = None - self.n_backend_pes = None - self.n_nodes = None - self.exp_dir = answerdict['exp_dir'].q_answer - self.oserver_restart = "NO" - - - def print_all_vars(self): - self.atmos.print_vars() - self.land.print_vars() - self.gocart.print_vars() - - - def config_models(self): - self.ocean.config() - self.atmos.config(self.ocean.NX, self.ocean.NY) - self.land.config() - self.gocart.config() - - - # setup some variables idk - def set_some_stuff(self): - if self.atmos.IM_hist >= self.ocean.IM: - self.interpolate_SST = True - else: - self.interpolate_SST = False - self.bcs_res = f"{self.atmos.res}_{self.ocean.res}" - self.tile_data = f"{self.atmos.res}_{self.ocean.res}_Pfafstetter.til" - self.tile_bin = f"{self.atmos.res}_{self.ocean.res}_Pfafstetter.TIL" - self.job_sgmt = f"{self.atmos.job_sgmt} 000000" - - - # setup experiment nodes - def set_nodes(self): - model_npes = self.atmos.NX * self.atmos.NY - - # Calculate OSERVER nodes based on recommended algorithm - if answerdict["io_server"].q_answer == True: - - # First we calculate the number of model nodes - n_model_nodes = math.ceil(model_NPES / envdict["n_CPUs"]) - - # Next the number of frontend PEs is 10% of the model PEs - n_frontend_pes = math.ceil(model_NPES * 0.1) - - # Now we roughly figure out the number of collections in the HISTORY.rc - n_hist_collections = 0 - with open(answerdict['history_template'].q_answer, 'r') as file: - in_collections = False - for line in file: - if line.split(' ', 1)[0] == "COLLECTIONS:": - in_collections = True - continue - if in_collections and line.split(' ', 1)[0] != "#": - n_hist_collections += 1 - if line.strip() == "::": - break - - # The total number of oserver PEs is frontend PEs plus number of history collections - n_oserver_pes = n_frontend_pes + n_hist_collections - - # calculate the number of oserver nodes - n_oserver_nodes = math.ceil(n_oserver_pes / envdict["n_CPUs"]) - - # The number of backend PEs is the number of history collections divided by the number of oserver nodes - n_backend_pes = math.ceil(n_hist_collections / n_oserver_nodes) - - # multigroup requires at least two backend pes - if (n_backend_pes < 2): n_backend_pes = 2 - - # Calculate the total number of nodes to request from batch - nodes = n_model_nodes + n_oserver_nodes - - else: - self.nodes = math.ceil(model_npes / envdict["n_CPUs"]) - self.n_oserver_nodes = 0 - self.n_backend_pes = 0 - - - - def set_stuff(self): - self.set_nodes() - # Longer job names are now supported with SLURM and PBS. Limits seem to be 1024 characters with SLURM - # and 230 with PBS. To be safe, we will limit to 200 - run_n = f"{answerdict['experiment_id'].q_answer[:200]}_RUN" # RUN Job Name - run_fn = f"{answerdict['experiment_id'].q_answer[:200]}_FCST" # Forecast Job Name - post_n = f"{answerdict['experiment_id'].q_answer[:200]}_POST" # POST Job Name - plot_n = f"{answerdict['experiment_id'].q_answer[:200]}_PLT" # PLOT Job Name - move_n = f"{answerdict['experiment_id'].q_answer[:200]}_PLT" # MOVE Job Name - archive_n = f"{answerdict['experiment_id'].q_answer[:200]}_ARCH" # ARCHIVE Job Name - regress_n = f"{answerdict['experiment_id'].q_answer[:200]}_RGRS" # REGRESS Job Name - - - # Here we need to convert POST_NDS to total tasks. Using 16 cores - # per task as a good default - post_npes = self.atmos.post_NDS * 16 - NPCUS = (post_npes + envdict["n_CPUs"] - 1)/envdict["n_CPUs"] - - ''' - Definition for each variable in the following if-else block: - - batch_cmd - PBS Batch command - batch_group - PBS Syntax for GROUP - batch_time - PBS Syntax for walltime - batch_jobname - PBS Syntax for job name - batch_outputname - PBS Syntax for job output name - batch_joinouterr - PBS Syntax for joining output and error - run_FT - Wallclock Time for gcm_forecast.j - run_FT - Wallclock Time for gcm_run.j - post_T - Wallclock Time for gcm_post.j - plot_T - Wallclock Time for gcm_plot.j - archive_T - Wallclock Time for gcm_archive.j - run_Q - Batch queue name for gcm_run.j - run_P - PE Configuration for gcm_run.j - run_FP - PE Configuration for gcm_forecast.j - post_Q - Batch queue name for gcm_post.j - plot_Q - Batch queue name for gcm_plot.j - move_Q - Batch queue name for gcm_moveplot.j - archive_Q - Batch queue name for gcm_archive.j - post_P - PE Configuration for gcm_post.j - plot_P - PE Configuration for gcm_plot.j - archive_P - PE Configuration for gcm_archive.j - move_P - PE Configuration for gcm_moveplot.j - bcs_dir - Location of Boundary Conditions - replay_ana_expID - Default Analysis Experiment for REPLAY - replay_ana_location - Default Analysis Location for REPLAY - M2_replay_ana_location - Default Analysis Location for M2 REPLAY - sst_dir - Location of SST Boundary Conditions - chem_dir - Locations of Aerosol Chemistry BCs - work_dir - User work directory <----------------- change this later - gwdrs_dir - Location of GWD_RIDGE files - coupled_dir - Coupled Ocean/Atmos Forcing - ''' - - if envdict['site'] == "NAS": - batch_cmd = "qsub" - batch_group = "PBS -W group_list=" - batch_time = "PBS -l walltime=" - batch_jobname = "PBS -N" - batch_outputname = "PBS -o " - batch_joinouterr = "PBS -j oe -k oed" - run_FT = "6:00:00" - run_T = "8:00:00" - post_T = "8:00:00" - plot_T = "8:00:00" - archive_T = "8:00:00" - run_Q = f"PBS -q normal" - run_P = f"PBS -l select={self.nodes}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" - run_FP = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" - post_Q = "PBS -q normal" - plot_Q = "PBS -q normal" - move_Q = "PBS -q normal" - archive_Q = "PBS -q normal" - post_P = f"PBS -l select={NPCUS}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" - plot_P = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs=1:model={answerdict['processor']}" - archive_P = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" - move_P = "PBS -l select=1:ncpus=1" - boundary_path = "/nobackup/gmao_SIteam/ModelData" - bcs_dir = f"{boundary_path}/bcs/{self.land.bcs}/{self.land.bcs}_{self.ocean.tag}" - replay_ana_expID = "ONLY_MERRA2_SUPPORTED" - replay_ana_location = "ONLY_MERRA2_SUPPORTED" - M2_replay_ana_location = f"{boundary_path}/merra2/data"# - - # defines location of SST Boundary Conditions - oceanres = f"{self.ocean.IM}x{self.ocean.JM}" - if oceanres == "1440x720": - sst_dir = f"{boundary_path}/fvInput/g5gcm/bcs/SST/{oceanres}" - else: - sst_dir = f"{boundary_path}/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{oceanres}" - if self.ocean.gridtype_abrv == "LL": - sst_dir = "/nobackupp2/estrobac/geos5/SSTDIR" - - chem_dir = f"{boundary_path}/fvInput_nc3" - work_dir = f"/nobackup/{os.environ.get('LOGNAME')}" - gwdrs_dir = f"{boundary_path}/GWD_RIDGE" - - # Coupled Ocean/Atmos Forcing - if self.ocean.name == "MIT": - coupled_dir = "/nobackupp2/estrobac/geos5/GRIDDIR" - else: - coupled_dir = f"{boundary_path}/aogcm" - - - elif envdict['site'] == "NCCS": - batch_cmd = "sbatch" - batch_group = "SBATCH --account=" - batch_time = "SBATCH --time=" - batch_jobname = "SBATCH --job-name=" - batch_outputname = "SBATCH --output=" - batch_joinouterr = "DELETE" - run_FT = "06:00:00" - run_T = "12:00:00" - post_T = "8:00:00" - plot_T = "12:00:00" - archive_T = "2:00:00" - run_Q = f"SBATCH --constraint={answerdict['processor']}" - run_P = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" - run_FP = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" - post_Q = f"SBATCH --constraint={answerdict['processor']}" - plot_Q = f"SBATCH --constraint={answerdict['processor']}" - move_Q = "SBATCH --partition=datamove" - archive_Q = "SBATCH --partition=datamove" - post_P = f"SBATCH --nodes={NPCUS} --ntasks-per-node={envdict['n_CPUs']}" - plot_P = f"SBATCH --nodes=4 --ntasks=4" - archive_P = "SBATCH --ntasks=1" - move_P = "SBATCH --ntasks=1" - boundary_path = "/discover/nobackup/projects/gmao" - bcs_dir = f"{boundary_path}bcs_shared/fvInput/ExtData/esm/tiles/{self.land.bcs}" - replay_ana_expID = "x0039" - replay_ana_location = f"{boundary_path}/g6dev/ltakacs/x0039" - M2_replay_ana_location = f"{boundary_path}/merra2/data" - - - # define location of SST Boundary Conditions - oceanres = f"{self.ocean.IM}x{self.ocean.JM}" - if oceanres == "1440x720": - sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/SST/{self.ocean.IM}x{self.ocean.JM}" - else: - sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" - if self.ocean.gridtype_abrv == "LL": - sst_dir = "/discover/nobackup/estrobac/geos5/SSTDIR" - - chem_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput_nc3" - work_dir = f"/discover/nobackup/{os.environ.get('LOGNAME')}" - gwdrs_dir = f"{boundary_path}/osse2/stage/BCS_FILES/GWD_RIDGE" - - # Coupled Ocean/Atmos Forcing - if self.ocean.name == "MIT": - coupled_dir = "/gpfsm/dnb32/estrobac/geos5/GRIDDIR" - else: - coupled_dir = f"{boundary_path}/bcs_shared/make_bcs_inputs/ocean" - - - elif envdict['site'] == "AWS" or envdict['SITE'] == "Azure": - batch_cmd = "sbatch" - batch_group = "#DELETE" - batch_time = "SBATCH --time=" - batch_jobname = "SBATCH --job-name=" - batch_outputname = "SBATCH --output=" - batch_joinouterr = "DELETE" - run_FT = "06:00:00" - run_T = "12:00:00" - post_T = "8:00:00" - plot_T = "12:00:00" - archive_T = "1:00:00" - run_Q = f"SBATCH --constraint={answerdict['processor']}" - run_P = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" - run_FP = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" - post_Q = "NULL" - plot_Q = "NULL" - move_Q = "NULL" - archive_Q = "NULL" - post_P = f"SBATCH --ntasks={post_npes}" - plot_P = f"SBATCH --nodes=4 --ntasks=4" - archive_P = "SBATCH --ntasks=1" - move_P = "SBATCH --ntasks=1" - boundary_path = "/ford1/share/gmao_SIteam/ModelData" - bcs_dir = f"{boundary_path}/bcs/{self.land.bcs}_{self.ocean.tag}" - replay_ana_expID = "REPLAY_UNSUPPORTED" - replay_ana_location = "REPLAY_UNSUPPORTED" - M2_replay_ana_location = "REPLAY_UNSUPPORTED" - sst_dir = f"{boundary_path}/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" - chem_dir = f"{boundary_path}/fvInput_nc3" - work_dir = os.environ.get('HOME') - gwdrs_dir = f"{boundary_path}/GWD_RIDGE" - coupled_dir = f"{boundary_path}/aogcm" - - else: - # These are defaults for the desktop - batch_cmd = "sbatch" - batch_group = "SBATCH --account=" - batch_time = "SBATCH --time=" - batch_jobname = "SBATCH --job-name=" - batch_outputname = "SBATCH --output=" - batch_joinouterr = "DELETE" - run_FT = "06:00:00" - run_T = "12:00:00" - post_T = "8:00:00" - plot_T = "12:00:00" - archive_T = "1:00:00" - run_Q = "NULL" - run_P = "NULL" - run_FP = "NULL" - post_Q = "NULL" - plot_Q = "NULL" - move_Q = "NULL" - archive_Q = "NULL" - post_P = "NULL" - plot_P = "NULL" - archive_P = "NULL" - move_P = "NULL" - boundary_path = "/ford1/share/gmao_SIteam/ModelData" - bcs_dir = f"{boundary_path}/bcs/{self.land.bcs} /{self.land.bcs}_{self.ocean.tag}" - replay_ana_expID = "REPLAY_UNSUPPORTED" - replay_ana_location = "REPLAY_UNSUPPORTED" - M2_replay_ana_location = "REPLAY_UNSUPPORTED" - sst_dir = f"{boundary_path}/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" - chem_dir = f"{boundary_path}/fvInput_nc3" - work_dir = os.environ.get('HOME') - gwdrs_dir = f"{boundary_path}/GWD_RIDGE" - coupled_dir = f"{boundary_path}/aogcm" - - # By default on desktop, just ignore IOSERVER for now - self.atmos.NX = 1 - self.atmos.NY = 6 - answerdict["io_server"] = False - self.n_oserver_nodes = 0 - self.n_backend_pes = 0 - - ''' - def set_hist_temp(self): - tmphist_d, tmphist_path = tempfile.mkstemp() - print(self.ocean.history_template) - shutil.copy(self.ocean.history_template, tmphist_path) - return tmphist_d, tmphist_path - ''' - - ''' - mainly used to create .{*}root files and/or populate them - ''' - def create_dotfile(self, path, content): - try: - path = Path(path) - path.parent.mkdir(parents=True, exist_ok=True) - path.touch() - with open(path, 'w') as file: - file.write(os.path.dirname(content)) - except Exception as e: - print(f"An error occurred while creating directory: {str(e)}") - exit(1) - - - ####################################################################### - # Copy Model Executable and RC Files to Experiment Directory - ####################################################################### - def RC_setup(self): - - # Make the experiment directory and the RC directory inside of it - RC_dir = os.path.join(self.exp_dir, 'RC') - - # Delete the destination directory if it exists - if os.path.exists(RC_dir): - shutil.rmtree(RC_dir) - - # Copy over all files and subdirs in install/etc, keeping symlinks, and ignoring *.tmpl files - shutil.copytree(pathdict['etc'], RC_dir, symlinks=True, ignore=shutil.ignore_patterns('*.tmpl', 'fvcore.layout.rc')) - - # Copy or symlink GEOSgcm.x (((IGNORE SINGULARITY/NATIVE BUILDS FOR NOW!!))) - geosgcmx_path = os.path.join(pathdict['bin'], 'GEOSgcm.x') - if linkx == True: - os.symlink(geosgcmx_path, os.path.join(self.exp_dir, 'GEOSgcm.x')) - else: - shutil.copy(geosgcmx_path, self.exp_dir) - - ####################################################################### - # Set Recommended MPI Stack Settings - ####################################################################### - def mpistacksettings(self): - - # load mpi config from YAML - with open('../yaml/mpi_config.yaml') as file: - mpidict = yaml.load(file, Loader=yaml.FullLoader) - - # retrieve config from correlating mpi setting being used - mpi_config = mpidict.get(envdict['mpi']) - - ####################################################################### - # Create directories and copy files over - ####################################################################### - # A little helper function for copying files and displaying the info to the user - def copy_helper(self, src, destination, filename): - shutil.copy(src, destination) - print(f"Creating {color.RED}{filename}{color.RESET} for Experiment: {answerdict['experiment_id'].q_answer}") - - def copy_files_into_exp(self, file_list): - print("\n\n\n") - - for file in file_list: - if file[-5:] == '.tmpl': - self.copy_helper(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file[:-5]}", file) - else: - self.copy_helper(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file}", file) - - # These files will be added if user chose to run coupled, regardless of ocean model selected. - if self.ocean.coupled == True: - self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/plotcon.j", f"{self.exp_dir}/plotcon.j", "plotcon.j") - self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/confon.py", f"{self.exp_dir}/__init__.py", "confon.py") - - if self.ocean.name == 'MOM5': - self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.IM}x{self.ocean.JM}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") - self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.IM}x{self.ocean.JM}/diag_table", f"{self.exp_dir}/diag_table.nml", "diag_table") - self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.IM}x{self.ocean.JM}/field_table", f"{self.exp_dir}/field_table.nml", "field_table") - elif self.ocean.name == 'MOM6': - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/MOM_input", f"{self.exp_dir}/MOM_input", "MOM_input") - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/MOM_override", f"{self.exp_dir}/MOM_override", "MOM_override") - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/diag_table", f"{self.exp_dir}/diag_table", "diag_table") - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/field_table", f"{self.exp_dir}/field_table", "field_table") - - if self.ocean.seaice_model == 'CICE6': - self.copy_helper(f"{pathdict['ect']}/CICE6/cice6_app/{self.ocean.IM}x{self.ocean.JM}/ice_in", f"{self.exp_dir}/ice_in") - - print(f"{color.GREEN}Done!{color.RESET}\n") - - - ####################################################################### - # Produce Final script and .rc files - ####################################################################### - - # THIS WHOLE SECTION IS WILDLY OUT OF DATE, HOWEVER I KEPT IT AS IT WAS - # IN THE ORIGINAL SCRIPT FOR NOW - def restarts(self): - # comment or un-comment restarts based on exp configuration - # --------------------------------------------------------- - rsnames = {'H2O': False, - 'MAM': False, - 'CARMA': False, - 'GMICHEM': False, - 'STRATCHEM': False} - rstypes = ['INTERNAL','IMPORT'] - - # Load Jinja2 template - with open(f"{answerdict['exp_dir'].q_answer}/AGCM.rc", "r") as file: - file_content = file.read() - #file = Template(file_content) - - # Template in a "#" if restart is set to false - for rst in rsnames: - for typ in rstypes: - rst_string = f"{rst}_{typ}" - comment = "#" if not rsnames[rst] else "" - file_content = file_content.replace(rst_string, f"{comment}{rst_string}") - - with open(f"{answerdict['exp_dir'].q_answer}/AGCM.rc", "w") as file: - file.write(file_content) - - - - -mymodel = model() -mymodel.config_models() -#mymodel.print_all_vars() -mymodel.set_nodes() -mymodel.set_stuff() -mymodel.create_dotfile(f"{os.environ.get('HOME')}/.EXPDIRroot", answerdict['exp_dir'].q_answer) -mymodel.create_dotfile(f"{os.environ.get('HOME')}/.GROUProot", answerdict['group_root'].q_answer) -mymodel.RC_setup() -mymodel.mpistacksettings() -file_list = ['gcm_run.j', - 'gcm_post.j', - 'gcm_archive.j', - 'gcm_regress.j', - 'gcm_plot.tmpl', - 'gcm_quickplot.csh', - 'gcm_moveplot.j', - 'gcm_forecast.tmpl', - 'gcm_forecast.setup', - 'gcm_emip.setup', - 'CAP.rc.tmpl', - 'AGCM.rc.tmpl', - 'HISTORY.rc.tmpl', - 'logging.yaml', - 'fvcore_layout.rc'] - -mymodel.copy_files_into_exp(file_list) -mymodel.restarts() - - - diff --git a/gcmpy/scripts/ocean.py b/gcmpy/scripts/ocean.py old mode 100644 new mode 100755 index 2f832bce..67c4d556 --- a/gcmpy/scripts/ocean.py +++ b/gcmpy/scripts/ocean.py @@ -4,38 +4,39 @@ class ocean: def __init__(self): - self.name = answerdict["OM_name"].q_answer - self.coupled = answerdict["OM_coupled"].q_answer - self.seaice_model = answerdict["OM_seaice_model"].q_answer - self.gridtype = "" - self.gridtype_abrv = "" - self.gridname = "" - self.data = "" - self.preload = "" - self.history_template = answerdict["history_template"].q_answer - self.IM = None - self.JM = None - self.LM = answerdict["OM_vertical_res"].q_answer - self.IMO = None - self.JMO = None - self.res = "" - self.tag = "Reynolds" - self.sst_name = "" - self.sst_file = "" - self.ice_file = "" - self.kpar_file = "" - self.ostia = "" - self.out = "" - self.NX = None - self.NY = None - self.NF = None - self.latlon = "" - self.cube = "" + self.model = answerdict['OM_name'].q_answer + self.coupled = answerdict['OM_coupled'].q_answer + self.seaice_model = answerdict['OM_seaice_model'].q_answer + self.gridtype = '' + self.gridtype_abrv = '' + self.gridname = '' + self.data = '' + self.preload = '' + self.history_template = answerdict['history_template'].q_answer + self.im = None + self.jm = None + self.lm = answerdict['OM_vertical_res'].q_answer + self.imo = None + self.jmo = None + self.res = '' + self.tag = 'Reynolds' + self.sst_name = '' + self.sst_file = '' + self.ice_file = '' + self.kpar_file = '' + self.ostia = '' + self.out = '' + self.nx = None + self.ny = None + self.nf = None + self.latlon = '' + self.cube = '' self.n_procs = None - self.MOM5 = "" - self.MOM6 = "" - self.MIT = "" - self.mpt_shepherd = "" + self.MOM5 = '' + self.MOM6 = '' + self.MIT = '' + self.mpt_shepherd = '' + # for debugging purposes def print_vars(self): @@ -43,20 +44,21 @@ def print_vars(self): for var_name, var_value in all_vars.items(): print(f"{color.CYAN}{var_name}: {var_value}{color.RESET}") + def set_IMO(self): - self.IMO = f"{str(self.IM):04}" + self.imo = f"{str(self.im):04}" def set_JMO(self): - self.JMO = f"{str(self.JM):04}" + self.jmo = f"{str(self.jm):04}" def set_res(self): hres = answerdict["OM_horizontal_res"].q_answer if self.coupled == False and hres == "CS": - self.res = f"{self.gridtype_abrv}{self.IMO}x6C" + self.res = f"{self.gridtype_abrv}{self.imo}x6C" elif self.coupled == False: - self.res = f"{self.gridtype_abrv}{self.IMO}xPE{self.JMO}" + self.res = f"{self.gridtype_abrv}{self.imo}xPE{self.jmo}" elif self.coupled == True: - self.res = f"{self.gridtype_abrv}{self.IMO}x{self.gridtype_abrv}{self.JMO}" + self.res = f"{self.gridtype_abrv}{self.imo}x{self.gridtype_abrv}{self.jmo}" # Testing at NAS shows that coupled runs *require* MPI_SHEPHERD=true # to run. We believe this is due to LD_PRELOAD. For now we only set # this for coupled runs. @@ -64,110 +66,104 @@ def set_res(self): def set_gridname(self): if self.gridtype_abrv == "CF": - self.gridname = f"OC{self.IM}x{self.JM}-{self.gridtype_abrv}" - elif self.name == "MIT": - self.gridname = f"{self.gridtype_abrv}{self.IM}x{self.JM}-{self.gridtype_abrv}" + self.gridname = f"OC{self.im}x{self.jm}-{self.gridtype_abrv}" + elif self.model == "MIT": + self.gridname = f"{self.gridtype_abrv}{self.im}x{self.jm}-{self.gridtype_abrv}" else: - self.gridname = f"PE{self.IM}x{self.JM}-{self.gridtype_abrv}" + self.gridname = f"PE{self.im}x{self.jm}-{self.gridtype_abrv}" def set_kpar_file(self): - self.kpar_file = f"SEAWIFS_KPAR_mon_clim.{self.IM}x{self.JM}" + self.kpar_file = f"SEAWIFS_KPAR_mon_clim.{self.im}x{self.jm}" def coupled_hres(self): - match self.name: - case "MOM5": - self.name = "MOM" - self.preload = "env LD_PRELOAD=$GEOSDIR/lib/libmom.dylib" - mom5_warning = ( - ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" - "You have chosen to set up a coupled model experiment with MOM5.\n" - "Be aware that such a set up is _known_ to have problems. See following for more details:\n" - "https://github.com/GEOS-ESM/MOM5/issues/19\n" - "If your intent is to help _fix_ above issue, your help is much appreciated. Thank you and good luck!\n" - "Otherwise, until this above issue is _fixed_ you are on your own with above choice.\n" - "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" - ) - print(color.GREEN + mom5_warning + color.RESET) - case "MOM6": - self.preload = "env LD_PRELOAD=$GEOSDIR/lib/libmom6.dylib" - case "MIT": - self.gridtype_abrv = "llc" - - match self.name: - case "MIT": - match answerdict["OM_MIT_horizontal_res"].q_answer: - case "cs32": - self.JM = 32 - self.IM = self.JM * 6 - self.gridtype_abrv = "CM" - case "llc90": - self.gridtype_abrv = "LL" - if answerdict["AM_horizontal_res"].q_answer == "c48": - self.JM = 30 - self.IM = self.JM * 96 - else: - self.JM = 15 - self.IM = self.JM * 360 - case "llc1080": - self.gridtype_abrv = "LL" - self.JM = 60 - self.IM = self.JM * 2880 - case "llc2160": - self.gridtype_abrv = "LL" - self.JM = 72 - self.IM = self.JM * 7776 - case "MOM", "MOM6": - temp = answerdict["OM_MOM_horizontal_res"].q_answer.split() - self.IM = int(temp[0]) - self.JM = int(temp[1]) - self.gridtype = "TM" + if self.model == 'MOM5': + self.model = 'MOM' + self.preload = "env LD_PRELOAD=$GEOSDIR/lib/libmom.dylib" + mom5_warning = ( + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" + "You have chosen to set up a coupled model experiment with MOM5.\n" + "Be aware that such a set up is _known_ to have problems. See following for more details:\n" + "https://github.com/GEOS-ESM/MOM5/issues/19\n" + "If your intent is to help _fix_ above issue, your help is much appreciated. Thank you and good luck!\n" + "Otherwise, until this above issue is _fixed_ you are on your own with above choice.\n" + "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" + ) + print(color.GREEN + mom5_warning + color.RESET) + elif self.model == 'MOM6': + self.preload = "env LD_PRELOAD=$GEOSDIR/lib/libmom6.dylib" + elif self.model == 'MIT': + self.gridtype_abrv = "llc" + + if self.model == 'MIT' and answerdict["OM_MIT_horizontal_res"].q_answer == 'cs32': + self.jm = 32 + self.im = self.jm * 6 + self.gridtype_abrv = "CM" + elif self.model == 'MIT' and answerdict["OM_MIT_horizontal_res"].q_answer == 'llc90': + self.gridtype_abrv = "LL" + if answerdict["AM_horizontal_res"].q_answer == "c48": + self.jm = 30 + self.im = self.jm * 96 + else: + self.jm = 15 + self.im = self.jm * 360 + elif self.model == 'MIT' and answerdict["OM_MIT_horizontal_res"].q_answer == 'llc1080': + self.gridtype_abrv = "LL" + self.jm = 60 + self.im = self.jm * 2880 + elif self.model == 'MIT' and answerdict["OM_MIT_horizontal_res"].q_answer == 'llc2160': + self.gridtype_abrv = "LL" + self.jm = 72 + self.im = self.jm * 7776 + elif self.model == "MOM" or self.model == "MOM6": + temp = answerdict["OM_MOM_horizontal_res"].q_answer.split() + self.im = int(temp[0]) + self.jm = int(temp[1]) + self.gridtype = "TM" def coupled_vres(self): if answerdict["AM_horizontal_res"].q_answer == "c12": - self.NX = 3 - self.NY = 2 + self.nx = 3 + self.ny = 2 else: - self.NX = 36 - self.NY = 10 + self.nx = 36 + self.ny = 10 - self.n_procs = self.NX*self.NY + self.n_procs = self.nx*self.ny - match self.name: - case "MOM", "MOM6": - self.gridtype = "Tripolar" - case "MIT": - if self.gridtype_abrv == "CM": - self.NX = 6 - self.NY = 1 - else: - match answerdict["AM_horizontal_res"].q_answer: - case "c48": - self.NX = 96 - self.NY = 1 - case "c90": - self.NX = 360 - self.NY = 1 - case "c720": - self.NX = 2880 - self.NY = 1 - case "c1440": - self.NX = 7776 - self.NY = 1 + if self.model == "MOM" or self.model == "MOM6": + self.gridtype = "Tripolar" + elif self.model == "MIT": + if self.gridtype_abrv == "CM": + self.nx = 6 + self.ny = 1 + elif answerdict["AM_horizontal_res"].q_answer == 'c48': + self.nx = 96 + self.ny = 1 + elif answerdict["AM_horizontal_res"].q_answer == 'c90': + self.nx = 360 + self.ny = 1 + elif answerdict["AM_horizontal_res"].q_answer == 'c720': + self.nx = 2880 + self.ny = 1 + elif answerdict["AM_horizontal_res"].q_answer == 'c1440': + self.nx = 7776 + self.ny = 1 + def uncoupled_hres(self): todays_date = date.today() match answerdict["OM_horizontal_res"].q_answer: case "o1": temp_res = "360 180" - self.IM, self.JM = map(int, temp_res.split()) + self.im, self.jm = map(int, temp_res.split()) self.gridtype = "LatLon" - self.NF = 1 + self.nf = 1 self.tag = "Reynolds" self.sst_name = "SST" self.out = "c" - self.sst_file = f"dataoceanfile_MERRA_sst_1971-current.{self.IM}x{self.JM}.LE" - self.ice_file = f"dataoceanfile_MERRA_fraci_1971-current.{self.IM}x{self.JM}.LE" + self.sst_file = f"dataoceanfile_MERRA_sst_1971-current.{self.im}x{self.jm}.LE" + self.ice_file = f"dataoceanfile_MERRA_fraci_1971-current.{self.im}x{self.jm}.LE" self.set_kpar_file() self.gridtype_abrv = "DE" self.latlon = "" @@ -176,14 +172,14 @@ def uncoupled_hres(self): self.data = "" case "o2": temp_res = "1440 720" - self.IM, self.JM = map(int, temp_res.split()) + self.im, self.jm = map(int, temp_res.split()) self.gridtype = "LatLon" - self.NF = 1 + self.nf = 1 self.tag = "MERRA-2" self.sst_name = "MERRA2" self.out = "e" - self.sst_file = f"dataoceanfile_MERRA2_SST.{self.IM}x{self.JM}.{todays_date.year}.data" - self.ice_file = f"dataoceanfile_MERRA2_ICE.{self.IM}x{self.JM}.{todays_date.year}.data" + self.sst_file = f"dataoceanfile_MERRA2_SST.{self.im}x{self.jm}.{todays_date.year}.data" + self.ice_file = f"dataoceanfile_MERRA2_ICE.{self.im}x{self.jm}.{todays_date.year}.data" self.set_kpar_file() self.gridtype_abrv = "DE" self.latlon = "" @@ -192,9 +188,9 @@ def uncoupled_hres(self): self.data = "" case "o3": temp_res = "2880 1440" - self.IM, self.JM = map(int, temp_res.split()) + self.im, self.jm = map(int, temp_res.split()) self.gridtype = "LatLon" - self.NF = 1 + self.nf = 1 self.tag = "Ostia" self.sst_name = "OSTIA_REYNOLDS" self.out = "f" @@ -208,15 +204,15 @@ def uncoupled_hres(self): self.data = "" case "CS": if int(answerdict["AM_horizontal_res"].q_answer[1:]) >= 90: - self.IM = int(answerdict["AM_horizontal_res"].q_answer[1:]) - self.JM = self.IM * 6 + self.im = int(answerdict["AM_horizontal_res"].q_answer[1:]) + self.jm = self.im * 6 self.gridtype = "Cubed-Sphere" - self.NF = 6 + self.nf = 6 self.tag = "Ostia" self.sst_name = "OSTIA_REYNOLDS" self.out = "f" - self.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{self.IM}x{self.JM}.{todays_date.year}.data" - self.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{self.IM}x{self.JM}.{todays_date.year}.data" + self.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{self.im}x{self.jm}.{todays_date.year}.data" + self.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{self.im}x{self.jm}.{todays_date.year}.data" self.set_kpar_file() self.gridtype_abrv = "CF" self.latlon = "#DELETE" @@ -232,7 +228,7 @@ def uncoupled_hres(self): self.set_IMO() self.set_JMO() self.set_res() - self.LM = 34 + self.lm = 34 self.model = f"Data Ocean ({answerdict['AM_horizontal_res'].q_answer})" self.coupled = "#DELETE" self.MOM5 = "#DELETE" diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py old mode 100644 new mode 100755 index 0e09cb97..2f8299e4 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -133,15 +133,14 @@ def history_template_valid(answerdict, i): @staticmethod def exp_dir_default(answerdict, i): - if i == "home_dir" or i == "exp_dir": - root = f"{os.environ.get('HOME')}/.{i[:3].upper()}DIRroot" + if i == "exp_dir": + root = f"{os.environ.get('HOME')}/.EXPDIRroot" if os.path.exists(root): try: - print("here") with open(root, "r") as file: - answerdict[i].q_default = f"{file.read()}/{answerdict['experiment_id'].q_answer}" + answerdict[i].q_default = f"{file.read().strip()}/{answerdict['experiment_id'].q_answer}" except Exception as e: - print(f"An error occurred while reading {color.BLUE}.HOMDIRroot{color.RESET}: {str(e)}") + print(f"An error occurred while reading {color.BLUE}.EXPDIRroot{color.RESET}: {str(e)}") elif envdict['site'] in ['NAS','NCCS']: answerdict[i].q_default = f"/{'discover/' if envdict['site'] == 'NCCS' else ''}nobackup/{os.environ.get('LOGNAME')}/{answerdict['experiment_id'].q_answer}" else: diff --git a/gcmpy/scripts/utility.py b/gcmpy/scripts/utility.py old mode 100644 new mode 100755 index 9d60c84a..64085b74 --- a/gcmpy/scripts/utility.py +++ b/gcmpy/scripts/utility.py @@ -64,3 +64,4 @@ def cleanup(): pathdict['GEOSgcm'] = os.path.dirname(pathdict['install']) pathdict['build'] = os.path.join(pathdict['GEOSgcm'], 'build') pathdict['GEOSgcm_App'] = os.path.join(pathdict['GEOSgcm'], 'src/Applications/@GEOSgcm_App') +pathdict['GEOS_Util'] = os.path.join(pathdict['GEOSgcm'], 'src/Shared/@GMAO_Shared/@GEOS_Util') diff --git a/gcmpy/yaml/atmospheric_model.yaml b/gcmpy/yaml/atmospheric_model.yaml old mode 100644 new mode 100755 index 9769d35f..38be2843 --- a/gcmpy/yaml/atmospheric_model.yaml +++ b/gcmpy/yaml/atmospheric_model.yaml @@ -37,7 +37,7 @@ io_server: type: 'confirm' prompt: 'Would you like to IOSERVER?' choices: '' - default_answer: 'True' + default_answer: True follows_up: '' diff --git a/gcmpy/yaml/directory_setup.yaml b/gcmpy/yaml/directory_setup.yaml old mode 100644 new mode 100755 diff --git a/gcmpy/yaml/exp_setup.yaml b/gcmpy/yaml/exp_setup.yaml old mode 100644 new mode 100755 diff --git a/gcmpy/yaml/gocart.yaml b/gcmpy/yaml/gocart.yaml old mode 100644 new mode 100755 diff --git a/gcmpy/yaml/land_model.yaml b/gcmpy/yaml/land_model.yaml old mode 100644 new mode 100755 index 86353a87..45fcd63d --- a/gcmpy/yaml/land_model.yaml +++ b/gcmpy/yaml/land_model.yaml @@ -1,7 +1,7 @@ LS_boundary_conditions: type: 'select' prompt: 'Select the Land Surface Boundary Conditions:' - choices: ['Icarus', 'Icarus-NLv3'] + choices: ['Icarus-NLv3', 'Icarus', 'v12'] default_answer: '' follows_up: '' @@ -10,5 +10,4 @@ LS_model: prompt: 'Select the Land Surface Model:' choices: ['Catchment', 'CatchmentCN-CLM4.0 (CN_CLM40)', 'CatchmentCN-CLM4.5 (CN_CLM45)'] default_answer: '' - follows_up: - - ['LS_boundary_conditions', 'Icarus-NLv3'] + follows_up: '' diff --git a/gcmpy/yaml/mpi_config.yaml b/gcmpy/yaml/mpi_config.yaml old mode 100644 new mode 100755 diff --git a/gcmpy/yaml/ocean_model.yaml b/gcmpy/yaml/ocean_model.yaml old mode 100644 new mode 100755 diff --git a/linkbcs.tmpl b/linkbcs.tmpl index 296be7ff..e255811e 100644 --- a/linkbcs.tmpl +++ b/linkbcs.tmpl @@ -1,43 +1,43 @@ #!/bin/csh -f -setenv BCSDIR @BCSDIR -@DATAOCEANsetenv SSTDIR @SSTDIR -@COUPLEDsetenv CPLDIR @COUPLEDIR/@OCNMODEL -setenv CHMDIR @CHMDIR -setenv BCRSLV @ATMOStag_@OCEANtag +setenv BCSDIR {{ BCSDIR }} +{{ DATAOCEAN }}setenv SSTDIR {{ SSTDIR }} +{{ COUPLED }}setenv CPLDIR {{ COUPLEDIR }}/{{ OCNMODEL }} +setenv CHMDIR {{ CHMDIR }} +setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} -@MOM5setenv SSTDIR @COUPLEDIR/SST/MERRA2/@OGCM_IMx@OGCM_JM/v1 -@MOM6setenv SSTDIR @COUPLEDIR/SST/MERRA2/@OGCM_IMx@OGCM_JM/v1 +{{ MOM5 }}setenv SSTDIR {{ COUPLEDIR }}/SST/MERRA2/{{ OGCM_IM }}x{{ OGCM_JM }}/v1 +{{ MOM6 }}setenv SSTDIR {{ COUPLEDIR }}/SST/MERRA2/{{ OGCM_IM }}x{{ OGCM_JM }}/v1 -@COUPLED /bin/mkdir -p RESTART +{{ COUPLED }} /bin/mkdir -p RESTART /bin/mkdir -p ExtData /bin/ln -sf $CHMDIR/* ExtData -@COUPLED/bin/ln -sf $CPLDIR/@OGCM_IMx@OGCM_JM/SEAWIFS_KPAR_mon_clim.@OGCM_IMx@OGCM_JM SEAWIFS_KPAR_mon_clim.data -@COUPLED/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/${BCRSLV}-Pfafstetter.til tile.data -@COUPLED/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/${BCRSLV}-Pfafstetter.TRN runoff.bin -@MOM5/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/MAPL_Tripolar.nc . -@MOM6/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/MAPL_Tripolar.nc . -@MIT/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/mit.ascii -@MOM5/bin/ln -sf $CPLDIR/@OGCM_IMx@OGCM_JM/vgrid@OGCM_LM.ascii ./vgrid.ascii -@MOM6/bin/ln -sf $CPLDIR/@OGCM_IMx@OGCM_JM/vgrid@OGCM_LM.ascii ./vgrid.ascii -@MIT/bin/ln -sf $CPLDIR/DC0360xPC0181_LL5400x15-LL.bin DC0360xPC0181_LL5400x15-LL.bin +{{ COUPLED }}/bin/ln -sf $CPLDIR/{{ OGCM_IM }}x{{ OGCM_JM }}/SEAWIFS_KPAR_mon_clim.{{ OGCM_IM }}x{{ OGCM_JM }} SEAWIFS_KPAR_mon_clim.data +{{ COUPLED }}/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/${BCRSLV}-Pfafstetter.til tile.data +{{ COUPLED }}/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/${BCRSLV}-Pfafstetter.TRN runoff.bin +{{ MOM5 }}/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/MAPL_Tripolar.nc . +{{ MOM6 }}/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/MAPL_Tripolar.nc . +{{ MIT }}/bin/ln -sf $BCSDIR/geometry/${BCRSLV}/mit.ascii +{{ MOM5 }}/bin/ln -sf $CPLDIR/{{ OGCM_IM }}x{{ OGCM_JM }}/vgrid{{ OGCM_LM }}.ascii ./vgrid.ascii +{{ MOM6 }}/bin/ln -sf $CPLDIR/{{ OGCM_IM }}x{{ OGCM_JM }}/vgrid{{ OGCM_LM }}.ascii ./vgrid.ascii +{{ MIT }}/bin/ln -sf $CPLDIR/DC0360xPC0181_LL5400x15-LL.bin DC0360xPC0181_LL5400x15-LL.bin # Precip correction #/bin/ln -s /discover/nobackup/projects/gmao/share/gmao_ops/fvInput/merra_land/precip_CPCUexcludeAfrica-CMAP_corrected_MERRA/GEOSdas-2_1_4 ExtData/PCP -@DATAOCEAN/bin/ln -sf $BCSDIR/geometry/$BCRSLV/${BCRSLV}-Pfafstetter.til tile.data -@DATAOCEANif( -e $BCSDIR/geometry/$BCRSLV/${BCRSLV}-Pfafstetter.TIL) then -@DATAOCEAN/bin/ln -sf $BCSDIR/geometry/$BCRSLV/${BCRSLV}-Pfafstetter.TIL tile.bin -@DATAOCEANendif +{{ DATAOCEAN }}/bin/ln -sf $BCSDIR/geometry/$BCRSLV/${BCRSLV}-Pfafstetter.til tile.data +{{ DATAOCEAN }}if( -e $BCSDIR/geometry/$BCRSLV/${BCRSLV}-Pfafstetter.TIL) then +{{ DATAOCEAN }}/bin/ln -sf $BCSDIR/geometry/$BCRSLV/${BCRSLV}-Pfafstetter.TIL tile.bin +{{ DATAOCEAN }}endif # DAS or REPLAY Mode (AGCM.rc: pchem_clim_years = 1-Year Climatology) # -------------------------------------------------------------------- -@OPS_SPECIES/bin/ln -sf $BCSDIR/PCHEM/pchem.species.Clim_Prod_Loss.z_721x72.nc4 species.data +{{ OPS_SPECIES }}/bin/ln -sf $BCSDIR/PCHEM/pchem.species.Clim_Prod_Loss.z_721x72.nc4 species.data # CMIP-5 Ozone Data (AGCM.rc: pchem_clim_years = 228-Years) # ---------------------------------------------------------- -@CMIP_SPECIES/bin/ln -sf $BCSDIR/PCHEM/pchem.species.CMIP-5.1870-2097.z_91x72.nc4 species.data +{{ CMIP_SPECIES }}/bin/ln -sf $BCSDIR/PCHEM/pchem.species.CMIP-5.1870-2097.z_91x72.nc4 species.data # S2S pre-industrial with prod/loss of stratospheric water vapor # (AGCM.rc: pchem_clim_years = 3-Years, and H2O_ProdLoss: 1 ) @@ -46,34 +46,34 @@ setenv BCRSLV @ATMOStag_@OCEANtag # MERRA-2 Ozone Data (AGCM.rc: pchem_clim_years = 39-Years) # ---------------------------------------------------------- -@MERRA2OX_SPECIES/bin/ln -sf $BCSDIR/PCHEM/pchem.species.CMIP-5.MERRA2OX.197902-201706.z_91x72.nc4 species.data +{{ MERRA2OX_SPECIES }}/bin/ln -sf $BCSDIR/PCHEM/pchem.species.CMIP-5.MERRA2OX.197902-201706.z_91x72.nc4 species.data -/bin/ln -sf $BCSDIR/land/$BCRSLV/visdf_@AGCM_IMx@AGCM_JM.dat visdf.dat -/bin/ln -sf $BCSDIR/land/$BCRSLV/nirdf_@AGCM_IMx@AGCM_JM.dat nirdf.dat -/bin/ln -sf $BCSDIR/land/$BCRSLV/vegdyn_@AGCM_IMx@AGCM_JM.dat vegdyn.data -/bin/ln -sf $BCSDIR/land/$BCRSLV/lai_clim_@AGCM_IMx@AGCM_JM.data lai.data -/bin/ln -sf $BCSDIR/land/$BCRSLV/green_clim_@AGCM_IMx@AGCM_JM.data green.data -/bin/ln -sf $BCSDIR/land/$BCRSLV/ndvi_clim_@AGCM_IMx@AGCM_JM.data ndvi.data +/bin/ln -sf $BCSDIR/land/$BCRSLV/visdf_{{ AGCM_IM }}x{{ AGCM_JM }}.dat visdf.dat +/bin/ln -sf $BCSDIR/land/$BCRSLV/nirdf_{{ AGCM_IM }}x{{ AGCM_JM }}.dat nirdf.dat +/bin/ln -sf $BCSDIR/land/$BCRSLV/vegdyn_{{ AGCM_IM }}x{{ AGCM_JM }}.dat vegdyn.data +/bin/ln -sf $BCSDIR/land/$BCRSLV/lai_clim_{{ AGCM_IM }}x{{ AGCM_JM }}.data lai.data +/bin/ln -sf $BCSDIR/land/$BCRSLV/green_clim_{{ AGCM_IM }}x{{ AGCM_JM }}.data green.data +/bin/ln -sf $BCSDIR/land/$BCRSLV/ndvi_clim_{{ AGCM_IM }}x{{ AGCM_JM }}.data ndvi.data ->>>GCMRUN_CATCHCN<<>>GCMRUN_CATCHCN<<>>GCMRUN_CATCHCN<< Date: Wed, 8 Jan 2025 06:06:32 -0500 Subject: [PATCH 12/37] AMIP experiments trivial zero diff --- AGCM.rc.tmpl | 56 +-- HISTORY.AGCM.rc.tmpl | 166 +++---- HISTORY.AOGCM-MOM5.rc.tmpl | 188 ++++---- HISTORY.AOGCM.rc.tmpl | 246 +++++----- HISTORY.AOGCM_MITgcm.rc.tmpl | 6 +- gcm_archive.j | 2 +- gcm_forecast.tmpl | 10 +- gcm_moveplot.j | 2 +- gcm_plot.tmpl | 2 +- gcm_post.j | 2 +- gcm_regress.j | 2 +- gcm_run.j | 34 +- gcm_setup | 431 +++++++++--------- gcmpy/jinjafy.py | 34 +- .../__pycache__/atmosphere.cpython-312.pyc | Bin 12201 -> 12838 bytes gcmpy/scripts/__pycache__/env.cpython-312.pyc | Bin 4887 -> 4807 bytes .../__pycache__/gocart.cpython-312.pyc | Bin 2697 -> 2697 bytes .../scripts/__pycache__/land.cpython-312.pyc | Bin 2669 -> 2660 bytes .../scripts/__pycache__/ocean.cpython-312.pyc | Bin 12802 -> 12811 bytes .../process_questions.cpython-312.pyc | Bin 12295 -> 11377 bytes gcmpy/scripts/atmosphere.py | 35 +- gcmpy/scripts/env.py | 14 +- gcmpy/scripts/gcm_setup.py | 124 ++--- gcmpy/scripts/gocart.py | 8 +- gcmpy/scripts/land.py | 16 +- gcmpy/scripts/ocean.py | 25 +- gcmpy/scripts/process_questions.py | 18 +- gcmpy/yaml/atmospheric_model.yaml | 2 +- gcmpy/yaml/directory_setup.yaml | 2 +- gcmpy/yaml/land_model.yaml | 4 +- linkbcs.tmpl | 4 +- 31 files changed, 713 insertions(+), 720 deletions(-) diff --git a/AGCM.rc.tmpl b/AGCM.rc.tmpl index d522d393..d7cb41a0 100644 --- a/AGCM.rc.tmpl +++ b/AGCM.rc.tmpl @@ -361,21 +361,21 @@ RECORD_REF_TIME: >>>REFTIME<<< >>>FCSTIME<<< # 4DIAU (recreate analysis tendency on the fly) # --------------------------------------------- -#>>>_4DIAUDAS<<< AINC_FILE: {{ EXPID }}.ana.eta.%y4%m2%d2_%h2%n2z.nc4 -#>>>_4DIAUDAS<<< NUDGE_STATE: YES -##>>>_4DIAUDAS<<< TAUANL: 3600 -#>>>_4DIAUDAS<<< AGCM_IMPORT_RESTART_FILE: agcm_import_rst.>>>ANA0YYYYMMDDHHMN<<>>_4DIAUDAS<<< AGCM_IMPORT_RESTART_TYPE: binary +#{{ _4DIAUDAS }} AINC_FILE: {{ EXPID }}.ana.eta.%y4%m2%d2_%h2%n2z.nc4 +#{{ _4DIAUDAS }} NUDGE_STATE: YES +##{{ _4DIAUDAS }} TAUANL: 3600 +#{{ _4DIAUDAS }} AGCM_IMPORT_RESTART_FILE: agcm_import_rst.>>>ANA0YYYYMMDDHHMN<<>>_4DIAUDAS<<< REPLAY_MODE: Exact ->>>_4DIAUDAS<<< REPLAY_FILE: agcm_import_rst.%y4%m2%d2_%h2%n2z.nc4 ->>>_4DIAUDAS<<< REPLAY_FILE_FREQUENCY: 7200 ->>>_4DIAUDAS<<< REPLAY_SHUTOFF: 21600.0 # ShutOff Replay after 6-hours for G5NCEP and G5ECMWF Forecasts +{{ _4DIAUDAS }} REPLAY_MODE: Exact +{{ _4DIAUDAS }} REPLAY_FILE: agcm_import_rst.%y4%m2%d2_%h2%n2z.nc4 +{{ _4DIAUDAS }} REPLAY_FILE_FREQUENCY: 7200 +{{ _4DIAUDAS }} REPLAY_SHUTOFF: 21600.0 # ShutOff Replay after 6-hours for G5NCEP and G5ECMWF Forecasts -#>>>_4DIAUDAS<<< REPLAY_INTERVAL: 3600.0 -#>>>_4DIAUDAS<<< PREDICTOR_OFFSET: 3600.0 +#{{ _4DIAUDAS }} REPLAY_INTERVAL: 3600.0 +#{{ _4DIAUDAS }} PREDICTOR_OFFSET: 3600.0 #################################################################################################### #### Miscellaneous Exact/Regular REPLAY Parameters #### @@ -408,22 +408,22 @@ RECORD_REF_TIME: >>>REFTIME<<< >>>FCSTIME<<< # REPLAY_V: YES or NO # (Default: YES) # REPLAY_T: YES or NO # (Default: YES) # REPLAY_QV: YES or NO # (Default: YES) ->>>REGULAR_REPLAY_GMAO<<< REPLAY_O3: YES or NO # (Default: YES) ->>>REGULAR_REPLAY_NCEP<<< REPLAY_O3: YES or NO # (Default: YES) ->>>REGULAR_REPLAY_ECMWF<<< REPLAY_O3: YES or NO # (Default: YES) +{{ REGULAR_REPLAY_GMAO }} REPLAY_O3: YES or NO # (Default: YES) +{{ REGULAR_REPLAY_NCEP }} REPLAY_O3: YES or NO # (Default: YES) +{{ REGULAR_REPLAY_ECMWF }} REPLAY_O3: YES or NO # (Default: YES) # REPLAY_TS: YES or NO # (Default: NO) # # Regular REPLAY Remapping and Blending Variables # ----------------------------------------------- # REPLAY_REMAP: YES # Default = YES, Remap ANA Data to BKG Topography ->>>REGULAR_REPLAY_ECMWF<<< REPLAY_DAMPBEG: 1000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) ->>>REGULAR_REPLAY_ECMWF<<< REPLAY_DAMPEND: 5000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) ->>>REGULAR_REPLAY_GMAO<<< REPLAY_DAMPBEG: 100.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) ->>>REGULAR_REPLAY_GMAO<<< REPLAY_DAMPEND: 5000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) ->>>REGULAR_REPLAY_NCEP<<< REPLAY_DAMPBEG: 1000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) ->>>REGULAR_REPLAY_NCEP<<< REPLAY_DAMPEND: 5000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) ->>>REGULAR_REPLAY<<< REPLAY_SHUTOFF: 21600 # ShutOff Replay after 6-hours of Integration ->>>REGULAR_REPLAY<<< REPLAY_WINDFIX: YES # Apply windfix to force vertically-integrated analysis divergence increment to zero +{{ REGULAR_REPLAY_ECMWF }} REPLAY_DAMPBEG: 1000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) +{{ REGULAR_REPLAY_ECMWF }} REPLAY_DAMPEND: 5000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) +{{ REGULAR_REPLAY_GMAO }} REPLAY_DAMPBEG: 100.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) +{{ REGULAR_REPLAY_GMAO }} REPLAY_DAMPEND: 5000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) +{{ REGULAR_REPLAY_NCEP }} REPLAY_DAMPBEG: 1000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) +{{ REGULAR_REPLAY_NCEP }} REPLAY_DAMPEND: 5000.0 # Default = 1, Linearly Damp Increments between DAMPBEG & DAMPEND (Pascals) +{{ REGULAR_REPLAY }} REPLAY_SHUTOFF: 21600 # ShutOff Replay after 6-hours of Integration +{{ REGULAR_REPLAY }} REPLAY_WINDFIX: YES # Apply windfix to force vertically-integrated analysis divergence increment to zero # # REPLAY_BLEND_QV_AT_TP: .FALSE. # Default = FALSE, Blend QV to BKG upwards from tropopause # @@ -566,14 +566,14 @@ LSM_CHOICE: {{ LSM_CHOICE }} # AGCM_INTERNAL = BIAS Correction Increment: BIAS(n+1) = ALPHA*IAU(n) + BETA*BIAS(n) # ---------------------------------------------------------------------------------- ->>>FORCEDAS<<>>FORCEGCM<<>>FORCEGCM<<>>FORCEGCM<<>>FORCEGCM<<>>FORCEGCM<<>>HIST_CATCHCN<<< 'CNLAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNTLAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNSAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNTOTC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNVEGC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNROOT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNFROOTC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNNPP' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNGPP' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNSR' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNNEE' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNXSMR' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNADD' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'PARABS' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'PARINC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'SCSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'SCUNS' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'BTRANT' , 'SURFACE' , 'BTRAN' , ->>>HIST_CATCHCN<<< 'SIF' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNLOSS' , 'SURFACE' , 'CLOSS' , ->>>HIST_CATCHCN<<< 'CNBURN' , 'SURFACE' , 'BURN' , ->>>HIST_CATCHCN<<< 'CNFSEL' , 'SURFACE' , 'FSEL' , ->>>HIST_CATCHCN<<< 'EVPICE' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPSNO' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPINT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPSOI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPVEG' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRUST' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRWLT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPUNST' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPWLT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPSURF' , 'SURFACE' , 'TSURF' , ->>>HIST_CATCHCN<<< 'GHTSKIN' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'WAT10CM' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'WATSOI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'ICESOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNLAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNTLAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNSAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNTOTC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNVEGC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNROOT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNFROOTC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNNPP' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNGPP' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNSR' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNNEE' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNXSMR' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNADD' , 'SURFACE' , +{{ HIST_CATCHCN }} 'PARABS' , 'SURFACE' , +{{ HIST_CATCHCN }} 'PARINC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'SCSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'SCUNS' , 'SURFACE' , +{{ HIST_CATCHCN }} 'BTRANT' , 'SURFACE' , 'BTRAN' , +{{ HIST_CATCHCN }} 'SIF' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNLOSS' , 'SURFACE' , 'CLOSS' , +{{ HIST_CATCHCN }} 'CNBURN' , 'SURFACE' , 'BURN' , +{{ HIST_CATCHCN }} 'CNFSEL' , 'SURFACE' , 'FSEL' , +{{ HIST_CATCHCN }} 'EVPICE' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPSNO' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPINT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPSOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPVEG' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRUST' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRWLT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPUNST' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPWLT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPSURF' , 'SURFACE' , 'TSURF' , +{{ HIST_CATCHCN }} 'GHTSKIN' , 'SURFACE' , +{{ HIST_CATCHCN }} 'WAT10CM' , 'SURFACE' , +{{ HIST_CATCHCN }} 'WATSOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'ICESOI' , 'SURFACE' , :: geosgcm_ocn.template: '%y4%m2%d2_%h2%n2z.nc4' , geosgcm_ocn.archive: '%c/Y%y4' , geosgcm_ocn.format: 'CFIO' , geosgcm_ocn.deflate: 1 , - geosgcm_ocn.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_ocn.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_ocn.regrid_method: 'BILINEAR', geosgcm_ocn.mode: 'time-averaged' , geosgcm_ocn.monthly: 1 , @@ -373,9 +373,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_meltwtr.archive: '%c/Y%y4' , geosgcm_meltwtr.format: 'CFIO' , geosgcm_meltwtr.deflate: 1 , - geosgcm_meltwtr.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_meltwtr.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_meltwtr.regrid_exch: 'tile.bin' , - geosgcm_meltwtr.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_meltwtr.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_meltwtr.regrid_method: 'BILINEAR', geosgcm_meltwtr.mode: 'time-averaged' , geosgcm_meltwtr.monthly: 1 , @@ -388,9 +388,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_landice.archive: '%c/Y%y4' , geosgcm_landice.format: 'CFIO' , geosgcm_landice.deflate: 1 , - geosgcm_landice.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_landice.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_landice.regrid_exch: 'tile.bin' , - geosgcm_landice.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_landice.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_landice.regrid_method: 'BILINEAR', geosgcm_landice.mode: 'time-averaged' , geosgcm_landice.monthly: 1 , @@ -423,9 +423,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_snowlayer.archive: '%c/Y%y4' , geosgcm_snowlayer.format: 'CFIO' , geosgcm_snowlayer.deflate: 1 , - geosgcm_snowlayer.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_snowlayer.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_snowlayer.regrid_exch: 'tile.bin' , - geosgcm_snowlayer.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_snowlayer.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_snowlayer.regrid_method: 'BILINEAR', geosgcm_snowlayer.mode: 'time-averaged' , geosgcm_snowlayer.monthly: 1 , @@ -447,7 +447,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_moist.archive: '%c/Y%y4' , geosgcm_moist.format: 'CFIO' , geosgcm_moist.deflate: 1 , - geosgcm_moist.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_moist.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_moist.regrid_method: 'BILINEAR', geosgcm_moist.mode: 'time-averaged' , geosgcm_moist.monthly: 1 , @@ -489,7 +489,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_turb.archive: '%c/Y%y4' , geosgcm_turb.format: 'CFIO' , geosgcm_turb.deflate: 1 , - geosgcm_turb.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_turb.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_turb.regrid_method: 'BILINEAR', geosgcm_turb.mode: 'time-averaged' , geosgcm_turb.monthly: 1 , @@ -520,7 +520,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_gwd.archive: '%c/Y%y4' , geosgcm_gwd.format: 'CFIO' , geosgcm_gwd.deflate: 1 , - geosgcm_gwd.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_gwd.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_gwd.regrid_method: 'BILINEAR', geosgcm_gwd.mode: 'time-averaged' , geosgcm_gwd.monthly: 1 , @@ -544,7 +544,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_tend.archive: '%c/Y%y4' , geosgcm_tend.format: 'CFIO' , geosgcm_tend.deflate: 1 , - geosgcm_tend.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_tend.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_tend.regrid_method: 'BILINEAR', geosgcm_tend.mode: 'time-averaged' , geosgcm_tend.monthly: 1 , @@ -582,7 +582,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_budi.archive: '%c/Y%y4' , geosgcm_budi.format: 'CFIO' , geosgcm_budi.deflate: 1 , - geosgcm_budi.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_budi.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_budi.regrid_method: 'CONSERVE', geosgcm_budi.frequency: 030000 , geosgcm_budi.fields: 'TQV' , 'AGCM' , @@ -596,7 +596,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_buda.archive: '%c/Y%y4' , geosgcm_buda.format: 'CFIO' , geosgcm_buda.deflate: 1 , - geosgcm_buda.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_buda.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_buda.regrid_method: 'CONSERVE', geosgcm_buda.mode: 'time-averaged' , geosgcm_buda.monthly: 1 , @@ -628,7 +628,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_iau.archive: '%c/Y%y4', geosgcm_iau.format: 'CFIO', geosgcm_iau.deflate: 1, - geosgcm_iau.grid_label: PC@HIST_IMx@HIST_JM-DC, + geosgcm_iau.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, geosgcm_iau.regrid_method: 'BILINEAR', geosgcm_iau.mode: 'time-averaged', # geosgcm_iau.monthly: 1, @@ -657,7 +657,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_conv.archive: '%c/Y%y4' , geosgcm_conv.format: 'CFIO' , geosgcm_conv.deflate: 1 , - geosgcm_conv.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_conv.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_conv.regrid_method: 'BILINEAR', geosgcm_conv.frequency: 010000 , geosgcm_conv.fields: 'TQV' , 'AGCM' , @@ -682,7 +682,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_bud.archive: '%c/Y%y4' , geosgcm_bud.format: 'CFIO' , geosgcm_bud.deflate: 1 , - geosgcm_bud.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_bud.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_bud.regrid_method: 'BILINEAR', geosgcm_bud.mode: 'time-averaged' , geosgcm_bud.frequency: 240000 , @@ -733,9 +733,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_catch.archive: '%c/Y%y4' , goswim_catch.format: 'CFIO' , goswim_catch.deflate: 1 , - goswim_catch.regrid_name: '@AGCM_GRIDNAME' , + goswim_catch.regrid_name: '{{ AGCM_GRIDNAME }}' , goswim_catch.regrid_exch: 'tile.bin' , - goswim_catch.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_catch.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_catch.regrid_method: 'BILINEAR', goswim_catch.mode: 'time-averaged' , goswim_catch.frequency: 240000 , @@ -767,7 +767,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_land.archive: '%c/Y%y4' , goswim_land.format: 'CFIO' , goswim_land.deflate: 1 , - goswim_land.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_land.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_land.regrid_method: 'BILINEAR', goswim_land.mode: 'time-averaged' , goswim_land.frequency: 240000 , @@ -796,9 +796,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_landice.archive: '%c/Y%y4' , goswim_landice.format: 'CFIO' , goswim_landice.deflate: 1 , - goswim_landice.regrid_name: '@AGCM_GRIDNAME' + goswim_landice.regrid_name: '{{ AGCM_GRIDNAME }}' goswim_landice.regrid_exch: 'tile.bin' , - goswim_landice.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_landice.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_landice.regrid_method: 'BILINEAR', goswim_landice.mode: 'time-averaged' , goswim_landice.frequency: 240000 , @@ -825,7 +825,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM tavg2d_aer_x.archive: '%c/Y%y4', tavg2d_aer_x.format: 'CFIO', tavg2d_aer_x.deflate: 1, - tavg2d_aer_x.grid_label: PC@HIST_IMx@HIST_JM-DC, + tavg2d_aer_x.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, tavg2d_aer_x.mode: 'time-averaged', tavg2d_aer_x.monthly: 1, # tavg2d_aer_x.frequency: 240000, @@ -1006,7 +1006,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM tavg3d_aer_p.archive: '%c/Y%y4', tavg3d_aer_p.format: 'CFIO', tavg3d_aer_p.deflate: 1, - tavg3d_aer_p.grid_label: PC@HIST_IMx@HIST_JM-DC, + tavg3d_aer_p.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, tavg3d_aer_p.mode: 'time-averaged', tavg3d_aer_p.monthly: 1, # tavg3d_aer_p.frequency: 240000, @@ -1051,7 +1051,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_tracer.archive: '%c/Y%y4' , geosgcm_tracer.format: 'CFIO' , geosgcm_tracer.deflate: 1 , - geosgcm_tracer.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_tracer.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_tracer.regrid_method: 'BILINEAR', geosgcm_tracer.mode: 'time-averaged' , geosgcm_tracer.monthly: 1 , @@ -1081,7 +1081,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_lidar.archive: '%c/Y%y4' , geosgcm_lidar.format: 'CFIO' , geosgcm_lidar.deflate: 1 , - geosgcm_lidar.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_lidar.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_lidar.regrid_method: 'BILINEAR', geosgcm_lidar.mode: 'time-averaged' , geosgcm_lidar.frequency: 030000 , @@ -1124,7 +1124,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_parasol.archive: '%c/Y%y4' , geosgcm_parasol.format: 'CFIO' , geosgcm_parasol.deflate: 1 , - geosgcm_parasol.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_parasol.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_parasol.regrid_method: 'BILINEAR', geosgcm_parasol.mode: 'time-averaged' , geosgcm_parasol.frequency: 030000 , @@ -1140,7 +1140,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_radar.archive: '%c/Y%y4' , geosgcm_radar.format: 'CFIO' , geosgcm_radar.deflate: 1 , - geosgcm_radar.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_radar.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_radar.regrid_method: 'BILINEAR', geosgcm_radar.mode: 'time-averaged' , geosgcm_radar.frequency: 030000 , @@ -1183,7 +1183,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_isccp.archive: '%c/Y%y4' , geosgcm_isccp.format: 'CFIO' , geosgcm_isccp.deflate: 1 , - geosgcm_isccp.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_isccp.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_isccp.regrid_method: 'BILINEAR', geosgcm_isccp.mode: 'time-averaged' , geosgcm_isccp.frequency: 030000 , @@ -1253,7 +1253,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_modis.archive: '%c/Y%y4' , geosgcm_modis.format: 'CFIO' , geosgcm_modis.deflate: 1 , - geosgcm_modis.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_modis.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_modis.regrid_method: 'BILINEAR', geosgcm_modis.mode: 'time-averaged' , geosgcm_modis.frequency: 030000 , @@ -1335,7 +1335,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_misr.archive: '%c/Y%y4' , geosgcm_misr.format: 'CFIO' , geosgcm_misr.deflate: 1 , - geosgcm_misr.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_misr.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_misr.regrid_method: 'BILINEAR', geosgcm_misr.mode: 'time-averaged' , geosgcm_misr.frequency: 030000 , diff --git a/HISTORY.AOGCM-MOM5.rc.tmpl b/HISTORY.AOGCM-MOM5.rc.tmpl index c5937806..d52e00b5 100644 --- a/HISTORY.AOGCM-MOM5.rc.tmpl +++ b/HISTORY.AOGCM-MOM5.rc.tmpl @@ -1,7 +1,7 @@ VERSION: 1 -EXPID: @EXPID -EXPDSC: @EXPDSC -EXPSRC: @EXPSRC +EXPID: {{ EXPID }} +EXPDSC: {{ EXPDSC }} +EXPSRC: {{ EXPSRC }} CONTACT: 'http://gmao.gsfc.nasa.gov' @@ -20,8 +20,8 @@ COLLECTIONS: 'geosgcm_prog' # 'geosgcm_meltwtr' # 'geosgcm_snowlayer' 'geosgcm_tracer' -@HIST_GOCART 'tavg2d_aer_x' -@HIST_GOCART 'tavg3d_aer_p' + {{ HIST_GOCART }} 'tavg2d_aer_x' + {{ HIST_GOCART }} 'tavg3d_aer_p' # 'geosgcm_iau' # 'geosgcm_conv' # 'goswim_catch' @@ -56,22 +56,22 @@ COLLECTIONS: 'geosgcm_prog' # list of COLLECTIONS for scripting purposes. # ################################################## -GRID_LABELS: PC@HIST_IMx@HIST_JM-DC +GRID_LABELS: PC{{ HIST_IM }}x{{ HIST_JM }}-DC :: -PC@HIST_IMx@HIST_JM-DC.GRID_TYPE: LatLon -PC@HIST_IMx@HIST_JM-DC.IM_WORLD: @HIST_IM -PC@HIST_IMx@HIST_JM-DC.JM_WORLD: @HIST_JM -PC@HIST_IMx@HIST_JM-DC.POLE: PC -PC@HIST_IMx@HIST_JM-DC.DATELINE: DC -PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.GRID_TYPE: LatLon +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.IM_WORLD: {{ HIST_IM }} +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.JM_WORLD: {{ HIST_JM }} +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.POLE: PC +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.DATELINE: DC +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} geosgcm_prog.template: '%y4%m2%d2_%h2%n2z.nc4' , geosgcm_prog.archive: '%c/Y%y4' , geosgcm_prog.format: 'CFIO' , geosgcm_prog.deflate: 1 , - geosgcm_prog.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_prog.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_prog.regrid_method: 'BILINEAR', geosgcm_prog.frequency: 060000 , geosgcm_prog.vscale: 100.0 , @@ -96,7 +96,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM prog.eta.archive: '%c/Y%y4' , prog.eta.format: 'CFIO' , prog.eta.deflate: 1 , - prog.eta.grid_label: PC@HIST_IMx@HIST_JM-DC , + prog.eta.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , prog.eta.regrid_method: 'BILINEAR', prog.eta.mode: 'instantaneous' , prog.eta.frequency: 060000 , @@ -126,7 +126,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_surf.archive: '%c/Y%y4' , geosgcm_surf.format: 'CFIO' , geosgcm_surf.deflate: 1 , - geosgcm_surf.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_surf.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_surf.regrid_method: 'BILINEAR', geosgcm_surf.mode: 'time-averaged' , geosgcm_surf.monthly: 1 , @@ -280,51 +280,51 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM 'PHIW' , 'SURFACE' , 'TAUTW' , 'SURFACE' , 'ZETA_W' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNLAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNTLAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNSAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNTOTC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNVEGC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNROOT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNFROOTC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNNPP' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNGPP' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNSR' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNNEE' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNXSMR' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNADD' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'PARABS' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'PARINC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'SCSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'SCUNS' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'BTRANT' , 'SURFACE' , 'BTRAN' , ->>>HIST_CATCHCN<<< 'SIF' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNLOSS' , 'SURFACE' , 'CLOSS' , ->>>HIST_CATCHCN<<< 'CNBURN' , 'SURFACE' , 'BURN' , ->>>HIST_CATCHCN<<< 'CNFSEL' , 'SURFACE' , 'FSEL' , ->>>HIST_CATCHCN<<< 'EVPICE' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPSNO' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPINT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPSOI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPVEG' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRUST' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRWLT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPUNST' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPWLT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPSURF' , 'SURFACE' , 'TSURF' , ->>>HIST_CATCHCN<<< 'GHTSKIN' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'WAT10CM' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'WATSOI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'ICESOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNLAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNTLAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNSAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNTOTC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNVEGC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNROOT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNFROOTC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNNPP' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNGPP' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNSR' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNNEE' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNXSMR' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNADD' , 'SURFACE' , +{{ HIST_CATCHCN }} 'PARABS' , 'SURFACE' , +{{ HIST_CATCHCN }} 'PARINC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'SCSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'SCUNS' , 'SURFACE' , +{{ HIST_CATCHCN }} 'BTRANT' , 'SURFACE' , 'BTRAN' , +{{ HIST_CATCHCN }} 'SIF' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNLOSS' , 'SURFACE' , 'CLOSS' , +{{ HIST_CATCHCN }} 'CNBURN' , 'SURFACE' , 'BURN' , +{{ HIST_CATCHCN }} 'CNFSEL' , 'SURFACE' , 'FSEL' , +{{ HIST_CATCHCN }} 'EVPICE' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPSNO' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPINT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPSOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPVEG' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRUST' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRWLT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPUNST' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPWLT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPSURF' , 'SURFACE' , 'TSURF' , +{{ HIST_CATCHCN }} 'GHTSKIN' , 'SURFACE' , +{{ HIST_CATCHCN }} 'WAT10CM' , 'SURFACE' , +{{ HIST_CATCHCN }} 'WATSOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'ICESOI' , 'SURFACE' , :: geosgcm_ocn.template: '%y4%m2%d2_%h2%n2z.nc4' , geosgcm_ocn.archive: '%c/Y%y4' , geosgcm_ocn.format: 'CFIO' , geosgcm_ocn.deflate: 1 , - geosgcm_ocn.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_ocn.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_ocn.regrid_method: 'BILINEAR', geosgcm_ocn.mode: 'time-averaged' , geosgcm_ocn.monthly: 1 , @@ -381,9 +381,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_meltwtr.archive: '%c/Y%y4' , geosgcm_meltwtr.format: 'CFIO' , geosgcm_meltwtr.deflate: 1 , - geosgcm_meltwtr.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_meltwtr.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_meltwtr.regrid_exch: 'tile.bin' , - geosgcm_meltwtr.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_meltwtr.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_meltwtr.regrid_method: 'BILINEAR', geosgcm_meltwtr.mode: 'time-averaged' , geosgcm_meltwtr.monthly: 1 , @@ -396,9 +396,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_landice.archive: '%c/Y%y4' , geosgcm_landice.format: 'CFIO' , geosgcm_landice.deflate: 1 , - geosgcm_landice.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_landice.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_landice.regrid_exch: 'tile.bin' , - geosgcm_landice.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_landice.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_landice.regrid_method: 'BILINEAR', geosgcm_landice.mode: 'time-averaged' , geosgcm_landice.monthly: 1 , @@ -431,9 +431,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_snowlayer.archive: '%c/Y%y4' , geosgcm_snowlayer.format: 'CFIO' , geosgcm_snowlayer.deflate: 1 , - geosgcm_snowlayer.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_snowlayer.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_snowlayer.regrid_exch: 'tile.bin' , - geosgcm_snowlayer.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_snowlayer.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_snowlayer.regrid_method: 'BILINEAR', geosgcm_snowlayer.mode: 'time-averaged' , geosgcm_snowlayer.monthly: 1 , @@ -455,7 +455,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_moist.archive: '%c/Y%y4' , geosgcm_moist.format: 'CFIO' , geosgcm_moist.deflate: 1 , - geosgcm_moist.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_moist.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_moist.regrid_method: 'BILINEAR', geosgcm_moist.mode: 'time-averaged' , geosgcm_moist.monthly: 1 , @@ -496,7 +496,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_turb.archive: '%c/Y%y4' , geosgcm_turb.format: 'CFIO' , geosgcm_turb.deflate: 1 , - geosgcm_turb.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_turb.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_turb.regrid_method: 'BILINEAR', geosgcm_turb.mode: 'time-averaged' , geosgcm_turb.monthly: 1 , @@ -527,7 +527,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_gwd.archive: '%c/Y%y4' , geosgcm_gwd.format: 'CFIO' , geosgcm_gwd.deflate: 1 , - geosgcm_gwd.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_gwd.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_gwd.regrid_method: 'BILINEAR', geosgcm_gwd.mode: 'time-averaged' , geosgcm_gwd.monthly: 1 , @@ -551,7 +551,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_tend.archive: '%c/Y%y4' , geosgcm_tend.format: 'CFIO' , geosgcm_tend.deflate: 1 , - geosgcm_tend.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_tend.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_tend.regrid_method: 'BILINEAR', geosgcm_tend.mode: 'time-averaged' , geosgcm_tend.monthly: 1 , @@ -588,7 +588,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_budi.archive: '%c/Y%y4' , geosgcm_budi.format: 'CFIO' , geosgcm_budi.deflate: 1 , - geosgcm_budi.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_budi.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_budi.regrid_method: 'CONSERVE', geosgcm_budi.frequency: 030000 , geosgcm_budi.fields: 'TQV' , 'AGCM' , @@ -602,7 +602,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_buda.archive: '%c/Y%y4' , geosgcm_buda.format: 'CFIO' , geosgcm_buda.deflate: 1 , - geosgcm_buda.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_buda.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_buda.regrid_method: 'CONSERVE', geosgcm_buda.mode: 'time-averaged' , geosgcm_buda.monthly: 1 , @@ -634,7 +634,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_iau.archive: '%c/Y%y4' , geosgcm_iau.format: 'CFIO' , geosgcm_iau.deflate: 1 , - geosgcm_iau.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_iau.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_iau.regrid_method: 'BILINEAR', geosgcm_iau.mode: 'time-averaged' , # geosgcm_iau.monthly: 1 , @@ -658,7 +658,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_conv.archive: '%c/Y%y4' , geosgcm_conv.format: 'CFIO' , geosgcm_conv.deflate: 1 , - geosgcm_conv.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_conv.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_conv.regrid_method: 'BILINEAR', geosgcm_conv.frequency: 010000 , geosgcm_conv.fields: 'TQV' , 'AGCM' , @@ -683,7 +683,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_bud.archive: '%c/Y%y4' , geosgcm_bud.format: 'CFIO' , geosgcm_bud.deflate: 1 , - geosgcm_bud.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_bud.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_bud.regrid_method: 'BILINEAR', geosgcm_bud.mode: 'time-averaged' , geosgcm_bud.frequency: 240000 , @@ -734,9 +734,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_catch.archive: '%c/Y%y4' , goswim_catch.format: 'CFIO' , goswim_catch.deflate: 1 , - goswim_catch.regrid_name: '@AGCM_GRIDNAME' , + goswim_catch.regrid_name: '{{ AGCM_GRIDNAME }}' , goswim_catch.regrid_exch: 'tile.bin' , - goswim_catch.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_catch.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_catch.regrid_method: 'BILINEAR', goswim_catch.mode: 'time-averaged' , goswim_catch.frequency: 240000 , @@ -768,7 +768,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_land.archive: '%c/Y%y4' , goswim_land.format: 'CFIO' , goswim_land.deflate: 1 , - goswim_land.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_land.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_land.regrid_method: 'BILINEAR', goswim_land.mode: 'time-averaged' , goswim_land.frequency: 240000 , @@ -797,9 +797,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_landice.archive: '%c/Y%y4' , goswim_landice.format: 'CFIO' , goswim_landice.deflate: 1 , - goswim_landice.regrid_name: '@AGCM_GRIDNAME' + goswim_landice.regrid_name: '{{ AGCM_GRIDNAME }}' goswim_landice.regrid_exch: 'tile.bin' , - goswim_landice.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_landice.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_landice.regrid_method: 'BILINEAR', goswim_landice.mode: 'time-averaged' , goswim_landice.frequency: 240000 , @@ -826,7 +826,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM tavg2d_aer_x.archive: '%c/Y%y4', tavg2d_aer_x.format: 'CFIO', tavg2d_aer_x.deflate: 1, - tavg2d_aer_x.grid_label: PC@HIST_IMx@HIST_JM-DC, + tavg2d_aer_x.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, tavg2d_aer_x.mode: 'time-averaged', tavg2d_aer_x.monthly: 1, # tavg2d_aer_x.frequency: 240000, @@ -1005,7 +1005,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM tavg3d_aer_p.archive: '%c/Y%y4', tavg3d_aer_p.format: 'CFIO', tavg3d_aer_p.deflate: 1, - tavg3d_aer_p.grid_label: PC@HIST_IMx@HIST_JM-DC, + tavg3d_aer_p.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, tavg3d_aer_p.mode: 'time-averaged', tavg3d_aer_p.monthly: 1, # tavg3d_aer_p.frequency: 240000, @@ -1050,7 +1050,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_tracer.archive: '%c/Y%y4' , geosgcm_tracer.format: 'CFIO' , geosgcm_tracer.deflate: 1 , - geosgcm_tracer.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_tracer.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_tracer.regrid_method: 'BILINEAR', geosgcm_tracer.mode: 'time-averaged' , geosgcm_tracer.monthly: 1 , @@ -1080,7 +1080,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_lidar.archive: '%c/Y%y4' , geosgcm_lidar.format: 'CFIO' , geosgcm_lidar.deflate: 1 , - geosgcm_lidar.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_lidar.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_lidar.regrid_method: 'BILINEAR', geosgcm_lidar.mode: 'time-averaged' , geosgcm_lidar.frequency: 030000 , @@ -1123,7 +1123,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_parasol.archive: '%c/Y%y4' , geosgcm_parasol.format: 'CFIO' , geosgcm_parasol.deflate: 1 , - geosgcm_parasol.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_parasol.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_parasol.regrid_method: 'BILINEAR', geosgcm_parasol.mode: 'time-averaged' , geosgcm_parasol.frequency: 030000 , @@ -1139,7 +1139,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_radar.archive: '%c/Y%y4' , geosgcm_radar.format: 'CFIO' , geosgcm_radar.deflate: 1 , - geosgcm_radar.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_radar.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_radar.regrid_method: 'BILINEAR', geosgcm_radar.mode: 'time-averaged' , geosgcm_radar.frequency: 030000 , @@ -1182,7 +1182,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_isccp.archive: '%c/Y%y4' , geosgcm_isccp.format: 'CFIO' , geosgcm_isccp.deflate: 1 , - geosgcm_isccp.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_isccp.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_isccp.regrid_method: 'BILINEAR', geosgcm_isccp.mode: 'time-averaged' , geosgcm_isccp.frequency: 030000 , @@ -1252,7 +1252,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_modis.archive: '%c/Y%y4' , geosgcm_modis.format: 'CFIO' , geosgcm_modis.deflate: 1 , - geosgcm_modis.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_modis.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_modis.regrid_method: 'BILINEAR', geosgcm_modis.mode: 'time-averaged' , geosgcm_modis.frequency: 030000 , @@ -1334,7 +1334,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_misr.archive: '%c/Y%y4' , geosgcm_misr.format: 'CFIO' , geosgcm_misr.deflate: 1 , - geosgcm_misr.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_misr.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_misr.regrid_method: 'BILINEAR', geosgcm_misr.mode: 'time-averaged' , geosgcm_misr.frequency: 030000 , @@ -1368,7 +1368,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_rad.archive: '%c/Y%y4', geosgcm_rad.format: 'CFIO', geosgcm_rad.deflate: 1 , - geosgcm_rad.grid_label: PC@HIST_IMx@HIST_JM-DC, + geosgcm_rad.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, geosgcm_rad.regrid_method: 'BILINEAR', geosgcm_rad.mode: 'time-averaged', geosgcm_rad.monthly: 1, @@ -1421,7 +1421,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_int.archive: '%c/Y%y4', geosgcm_int.format: 'CFIO' , geosgcm_int.deflate: 1 , - geosgcm_int.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_int.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_int.regrid_method: 'BILINEAR', geosgcm_int.mode: 'time-averaged' , geosgcm_int.monthly: 1 , @@ -1447,7 +1447,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_seaice.archive: '%c/Y%y4', geosgcm_seaice.format: 'CFIO', geosgcm_seaice.deflate: 1 , -# geosgcm_seaice.grid_label: PC@HIST_IMx@HIST_JM-DC , +# geosgcm_seaice.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , # geosgcm_seaice.regrid_method: 'BILINEAR', geosgcm_seaice.mode: 'time-averaged' , geosgcm_seaice.monthly: 1 , @@ -1495,13 +1495,13 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_icethm.archive: '%c/Y%y4', geosgcm_icethm.format: 'CFIO', geosgcm_icethm.deflate: 1 , -# geosgcm_icethm.grid_label: PC@HIST_IMx@HIST_JM-DC , +# geosgcm_icethm.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , # geosgcm_icethm.regrid_method: 'BILINEAR', geosgcm_icethm.mode: 'time-averaged' , geosgcm_icethm.monthly: 1 , # geosgcm_icethm.frequency: 240000, geosgcm_icethm.regrid_exch:'tile.bin', - geosgcm_icethm.regrid_name:'@OGCM_GRIDNAME', + geosgcm_icethm.regrid_name:'{{ OGCM_GRIDNAME }}', geosgcm_icethm.fields: 'DVIDTT' , 'SEAICETHERMO', 'dvidtt', 'DAIDTT' , 'SEAICETHERMO', 'daidtt', 'FBOT' , 'SEAICETHERMO', 'fbot', @@ -1528,7 +1528,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_ocn3d.deflate: 1 , geosgcm_ocn3d.monthly: 1 , geosgcm_ocn3d.mode: 'time-averaged', - geosgcm_ocn3d.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_ocn3d.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_ocn3d.levels: 'vgrid.ascii' geosgcm_ocn3d.fields: 'DH' , 'MOM', 'T' , 'MOM', @@ -1547,7 +1547,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_ocn2d.deflate: 1 , geosgcm_ocn2d.monthly: 1 , geosgcm_ocn2d.mode: 'time-averaged', - geosgcm_ocn2d.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_ocn2d.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_ocn2d.fields: 'UW' , 'MOM', 'US' 'VW' , 'MOM', 'VS' 'TW' , 'MOM', 'TS' @@ -1631,13 +1631,13 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_aoflux.archive: '%c/Y%y4', geosgcm_aoflux.format: 'CFIO', geosgcm_aoflux.deflate: 1 , -# geosgcm_aoflux.grid_label: PC@HIST_IMx@HIST_JM-DC , +# geosgcm_aoflux.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , # geosgcm_aoflux.regrid_method: 'BILINEAR', geosgcm_aoflux.mode: 'time-averaged' , geosgcm_aoflux.monthly: 1 , geosgcm_aoflux.frequency: 240000, # geosgcm_aoflux.regrid_exch:'tile.bin', - geosgcm_aoflux.regrid_name:'@OGCM_GRIDNAME', + geosgcm_aoflux.regrid_name:'{{ OGCM_GRIDNAME }}', geosgcm_aoflux.fields: 'TS_FOUND' , 'OPENWATER', 'SS_FOUND' , 'OPENWATER', 'AO_DRNIR' , 'OPENWATER', @@ -1699,7 +1699,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_iceflxn.mode: 'time-averaged', # geosgcm_iceflxn.frequency: 240000, geosgcm_iceflxn.regrid_exch:'tile.bin', - geosgcm_iceflxn.regrid_name:'@OGCM_GRIDNAME', + geosgcm_iceflxn.regrid_name:'{{ OGCM_GRIDNAME }}', geosgcm_iceflxn.fields: 'FCONDBOTN' , 'SEAICETHERMO', 'fcondbotn', 'SHICEN' , 'SEAICETHERMO', 'FSWSFCN' , 'SEAICETHERMO', @@ -1720,7 +1720,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_iceflx.mode: 'time-averaged', # geosgcm_iceflx.frequency: 240000, geosgcm_iceflx.regrid_exch:'tile.bin', - geosgcm_iceflx.regrid_name:'@OGCM_GRIDNAME', + geosgcm_iceflx.regrid_name:'{{ OGCM_GRIDNAME }}', geosgcm_iceflx.fields: 'LWDNSRF' , 'SEAICETHERMO', 'SWDNSRF' , 'SEAICETHERMO', 'HLWUPICE' , 'SEAICETHERMO', diff --git a/HISTORY.AOGCM.rc.tmpl b/HISTORY.AOGCM.rc.tmpl index 0d6cbf97..0a7a87ac 100644 --- a/HISTORY.AOGCM.rc.tmpl +++ b/HISTORY.AOGCM.rc.tmpl @@ -1,7 +1,7 @@ VERSION: 1 -EXPID: @EXPID -EXPDSC: @EXPDSC -EXPSRC: @EXPSRC +EXPID: {{ EXPID }} +EXPDSC: {{ EXPDSC }} +EXPSRC: {{ EXPSRC }} CONTACT: 'http://gmao.gsfc.nasa.gov' @@ -20,8 +20,8 @@ COLLECTIONS: 'geosgcm_prog' # 'geosgcm_meltwtr' # 'geosgcm_snowlayer' 'geosgcm_tracer' -@HIST_GOCART 'tavg2d_aer_x' -@HIST_GOCART 'tavg3d_aer_p' + {{ HIST_GOCART }} 'tavg2d_aer_x' + {{ HIST_GOCART }} 'tavg3d_aer_p' # 'geosgcm_iau' # 'geosgcm_conv' # 'goswim_catch' @@ -39,7 +39,7 @@ COLLECTIONS: 'geosgcm_prog' 'geosgcm_rad' # 'geosgcm_int' 'geosgcm_seaice' ->>>HIST_CICE4<<< 'geosgcm_icethm' +{{ {{ HIST_CICE4 }} }} 'geosgcm_icethm' 'geosgcm_ocn2dT' # 'geosgcm_aoflux' # 'geosgcm_icecat' @@ -53,22 +53,22 @@ COLLECTIONS: 'geosgcm_prog' # list of COLLECTIONS for scripting purposes. # ################################################## -GRID_LABELS: PC@HIST_IMx@HIST_JM-DC +GRID_LABELS: PC{{ HIST_IM }}x{{ HIST_JM }}-DC :: -PC@HIST_IMx@HIST_JM-DC.GRID_TYPE: LatLon -PC@HIST_IMx@HIST_JM-DC.IM_WORLD: @HIST_IM -PC@HIST_IMx@HIST_JM-DC.JM_WORLD: @HIST_JM -PC@HIST_IMx@HIST_JM-DC.POLE: PC -PC@HIST_IMx@HIST_JM-DC.DATELINE: DC -PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.GRID_TYPE: LatLon +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.IM_WORLD: {{ HIST_IM }} +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.JM_WORLD: {{ HIST_JM }} +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.POLE: PC +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.DATELINE: DC +PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} geosgcm_prog.template: '%y4%m2%d2_%h2%n2z.nc4' , geosgcm_prog.archive: '%c/Y%y4' , geosgcm_prog.format: 'CFIO' , geosgcm_prog.deflate: 1 , - geosgcm_prog.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_prog.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_prog.regrid_method: 'BILINEAR', geosgcm_prog.frequency: 060000 , geosgcm_prog.vscale: 100.0 , @@ -93,7 +93,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM prog.eta.archive: '%c/Y%y4' , prog.eta.format: 'CFIO' , prog.eta.deflate: 1 , - prog.eta.grid_label: PC@HIST_IMx@HIST_JM-DC , + prog.eta.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , prog.eta.regrid_method: 'BILINEAR', prog.eta.mode: 'instantaneous' , prog.eta.frequency: 060000 , @@ -123,7 +123,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_surf.archive: '%c/Y%y4' , geosgcm_surf.format: 'CFIO' , geosgcm_surf.deflate: 1 , - geosgcm_surf.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_surf.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_surf.regrid_method: 'BILINEAR', geosgcm_surf.mode: 'time-averaged' , geosgcm_surf.monthly: 1 , @@ -277,51 +277,51 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM 'PHIW' , 'SURFACE' , 'TAUTW' , 'SURFACE' , 'ZETA_W' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNLAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNTLAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNSAI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNTOTC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNVEGC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNROOT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNFROOTC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNNPP' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNGPP' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNSR' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNNEE' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNXSMR' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNADD' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'PARABS' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'PARINC' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'SCSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'SCUNS' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'BTRANT' , 'SURFACE' , 'BTRAN' , ->>>HIST_CATCHCN<<< 'SIF' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'CNLOSS' , 'SURFACE' , 'CLOSS' , ->>>HIST_CATCHCN<<< 'CNBURN' , 'SURFACE' , 'BURN' , ->>>HIST_CATCHCN<<< 'CNFSEL' , 'SURFACE' , 'FSEL' , ->>>HIST_CATCHCN<<< 'EVPICE' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPSNO' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPINT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPSOI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'EVPVEG' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRUST' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'FRWLT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPSAT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPUNST' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPWLT' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'TPSURF' , 'SURFACE' , 'TSURF' , ->>>HIST_CATCHCN<<< 'GHTSKIN' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'WAT10CM' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'WATSOI' , 'SURFACE' , ->>>HIST_CATCHCN<<< 'ICESOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNLAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNTLAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNSAI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNTOTC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNVEGC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNROOT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNFROOTC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNNPP' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNGPP' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNSR' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNNEE' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNXSMR' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNADD' , 'SURFACE' , +{{ HIST_CATCHCN }} 'PARABS' , 'SURFACE' , +{{ HIST_CATCHCN }} 'PARINC' , 'SURFACE' , +{{ HIST_CATCHCN }} 'SCSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'SCUNS' , 'SURFACE' , +{{ HIST_CATCHCN }} 'BTRANT' , 'SURFACE' , 'BTRAN' , +{{ HIST_CATCHCN }} 'SIF' , 'SURFACE' , +{{ HIST_CATCHCN }} 'CNLOSS' , 'SURFACE' , 'CLOSS' , +{{ HIST_CATCHCN }} 'CNBURN' , 'SURFACE' , 'BURN' , +{{ HIST_CATCHCN }} 'CNFSEL' , 'SURFACE' , 'FSEL' , +{{ HIST_CATCHCN }} 'EVPICE' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPSNO' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPINT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPSOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'EVPVEG' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRUST' , 'SURFACE' , +{{ HIST_CATCHCN }} 'FRWLT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPSAT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPUNST' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPWLT' , 'SURFACE' , +{{ HIST_CATCHCN }} 'TPSURF' , 'SURFACE' , 'TSURF' , +{{ HIST_CATCHCN }} 'GHTSKIN' , 'SURFACE' , +{{ HIST_CATCHCN }} 'WAT10CM' , 'SURFACE' , +{{ HIST_CATCHCN }} 'WATSOI' , 'SURFACE' , +{{ HIST_CATCHCN }} 'ICESOI' , 'SURFACE' , :: geosgcm_ocn.template: '%y4%m2%d2_%h2%n2z.nc4' , geosgcm_ocn.archive: '%c/Y%y4' , geosgcm_ocn.format: 'CFIO' , geosgcm_ocn.deflate: 1 , - geosgcm_ocn.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_ocn.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_ocn.regrid_method: 'BILINEAR', geosgcm_ocn.mode: 'time-averaged' , geosgcm_ocn.monthly: 1 , @@ -378,9 +378,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_meltwtr.archive: '%c/Y%y4' , geosgcm_meltwtr.format: 'CFIO' , geosgcm_meltwtr.deflate: 1 , - geosgcm_meltwtr.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_meltwtr.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_meltwtr.regrid_exch: 'tile.bin' , - geosgcm_meltwtr.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_meltwtr.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_meltwtr.regrid_method: 'BILINEAR', geosgcm_meltwtr.mode: 'time-averaged' , geosgcm_meltwtr.monthly: 1 , @@ -393,9 +393,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_landice.archive: '%c/Y%y4' , geosgcm_landice.format: 'CFIO' , geosgcm_landice.deflate: 1 , - geosgcm_landice.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_landice.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_landice.regrid_exch: 'tile.bin' , - geosgcm_landice.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_landice.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_landice.regrid_method: 'BILINEAR', geosgcm_landice.mode: 'time-averaged' , geosgcm_landice.monthly: 1 , @@ -428,9 +428,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_snowlayer.archive: '%c/Y%y4' , geosgcm_snowlayer.format: 'CFIO' , geosgcm_snowlayer.deflate: 1 , - geosgcm_snowlayer.regrid_name: '@AGCM_GRIDNAME' , + geosgcm_snowlayer.regrid_name: '{{ AGCM_GRIDNAME }}' , geosgcm_snowlayer.regrid_exch: 'tile.bin' , - geosgcm_snowlayer.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_snowlayer.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_snowlayer.regrid_method: 'BILINEAR', geosgcm_snowlayer.mode: 'time-averaged' , geosgcm_snowlayer.monthly: 1 , @@ -452,7 +452,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_moist.archive: '%c/Y%y4' , geosgcm_moist.format: 'CFIO' , geosgcm_moist.deflate: 1 , - geosgcm_moist.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_moist.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_moist.regrid_method: 'BILINEAR', geosgcm_moist.mode: 'time-averaged' , geosgcm_moist.monthly: 1 , @@ -493,7 +493,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_turb.archive: '%c/Y%y4' , geosgcm_turb.format: 'CFIO' , geosgcm_turb.deflate: 1 , - geosgcm_turb.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_turb.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_turb.regrid_method: 'BILINEAR', geosgcm_turb.mode: 'time-averaged' , geosgcm_turb.monthly: 1 , @@ -524,7 +524,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_gwd.archive: '%c/Y%y4' , geosgcm_gwd.format: 'CFIO' , geosgcm_gwd.deflate: 1 , - geosgcm_gwd.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_gwd.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_gwd.regrid_method: 'BILINEAR', geosgcm_gwd.mode: 'time-averaged' , geosgcm_gwd.monthly: 1 , @@ -548,7 +548,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_tend.archive: '%c/Y%y4' , geosgcm_tend.format: 'CFIO' , geosgcm_tend.deflate: 1 , - geosgcm_tend.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_tend.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_tend.regrid_method: 'BILINEAR', geosgcm_tend.mode: 'time-averaged' , geosgcm_tend.monthly: 1 , @@ -585,7 +585,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_budi.archive: '%c/Y%y4' , geosgcm_budi.format: 'CFIO' , geosgcm_budi.deflate: 1 , - geosgcm_budi.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_budi.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_budi.regrid_method: 'CONSERVE', geosgcm_budi.frequency: 030000 , geosgcm_budi.fields: 'TQV' , 'AGCM' , @@ -599,7 +599,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_buda.archive: '%c/Y%y4' , geosgcm_buda.format: 'CFIO' , geosgcm_buda.deflate: 1 , - geosgcm_buda.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_buda.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_buda.regrid_method: 'CONSERVE', geosgcm_buda.mode: 'time-averaged' , geosgcm_buda.monthly: 1 , @@ -631,7 +631,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_iau.archive: '%c/Y%y4' , geosgcm_iau.format: 'CFIO' , geosgcm_iau.deflate: 1 , - geosgcm_iau.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_iau.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_iau.regrid_method: 'BILINEAR', geosgcm_iau.mode: 'time-averaged' , # geosgcm_iau.monthly: 1 , @@ -655,7 +655,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_conv.archive: '%c/Y%y4' , geosgcm_conv.format: 'CFIO' , geosgcm_conv.deflate: 1 , - geosgcm_conv.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_conv.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_conv.regrid_method: 'BILINEAR', geosgcm_conv.frequency: 010000 , geosgcm_conv.fields: 'TQV' , 'AGCM' , @@ -680,7 +680,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_bud.archive: '%c/Y%y4' , geosgcm_bud.format: 'CFIO' , geosgcm_bud.deflate: 1 , - geosgcm_bud.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_bud.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_bud.regrid_method: 'BILINEAR', geosgcm_bud.mode: 'time-averaged' , geosgcm_bud.frequency: 240000 , @@ -731,9 +731,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_catch.archive: '%c/Y%y4' , goswim_catch.format: 'CFIO' , goswim_catch.deflate: 1 , - goswim_catch.regrid_name: '@AGCM_GRIDNAME' , + goswim_catch.regrid_name: '{{ AGCM_GRIDNAME }}' , goswim_catch.regrid_exch: 'tile.bin' , - goswim_catch.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_catch.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_catch.regrid_method: 'BILINEAR', goswim_catch.mode: 'time-averaged' , goswim_catch.frequency: 240000 , @@ -765,7 +765,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_land.archive: '%c/Y%y4' , goswim_land.format: 'CFIO' , goswim_land.deflate: 1 , - goswim_land.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_land.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_land.regrid_method: 'BILINEAR', goswim_land.mode: 'time-averaged' , goswim_land.frequency: 240000 , @@ -794,9 +794,9 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM goswim_landice.archive: '%c/Y%y4' , goswim_landice.format: 'CFIO' , goswim_landice.deflate: 1 , - goswim_landice.regrid_name: '@AGCM_GRIDNAME' + goswim_landice.regrid_name: '{{ AGCM_GRIDNAME }}' goswim_landice.regrid_exch: 'tile.bin' , - goswim_landice.grid_label: PC@HIST_IMx@HIST_JM-DC , + goswim_landice.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , goswim_landice.regrid_method: 'BILINEAR', goswim_landice.mode: 'time-averaged' , goswim_landice.frequency: 240000 , @@ -823,7 +823,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM tavg2d_aer_x.archive: '%c/Y%y4', tavg2d_aer_x.format: 'CFIO', tavg2d_aer_x.deflate: 1, - tavg2d_aer_x.grid_label: PC@HIST_IMx@HIST_JM-DC, + tavg2d_aer_x.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, tavg2d_aer_x.mode: 'time-averaged', tavg2d_aer_x.monthly: 1, # tavg2d_aer_x.frequency: 240000, @@ -1002,7 +1002,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM tavg3d_aer_p.archive: '%c/Y%y4', tavg3d_aer_p.format: 'CFIO', tavg3d_aer_p.deflate: 1, - tavg3d_aer_p.grid_label: PC@HIST_IMx@HIST_JM-DC, + tavg3d_aer_p.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, tavg3d_aer_p.mode: 'time-averaged', tavg3d_aer_p.monthly: 1, # tavg3d_aer_p.frequency: 240000, @@ -1047,7 +1047,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_tracer.archive: '%c/Y%y4' , geosgcm_tracer.format: 'CFIO' , geosgcm_tracer.deflate: 1 , - geosgcm_tracer.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_tracer.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_tracer.regrid_method: 'BILINEAR', geosgcm_tracer.mode: 'time-averaged' , geosgcm_tracer.monthly: 1 , @@ -1077,7 +1077,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_lidar.archive: '%c/Y%y4' , geosgcm_lidar.format: 'CFIO' , geosgcm_lidar.deflate: 1 , - geosgcm_lidar.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_lidar.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_lidar.regrid_method: 'BILINEAR', geosgcm_lidar.mode: 'time-averaged' , geosgcm_lidar.frequency: 030000 , @@ -1120,7 +1120,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_parasol.archive: '%c/Y%y4' , geosgcm_parasol.format: 'CFIO' , geosgcm_parasol.deflate: 1 , - geosgcm_parasol.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_parasol.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_parasol.regrid_method: 'BILINEAR', geosgcm_parasol.mode: 'time-averaged' , geosgcm_parasol.frequency: 030000 , @@ -1136,7 +1136,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_radar.archive: '%c/Y%y4' , geosgcm_radar.format: 'CFIO' , geosgcm_radar.deflate: 1 , - geosgcm_radar.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_radar.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_radar.regrid_method: 'BILINEAR', geosgcm_radar.mode: 'time-averaged' , geosgcm_radar.frequency: 030000 , @@ -1179,7 +1179,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_isccp.archive: '%c/Y%y4' , geosgcm_isccp.format: 'CFIO' , geosgcm_isccp.deflate: 1 , - geosgcm_isccp.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_isccp.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_isccp.regrid_method: 'BILINEAR', geosgcm_isccp.mode: 'time-averaged' , geosgcm_isccp.frequency: 030000 , @@ -1249,7 +1249,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_modis.archive: '%c/Y%y4' , geosgcm_modis.format: 'CFIO' , geosgcm_modis.deflate: 1 , - geosgcm_modis.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_modis.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_modis.regrid_method: 'BILINEAR', geosgcm_modis.mode: 'time-averaged' , geosgcm_modis.frequency: 030000 , @@ -1331,7 +1331,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_misr.archive: '%c/Y%y4' , geosgcm_misr.format: 'CFIO' , geosgcm_misr.deflate: 1 , - geosgcm_misr.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_misr.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_misr.regrid_method: 'BILINEAR', geosgcm_misr.mode: 'time-averaged' , geosgcm_misr.frequency: 030000 , @@ -1365,7 +1365,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_rad.archive: '%c/Y%y4', geosgcm_rad.format: 'CFIO', geosgcm_rad.deflate: 1 , - geosgcm_rad.grid_label: PC@HIST_IMx@HIST_JM-DC, + geosgcm_rad.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC, geosgcm_rad.regrid_method: 'BILINEAR', geosgcm_rad.mode: 'time-averaged', geosgcm_rad.monthly: 1, @@ -1418,7 +1418,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_int.archive: '%c/Y%y4', geosgcm_int.format: 'CFIO' , geosgcm_int.deflate: 1 , - geosgcm_int.grid_label: PC@HIST_IMx@HIST_JM-DC , + geosgcm_int.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , geosgcm_int.regrid_method: 'BILINEAR', geosgcm_int.mode: 'time-averaged' , geosgcm_int.monthly: 1 , @@ -1444,61 +1444,61 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_seaice.archive: '%c/Y%y4', geosgcm_seaice.format: 'CFIO', geosgcm_seaice.deflate: 1 , -# geosgcm_seaice.grid_label: PC@HIST_IMx@HIST_JM-DC , +# geosgcm_seaice.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , # geosgcm_seaice.regrid_method: 'BILINEAR', geosgcm_seaice.mode: 'time-averaged' , geosgcm_seaice.monthly: 1 , # geosgcm_seaice.frequency: 240000, geosgcm_seaice.fields: 'UI' , 'SEAICE', 'VI' , 'SEAICE', ->>>HIST_CICE4<<< 'VEL' , 'SEAICE', ->>>HIST_CICE4<<< 'STRENGTH' , 'SEAICE', ->>>HIST_CICE4<<< 'SHEAR' , 'SEAICE', ->>>HIST_CICE4<<< 'DIVU' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'VEL' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'STRENGTH' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'SHEAR' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'DIVU' , 'SEAICE', 'HICE' , 'SEAICE', ->>>HIST_CICE4<<< 'HICE0' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'HICE0' , 'SEAICE', 'HSNO' , 'SEAICE', ->>>HIST_CICE4<<< 'HSNO0' , 'SEAICE', ->>>HIST_CICE4<<< 'DRAFT' , 'SEAICE', ->>>HIST_CICE4<<< 'DRAFT0' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'HSNO0' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'DRAFT' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'DRAFT0' , 'SEAICE', 'AICE' , 'SEAICE', ->>>HIST_CICE4<<< 'DVIDTD' , 'SEAICE', ->>>HIST_CICE4<<< 'DAIDTD' , 'SEAICE', ->>>HIST_CICE4<<< 'DVIRDGDT' , 'SEAICE', ->>>HIST_CICE4<<< 'STRCORX' , 'SEAICE', ->>>HIST_CICE4<<< 'STRCORY' , 'SEAICE', ->>>HIST_CICE4<<< 'STRTLTX' , 'SEAICE', ->>>HIST_CICE4<<< 'STRTLTY' , 'SEAICE', ->>>HIST_CICE4<<< 'STRINTX' , 'SEAICE', ->>>HIST_CICE4<<< 'STRINTY' , 'SEAICE', ->>>HIST_CICE4<<< 'TAUXOCNB' , 'SEAICE', ->>>HIST_CICE4<<< 'TAUYOCNB' , 'SEAICE', ->>>HIST_CICE4<<< 'TAUXI' , 'SEAICE', ->>>HIST_CICE4<<< 'TAUYI' , 'SEAICE', ->>>HIST_CICE4<<< 'TAUXIB' , 'SEAICE', ->>>HIST_CICE4<<< 'TAUYIB' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'DVIDTD' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'DAIDTD' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'DVIRDGDT' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'STRCORX' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'STRCORY' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'STRTLTX' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'STRTLTY' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'STRINTX' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'STRINTY' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'TAUXOCNB' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'TAUYOCNB' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'TAUXI' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'TAUYI' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'TAUXIB' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'TAUYIB' , 'SEAICE', 'TAUXBOT' , 'SEAICE', 'TAUYBOT' , 'SEAICE', ->>>HIST_CICE4<<< 'UOCN' , 'SEAICE', ->>>HIST_CICE4<<< 'VOCN' , 'SEAICE', ->>>HIST_CICE4<<< 'SSH' , 'SEAICE', ->>>HIST_CICE4<<< 'SLV' , 'SEAICE', ->>>HIST_CICE4<<< 'AREA' , 'SEAICE', ->>>HIST_CICE4<<< 'FROCEAN' , 'SEAICE', ->>>HIST_CICE4<<< 'TMASK' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'UOCN' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'VOCN' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'SSH' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'SLV' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'AREA' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'FROCEAN' , 'SEAICE', +{{ {{ HIST_CICE4 }} }} 'TMASK' , 'SEAICE', :: geosgcm_icethm.template: '%y4%m2%d2_%h2%n2z.nc4', geosgcm_icethm.archive: '%c/Y%y4', geosgcm_icethm.format: 'CFIO', geosgcm_icethm.deflate: 1 , -# geosgcm_icethm.grid_label: PC@HIST_IMx@HIST_JM-DC , +# geosgcm_icethm.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , # geosgcm_icethm.regrid_method: 'BILINEAR', geosgcm_icethm.mode: 'time-averaged' , geosgcm_icethm.monthly: 1 , # geosgcm_icethm.frequency: 240000, geosgcm_icethm.regrid_exch:'tile.bin', - geosgcm_icethm.regrid_name:'@OGCM_GRIDNAME', + geosgcm_icethm.regrid_name:'{{ OGCM_GRIDNAME }}', geosgcm_icethm.fields: 'DVIDTT' , 'SEAICETHERMO', 'dvidtt', 'DAIDTT' , 'SEAICETHERMO', 'daidtt', 'FBOT' , 'SEAICETHERMO', 'fbot', @@ -1556,13 +1556,13 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_aoflux.archive: '%c/Y%y4', geosgcm_aoflux.format: 'CFIO', geosgcm_aoflux.deflate: 1 , -# geosgcm_aoflux.grid_label: PC@HIST_IMx@HIST_JM-DC , +# geosgcm_aoflux.grid_label: PC{{ HIST_IM }}x{{ HIST_JM }}-DC , # geosgcm_aoflux.regrid_method: 'BILINEAR', geosgcm_aoflux.mode: 'time-averaged' , geosgcm_aoflux.monthly: 1 , geosgcm_aoflux.frequency: 240000, # geosgcm_aoflux.regrid_exch:'tile.bin', - geosgcm_aoflux.regrid_name:'@OGCM_GRIDNAME', + geosgcm_aoflux.regrid_name:'{{ OGCM_GRIDNAME }}', geosgcm_aoflux.fields: 'TS_FOUND' , 'OPENWATER', 'SS_FOUND' , 'OPENWATER', 'AO_DRNIR' , 'OPENWATER', @@ -1624,7 +1624,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_iceflxn.mode: 'time-averaged', # geosgcm_iceflxn.frequency: 240000, geosgcm_iceflxn.regrid_exch:'tile.bin', - geosgcm_iceflxn.regrid_name:'@OGCM_GRIDNAME', + geosgcm_iceflxn.regrid_name:'{{ OGCM_GRIDNAME }}', geosgcm_iceflxn.fields: 'FCONDBOTN' , 'SEAICETHERMO', 'fcondbotn', 'SHICEN' , 'SEAICETHERMO', 'FSWSFCN' , 'SEAICETHERMO', @@ -1645,7 +1645,7 @@ PC@HIST_IMx@HIST_JM-DC.LM: @AGCM_LM geosgcm_iceflx.mode: 'time-averaged', # geosgcm_iceflx.frequency: 240000, geosgcm_iceflx.regrid_exch:'tile.bin', - geosgcm_iceflx.regrid_name:'@OGCM_GRIDNAME', + geosgcm_iceflx.regrid_name:'{{ OGCM_GRIDNAME }}', geosgcm_iceflx.fields: 'LWDNSRF' , 'SEAICETHERMO', 'SWDNSRF' , 'SEAICETHERMO', 'HLWUPICE' , 'SEAICETHERMO', diff --git a/HISTORY.AOGCM_MITgcm.rc.tmpl b/HISTORY.AOGCM_MITgcm.rc.tmpl index 61f2873f..076b217f 100755 --- a/HISTORY.AOGCM_MITgcm.rc.tmpl +++ b/HISTORY.AOGCM_MITgcm.rc.tmpl @@ -1,7 +1,7 @@ VERSION: 1 -EXPID: @EXPID -EXPDSC: @EXPDSC -EXPSRC: @EXPSRC +EXPID: {{ EXPID }} +EXPDSC: {{ EXPDSC }} +EXPSRC: {{ EXPSRC }} CONTACT: 'http://gmao.gsfc.nasa.gov' diff --git a/gcm_archive.j b/gcm_archive.j index 722f5a1c..a6d58a36 100644 --- a/gcm_archive.j +++ b/gcm_archive.j @@ -19,7 +19,7 @@ umask 022 limit stacksize unlimited -@SETENVS +{{ SETENVS }} {{ MPT_SHEPHERD }} diff --git a/gcm_forecast.tmpl b/gcm_forecast.tmpl index 2a26a7ba..9520df3f 100755 --- a/gcm_forecast.tmpl +++ b/gcm_forecast.tmpl @@ -359,10 +359,10 @@ setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} setenv EMISSIONS {{ EMISSIONS }} chmod +x linkbcs ->>>GCMRUN_CATCHCN<<>>GCMRUN_CATCHCN<<>>GCMRUN_CATCHCN<<< grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc ->>>GCMRUN_CATCHCN<< Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc +{{ GCMRUN_CATCHCN }}endif ####################################################################### # Get Executable and RESTARTS @@ -718,7 +718,7 @@ endif # Environment variables for MPI, etc # ---------------------------------- -@SETENVS +{{ SETENVS }} {{ MPT_SHEPHERD }} diff --git a/gcm_moveplot.j b/gcm_moveplot.j index cc293ee3..2624022d 100755 --- a/gcm_moveplot.j +++ b/gcm_moveplot.j @@ -19,7 +19,7 @@ umask 022 limit stacksize unlimited -@SETENVS +{{ SETENVS }} {{ MPT_SHEPHERD }} diff --git a/gcm_plot.tmpl b/gcm_plot.tmpl index e9f26a7c..17f6c479 100755 --- a/gcm_plot.tmpl +++ b/gcm_plot.tmpl @@ -19,7 +19,7 @@ umask 022 limit stacksize unlimited -@SETENVS +{{ SETENVS }} {{ MPT_SHEPHERD }} diff --git a/gcm_post.j b/gcm_post.j index 8a589028..97a4a10f 100755 --- a/gcm_post.j +++ b/gcm_post.j @@ -20,7 +20,7 @@ umask 022 limit stacksize unlimited -@SETENVS +{{ SETENVS }} {{ MPT_SHEPHERD }} diff --git a/gcm_regress.j b/gcm_regress.j index 99f70287..622f4cac 100755 --- a/gcm_regress.j +++ b/gcm_regress.j @@ -18,7 +18,7 @@ umask 022 limit stacksize unlimited -@SETENVS +{{ SETENVS }} {{ MPT_SHEPHERD }} diff --git a/gcm_run.j b/gcm_run.j index 7e56e855..aa32e48b 100755 --- a/gcm_run.j +++ b/gcm_run.j @@ -176,24 +176,24 @@ awk '{$1=$1};1' < CAP.rc.orig > CAP.rc set year = `echo $RSTDATE | cut -d_ -f1 | cut -b1-4` set month = `echo $RSTDATE | cut -d_ -f1 | cut -b5-6` ->>>EMIP_OLDLAND<<<# Copy MERRA-2 Restarts ->>>EMIP_OLDLAND<<<# --------------------- ->>>EMIP_NEWLAND<<<# Copy Jason-3_4 REPLAY MERRA-2 NewLand Restarts ->>>EMIP_NEWLAND<<<# ---------------------------------------------- +{{ EMIP_OLDLAND }}# Copy MERRA-2 Restarts +{{ EMIP_OLDLAND }}# --------------------- +{{ EMIP_NEWLAND }}# Copy Jason-3_4 REPLAY MERRA-2 NewLand Restarts +{{ EMIP_NEWLAND }}# ---------------------------------------------- cp /discover/nobackup/projects/gmao/g6dev/ltakacs/{{ EMIP_MERRA2 }}/restarts/AMIP/M${month}/restarts.${year}${month}.tar . tar xf restarts.${year}${month}.tar /bin/rm restarts.${year}${month}.tar ->>>EMIP_OLDLAND<<>>EMIP_OLDLAND<<<# Regrid MERRA-2 Restarts ->>>EMIP_OLDLAND<<<# ----------------------- ->>>EMIP_NEWLAND<<<# Regrid Jason-3_4 REPLAY MERRA-2 NewLand Restarts ->>>EMIP_NEWLAND<<<# ------------------------------------------------ +{{ EMIP_OLDLAND }}# Regrid MERRA-2 Restarts +{{ EMIP_OLDLAND }}# ----------------------- +{{ EMIP_NEWLAND }}# Regrid Jason-3_4 REPLAY MERRA-2 NewLand Restarts +{{ EMIP_NEWLAND }}# ------------------------------------------------ set RSTID = `/bin/ls *catch* | cut -d. -f1` set day = `/bin/ls *catch* | cut -d. -f3 | awk 'match($0,/[0-9]{8}/) {print substr($0,RSTART+6,2)}'` $GEOSBIN/remap_restarts.py command_line -np -ymdh ${year}${month}${day}21 -grout C${AGCM_IM} -levsout ${AGCM_LM} -out_dir . -rst_dir . -expid $RSTID -bcvin {{ EMIP_BCS_IN }} -oceanin 1440x720 -nobkg -lbl -nolcv -bcvout {{ LSMBCS }} -rs 3 -oceanout {{ OCEANOUT }} -in_bc_base @BC_BASE -out_bc_base @BC_BASE ->>>EMIP_OLDLAND<<>>EMIP_OLDLAND<<>>EMIP_OLDLAND<<<$GEOSBIN/gogo.x -s $RSTID.Chem_Registry.rc.${year}${month}${day}_21z -t $EXPDIR/RC/Chem_Registry.rc -i gocart_internal_rst.merra2 -o gocart_internal_rst -r C${AGCM_IM} -l ${AGCM_LM} +{{ EMIP_OLDLAND }}/bin/mv gocart_internal_rst gocart_internal_rst.merra2 +{{ EMIP_OLDLAND }}$GEOSBIN/gogo.x -s $RSTID.Chem_Registry.rc.${year}${month}${day}_21z -t $EXPDIR/RC/Chem_Registry.rc -i gocart_internal_rst.merra2 -o gocart_internal_rst -r C${AGCM_IM} -l ${AGCM_LM} # Create CAP.rc and cap_restart @@ -327,10 +327,10 @@ setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} setenv EMISSIONS {{ EMISSIONS }} chmod +x linkbcs ->>>GCMRUN_CATCHCN<<>>GCMRUN_CATCHCN<<>>GCMRUN_CATCHCN<<< grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc ->>>GCMRUN_CATCHCN<< Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc +{{ GCMRUN_CATCHCN }}endif ####################################################################### # Setup executable ####################################################################### @@ -931,7 +931,7 @@ endif # Environment variables for MPI, etc # ---------------------------------- -@SETENVS +{{ SETENVS }} {{ MPT_SHEPHERD }} diff --git a/gcm_setup b/gcm_setup index 08c2dcdb..62ea226a 100755 --- a/gcm_setup +++ b/gcm_setup @@ -176,7 +176,7 @@ endif ####################################################################### # Get MPI stack from CMake -set MPI_STACK = @MPI_STACK@ +set MPI_STACK = intelmpi ####################################################################### # Enter Experiment Specific Run Parameters @@ -418,7 +418,7 @@ ASKPROC: if ( $SITE == 'NCCS' ) then - set BUILT_ON_SLES15 = @BUILT_ON_SLES15@ + set BUILT_ON_SLES15 = if ("$BUILT_ON_SLES15" == "TRUE") then echo "Enter the ${C1}Processor Type${CN} you wish to run on:" @@ -622,7 +622,7 @@ if( $OGCM == TRUE ) then if ( "$OCNMODEL" == "MOM5" ) then set OCEAN_NAME="MOM" set OGRIDTYP = "M5TP" - set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=$GEOSDIR/lib/libmom@CMAKE_SHARED_LIBRARY_SUFFIX@' + set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=$GEOSDIR/lib/libmom.so' set MOM5="" set MOM6 = "#DELETE" set DEFAULT_HISTORY_TEMPLATE="HISTORY.AOGCM-MOM5.rc.tmpl" @@ -633,7 +633,7 @@ if( $OGCM == TRUE ) then else if ( "$OCNMODEL" == "MOM6" ) then set OCEAN_NAME="MOM6" set OGRIDTYP = "M6TP" - set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=\$GEOSDIR/lib/libmom6@CMAKE_SHARED_LIBRARY_SUFFIX@' + set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=\$GEOSDIR/lib/libmom6.so' set MOM6="" set MOM5 = "#DELETE" set DEFAULT_HISTORY_TEMPLATE="HISTORY.AOGCM.rc.tmpl" @@ -769,13 +769,13 @@ if( $OGCM == TRUE ) then # suffix is different on Linux and macOS. This is set by configure_file() if ( $SEAICEMODEL == "CICE4" ) then set SEAICE_NAME="CICE4" - set SEAICE_PRELOAD = '$GEOSDIR/lib/libCICE4@CMAKE_SHARED_LIBRARY_SUFFIX@' + set SEAICE_PRELOAD = '$GEOSDIR/lib/libCICE4.so' set CICE4="" set CICE6 = "#DELETE" set HIST_CICE4 = "" else if ( $SEAICEMODEL == "CICE6" ) then set SEAICE_NAME="CICE6" - set SEAICE_PRELOAD = '$GEOSDIR/lib/libcice6@CMAKE_SHARED_LIBRARY_SUFFIX@' + set SEAICE_PRELOAD = '$GEOSDIR/lib/libcice6.so' set CICE6="" set CICE4 = "#DELETE" set HIST_CICE4 = "#DELETE" @@ -2256,210 +2256,209 @@ endif # if mpi ####################################################################### cat > $HOMDIR/sedfile << EOF -/@SETENVS/ { +/{{ SETENVS }}/ { t success : success r $HOMDIR/SETENV.commands d } -s?@GCMVER?$GCMVER?g -s?@EXPSRC?$GEOSTAG?g -s?@EXPID?$EXPID?g -s?@RUN_N?$RUN_N?g -s?@RUN_FN?$RUN_FN?g -s?@RUN_FT?$RUN_FT?g -s?@RUN_T?$RUN_T?g -s?@RUN_P?$RUN_P?g -s?@RUN_FP?$RUN_FP?g -s?@RUN_Q?$RUN_Q?g -s?@POST_N?$POST_N?g -s?@POST_T?$POST_T?g -s?@POST_P?$POST_P?g -s?@POST_Q?$POST_Q?g -s?@MOVE_N?$MOVE_N?g -s?@PLOT_N?$PLOT_N?g -s?@PLOT_T?$PLOT_T?g -s?@PLOT_P?$PLOT_P?g -s?@PLOT_Q?$PLOT_Q?g -s?@MOVE_Q?$MOVE_Q?g -s?@MOVE_P?$MOVE_P?g -s?@ARCHIVE_N?$ARCHIVE_N?g -s?@ARCHIVE_T?$ARCHIVE_T?g -s?@ARCHIVE_P?$ARCHIVE_P?g -s?@ARCHIVE_Q?$ARCHIVE_Q?g -s?@REGRESS_N?$REGRESS_N?g -s?@BCSDIR?$BCSDIR?g -s?@SSTDIR?$SSTDIR?g -s?@SSTNAME?$SSTNAME?g -s?@OCEANOUT?$OCEANOUT?g -s?@LSMBCS?$LSM_BCS?g -s?@EMIP_BCS_IN?$EMIP_BCS_IN?g -s?@EMIP_MERRA2?$EMIP_MERRA2?g -s?@BCSTAG?$OCEAN_TAG?g -s?@SSTFILE?$SSTFILE?g -s?@ICEFILE?$ICEFILE?g -s?@KPARFILE?$KPARFILE?g -s?@CHMDIR?$CHMDIR?g -s?@COUPLEDIR?$COUPLEDIR?g -s?@GWDRSDIR?$GWDRSDIR?g -s?@EXPDIR?$EXPDIR?g -s?@EXPDSC?$EXPDSC?g -s?@HOMDIR?$HOMDIR?g -s?@BATCH_GROUP?${BATCH_GROUP}${GROUP}?g -s?@BATCH_TIME?$BATCH_TIME?g -s?@BATCH_CMD?$BATCH_CMD?g -s?@BATCH_JOBNAME?$BATCH_JOBNAME?g -s?@BATCH_OUTPUTNAME?$BATCH_OUTPUTNAME?g -s?@BATCH_JOINOUTERR?$BATCH_JOINOUTERR?g -s?@SITE?$SITE?g -s?@GEOSDIR?$GEOSDIR?g -s?@GEOSSRC?$GEOSSRC?g -s?@GEOSBIN?$GEOSBIN?g -s?@GEOSETC?$GEOSETC?g -s?@GEOSUTIL?$GEOSUTIL?g -s?@SINGULARITY_BUILD?$SINGULARITY_BUILD?g -s?@NATIVE_BUILD?$NATIVE_BUILD?g -s?@MPT_SHEPHERD?$MPT_SHEPHERD?g -s?@SINGULARITY_SANDBOX?$SINGULARITY_SANDBOX?g -s?@REAL_BIND_PATH?$REAL_BIND_PATH?g -s?@BASE_BIND_PATH?$BASE_BIND_PATH?g -s?@BC_BASE?$BC_BASE?g -s?@BOUNDARY_DIR?$BOUNDARY_DIR?g - -s?@CHECKPOINT_TYPE?default?g - -s?@OGCM_NX?$OGCM_NX?g -s?@OGCM_NY?$OGCM_NY?g -s?@OGCM_NPROCS?$OGCM_NPROCS?g - -s?@OBSERVER_FRQ?0?g +s?{{ GCMVER }}?$GCMVER?g +s?{{ EXPSRC }}?$GEOSTAG?g +s?{{ EXPID }}?$EXPID?g +s?{{ RUN_N }}?$RUN_N?g +s?{{ RUN_FN }}?$RUN_FN?g +s?{{ RUN_FT }}?$RUN_FT?g +s?{{ RUN_T }}?$RUN_T?g +s?{{ RUN_P }}?$RUN_P?g +s?{{ RUN_FP }}?$RUN_FP?g +s?{{ RUN_Q }}?$RUN_Q?g +s?{{ POST_N }}?$POST_N?g +s?{{ POST_T }}?$POST_T?g +s?{{ POST_P }}?$POST_P?g +s?{{ POST_Q }}?$POST_Q?g +s?{{ MOVE_N }}?$MOVE_N?g +s?{{ PLOT_N }}?$PLOT_N?g +s?{{ PLOT_T }}?$PLOT_T?g +s?{{ PLOT_P }}?$PLOT_P?g +s?{{ PLOT_Q }}?$PLOT_Q?g +s?{{ MOVE_Q }}?$MOVE_Q?g +s?{{ MOVE_P }}?$MOVE_P?g +s?{{ ARCHIVE_N }}?$ARCHIVE_N?g +s?{{ ARCHIVE_T }}?$ARCHIVE_T?g +s?{{ ARCHIVE_P }}?$ARCHIVE_P?g +s?{{ ARCHIVE_Q }}?$ARCHIVE_Q?g +s?{{ REGRESS_N }}?$REGRESS_N?g +s?{{ BCSDIR }}?$BCSDIR?g +s?{{ SSTDIR }}?$SSTDIR?g +s?{{ SSTNAME }}?$SSTNAME?g +s?{{ OCEANOUT }}?$OCEANOUT?g +s?{{ LSMBCS }}?$LSM_BCS?g +s?{{ EMIP_BCS_IN }}?$EMIP_BCS_IN?g +s?{{ EMIP_MERRA2 }}?$EMIP_MERRA2?g +s?{{ BCSTAG }}?$OCEAN_TAG?g +s?{{ SSTFILE }}?$SSTFILE?g +s?{{ ICEFILE }}?$ICEFILE?g +s?{{ KPARFILE }}?$KPARFILE?g +s?{{ CHMDIR }}?$CHMDIR?g +s?{{ COUPLEDIR }}?$COUPLEDIR?g +s?{{ GWDRSDIR }}?$GWDRSDIR?g +s?{{ EXPDIR }}?$EXPDIR?g +s?{{ EXPDSC }}?$EXPDSC?g +s?{{ HOMDIR }}?$HOMDIR?g +s?{{ BATCH_GROUP }}?${BATCH_GROUP}${GROUP}?g +s?{{ BATCH_TIME }}?$BATCH_TIME?g +s?{{ BATCH_CMD }}?$BATCH_CMD?g +s?{{ BATCH_JOBNAME }}?$BATCH_JOBNAME?g +s?{{ BATCH_OUTPUTNAME }}?$BATCH_OUTPUTNAME?g +s?{{ BATCH_JOINOUTERR }}?$BATCH_JOINOUTERR?g +s?{{ SITE }}?$SITE?g +s?{{ GEOSDIR }}?$GEOSDIR?g +s?{{ GEOSSRC }}?$GEOSSRC?g +s?{{ GEOSBIN }}?$GEOSBIN?g +s?{{ GEOSETC }}?$GEOSETC?g +s?{{ GEOSUTIL }}?$GEOSUTIL?g +s?{{ SINGULARITY_BUILD }}?$SINGULARITY_BUILD?g +s?{{ NATIVE_BUILD }}?$NATIVE_BUILD?g +s?{{ MPT_SHEPHERD }}?$MPT_SHEPHERD?g +s?{{ SINGULARITY_SANDBOX }}?$SINGULARITY_SANDBOX?g +s?{{ REAL_BIND_PATH }}?$REAL_BIND_PATH?g +s?{{ BASE_BIND_PATH }}?$BASE_BIND_PATH?g +s?{{ BC_BASE }}?$BC_BASE?g +s?{{ BOUNDARY_DIR }}?$BOUNDARY_DIR?g + +s?{{ CHECKPOINT_TYPE }}?default?g + +s?{{ OGCM_NX }}?$OGCM_NX?g +s?{{ OGCM_NY }}?$OGCM_NY?g +s?{{ OGCM_NPROCS }}?$OGCM_NPROCS?g + +s?{{ OBSERVER_FRQ }}?0?g s?^[ \t]*RECORD_?#RECORD_?g -s?@DASTUNING?#?g - -s?>>>FORCEDAS<<>>FORCEGCM<<>>HIST_CICE4<<>>GOCART<<>>FVCUBED<<>>OSTIA<<>>HIST_CATCHCN<<>>GCMRUN_CATCHCN<<>>EMIP_OLDLAND<<>>EMIP_NEWLAND<<>>4DIAUDAS<<>>REGULAR_REPLAY<<>>REGULAR_REPLAY_GMAO<<>>REGULAR_REPLAY_NCEP<<>>REGULAR_REPLAY_ECMWF<<> $HOMDIR/sedfile << EOF -s^@HYDROSTATIC^$HYDROSTATIC^g -s?@FV_SCHMIDT?$SCHMIDT?g -s?@FV_STRETCH_FAC?$STRETCH_FAC?g -s?@FV_TARGET_LON?$TARGET_LON?g -s?@FV_TARGET_LAT?$TARGET_LAT?g -s?@FV_MAKENH?$FV_MAKENH?g -s?@FV_HYDRO?$FV_HYDRO?g -s?@GFDL_PROG_CCN?$GFDL_PROG_CCN?g -s?@GFDL_USE_CCN?$GFDL_USE_CCN?g -s?@GFDL_HYDRO?$GFDL_HYDRO?g +s^{{ HYDROSTATIC }}^$HYDROSTATIC^g +s?{{ FV_SCHMIDT }}?$SCHMIDT?g +s?{{ FV_STRETCH_FAC }}?$STRETCH_FAC?g +s?{{ FV_TARGET_LON }}?$TARGET_LON?g +s?{{ FV_TARGET_LAT }}?$TARGET_LAT?g +s?{{ FV_MAKENH }}?$FV_MAKENH?g +s?{{ FV_HYDRO }}?$FV_HYDRO?g +s?{{ GFDL_PROG_CCN }}?$GFDL_PROG_CCN?g +s?{{ GFDL_USE_CCN }}?$GFDL_USE_CCN?g +s?{{ GFDL_HYDRO }}?$GFDL_HYDRO?g EOF @@ -2823,8 +2822,8 @@ if( -e $HOMDIR/sedfile ) /bin/rm $HOMDIR/sedfile # NOTE: This variable is set at CMake time depending on # how the build was configured. -set INSTALL_TARFILE = @CFG_INSTALL_SOURCE_TARFILE@ -set TARFILE_NAME = "@CMAKE_PROJECT_NAME@.tar.gz" +set INSTALL_TARFILE = FALSE +set TARFILE_NAME = "GEOSgcm.tar.gz" if ( $INSTALL_TARFILE == "TRUE" ) then @@ -3214,8 +3213,8 @@ echo "" # NOTE: This variable is set at CMake time depending on # how the build was configured. -set INSTALL_TARFILE = @CFG_INSTALL_SOURCE_TARFILE@ -set TARFILE_NAME = "@CMAKE_PROJECT_NAME@.tar.gz" +set INSTALL_TARFILE = FALSE +set TARFILE_NAME = "GEOSgcm.tar.gz" if ( $INSTALL_TARFILE == "TRUE" ) then diff --git a/gcmpy/jinjafy.py b/gcmpy/jinjafy.py index 263541ed..72be1b53 100755 --- a/gcmpy/jinjafy.py +++ b/gcmpy/jinjafy.py @@ -28,7 +28,8 @@ def replace_strings_in_file(file_path, replacements): def main(file_list, replacements): for file_path in file_list: - file_path = f"{os.path.dirname(os.getcwd())}/{file_path}" + #file_path = f"{os.path.dirname(os.getcwd())}/{file_path}" + file_path = f"/discover/nobackup/sshakoor/GEOSgcm/install/bin/{file_path}" if os.path.isfile(file_path): replace_strings_in_file(file_path, replacements) else: @@ -50,6 +51,10 @@ def main(file_list, replacements): 'CAP.rc.tmpl', 'AGCM.rc.tmpl', 'HISTORY.rc.tmpl', + 'HISTORY.AOGCM-MOM5.rc.tmpl', + 'HISTORY.AOGCM.rc.tmpl', + 'HISTORY.AOGCM_MITgcm.rc.tmpl', + 'HISTORY.AGCM.rc.tmpl', 'logging.yaml', 'fvcore_layout.rc', 'linkbcs.tmpl' @@ -57,6 +62,7 @@ def main(file_list, replacements): # Dictionary with keys to find and values to replace replacements = { + '@SETENVS': '{{ SETENVS }}', '@GCMVER': '{{ GCMVER }}', '@EXPSRC': '{{ EXPSRC }}', '@EXPID': '{{ EXPID }}', @@ -126,8 +132,8 @@ def main(file_list, replacements): '@OGCM_NPROCS': '{{ OGCM_NPROCS }}', '@OBSERVER_FRQ': '{{ OBSERVER_FRQ }}', '@DASTUNING': '{{ DASTUNING }}', - '>>>FORCEDAS<<<': '>>>FORCEDAS<<<', - '>>>FORCEGCM<<<': '>>>FORCEGCM<<<', + '>>>FORCEDAS<<<': '{{ FORCEDAS }}', + '>>>FORCEGCM<<<': '{{ FORCEGCM }}', '@COUPLED': '{{ COUPLED }}', '@CLDMICRO': '{{ CLDMICRO }}', '@MOM5': '{{ MOM5 }}', @@ -135,28 +141,28 @@ def main(file_list, replacements): '@OCNMODEL': '{{ OCNMODEL }}', '@CICE4': '{{ CICE4 }}', '@CICE6': '{{ CICE6 }}', - '>>>HIST_CICE4<<<': '{{ >>>HIST_CICE4<<< }}', + '>>>HIST_CICE4<<<': '{{ HIST_CICE4 }}', '@MIT': '{{ MIT }}', '@DATAOCEAN': '{{ DATAOCEAN }}', '>>>GOCART<<<': '>>>GOCART<<<', '@OPS_SPECIES': '{{ OPS_SPECIES }}', '@CMIP_SPECIES': '{{ CMIP_SPECIES }}', '@MERRA2OX_SPECIES': '{{ MERRA2OX_SPECIES }}', - '>>>FVCUBED<<<': '>>>FVCUBED<<<', + '>>>FVCUBED<<<': '{{ FVCUBED }}', '@HIST_GOCART': ' {{ HIST_GOCART }}', '>>>OSTIA<<<': '>>>OSTIA<<<', - '>>>HIST_CATCHCN<<<': '>>>HIST_CATCHCN<<<', - '>>>GCMRUN_CATCHCN<<<': '>>>GCMRUN_CATCHCN<<<', - '>>>EMIP_OLDLAND<<<': '>>>EMIP_OLDLAND<<<', - '>>>EMIP_NEWLAND<<<': '>>>EMIP_NEWLAND<<<', + '>>>HIST_CATCHCN<<<': '{{ HIST_CATCHCN }}', + '>>>GCMRUN_CATCHCN<<<': '{{ GCMRUN_CATCHCN }}', + '>>>EMIP_OLDLAND<<<': '{{ EMIP_OLDLAND }}', + '>>>EMIP_NEWLAND<<<': '{{ EMIP_NEWLAND }}', '@LSM_PARMS': '{{ LSM_PARMS }}', '@OCEAN_NAME': '{{ OCEAN_NAME }}', '@OCEAN_PRELOAD': '{{ OCEAN_PRELOAD }}', - '>>>4DIAUDAS<<<': '>>>4DIAUDAS<<<', - '>>>REGULAR_REPLAY<<<': '>>>REGULAR_REPLAY<<<', - '>>>REGULAR_REPLAY_GMAO<<<': '>>>REGULAR_REPLAY_GMAO<<<', - '>>>REGULAR_REPLAY_NCEP<<<': '>>>REGULAR_REPLAY_NCEP<<<', - '>>>REGULAR_REPLAY_ECMWF<<<': '>>>REGULAR_REPLAY_ECMWF<<<', + '{{ 4DIAUDAS }}': '{{ _4DIAUDAS }}', + '>>>REGULAR_REPLAY<<<': '{{ REGULAR_REPLAY }}', + '>>>REGULAR_REPLAY_GMAO<<<': '{{ REGULAR_REPLAY_GMAO }}', + '>>>REGULAR_REPLAY_NCEP<<<': '{{ REGULAR_REPLAY_NCEP }}', + '>>>REGULAR_REPLAY_ECMWF<<<': '{{ REGULAR_REPLAY_ECMWF }}', 'ana4replay.eta.%y4%m2%d2_%h2z.nc4': '{{ ana4replay.eta.%y4%m2%d2_%h2z.nc4 }}', '@REPLAY_ANA_EXPID': '{{ REPLAY_ANA_EXPID }}', '@REPLAY_ANA_LOCATION': '{{ REPLAY_ANA_LOCATION }}', diff --git a/gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc b/gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc index d97f50573188cdca56fab4774fce29ab835dbe8a..2c5db8592113a6fdd77fc6bf5a013d384aeef240 100644 GIT binary patch delta 3355 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 diff --git a/gcmpy/scripts/__pycache__/env.cpython-312.pyc b/gcmpy/scripts/__pycache__/env.cpython-312.pyc index 857deed04a32a112bf630b96a7ba5159043101db..f54cf81cd4a8cdd7c7197bd908b3c282d662ddc1 100644 GIT binary patch delta 552 zcmbQPc3hSBG%qg~0}vF3*QGC<$ScWsY@_-;X2#gb8(3r~|7T%UnZQ`&#mSJOn#z`< zYy(s{fices$QG6avQyNuH5eF*GQf&6Swt8W!K~Rp76*`}%*&Rd1k;!I0cxa>`i&HA zxacLgSvnxIiaFqX-N`Ymiu`(2Kzra~`jdNDl^G2tZ(!9|Gz5u)Tm+=~!LBg^yT+W8 zfr%kiG{txlTRx-dUM&gKw44ki}UOY8=d69gn# zLN9X~O|BKtK@zzH6ah-Tjgzz)Z`#1UE|;Bv;G<=j%;2V^!qWuL9Zw7c-cg#;VL{IJt{eU(pC83UU#U<_EjR z7;L&ZCj%2hs%VPI=h2YcR_O$g%~o zDj8Gk;PUoxc?XdEWG;4RM$^fD?8#u#lzU1!Lj`jrLph_SPuaaD6^kq@GW+a#NzVQoSc^uAR$htqWr`ZFkc3& z#L?Gf^DQo8X0Bu)ml24I>o<$@aWJu1UScJm^2 ztOmqbB_O}~vcOJ8YYh%RA%@cis(x(DXGB5lGwKrlEDYz^SpE3f&vCN@Ma~K7_%kw} SXJ7=8EIR(i%;$|5fg}K!SBfqG diff --git a/gcmpy/scripts/__pycache__/gocart.cpython-312.pyc b/gcmpy/scripts/__pycache__/gocart.cpython-312.pyc index 065a559f75a2ceaa227597b8a472d08fbfdc3861..bfe96c8b1d5c7795c4d86ed3d048c3ca652d5cf0 100644 GIT binary patch delta 134 zcmeAa?G)ub&CAQh00d2ub?L<$c^|M#G5ZGu7x4gvUNQoSDi#Ah1A|*Ej=r7&li4|B z1%!cuMPeXA97KptHsOfoF}=iXa6?6{!{rK(%;eb|8j4|;c#WX~if~#%v%}>okL(9_ R20oL?@vPFD|8sOP0sxA>Bjo@9 delta 134 zcmeAa?G)ub&CAQh00h!!S<;I(@;+dfVsZ5K3@G9OioIk65>+e)dIko!nEeBSC$n?N z3Wx&5io`&KIEWCQY{C)EV|Iz#@P>+7hszZn#mTcdG!#QG@ftw|WMC3E6f`?ruJXu! SU}xYno*d6Az4<>!7b5^y$|H6F diff --git a/gcmpy/scripts/__pycache__/land.cpython-312.pyc b/gcmpy/scripts/__pycache__/land.cpython-312.pyc index acd9e966277778b01a8cbcf26ab424e0d2068de7..ad7859f922b23a66917e2f8877231eeba6c35d49 100644 GIT binary patch delta 541 zcmaDW@l;QF8KG4#~|ISppbYihvH7ti+}^ z*_TaHPzdObB2gew%m^eDio_=uu^oY^o*clgDGL;Y0B`_+)PMn)$255+tK#JC>{62x zSj8v5V3%N2o6N`|s|50(CUX%FkSY=e5h5T0#S&i*ZAm|%XamCyZvK9&POBNxm$+4K zsHu0j^mt94#9;+?LXMyzhE6X|OQ2i}r?#R5NKP3<=zs{YQez-%B}0)UNI-n@1x^_W z)lU-4tnQ4TxP(~EKWTBWYJL`BVwEkDoXoYcRG%qg~0}$Ll#gcw$Bd-Z#JwpvcJPSw&1X4geRtOu)V?*JwqwqLTc$_Fa zur(l&N(N14zgrwW!ST8IDXBTP#DJ`%{L;LX#G=ahtN~Ozo7)A zu5d^|X-PC1CN2#WUo6JV$S68loJEIGY_bbWDWk+>8+OUfmstWB8E;KiXH#S00op#< zhfRt{1js061QH5GVw20+j)0XqP5#3o!O9HuF!SWu?AH8DKzT4oVFQajWmoW31qxIN zIVYARXXK{ll{ow9I{WyV=o!2ODK1h65}GVU+(7CUcTQqnN_=uger9rNkq}5$7(}4h z?8>3d=s&rTLyY+fkIdvw4l9V0C*S1=7Bs?8?Z{~fl&|L04iyKBowHozz<%}KQ@vYu?mrNjb~0RX@Sbld;{ diff --git a/gcmpy/scripts/__pycache__/ocean.cpython-312.pyc b/gcmpy/scripts/__pycache__/ocean.cpython-312.pyc index 83d662d19ed58579ab51062aaf63f96da3c938bd..6819641f8ec7b2ae8663e83e9373d8736f908afc 100644 GIT binary patch delta 737 zcmZXSUuaTs6vyw+Ki8}GnzB`-DQaqX?W*@KnHD|N+LDHtr9`#BHWh1=DL;!g88Hfa ziCA!6DuN1n33{jrdmQYwUUF=?q|xXldMftPOAq~yK}G$zeD3$0bI`jAu{Ah!uJZJi)h8Y z2(G?97S3}U{f_&?k5dm)?S4P32)qBdIsSK}M_G@o1I3&mL#>kewSkPbVmodVc3ZNk zR#Je^F88UkI4Hu<74q~-y;dEkG>W;4h%rPJaS1WO(A5_YskDU3P)rP{w1U!D)Z%fK zPPTIHA12~$WrOc@+6k=aYFg8Da8UJXNwv$T$FHVq)4wcjJ-1vg-^Kb2tHbF~h>Sur zR5T0dH^cnlW2j;=4*#i|hX*y3Of#@3 z-{tFAt-(lGBYC(U&Wgt{F^ovVYWO_~z>5RRBnVT=Te2UHM7|P#ONpK*y}!E%3o#j@ z7L(C8$4wd`yUzumVqSjQ&O$SW1|~!lp;=DWXDDuXUgoJDC)g1U#0|tl#2L1$(UT)g z&T}8cUH7VO(ccl3wy3-`tcvjs$=;FNZOOeRd4B74$+LxdPh0Y=Nxm&X>Ijau;8+*- z!it)Z|N5rh2t*$7&+JFw)8c$!n@Sx+F|kpmbE>~GuDC!vf*U-rYD4K Va?VZ8!LILyhMu^#IV6p<@=wS{wIKii delta 777 zcmaKqO=uHQ5Xax!O=4=BWFu{~Arae{&2DOw-LMdqQpJ>5A;y-3B7z@jHm%iY>$3qP zITQ~fYC#;uN=p?FLh&Ry7R000O9Pf_=)tQeOTDQF-vkZ4=!5;u{AcFPuqIU z^ROjO2dW2KRxC7C6`i*!H+Nl{gXUn_=Rb9tm#|)rx;@J#rY4Iy#v&Lyhd7J4iWo(h z9Ca~&NMmE@S@Q9i#wO6U=5@o+Sg{)N|Jng+z*UU}-wAXOeug^TjRvm9-b^N2r+Mg6 z6q${FnaX6=43@MsWH5uW!p zP*W%o)=f!;T(ZJu&&ujZ83oza>zy5a8lB(<+gT{WreqZDZRYf_-@_B3RmCI!}{;HF4+ z?S>UCu5SB39FRqfAhr!fxd>t1uqj(MYE{70gQCqU!+rg*_XTG0g|QgN4}0I0NwZWe T^s|@nMfbUwNaZbpY!v+l`!cjA diff --git a/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc b/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc index 32776d843a9266e04b39f6c58a40d0835faa9dd4..d0296781603b8189d2669ee2b66829f743129532 100644 GIT binary patch delta 1025 zcmZvaOH30%7{~Y9-4^IlD33O@rM%?PEny2N@(=`~L_rHiN|eONt1DCu z3@B~p05QQ3PZ~8b*^5U`Mng1_gxIW@ct9>*FkU=(aAryH5hj^m=KIfo=KCh!EcAZA zYTPs$4GbB3U9*GPG2>f!AN#n*CNVe!<$S~_rYNsqStoG=eLIg-VWh~S&{J3`TsV-iJr^a* z6=nu}Fzh5^^92?@=oTelLyL- zkGMF(h=z96G~^G40w~fGl1Il!`a&`~K{Bhnr^8b@~hhDsx-=vqxv(OO!kYAu5qf6Q- zo03t`!Df%pIEA8y;GfP<cX2vUS8=JEZa9ANPC zA|%?>ei%iEW}ACU6_!GM*B@!DD>G zRS5OUqHB`nqp;M7E6N(WQqeL^z)>Vp{8yJ&(w}N<)MBU53f5}XD$F37$RGUj2l!1{ vv0;TM8)ODAC_l?`0CsVSyINQv3erBkjQ#FfLCa39=q`TY&Vq;dwY&K@Nbmz; delta 1561 zcmaJ>OH3O_820S?i80u~ZVd)w9853|n-Cy^Kvah!k|;I}k3dMMalDIhY`k>5P;8;5 zsrtyF61Z~!iBi#9+f*vmUZ~mwmr9LVwN67twRNTR&{I{(Rg_DVN}XA&2qM&fwV!wX z@B3%I-G9b^PrN&A`p#r3QsKz8X(MlDO!q-9v%iTJL0bh+bEdac_Xvq&(wr)Bmr9?4 z70rNdB$kSYV*JzM{!lU;;&{hpJd){vZ^W&E4y=}S7edL`_;_44oQFb)Bag5S6KTEA z|B_=^nB!4I_Xk))e!WfGv7N{^4WK#w3m_`Jtrq}rNly$x09vFm<1+wGNyDaHO51|# zVF$9By~b9u2HoD?2|Z}oe50%rkKHsh6NQC9pR{Z4r9dD0r>s@mO)@>Gt=tM4(XOcq zh0DL{d4!W|s%5}|SRZ!{{lf!4&NOU(NV`u4w*^u^r~dv!00q?pLPjF!xH< z6FlI4Vc5gm)vRayfXg$g;uEj}dk9k)aJoa6sO&px@~Vv{hzAU)PL{Cc%3!r6QM` z4!~5!T{9a>aB<#qJpDSJAi0d;4b>xKan|ho$>_|n*0o3`vX;mswkEg1 zM^pQ*vkzQn_t@T?naNr`pDlcz`Xu#nY^Q1W%9pJ>wcj&8+U^@{-oU8}KQrF2v3ccKD1hs|z<1PhbXxrU4X@;w0F|uQ!p1^ZP6_1KN#aR`R*a#?Z zpqN*DE0)VK;Z_&^-B!@~riP+*oY}>9^11|@?7))Km+b3Z5A?3BTibPe`i>mRG@miv p#R}L>Ac!6|ch@VHNGW`W06Ai?48v1>@0`Fb#QAe@1GTmI{sj_lrxpMJ diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py index ab853446..c9a85472 100755 --- a/gcmpy/scripts/atmosphere.py +++ b/gcmpy/scripts/atmosphere.py @@ -21,8 +21,8 @@ def __init__(self): self.nf = 6 self.use_hydrostatic = answerdict["use_hydrostatic"].q_answer self.microphysics = answerdict["AM_microphysics"].q_answer - self.im_hist = self.im * 4 - self.jm_hist = self.jm * 2 + 1 + self.hist_im = self.im * 4 + self.hist_jm = self.im * 2 + 1 self.gridfile = f"Gnomonic_c{self.im}.dat" self.job_sgmt = None self.num_sgmt = None @@ -30,8 +30,9 @@ def __init__(self): self.post_NDS = None self.nx_convert = 2 self.ny_convert = 24 - self.conus = "#" - self.stretch_factor = None + self.conus = '#' + self.stretch_factor = '' + self.FV_stretch_fac = '' self.gridname = f"PE{self.im}x{self.jm}-CF" self.res_dateline = f"{self.im}x{self.jm}" self.BACM_1M = "#" @@ -78,6 +79,7 @@ def hres(self, ocean_nx, ocean_ny): self.post_NDS = 4 self.nx_convert = 1 self.ny_convert = 6 + self.res = 'CF0012x6C' case "c24": self.dt_solar = 3600 @@ -91,6 +93,7 @@ def hres(self, ocean_nx, ocean_ny): self.post_NDS = 4 self.nx_convert = 1 self.ny_convert = 6 + self.res = 'CF0024x6C' case "c48": self.dt_solar = 3600 @@ -104,6 +107,9 @@ def hres(self, ocean_nx, ocean_ny): self.job_sgmt = f"{15:08}" self.num_sgmt = 20 self.post_NDS = 4 + self.res = 'CF0048x6C' + self.hist_im = 180 + self.hist_jm = 91 case "c90": self.dt_solar = 3600 @@ -125,6 +131,7 @@ def hres(self, ocean_nx, ocean_ny): self.job_sgmt = f"{32:08}" self.num_sgmt = 4 self.post_NDS = 8 + self.res = 'CF0090x6C' case "c180": self.dt_solar = 3600 @@ -142,6 +149,7 @@ def hres(self, ocean_nx, ocean_ny): self.num_sgmt = 1 self.post_NDS = 8 self.num_readers = 2 + self.res = 'CF0180x6C' case "c360": self.dt_solar = 3600 @@ -155,6 +163,7 @@ def hres(self, ocean_nx, ocean_ny): self.num_sgmt = 1 self.post_NDS = 12 self.nx_convert = 4 + self.res = 'CF0360x6C' case "c720": self.dt_solar = 3600 @@ -169,6 +178,7 @@ def hres(self, ocean_nx, ocean_ny): self.post_NDS = 16 self.nx_convert = 8 self.use_SHMEM = True + self.res = 'CF0720x6C' case "c1440": self.dt_solar = 1800 @@ -183,6 +193,7 @@ def hres(self, ocean_nx, ocean_ny): self.post_NDS = 32 self.nx_convert = 8 self.use_SHMEM = True + self.res = 'CF1440x6C' case "c2880": self.dt_solar = 1800 @@ -198,6 +209,7 @@ def hres(self, ocean_nx, ocean_ny): self.nx_convert = 8 self.use_SHMEM = True self.convpar_option = 'NONE' + self.res = 'CF2880x6C' case "c5760": self.dt_solar = 900 @@ -213,6 +225,7 @@ def hres(self, ocean_nx, ocean_ny): self.nx_convert = 8 self.use_SHMEM = True self.convpar_option = 'NONE' + self.res = 'CF5760x6C' case "c270": self.dt_solar = 3600 @@ -229,6 +242,7 @@ def hres(self, ocean_nx, ocean_ny): self.use_SHMEM = True self.conus = "" self.stretch_factor = 2.5 + self.res = 'CF0270x6C-SG001' case "c540": self.dt_solar = 3600 @@ -245,6 +259,7 @@ def hres(self, ocean_nx, ocean_ny): self.use_SHMEM = True self.conus = "" self.stretch_factor = 2.5 + self.res = 'CF0540x6C-SG001' case "c1080": self.dt_solar = 900 @@ -260,7 +275,8 @@ def hres(self, ocean_nx, ocean_ny): self.nx_convert = 8 self.use_SHMEM = True self.conus = "" - self.stretch_factor = 2. + self.stretch_factor = 2.5 + self.res = 'CF1080x6C-SG001' case "c1536": self.dt_solar = 900 @@ -277,6 +293,7 @@ def hres(self, ocean_nx, ocean_ny): self.use_SHMEM = True self.conus = "" self.stretch_factor = 3.0 + self.res = 'CF1536x6C-SG002' case "c2160": self.dt_solar = 900 @@ -293,6 +310,7 @@ def hres(self, ocean_nx, ocean_ny): self.use_SHMEM = True self.conus = "" self.stretch_factor = 2.5 + self.res = 'CF2160x6C-SG001' if answerdict["OM_name"].q_answer == "MIT": self.dt_ocean = self.dt @@ -328,14 +346,15 @@ def set_fvcore_layout(self): def set_conus(self): if self.conus == "#": self.schmidt = "do_schmidt = .false." - self.stretch_factor = "stretch_fac = 1.0" + self.FV_stretch_fac = "stretch_fac = 1.0" self.target_lon = "target_lon = 0.0" - self.target_lat = "target_lat = 0.0" + self.target_lat = "target_lat = -90.0" else: self.schmidt = "do_schmidt = .true." - self.stretch_factor = "stretch_fac = $STRETCH_FACTOR" + self.FV_stretch_fac = "stretch_fac = $STRETCH_FACTOR" self.target_lon = "target_lon = -98.35" self.target_lat = "target_lat = 39.5" + self.FV_hwt = '' def set_wsub_extdata(self): if self.microphysics == 'BACM_1M' or self.microphysics == 'GFDL_1M': diff --git a/gcmpy/scripts/env.py b/gcmpy/scripts/env.py index a4be198d..e80ee7bb 100755 --- a/gcmpy/scripts/env.py +++ b/gcmpy/scripts/env.py @@ -76,9 +76,9 @@ if envdict['site'] == 'NCCS': # NOTE: in the current version of gcm_setup, we never build on # SLES15, so milan nodes are not an option for NCCS. - if answerdict['processor'].q_answer == 'Skylake': + if answerdict['processor'].q_answer == 'sky': envdict['n_CPUs'] = 40 - elif answerdict['processor'].q_answer == 'Cascade': + elif answerdict['processor'].q_answer == 'cas': ''' NCCS currently recommends that users do not run with 48 cores per n_CPUs on SCU16 due to OS issues and @@ -89,15 +89,15 @@ envdict['n_CPUs'] = 45 elif envdict['site'] == 'NAS': - if answerdict['processor'].q_answer == 'Haswell': + if answerdict['processor'].q_answer == 'has': envdict['n_CPUs'] = 24 - elif answerdict['processor'].q_answer == 'Broadwell': + elif answerdict['processor'].q_answer == 'bro': envdict['n_CPUs'] = 28 - elif answerdict['processor'].q_answer == 'Skylake': + elif answerdict['processor'].q_answer == 'sky': envdict['n_CPUs'] = 40 - elif answerdict['processor'].q_answer == 'Cascade': + elif answerdict['processor'].q_answer == 'cas': envdict['n_CPUs'] = 40 - elif answerdict['processor'].q_answer == 'AMD': + else: envdict['n_CPUs'] = 128 elif envdict['site'] == 'AWS' or envdict['site'] == 'AZURE': diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index c1602591..fdb87cdf 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -43,7 +43,6 @@ def __init__(self): 'gcm_emip.setup', 'CAP.rc.tmpl', 'AGCM.rc.tmpl', - 'HISTORY.rc.tmpl', 'logging.yaml', 'fvcore_layout.rc', 'linkbcs.tmpl'] @@ -53,11 +52,12 @@ def config_models(self): self.atmos.config(self.ocean.nx, self.ocean.ny) self.land.config() self.gocart.config() + self.file_list.append(self.ocean.history_template) # setup some variables idk def set_some_stuff(self): - if self.atmos.im_hist >= self.ocean.im: + if self.atmos.hist_im >= self.ocean.im: self.interpolate_sst = True else: self.interpolate_sst = False @@ -82,7 +82,7 @@ def set_nodes(self): # Now we roughly figure out the number of collections in the HISTORY.rc n_hist_collections = 0 - with open(answerdict['history_template'].q_answer, 'r') as file: + with open(f"{pathdict['etc']}/{answerdict['history_template'].q_answer}", 'r') as file: in_collections = False for line in file: if line.split(' ', 1)[0] == "COLLECTIONS:": @@ -182,15 +182,15 @@ def set_stuff(self): self.plot_t = "8:00:00" self.archive_t = "8:00:00" self.run_q = f"PBS -q normal" - self.run_p = f"PBS -l select={self.nodes}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" - self.run_fp = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + self.run_p = f"PBS -l select={self.nodes}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" + self.run_fp = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" self.post_q = "PBS -q normal" self.plot_q = "PBS -q normal" self.move_q = "PBS -q normal" self.archive_q = "PBS -q normal" - self.post_p = f"PBS -l select={NPCUS}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" - self.plot_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs=1:model={answerdict['processor']}" - self.archive_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor']}" + self.post_p = f"PBS -l select={NPCUS}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" + self.plot_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs=1:model={answerdict['processor'].q_answer}" + self.archive_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" self.move_p = "PBS -l select=1:ncpus=1" self.boundary_path = "/nobackup/gmao_SIteam/ModelData" self.bcs_dir = f"{self.boundary_path}/bcs/{self.land.bcs}/{self.land.bcs}_{self.ocean.tag}" @@ -203,7 +203,7 @@ def set_stuff(self): if oceanres == "1440x720": self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/SST/{oceanres}" else: - self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{oceanres}" + self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/realtime/@SSTNAME/{oceanres}" if self.ocean.gridtype_abrv == "LL": self.sst_dir = "/nobackupp2/estrobac/geos5/SSTDIR" @@ -230,11 +230,11 @@ def set_stuff(self): self.post_t = "8:00:00" self.plot_t = "12:00:00" self.archive_t = "2:00:00" - self.run_q = f"SBATCH --constraint={answerdict['processor']}" + self.run_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" self.run_fp = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" - self.post_q = f"SBATCH --constraint={answerdict['processor']}" - self.plot_q = f"SBATCH --constraint={answerdict['processor']}" + self.post_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" + self.plot_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.move_q = "SBATCH --partition=datamove" self.archive_q = "SBATCH --partition=datamove" self.post_p = f"SBATCH --nodes={NPCUS} --ntasks-per-node={envdict['n_CPUs']}" @@ -242,7 +242,7 @@ def set_stuff(self): self.archive_p = "SBATCH --ntasks=1" self.move_p = "SBATCH --ntasks=1" self.boundary_path = "/discover/nobackup/projects/gmao" - self.bcs_dir = f"{self.boundary_path}bcs_shared/fvInput/ExtData/esm/tiles/{self.land.bcs}" + self.bcs_dir = f"{self.boundary_path}/bcs_shared/fvInput/ExtData/esm/tiles/{self.land.bcs}" self.replay_ana_expID = "x0039" self.replay_ana_location = f"{self.boundary_path}/g6dev/ltakacs/x0039" self.M2_replay_ana_location = f"{self.boundary_path}/merra2/data" @@ -253,7 +253,7 @@ def set_stuff(self): if oceanres == "1440x720": self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/SST/{oceanres}" else: - self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{oceanres}" + self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/realtime/@SSTNAME/{oceanres}" if self.ocean.gridtype_abrv == "LL": self.sst_dir = "/discover/nobackup/estrobac/geos5/SSTDIR" @@ -280,7 +280,7 @@ def set_stuff(self): self.post_t = "8:00:00" self.plot_t = "12:00:00" self.archive_t = "1:00:00" - self.run_q = f"SBATCH --constraint={answerdict['processor']}" + self.run_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" self.run_fp = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" self.post_q = "NULL" @@ -296,7 +296,7 @@ def set_stuff(self): self.replay_ana_expID = "REPLAY_UNSUPPORTED" self.replay_ana_location = "REPLAY_UNSUPPORTED" self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" - self.sst_dir = f"{self.boundary_path}/{self.ocean.sst_name}/{self.ocean.im}x{self.ocean.jm}" + self.sst_dir = f"{self.boundary_path}/@SSTNAME/{self.ocean.im}x{self.ocean.jm}" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" self.work_dir = os.environ.get('HOME') self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" @@ -331,7 +331,7 @@ def set_stuff(self): self.replay_ana_expID = "REPLAY_UNSUPPORTED" self.replay_ana_location = "REPLAY_UNSUPPORTED" self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" - self.sst_dir = f"{self.boundary_path}/{self.ocean.sst_name}/{self.ocean.im}x{self.ocean.jm}" + self.sst_dir = f"{self.boundary_path}/@SSTNAME/{self.ocean.im}x{self.ocean.jm}" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" self.work_dir = os.environ.get('HOME') self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" @@ -340,21 +340,12 @@ def set_stuff(self): # By default on desktop, just ignore IOSERVER for now self.atmos.NX = 1 self.atmos.NY = 6 - answerdict["io_server"] = False + answerdict["io_server"].q_answer = False self.n_oserver_nodes = 0 self.n_backend_pes = 0 - ''' - def set_hist_temp(self): - tmphist_d, tmphist_path = tempfile.mkstemp() - print(self.ocean.history_template) - shutil.copy(self.ocean.history_template, tmphist_path) - return tmphist_d, tmphist_path - ''' - - ''' - mainly used to create .{*}root files and/or populate them - ''' + + # mainly used to create .{*}root files and/or populate them def create_dotfile(self, path, content): try: path = Path(path) @@ -399,13 +390,25 @@ def mpistacksettings(self): with open('../yaml/mpi_config.yaml') as file: mpidict = yaml.load(file, Loader=yaml.FullLoader) - # retrieve config from correlating mpi setting being used - mpi_config = mpidict.get(envdict['mpi']) - # restart by oserver if using openmpi or mvapich if envdict['mpi'] == 'openmpi' or envdict['mpi'] == 'mvapich': self.restart_by_oserver = 'YES' + # retrieve config from correlating mpi setting being used + self.mpi_config = mpidict.get(envdict['mpi']) + + # These are options determined to be useful at NCCS + # Not setting generally as they are more fabric/cluster + # specific compared to the above adjustments + if envdict['site'] == 'NCCS': + self.mpi_config += "\nsetenv I_MPI_SHM_HEAP_VSIZE 512 \ + \nsetenv PSM2_MEMORY large" + + # as of right now, sigularity is not an option so this will always be added + self.mpi_config += "\nsetenv I_MPI_EXTRA_FILESYSTEM 1 \ + \nsetenv I_MPI_EXTRA_FILESYSTEM_FORCE gpfs" + + ####################################################################### @@ -586,28 +589,13 @@ def config_heartbeat(self): with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'r') as file: file.write(file_content) - ''' - This is a helper function that extends jinja's Undefined class to ignore - template variables that aren't detemplated by this script - ''' - def get_undefined_handler(variable_start_string, variable_end_string, self): - class PreserveUndefined(Undefined): - __slots__ = () - - def __init__(self, *args, **kwargs): - super(PreserveUndefined, self).__init__(**kwargs) - - def __str__(self): - return f"{variable_start_string}{self._undefined_name}{variable_end_string}" - return PreserveUndefined - - # another templating helper function that removes lines from a file that begin with #DELETE + # Templating helper function -- Removes lines marked with "#DELETE" def cleanup(self, file_path): with open(file_path, 'r') as file: content = file.read() - content = re.sub(r'^\s*#DELETE.*\n', r'', content, flags=re.MULTILINE) + content = re.sub(r'.*#DELETE.*\n?', r'', content) with open(file_path, 'w') as file: file.write(content) @@ -617,6 +605,7 @@ def cleanup(self, file_path): def template(self): # this dictionary holds template values for the default jinja2 delimiter "{{ val }}" jinja_dict = { + 'SETENVS': self.mpi_config, 'GCMVER': self.gcm_version, 'EXPSRC': self.gcm_version, 'EXPID': answerdict['experiment_id'].q_answer, @@ -701,7 +690,7 @@ def template(self): 'LSM_PARMS': self.land.parameters, 'OCEAN_NAME': self.ocean.model, 'OCEAN_PRELOAD': self.ocean.preload, - #'ana4replay.eta.%y4%m2%d2_%h2z.nc4': '/discover/nobackup/projects/gmao/merra2/data/ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4?g', + 'ana4replay.eta.%y4%m2%d2_%h2z.nc4': '/discover/nobackup/projects/gmao/merra2/data/ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4?g', 'REPLAY_ANA_EXPID': self.replay_ana_expID, 'REPLAY_ANA_LOCATION': self.replay_ana_location, 'M2_REPLAY_ANA_LOCATION': self.M2_replay_ana_location, @@ -760,8 +749,8 @@ def template(self): 'CONVPAR_OPTION': self.atmos.convpar_option, 'STRETCH_FACTOR': self.atmos.stretch_factor, 'INTERPOLATE_SST': self.interpolate_sst, - 'HIST_IM': self.atmos.im_hist, - 'HIST_JM': self.atmos.jm_hist, + 'HIST_IM': self.atmos.hist_im, + 'HIST_JM': self.atmos.hist_jm, 'ISCCP_SATSIM': 1, 'MODIS_SATSIM': 0, 'RADAR_SATSIM': 0, @@ -780,24 +769,18 @@ def template(self): 'RUN_CMD': envdict['run_command'], 'HYDROSTATIC': self.atmos.use_hydrostatic, 'FV_SCHMIDT': self.atmos.schmidt, - 'FV_STRETCH_FAC': self.atmos.stretch_factor, + 'FV_STRETCH_FAC': self.atmos.FV_stretch_fac, 'FV_TARGET_LON': self.atmos.target_lon, 'FV_TARGET_LAT': self.atmos.target_lat, 'FV_MAKENH': self.atmos.FV_make_NH, 'FV_HYDRO': self.atmos.FV_hydro, 'GFDL_PROG_CCN': self.atmos.GFDL_prog_ccn, 'GFDL_USE_CCN': self.atmos.GFDL_use_ccn, - 'GFDL_HYDRO': self.atmos.GFDL_hydro - } - - # this dictionary holds values that use the ">>>val<<<" delimiter - jinja_dict_special_delimiter = { + 'GFDL_HYDRO': self.atmos.GFDL_hydro, 'FORCEDAS': self.atmos.force_das, 'FORCEGCM': self.atmos.force_gcm, 'HIST_CICE4': '#DELETE', - 'GOCART': self.gocart.gocart, 'FVCUBED': '', - 'OSTIA': self.ocean.ostia, 'HIST_CATCHCN': self.land.HIST_catchment, 'GCMRUN_CATCHCN': self.land.GCMRUN_catchment, 'EMIP_OLDLAND': self.land.emip_oldland, @@ -812,13 +795,12 @@ def template(self): exp_dir = answerdict['exp_dir'].q_answer - # this is an edge-case that can't be handled with jinja2 - # original csh line: s?^[ \t]*RECORD_?#RECORD_?g + # this is an edge-case that can't be handled with jinja2 for file in self.file_list: with open(f"{exp_dir}/{file}", 'r') as tmpl: file_content = tmpl.read() - file_content = re.sub(r'^[ \t]*(RECORD_.*)', r'#\1', file_content) + file_content = re.sub(r'[ \t]*RECORD_', r'#RECORD_', file_content) with open(f"{exp_dir}/{file}", 'w') as tmpl: tmpl.write(file_content) @@ -833,20 +815,6 @@ def template(self): with open(f"{exp_dir}/{file}", 'w') as tmpl: tmpl.write(content) - # this block handles the special case for jinja templating - PreserveUndefined = self.get_undefined_handler('>>>', '<<<') - special_env = Environment( - loader=FileSystemLoader(exp_dir), - undefined=PreserveUndefined, - variable_start_string=">>>", - variable_end_string="<<<" - ) - for file in self.file_list: - template = special_env.get_template(file) - content = template.render(jinja_dict_special_delimiter) - with open(f"{exp_dir}/{file}", 'w') as tmpl: - tmpl.write(content) - # remove #DELETE lines for file in self.file_list: file_path = f"{exp_dir}/{file}" @@ -885,7 +853,7 @@ def organize_exp_dir(self): # rename tmpl files os.rename(f"{exp_dir}/CAP.rc.tmpl", f"{exp_dir}/CAP.rc") os.rename(f"{exp_dir}/AGCM.rc.tmpl", f"{exp_dir}/AGCM.rc") - os.rename(f"{exp_dir}/HISTORY.rc.tmpl", f"{exp_dir}/HISTORY.rc") + os.rename(f"{exp_dir}/{self.ocean.history_template}", f"{exp_dir}/HISTORY.rc") os.rename(f"{exp_dir}/linkbcs.tmpl", f"{exp_dir}/linkbcs") # update file permissions diff --git a/gcmpy/scripts/gocart.py b/gcmpy/scripts/gocart.py index 309109a1..e64e6166 100755 --- a/gcmpy/scripts/gocart.py +++ b/gcmpy/scripts/gocart.py @@ -33,12 +33,12 @@ def set_gocart(self): self.gocart_hist = '#DELETE' def set_emissions(self): - if self.emissions.split('_')[0] == 'AMIP': - self.MERRA2OX_species = '' + if self.emissions.split('_')[0] == 'OPS': + self.ops_species = '' self.pchem_clim_years = 1 self.ox_relaxtime = '0.00' - elif self.emissions.split('_')[0] == 'OPS': - self.ops_species = '' + elif self.emissions.split('_')[0] == 'AMIP': + self.MERRA2OX_species = '' self.pchem_clim_years = 39 self.ox_relaxtime = '259200.' diff --git a/gcmpy/scripts/land.py b/gcmpy/scripts/land.py index 0cc2d664..7e3059a5 100755 --- a/gcmpy/scripts/land.py +++ b/gcmpy/scripts/land.py @@ -5,13 +5,13 @@ class land: def __init__(self): self.model = answerdict["LS_model"].q_answer self.bcs = answerdict["LS_boundary_conditions"].q_answer - self.parameters = None - self.emip_bcs_in = None - self.emip_oldland = None - self.emip_newland = None - self.emip_MERRA2 = None - self.HIST_catchment = None - self.GCMRUN_catchment = None + self.parameters = '' + self.emip_bcs_in = '' + self.emip_oldland = '' + self.emip_newland = '' + self.emip_MERRA2 = '' + self.HIST_catchment = '' + self.GCMRUN_catchment = '' # for debugging purposes def print_vars(self): @@ -42,7 +42,7 @@ def set_bcs(self): def set_catchment(self): if self.model == "Catchment": - self.land_choice = 1 + self.model = 1 self.HIST_catchment = "#DELETE" self.GCMRUN_catchment = "#DELETE" elif self.model == "CatchmentCN-CLM4.0": diff --git a/gcmpy/scripts/ocean.py b/gcmpy/scripts/ocean.py index 67c4d556..15d2eb10 100755 --- a/gcmpy/scripts/ocean.py +++ b/gcmpy/scripts/ocean.py @@ -46,10 +46,10 @@ def print_vars(self): def set_IMO(self): - self.imo = f"{str(self.im):04}" + self.imo = "%04d" % self.im def set_JMO(self): - self.jmo = f"{str(self.jm):04}" + self.jmo = "%04d" % self.jm def set_res(self): hres = answerdict["OM_horizontal_res"].q_answer @@ -161,7 +161,7 @@ def uncoupled_hres(self): self.nf = 1 self.tag = "Reynolds" self.sst_name = "SST" - self.out = "c" + self.out = "360x180" self.sst_file = f"dataoceanfile_MERRA_sst_1971-current.{self.im}x{self.jm}.LE" self.ice_file = f"dataoceanfile_MERRA_fraci_1971-current.{self.im}x{self.jm}.LE" self.set_kpar_file() @@ -177,7 +177,7 @@ def uncoupled_hres(self): self.nf = 1 self.tag = "MERRA-2" self.sst_name = "MERRA2" - self.out = "e" + self.out = "1440x720" self.sst_file = f"dataoceanfile_MERRA2_SST.{self.im}x{self.jm}.{todays_date.year}.data" self.ice_file = f"dataoceanfile_MERRA2_ICE.{self.im}x{self.jm}.{todays_date.year}.data" self.set_kpar_file() @@ -193,7 +193,7 @@ def uncoupled_hres(self): self.nf = 1 self.tag = "Ostia" self.sst_name = "OSTIA_REYNOLDS" - self.out = "f" + self.out = "2880x1440" self.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{OGCM_IM}x{OGCM_JM}.{todays_date.year}.data" self.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{OGCM_IM}x{OGCM_JM}.{todays_date.year}.data" self.set_kpar_file() @@ -210,7 +210,7 @@ def uncoupled_hres(self): self.nf = 6 self.tag = "Ostia" self.sst_name = "OSTIA_REYNOLDS" - self.out = "f" + self.out = "CS" self.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{self.im}x{self.jm}.{todays_date.year}.data" self.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{self.im}x{self.jm}.{todays_date.year}.data" self.set_kpar_file() @@ -239,12 +239,13 @@ def uncoupled_hres(self): # ocean model driver def config(self): - match answerdict["OM_coupled"].q_answer: - case True: - self.coupled_hres() - self.coupled_vres() - case False: - self.uncoupled_hres() + if answerdict["OM_coupled"].q_answer == True: + self.coupled_hres() + self.coupled_vres() + else: + self.uncoupled_hres() + + self.set_gridname() diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index 2f8299e4..06681057 100755 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -26,9 +26,9 @@ def experiment_desc(answerdict, i): def processor_choices(answerdict, i): if i == "processor": if envdict["site"] == "NCCS": - answerdict[i].q_choices = ["Skylake", "Cascade Lake"] + answerdict[i].q_choices = ["cas", "sky"] elif envdict["site"] == "NAS": - answerdict[i].q_choices = ["Skylake", "Haswell", "Broadwell", "Cascade Lake", "AMD Rome"] + answerdict[i].q_choices = ["sky", "has", "bro", "cas", "rom", "mil"] else: exit(1) @@ -114,22 +114,22 @@ def history_template_default(answerdict, i): match answerdict["OM_name"]: case "MOM5": - answerdict[i].q_default = f"{pathdict['etc']}/HISTORY.AOGCM-MOM5.rc.tmpl" + answerdict[i].q_default = "HISTORY.AOGCM-MOM5.rc.tmpl" case "MOM6": - answerdict[i].q_default = f"{pathdict['etc']}/HISTORY.AOGCM.rc.tmpl" + answerdict[i].q_default = "HISTORY.AOGCM.rc.tmpl" case "MIT": - answerdict[i].q_default = f"{pathdict['etc']}/HISTORY.AOGCM_MITgcm.rc.tmpl" + answerdict[i].q_default = "HISTORY.AOGCM_MITgcm.rc.tmpl" case _: - answerdict[i].q_default = f"{pathdict['etc']}/HISTORY.AGCM.rc.tmpl" + answerdict[i].q_default = "HISTORY.AGCM.rc.tmpl" - + ''' @staticmethod def history_template_valid(answerdict, i): if i == "history_template": while not os.path.exists(answerdict[i].q_answer): print(f"Error: Could not find {color.RED}{answerdict[i]}{color.RESET}") answerdict[i].load_question(answerdict) - + ''' @staticmethod def exp_dir_default(answerdict, i): @@ -221,7 +221,7 @@ def process(): handle.experiment_desc(answerdict, i) handle.OM_hres_valid(answerdict, i) handle.heartbeat_valid(answerdict, i) - handle.history_template_valid(answerdict, i) + #handle.history_template_valid(answerdict, i) handle.exp_dir_valid(answerdict, i) # strips the first word from every select type question diff --git a/gcmpy/yaml/atmospheric_model.yaml b/gcmpy/yaml/atmospheric_model.yaml index 38be2843..719d1bd4 100755 --- a/gcmpy/yaml/atmospheric_model.yaml +++ b/gcmpy/yaml/atmospheric_model.yaml @@ -37,7 +37,7 @@ io_server: type: 'confirm' prompt: 'Would you like to IOSERVER?' choices: '' - default_answer: True + default_answer: False follows_up: '' diff --git a/gcmpy/yaml/directory_setup.yaml b/gcmpy/yaml/directory_setup.yaml index 4edbcfe2..68cd6f28 100755 --- a/gcmpy/yaml/directory_setup.yaml +++ b/gcmpy/yaml/directory_setup.yaml @@ -1,5 +1,5 @@ history_template: - type: 'path' + type: 'text' prompt: 'Enter the location of HISTORY template to use (press ENTER for recommended template):' choices: '' default_answer: '' diff --git a/gcmpy/yaml/land_model.yaml b/gcmpy/yaml/land_model.yaml index 45fcd63d..7972cbfb 100755 --- a/gcmpy/yaml/land_model.yaml +++ b/gcmpy/yaml/land_model.yaml @@ -1,13 +1,13 @@ LS_boundary_conditions: type: 'select' prompt: 'Select the Land Surface Boundary Conditions:' - choices: ['Icarus-NLv3', 'Icarus', 'v12'] + choices: ['NL3', 'ICA', 'v12'] default_answer: '' follows_up: '' LS_model: type: 'select' prompt: 'Select the Land Surface Model:' - choices: ['Catchment', 'CatchmentCN-CLM4.0 (CN_CLM40)', 'CatchmentCN-CLM4.5 (CN_CLM45)'] + choices: ['Catchment', 'CatchmentCN-CLM4.0 (CN_CLM40)'] default_answer: '' follows_up: '' diff --git a/linkbcs.tmpl b/linkbcs.tmpl index e255811e..ee643a18 100644 --- a/linkbcs.tmpl +++ b/linkbcs.tmpl @@ -55,8 +55,8 @@ setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} /bin/ln -sf $BCSDIR/land/$BCRSLV/green_clim_{{ AGCM_IM }}x{{ AGCM_JM }}.data green.data /bin/ln -sf $BCSDIR/land/$BCRSLV/ndvi_clim_{{ AGCM_IM }}x{{ AGCM_JM }}.data ndvi.data ->>>GCMRUN_CATCHCN<<>>GCMRUN_CATCHCN<< Date: Wed, 8 Jan 2025 13:56:20 -0500 Subject: [PATCH 13/37] Delete gcmpy/sync.sh --- gcmpy/sync.sh | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100755 gcmpy/sync.sh diff --git a/gcmpy/sync.sh b/gcmpy/sync.sh deleted file mode 100755 index 4e48f1f7..00000000 --- a/gcmpy/sync.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -''' -The purpose of this script to sync up the gcmpy directories between the @GEOSgcm_App dir and bin dir without having to make install -''' - - -# Source and destination directories -source_dir="/discover/nobackup/sshakoor/GEOSgcm/src/Applications/@GEOSgcm_App/gcmpy" -destination_dir="/discover/nobackup/sshakoor/GEOSgcm/install/bin/gcmpy" - -# Synchronize scripts -rsync -av --exclude='sync.sh' --exclude='**/CMakeLists.txt' "$source_dir/" "$destination_dir/" From 2a003da4326549eb7f45000c2502d762ef7cb685 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 8 Jan 2025 13:56:31 -0500 Subject: [PATCH 14/37] Delete gcmpy/jinjafy.py --- gcmpy/jinjafy.py | 257 ----------------------------------------------- 1 file changed, 257 deletions(-) delete mode 100755 gcmpy/jinjafy.py diff --git a/gcmpy/jinjafy.py b/gcmpy/jinjafy.py deleted file mode 100755 index 72be1b53..00000000 --- a/gcmpy/jinjafy.py +++ /dev/null @@ -1,257 +0,0 @@ -''' -The purpose of this script is to "jinja-fy" the template files affected by gcm_setup. - -Jinja can't process items unless they are enclosed on both sides with an -identifier. The old/current way to identify template items is "@ITEM_NAME". -This script will replace all these instances with "{{ ITEM_NAME }}". - -Variables templated at run time (identified with ">>>ITEM<<<") are kept -the same but included in case someone wants this changed. - -This script only needs to be run once. -''' - -import os - -def replace_strings_in_file(file_path, replacements): - # Read the content of the file - with open(file_path, 'r') as file: - content = file.read() - - # Replace all occurrences of the keys with their corresponding values - for key, value in replacements.items(): - content = content.replace(key, value) - - # Write the modified content back to the file - with open(file_path, 'w') as file: - file.write(content) - -def main(file_list, replacements): - for file_path in file_list: - #file_path = f"{os.path.dirname(os.getcwd())}/{file_path}" - file_path = f"/discover/nobackup/sshakoor/GEOSgcm/install/bin/{file_path}" - if os.path.isfile(file_path): - replace_strings_in_file(file_path, replacements) - else: - print(f"File {file_path} not found.") - -if __name__ == "__main__": - # List of files to process - file_list = [ - 'gcm_run.j', - 'gcm_post.j', - 'gcm_archive.j', - 'gcm_regress.j', - 'gcm_plot.tmpl', - 'gcm_quickplot.csh', - 'gcm_moveplot.j', - 'gcm_forecast.tmpl', - 'gcm_forecast.setup', - 'gcm_emip.setup', - 'CAP.rc.tmpl', - 'AGCM.rc.tmpl', - 'HISTORY.rc.tmpl', - 'HISTORY.AOGCM-MOM5.rc.tmpl', - 'HISTORY.AOGCM.rc.tmpl', - 'HISTORY.AOGCM_MITgcm.rc.tmpl', - 'HISTORY.AGCM.rc.tmpl', - 'logging.yaml', - 'fvcore_layout.rc', - 'linkbcs.tmpl' - ] - - # Dictionary with keys to find and values to replace - replacements = { - '@SETENVS': '{{ SETENVS }}', - '@GCMVER': '{{ GCMVER }}', - '@EXPSRC': '{{ EXPSRC }}', - '@EXPID': '{{ EXPID }}', - '@RUN_N': '{{ RUN_N }}', - '@RUN_FN': '{{ RUN_FN }}', - '@RUN_FT': '{{ RUN_FT }}', - '@RUN_T': '{{ RUN_T }}', - '@RUN_P': '{{ RUN_P }}', - '@RUN_FP': '{{ RUN_FP }}', - '@RUN_Q': '{{ RUN_Q }}', - '@POST_N': '{{ POST_N }}', - '@POST_T': '{{ POST_T }}', - '@POST_P': '{{ POST_P }}', - '@POST_Q': '{{ POST_Q }}', - '@MOVE_N': '{{ MOVE_N }}', - '@PLOT_N': '{{ PLOT_N }}', - '@PLOT_T': '{{ PLOT_T }}', - '@PLOT_P': '{{ PLOT_P }}', - '@PLOT_Q': '{{ PLOT_Q }}', - '@MOVE_Q': '{{ MOVE_Q }}', - '@MOVE_P': '{{ MOVE_P }}', - '@ARCHIVE_N': '{{ ARCHIVE_N }}', - '@ARCHIVE_T': '{{ ARCHIVE_T }}', - '@ARCHIVE_P': '{{ ARCHIVE_P }}', - '@ARCHIVE_Q': '{{ ARCHIVE_Q }}', - '@REGRESS_N': '{{ REGRESS_N }}', - '@BCSDIR': '{{ BCSDIR }}', - '@SSTDIR': '{{ SSTDIR }}', - '@SSTNAME': '{{ SSTNAME }}', - '@OCEANOUT': '{{ OCEANOUT }}', - '@LSMBCS': '{{ LSMBCS }}', - '@EMIP_BCS_IN': '{{ EMIP_BCS_IN }}', - '@EMIP_MERRA2': '{{ EMIP_MERRA2 }}', - '@BCSTAG': '{{ BCSTAG }}', - '@SSTFILE': '{{ SSTFILE }}', - '@ICEFILE': '{{ ICEFILE }}', - '@KPARFILE': '{{ KPARFILE }}', - '@CHMDIR': '{{ CHMDIR }}', - '@COUPLEDIR': '{{ COUPLEDIR }}', - '@shared_COUPLED': '{{ shared_COUPLED }}', - '@GWDRSDIR': '{{ GWDRSDIR }}', - '@EXPDIR': '{{ EXPDIR }}', - '@EXPDSC': '{{ EXPDSC }}', - '@HOMDIR': '{{ HOMDIR }}', - '@BATCH_GROUP': '{{ BATCH_GROUP }}', - '@BATCH_TIME': '{{ BATCH_TIME }}', - '@BATCH_CMD': '{{ BATCH_CMD }}', - '@BATCH_JOBNAME': '{{ BATCH_JOBNAME }}', - '@BATCH_OUTPUTNAME': '{{ BATCH_OUTPUTNAME }}', - '@BATCH_JOINOUTERR': '{{ BATCH_JOINOUTERR }}', - '@SITE': '{{ SITE }}', - '@GEOSDIR': '{{ GEOSDIR }}', - '@GEOSSRC': '{{ GEOSSRC }}', - '@GEOSBIN': '{{ GEOSBIN }}', - '@GEOSETC': '{{ GEOSETC }}', - '@GEOSUTIL': '{{ GEOSUTIL }}', - '@SINGULARITY_BUILD': '{{ SINGULARITY_BUILD }}', - '@NATIVE_BUILD': '{{ NATIVE_BUILD }}', - '@MPT_SHEPHERD': '{{ MPT_SHEPHERD }}', - '@SINGULARITY_SANDBOX': '{{ SINGULARITY_SANDBOX }}', - '@REAL_BIND_PATH': '{{ REAL_BIND_PATH }}', - '@BASE_BIND_PATH': '{{ BASE_BIND_PATH }}', - '@BOUNDARY_DIR': '{{ BOUNDARY_DIR }}', - '@CHECKPOINT_TYPE': '{{ CHECKPOINT_TYPE }}', - '@OGCM_NX': '{{ OGCM_NX }}', - '@OGCM_NY': '{{ OGCM_NY }}', - '@OGCM_NPROCS': '{{ OGCM_NPROCS }}', - '@OBSERVER_FRQ': '{{ OBSERVER_FRQ }}', - '@DASTUNING': '{{ DASTUNING }}', - '>>>FORCEDAS<<<': '{{ FORCEDAS }}', - '>>>FORCEGCM<<<': '{{ FORCEGCM }}', - '@COUPLED': '{{ COUPLED }}', - '@CLDMICRO': '{{ CLDMICRO }}', - '@MOM5': '{{ MOM5 }}', - '@MOM6': '{{ MOM6 }}', - '@OCNMODEL': '{{ OCNMODEL }}', - '@CICE4': '{{ CICE4 }}', - '@CICE6': '{{ CICE6 }}', - '>>>HIST_CICE4<<<': '{{ HIST_CICE4 }}', - '@MIT': '{{ MIT }}', - '@DATAOCEAN': '{{ DATAOCEAN }}', - '>>>GOCART<<<': '>>>GOCART<<<', - '@OPS_SPECIES': '{{ OPS_SPECIES }}', - '@CMIP_SPECIES': '{{ CMIP_SPECIES }}', - '@MERRA2OX_SPECIES': '{{ MERRA2OX_SPECIES }}', - '>>>FVCUBED<<<': '{{ FVCUBED }}', - '@HIST_GOCART': ' {{ HIST_GOCART }}', - '>>>OSTIA<<<': '>>>OSTIA<<<', - '>>>HIST_CATCHCN<<<': '{{ HIST_CATCHCN }}', - '>>>GCMRUN_CATCHCN<<<': '{{ GCMRUN_CATCHCN }}', - '>>>EMIP_OLDLAND<<<': '{{ EMIP_OLDLAND }}', - '>>>EMIP_NEWLAND<<<': '{{ EMIP_NEWLAND }}', - '@LSM_PARMS': '{{ LSM_PARMS }}', - '@OCEAN_NAME': '{{ OCEAN_NAME }}', - '@OCEAN_PRELOAD': '{{ OCEAN_PRELOAD }}', - '{{ 4DIAUDAS }}': '{{ _4DIAUDAS }}', - '>>>REGULAR_REPLAY<<<': '{{ REGULAR_REPLAY }}', - '>>>REGULAR_REPLAY_GMAO<<<': '{{ REGULAR_REPLAY_GMAO }}', - '>>>REGULAR_REPLAY_NCEP<<<': '{{ REGULAR_REPLAY_NCEP }}', - '>>>REGULAR_REPLAY_ECMWF<<<': '{{ REGULAR_REPLAY_ECMWF }}', -'ana4replay.eta.%y4%m2%d2_%h2z.nc4': '{{ ana4replay.eta.%y4%m2%d2_%h2z.nc4 }}', - '@REPLAY_ANA_EXPID': '{{ REPLAY_ANA_EXPID }}', - '@REPLAY_ANA_LOCATION': '{{ REPLAY_ANA_LOCATION }}', - '@M2_REPLAY_ANA_LOCATION': '{{ M2_REPLAY_ANA_LOCATION }}', - '@OX_RELAXTIME': '{{ OX_RELAXTIME }}', - '@PCHEM_CLIM_YEARS': '{{ PCHEM_CLIM_YEARS }}', - '@RATS_PROVIDER': '{{ RATS_PROVIDER }}', - '@AERO_PROVIDER': '{{ AERO_PROVIDER }}', - '@OANA_PROVIDER': '{{ OANA_PROVIDER }}', - '@EMISSIONS': '{{ EMISSIONS }}', - '@DYCORE': '{{ DYCORE }}', - '@AGCM_GRIDNAME': '{{ AGCM_GRIDNAME }}', - '@OGCM_GRIDNAME': '{{ OGCM_GRIDNAME }}', - '@OGCM_IS_FCST': '{{ OGCM_IS_FCST }}', - '@BOOT': '{{ BOOT }}', - '@BCSRES': '{{ BCSRES }}', - '@OCEANtag': '{{ OCEANtag }}', - '@ATMOStag': '{{ ATMOStag }}', - '@RES_DATELINE': '{{ RES_DATELINE }}', - '@TILEDATA': '{{ TILEDATA }}', - '@TILEBIN': '{{ TILEBIN }}', - '@DT': '{{ DT }}', - '@SOLAR_DT': '{{ SOLAR_DT }}', - '@IRRAD_DT': '{{ IRRAD_DT }}', - '@OCEAN_DT': '{{ OCEAN_DT }}', - '@LONG_DT': '{{ LONG_DT }}', - '@NX': '{{ NX }}', - '@NY': '{{ NY }}', - '@USE_SHMEM': '{{ USE_SHMEM }}', - '@USE_IOSERVER': '{{ USE_IOSERVER }}', - '@NUM_OSERVER_NODES': '{{ NUM_OSERVER_NODES }}', - '@NUM_BACKEND_PES': '{{ NUM_BACKEND_PES }}', - '@RESTART_BY_OSERVER': '{{ RESTART_BY_OSERVER }}', - '@NCPUS_PER_NODE': '{{ NCPUS_PER_NODE }}', - '@NUM_READERS': '{{ NUM_READERS }}', - '@NUM_WRITERS': '{{ NUM_WRITERS }}', - '@LATLON_AGCM': '{{ LATLON_AGCM }}', - '@LATLON_OGCM': '{{ LATLON_OGCM }}', - '@CUBE_AGCM': '{{ CUBE_AGCM }}', - '@CUBE_OGCM': '{{ CUBE_OGCM }}', - '@GRID_TYPE': '{{ GRID_TYPE }}', - '@AGCM_NF': '{{ AGCM_NF }}', - '@AGCM_IM': '{{ AGCM_IM }}', - '@AGCM_JM': '{{ AGCM_JM }}', - '@AGCM_LM': '{{ AGCM_LM }}', - '@OGCM_IM': '{{ OGCM_IM }}', - '@OGCM_JM': '{{ OGCM_JM }}', - '@OGCM_LM': '{{ OGCM_LM }}', - '@OGCM_NF': '{{ OGCM_NF }}', - '@OGCM_GRID_TYPE': '{{ OGCM_GRID_TYPE }}', - '@BEG_DATE': '{{ BEG_DATE }}', - '@END_DATE': '{{ END_DATE }}', - '@JOB_SGMT': '{{ JOB_SGMT }}', - '@NUM_SGMT': '{{ NUM_SGMT }}', - '@CONUS': '{{ CONUS }}', - '@FV_HWT': '{{ FV_HWT }}', - '@CONVPAR_OPTION': '{{ CONVPAR_OPTION }}', - '@STRETCH_FACTOR': '{{ STRETCH_FACTOR }}', - '@INTERPOLATE_SST': '{{ INTERPOLATE_SST }}', - '@HIST_IM': '{{ HIST_IM }}', - '@HIST_JM': '{{ HIST_JM }}', - '@ISCCP_SATSIM': '{{ ISCCP_SATSIM }}', - '@MODIS_SATSIM': '{{ MODIS_SATSIM }}', - '@RADAR_SATSIM': '{{ RADAR_SATSIM }}', - '@LIDAR_SATSIM': '{{ LIDAR_SATSIM }}', - '@MISR_SATSIM': '{{ MISR_SATSIM }}', - '@SATSIM': '{{ SATSIM }}', - '@USE_SKIN_LAYER': '{{ USE_SKIN_LAYER }}', - '@ANALYZE_TS': '{{ ANALYZE_TS }}', - '@LSM_CHOICE': '{{ LSM_CHOICE }}', - '@MP_TURN_OFF_WSUB_EXTDATA': '{{ MP_TURN_OFF_WSUB_EXTDATA }}', - '@BACM_1M_': '{{ BACM_1M_ }}', - '@GFDL_1M_': '{{ GFDL_1M_ }}', - '@MGB2_2M_': '{{ MGB2_2M_ }}', - '@PRELOAD_COMMAND': '{{ PRELOAD_COMMAND }}', - '@LD_LIBRARY_PATH_CMD': '{{ LD_LIBRARY_PATH_CMD }}', - '@RUN_CMD': '{{ RUN_CMD }}', - '@HYDROSTATIC': '{{ HYDROSTATIC }}', - '@FV_SCHMIDT': '{{ FV_SCHMIDT }}', - '@FV_STRETCH_FAC': '{{ FV_STRETCH_FAC }}', - '@FV_TARGET_LON': '{{ FV_TARGET_LON }}', - '@FV_TARGET_LAT': '{{ FV_TARGET_LAT }}', - '@FV_MAKENH': '{{ FV_MAKENH }}', - '@FV_HYDRO': '{{ FV_HYDRO }}', - '@GFDL_PROG_CCN': '{{ GFDL_PROG_CCN }}', - '@GFDL_USE_CCN': '{{ GFDL_USE_CCN }}', - '@GFDL_HYDRO': '{{ GFDL_HYDRO }}' - - } - - main(file_list, replacements) - From a4e0e8012ba9ba76f4055b1e3547e4202d20e6ac Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 8 Jan 2025 13:56:52 -0500 Subject: [PATCH 15/37] Delete gcmpy/scripts/__pycache__ directory --- .../__pycache__/atmosphere.cpython-312.pyc | Bin 12838 -> 0 bytes gcmpy/scripts/__pycache__/env.cpython-312.pyc | Bin 4807 -> 0 bytes .../generate_question.cpython-312.pyc | Bin 2995 -> 0 bytes .../scripts/__pycache__/gocart.cpython-312.pyc | Bin 2697 -> 0 bytes gcmpy/scripts/__pycache__/land.cpython-312.pyc | Bin 2660 -> 0 bytes gcmpy/scripts/__pycache__/ocean.cpython-312.pyc | Bin 12811 -> 0 bytes .../process_questions.cpython-312.pyc | Bin 11377 -> 0 bytes .../scripts/__pycache__/utility.cpython-312.pyc | Bin 3860 -> 0 bytes 8 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/env.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/gocart.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/land.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/ocean.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/utility.cpython-312.pyc diff --git a/gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc b/gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc deleted file mode 100644 index 2c5db8592113a6fdd77fc6bf5a013d384aeef240..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12838 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 MHn=w!3`xQN1*$*}k^lez diff --git a/gcmpy/scripts/__pycache__/env.cpython-312.pyc b/gcmpy/scripts/__pycache__/env.cpython-312.pyc deleted file mode 100644 index f54cf81cd4a8cdd7c7197bd908b3c282d662ddc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4807 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 Tf9<5m{m9`_p8i`Sh423Xi#vw+ diff --git a/gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc b/gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc deleted file mode 100644 index a4d5b6bbefaa6fbaaabb988d15eaacaf38caba86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2995 zcmb_eT}%{L6u$GbKd>xpS;j5}WVN-hrg0l7H72#zM6o8#VufO|woa!r11#*%aPNRF zS$`gQz(}KSl0IqDL=7gs>XSBU(k6Xjfn>L%Nln_9z9BrA_|$V|c2-!VX%kPf_ug~Q z&pmU_z2Dj2g28$Mbl|U^;m3YL{zS$lv9efCz~Tnch{mN!(wVs=2RxtVGJKNH2uXn> zb%ZC!i6+btOFkZ8$>4OXC^pQeH)x%bOQX= zhizX4u0Z6fxWEJFo<<4+aFwqiq#y!^mNpeUz`0o>1ut+OSEdo*ye^j~F)k7FS>6db zt7LSX&Ag#o{t4Njxr||2brZ5WnoFrV!=7-pHcmi?}$C(hWYGM>xP`0-=?10!lC z&ZrtcVi@U^s$jNQ{IiNghTS-582LC;Y05BJ+)b@KQOWH-BX9X-Ih9SBvOL}D%H7oO zb43^#`v`{1q`aejR-6mCQzQypu-v*Erbc&a@17M`{H^5(sD2+@2RouxD*+7F!LH&D zu($#F9)r1-=;7DzA0^+!3HciQUEnVWa0B>OFdf_Izv8MOOc55*ID6*i+W$>gBjX3) z8@ahSNAkQ#@Ya*eDb=)s2GyskS+zons_KTR zYn7@qhIb9?Nkg_N8_i9oLCVIb+qNYAl`sOzY#Ihgd!VTlXkQAnmwOJBdX5%*j;;|t z7%hh4*Mp0l@p8ChK2r>TPzv`J!@Y|KPZYx^e$^LGk1Qod7SmI!gq-J&@y`j#aDDs> zocbNEp9k3hf0~CXWw_J)?`@r{9&o(sB`vMxrZ8=W<2Mx#ABtVPpCRRT@v2V_Bo!)f z3zc2Q<*~r8DUZgDcf*B0X;z=!SoPVte&FGfF?=gE1iLo;ZQeHVp4v2qm8zk8{6Yl) z#@?zC0lQGyy1?5og3r*VZKD_L=#OlO9#d6A|0nu;Rq%Zy@p-ny*HRN4u-nGBW2^4H zY9n|f@%ild4sOUFUiTW>Hon(X|G(z%61IsA^^N%xmT2ndP3UPp7r*^ePIJ>OpPI`K zr)Va|(Kd+A@&bPAsu|-zQo()EP|VR-BgGG}LEQ?t2&>RMeFwK~n8*8R)la-?oOq0k zX9Li%aoT~J*e0EZ5XF^^If9KjRDuo5>i`eK%Up$&U^=I0RRo&exdl}=$#;V(yCIocsKaKe01^Q#T6-0l1>$+Q_IpI zSo&Q{pKG~&*wPmz>10tlxh$QU?Rys4iLu%Mmxy_>4`PRxWvgD6GdXQCjq3&(lB%Q~ z2}Rs+s{B5z?h@PB#&n9%We?cO87j_@HQwjxSc`Z)E$b~IPp6}eiYol7_MuycemqJn&8 z;{zll+O!EK#)Li<>q}poH0f)TzOV>kGts0;pM0~Bw24nWXJ&R5v?RR==icx9-Mi;+ z_&pS=B(T1|{N=deBjis6rNz64ttcE8iAq!^Mbb=yVerhR*ff{m7{Zc1qH=eM%0FQp ziv*t+B;N}J5@S^=8RH9$s(R7{BqXz`EKNF!4rN@hbsP?hL?a1CB?(q#?vezjvOszC zpAb|Ys81Du`tv@?Z~4ZvNrjrpk_U8zZ{Xl>>u(^7#02Urm8pfpg!{%47xx(=d)#gM z>~8uG;rBjb!3yuOmx?}0@q$PI5>C1}%m=cd zhx~v-C6p(U7`LjO(8!8Lvqm;$cnmGA8-||ESe0^Y=)&meh2i+#qgAsaa@scVK6Os4gm zhxQD`Mn-x%hd(QGa>*N7T27|)w4B!z3KrShGSyPbZBtKc6k}!u+~09SH%u#p_scn& zozhi}S|O^Kh6f)r7H?>&>jqXsOh@#L zVJfLq_;r=;(A^5B{vJ&knw4U8)9VoO8th5aN_R&iCQxH`Z!$;@%HStg}+`4_Qb#Z+$ z+=6`AZ9U)vUI>)U+E83q3`=wTx>&abPar$WAB)K@{~zH1Jn)O~YvAX=PqQm~W9z~5 ze{rZ!8^GU=^mxeRGcwh0#y!>H>YgmB{9F7C*Jjhv!v_^ zr$^ZnPLFM#ocZDFNt%;N>O93MV^y7lCRI!r-Q#*vNsUpQMAQD}-q>JlEC$)w1DNhb zf<;0PA$c2!(~NHX4b7CDxO?$0vvAlNaUgd{F;IQ)%>0=L@2v)!i{WE)y=%e4*a*D~ z1NOEKFjRBz%KVj;`u5dOJ9dYo)9UD)nCk_dmwr;!@n#C}r{dq%A3%0X!GHCK%9N^B zwLc9i=LQ!Cd^wyLYA>8Bh8oMzUc05~f8FNacAM9es<`8}ik-JXDl6j_BU5~x#SLE^ zwbS_mD`A?Cc0{8V-!pXK;)`R*@OPekzcU)`kbJZT^#voB(oMP#&h!A1gGk;&@_K4R zm`CrMFumXHt{vQFFf_72oCJ5zcW(q53W0_t?rET9>ElA+*z(EMK(yH6CbI>SxfX0H zHUeG`)?>!6&R^XKH5EclOU+M1N0)9DLelaltD!E}rpenICEEro;N3SX0Ha}7KrbBZ z3h-J3815=fLk3&R%V$YSNLdb1X5tb{+d)WSa=sZJUoxAyu8&WL+_*Tf15^#{6bOhI zyjMM6y(ZSeX+x|lh;{4YVf*EANyHBkjy73_kG7o7s*@=^2W9ydw5TJYNAO|^N%%>TyZ1I4v{f z{6pZMGOB%T?6apCC4z#b5i%5)c(V_G4-1Sh;8;S DzX(Im diff --git a/gcmpy/scripts/__pycache__/land.cpython-312.pyc b/gcmpy/scripts/__pycache__/land.cpython-312.pyc deleted file mode 100644 index ad7859f922b23a66917e2f8877231eeba6c35d49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2660 zcmb_eO>7fK6rTOFH~vW=KnOo6)S)TMpMg+7QAHIc#!!-tlz;?Q+m+*8!iM$Q>~4Z= zB@zb?i4+N{R!SsPDV!S0rPoT8dTKAdkd%mM1gD<3(d1BxQ{S8QuH#5hsp?36^WK~H z=FQIc&5VCfCSwFz_Vo3!U!#QliAK=GnzC^clzE~PowG=h%W)j)yu}xVoWK#DWQi`^ zC%X8Q_cL;0MN%TK(NH)V%iHc7HnI{IxaXQKII(MJs z1f2&d;`}*D7ePjJ31qYqQKD3|^0rtmy(|2m1uO0G8A+7HP0xhyBJPZ-l=GXlC7JbS+ZS9l(>V-qVgTh-*77V8Nz76rLl6}$rlaJa9kQUie^~@uV&gb z!Hkln<5t!z+qlatKX5QJJluPlHeb3ta#btjy~3@cVS992wr_Cwnp*cf;i%{u)=d}j zIQaIn^jP_(TTJWrXm@wob#LWwmr71Ln;9AzD-_eF?Rt63N{^a$8tifz{h=3kXNHlPA&;1=S=xb*`lz^#yXQ{-t)pXR2x@sJ%j zgWsOk`hN1|CxmnVwOEuI!k$=OB5h*mt8>rP6R_By&{}oi_BzfR4rzWRRK- z?4eDlP3El$!^OOV(45^E9AlHQ@M?<>AkNMl+abWc0s`>bv3o)Mre{W8>pc4Xg~u2E z=!nz;Cv zfbk9<&IWM8gMSvFn1@3>4iQ_M&fPvth;vBi;h=`_vBMZ%0lEldA%rXvzm+vz+I+w( z@2V21Rl%9+RU%;3tKbUiRWPz%B??wZjdxa&|KBP=lqQu5m-~9(Mmzg61DUHCDr5)G zI7l-ZsoesCI?zp3^O8^Dy=u%+2}}GySXJ zPi}v3efIjou9f5mEM{{G%)ml})U*FJ6>1 zc_;oN!@rGjGMI?y$g=uO4Vv^c{sXR|VlC+cVpF_p@cIij1!u zUagu&V;Vm36BghKdWM^z*$81|(9?;$$jnU?8Q*t_7*c@8JW`C{?H}M(DtiC` diff --git a/gcmpy/scripts/__pycache__/ocean.cpython-312.pyc b/gcmpy/scripts/__pycache__/ocean.cpython-312.pyc deleted file mode 100644 index 6819641f8ec7b2ae8663e83e9373d8736f908afc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12811 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 k0q!P%H2nAyh#qTcn*N?D`JO6cVF8}}l diff --git a/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc b/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc deleted file mode 100644 index d0296781603b8189d2669ee2b66829f743129532..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11377 zcmb_ieQ*;=cApt(^lj?{%h<-?0b`8tw~Ya_yRgQVSp&8K+bnhfA!`O(LYBnL7-Jpm z@drsDA-5*C7reJe;@u>5c5Uv?SNBJ_s;dfIZ7NiyDy6YaSQ+axS1<2ed zSb`KE=-Rbh7IG!VdJ=I*hCU$f+CI*to|0k(w|aF zo5N<-aElnWutrF&Q>4fATU5~NA!WxX7vXrn$eo(t1Th$mcyzLni(F-c0Z}%^{NfnS z(Sc|<$_JF@lr-Ho@#3F=zE5xj>f@o8FeSPwLnMbkj*vS9<0npYgx)5kv7Hyv@@D$31F@J;&a{=`& z(fgno(!u}5UqN!8xK3OrOCcA6f9}PSmv<8ce@K(bZYM3w5|{UbOwH?LLUeA+1e$e9 zomp0gdZ4!8BUR}s0{uMtUfCdU@EYQ8Q4x=N0TXPv;uEK0oNT({^GAe9j+bd677mK@ zlx$HLc+$zBfGRM|s}l{Qu}i{u0~;A>X=xCIG5_Ugly5ld?du;6j5h=$g6I#28%BbW z2B2e84MKnq#zdhZ#zzC3Ao#ANwM(dvP03cJOSlhlmom`xSv)H|R5%OCP2zK_d)j~J zt)#U=vR2F@5oB{gao zA(yI-J!z7vdTt+^zH+DMsclEfNHq1432V&@Xq(7CwZ$+_FtucQ0&l59n|G3x3A}P0 zmg+`|0A@$efW;bJy3%{Xcp~-aV

2Ag!Fd3klgXkHbBS7pL_q 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 diff --git a/gcmpy/scripts/__pycache__/utility.cpython-312.pyc b/gcmpy/scripts/__pycache__/utility.cpython-312.pyc deleted file mode 100644 index 4358525d4379b95fc1d91083613f168c2eccd8ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3860 zcmd5mZMCC0K7N^v)KY=x>MrgGfWwro@u8O5nYJCcPWYZvUAyAoGg za@n`bL}Uz91$?l96gj#=4M>L`EclWD0h0fai?%9IVd0_$ddf|*0tCpZGjB<1r4TBb zQy;M3dv9jm?96ax-ty~sTqH0y{t;Y!4y%9TrZqy%#r{@+kjF$NDrXScn>m?d`+yt> zkSU@D9uPJ74CHXgK}HJ!jc?OJI+1yJ!U3X@rEX8skI$MLEv$yeVGU9}e!jO}dg+HW zJn;&UpK%@!_K{;W^mWt_K@Fa`l?bDI?kve*OI(kt@ol7Ub!8FJh5nH2~KV&}( zl*f>PnB{Un<>a6mkV9%v=GBlKR(Uz1hGjvG$Wc|0MKvnNR8j7NC$7dG5V>3J0!-B7 z>28-VnubXmeE*$G7t3t=Ih!tc)1|jO;+QvG@TQ-Y8=?L?9)bX@-z*nf)}ggnX+e1Q z4S>hQ2K2^Kvj$sxoPFF@P5amlSl=gzKDn?@pt(eeIkL&+(;8#7o z=H_y@)0`WsDt5_2Q>E{(XBMjqRym_q?p?T$v8(K*B5?*7S1z07|6DK}xJZe12t-rVS zo|8EL^n{Zb`GWs4_Ib=nT-g$??1LEj|A-;Q=(eKBPtE3Xc`5*jMv)FNT+j{8iy@5x zsTBky9}WUiumF8Q`1sMsPv+OPGWpZ7^iU%&Zm1^p-`wO zWvx(f#X_NMsx<@GU4_E$YKqb1gm2By-kOGAc=CgZyeniUW`Bh%8UYR!uzj_0KZF4We96!DfaMja~8ao&E>%j3BHk2upHXsx?Ae1*?xX!1; zuBfdPwW_U~73+{L9#jP3+5ZdEWw*=HZkOH?8gOLT?UGVCY>rq?YJg#o6<;TQi1B%b zVTKWg0>da`t4(vn#`IxB6%VL&l8)tFac*+<#;x1=iJ4sE?69OrmS)$gl2>rjf=MO2 zq)Awr($wUPC^m%XyrnE^m!(Ehx?{31D2B9PD2u-V?$xLSV`Rk8E6ccIV;VQj;vQX* z^ongt+DcWUdReR3lB!d!Xq&VyHpZIAExoc>GZYH7E=hBmErCgMKH9-)v2i*ojg;V( zCC#X|-YCtL%#WlR8rm2Y#TyIo(htpLO_dbGtZ2i`siu##RM}Aie`$ zmrbg{AqYTO!Jm3qsv4SNX;RUw*h3of1+*%^7J*J zrvvm1OcaZClXHV*Yti2gPf$g-G>DK!3+?zce$rlAqn!lKgE9+0C|S%N7C#Z63tj)k zi7bd8x?J0a1EV<(IflJ~jl+)7K_I4s^fXLvl39n=w=HI#(l>zX_p{G)V?lvi(&s4D zRI4vF9X%p3gnCW^pr^^d3+Ei++(z+l!q6dyfq!VQUo8Zr$D~f!4drF#k@Sodp*||L zY9r}0qe;uaX$wQJN_K=UmK^zXgyJnt@k5iIKsbkhHqsFUJanW6SezJOqqI%}JRmPZ z0^jrEWB@<_*cUlI?v)LTYNYw?;PUKK!VT4xvf&2d+ro`BKQ!E+W*6N^vqQQ3y_#;Q zjaMyN%uH0PhF)YHz{>oxDNz8b8}n@%XHXW(oN6ja%}m@Zv^UT>3-j>V;zscRTc%@f zz_i?;RkvKBYA7~#8Lts|CTo=su@BI*;Gi2`1nWLhDgGaGBhW1I7Is5Rrd~M`p6`Wm z@5a7HCqNiW%(@P^8{|0dpXB9j^741#BzJX>0DL!eii__NfZb~(7GI6*00=v&vwu3X zo?c7;`KPPG!&e;g(oSk%eQ<4XJ+qd1`o?FMoT01RscXPH<&fSMZ+LBZW974mGx&?I z&TpqCfP2y*JuR+x@@;46%64iTczu6J9A;hI%xtGFA9X1_{gANXFjsJE#r2xDCucVLV(|-VH+&KCG From 7a2187b36cf04182be77453c4cb53d50a636c249 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Thu, 30 Jan 2025 04:17:25 -0500 Subject: [PATCH 16/37] revamped ocean script and other minor bug fixes --- HISTORY.AOGCM.rc.tmpl | 72 ++--- gcmpy/scripts/atmosphere.py | 24 +- gcmpy/scripts/gcm_setup.py | 94 +++--- gcmpy/scripts/ocean.py | 471 +++++++++++++++-------------- gcmpy/scripts/process_questions.py | 39 ++- gcmpy/yaml/atmospheric_model.yaml | 1 + gcmpy/yaml/ocean_model.yaml | 10 +- 7 files changed, 357 insertions(+), 354 deletions(-) mode change 100755 => 100644 gcmpy/scripts/ocean.py diff --git a/HISTORY.AOGCM.rc.tmpl b/HISTORY.AOGCM.rc.tmpl index 0a7a87ac..486f3572 100644 --- a/HISTORY.AOGCM.rc.tmpl +++ b/HISTORY.AOGCM.rc.tmpl @@ -39,7 +39,7 @@ COLLECTIONS: 'geosgcm_prog' 'geosgcm_rad' # 'geosgcm_int' 'geosgcm_seaice' -{{ {{ HIST_CICE4 }} }} 'geosgcm_icethm' + {{ HIST_CICE4 }} 'geosgcm_icethm' 'geosgcm_ocn2dT' # 'geosgcm_aoflux' # 'geosgcm_icecat' @@ -1451,41 +1451,41 @@ PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} # geosgcm_seaice.frequency: 240000, geosgcm_seaice.fields: 'UI' , 'SEAICE', 'VI' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'VEL' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'STRENGTH' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'SHEAR' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'DIVU' , 'SEAICE', - 'HICE' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'HICE0' , 'SEAICE', - 'HSNO' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'HSNO0' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'DRAFT' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'DRAFT0' , 'SEAICE', - 'AICE' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'DVIDTD' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'DAIDTD' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'DVIRDGDT' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'STRCORX' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'STRCORY' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'STRTLTX' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'STRTLTY' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'STRINTX' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'STRINTY' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'TAUXOCNB' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'TAUYOCNB' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'TAUXI' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'TAUYI' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'TAUXIB' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'TAUYIB' , 'SEAICE', - 'TAUXBOT' , 'SEAICE', - 'TAUYBOT' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'UOCN' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'VOCN' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'SSH' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'SLV' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'AREA' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'FROCEAN' , 'SEAICE', -{{ {{ HIST_CICE4 }} }} 'TMASK' , 'SEAICE', +{{ HIST_CICE4 }} 'VEL' , 'SEAICE', +{{ HIST_CICE4 }} 'STRENGTH' , 'SEAICE', +{{ HIST_CICE4 }} 'SHEAR' , 'SEAICE', +{{ HIST_CICE4 }} 'DIVU' , 'SEAICE', + 'HICE' , 'SEAICE', +{{ HIST_CICE4 }} 'HICE0' , 'SEAICE', + 'HSNO' , 'SEAICE', +{{ HIST_CICE4 }} 'HSNO0' , 'SEAICE', +{{ HIST_CICE4 }} 'DRAFT' , 'SEAICE', +{{ HIST_CICE4 }} 'DRAFT0' , 'SEAICE', + 'AICE' , 'SEAICE', +{{ HIST_CICE4 }} 'DVIDTD' , 'SEAICE', +{{ HIST_CICE4 }} 'DAIDTD' , 'SEAICE', +{{ HIST_CICE4 }} 'DVIRDGDT' , 'SEAICE', +{{ HIST_CICE4 }} 'STRCORX' , 'SEAICE', +{{ HIST_CICE4 }} 'STRCORY' , 'SEAICE', +{{ HIST_CICE4 }} 'STRTLTX' , 'SEAICE', +{{ HIST_CICE4 }} 'STRTLTY' , 'SEAICE', +{{ HIST_CICE4 }} 'STRINTX' , 'SEAICE', +{{ HIST_CICE4 }} 'STRINTY' , 'SEAICE', +{{ HIST_CICE4 }} 'TAUXOCNB' , 'SEAICE', +{{ HIST_CICE4 }} 'TAUYOCNB' , 'SEAICE', +{{ HIST_CICE4 }} 'TAUXI' , 'SEAICE', +{{ HIST_CICE4 }} 'TAUYI' , 'SEAICE', +{{ HIST_CICE4 }} 'TAUXIB' , 'SEAICE', +{{ HIST_CICE4 }} 'TAUYIB' , 'SEAICE', + 'TAUXBOT' , 'SEAICE', + 'TAUYBOT' , 'SEAICE', +{{ HIST_CICE4 }} 'UOCN' , 'SEAICE', +{{ HIST_CICE4 }} 'VOCN' , 'SEAICE', +{{ HIST_CICE4 }} 'SSH' , 'SEAICE', +{{ HIST_CICE4 }} 'SLV' , 'SEAICE', +{{ HIST_CICE4 }} 'AREA' , 'SEAICE', +{{ HIST_CICE4 }} 'FROCEAN' , 'SEAICE', +{{ HIST_CICE4 }} 'TMASK' , 'SEAICE', :: geosgcm_icethm.template: '%y4%m2%d2_%h2%n2z.nc4', diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py index c9a85472..9e015eb1 100755 --- a/gcmpy/scripts/atmosphere.py +++ b/gcmpy/scripts/atmosphere.py @@ -8,10 +8,10 @@ def __init__(self): self.force_gcm = "#" self.num_readers = 1 self.num_writers = 1 - self.dt = answerdict["heartbeat"].q_answer + self.dt = answerdict['heartbeat'].q_answer self.dt_solar = None self.dt_irrad = None - self.dt_ocean = None + self.DT_ocean = answerdict['heartbeat'].q_answer self.dt_long = None self.lm = int(answerdict['AM_vertical_res'].q_answer) self.im = int(answerdict['AM_horizontal_res'].q_answer[1:]) @@ -67,7 +67,6 @@ def hres(self, ocean_nx, ocean_ny): case "c12": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_ocean = self.dt_irrad self.dt_long = self.dt if answerdict["OM_name"].q_answer == "MOM6": self.nx = 1 @@ -84,7 +83,6 @@ def hres(self, ocean_nx, ocean_ny): case "c24": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_ocean = self.dt_irrad self.dt_long = self.dt self.nx = 4 self.ny = self.nx * 6 @@ -98,7 +96,6 @@ def hres(self, ocean_nx, ocean_ny): case "c48": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_ocean = self.dt_irrad self.dt_long = self.dt self.nx = 4 self.ny = self.nx * 6 @@ -119,15 +116,12 @@ def hres(self, ocean_nx, ocean_ny): case "MIT": self.nx = 10 self.ny = 36 - self.dt_ocean = self.dt case "MOM5","MOM6": self.nx = ocean_nx self.ny = ocean_ny - self.dt_ocean = self.dt case _: self.nx = 3 self.ny = self.nx * 6 - self.dt_ocean = self.dt_irrad self.job_sgmt = f"{32:08}" self.num_sgmt = 4 self.post_NDS = 8 @@ -140,11 +134,9 @@ def hres(self, ocean_nx, ocean_ny): if answerdict["OM_coupled"].q_answer == True: self.nx = ocean_nx self.ny = ocean_ny - self.dt_ocean = self.dt else: self.nx = 6 self.ny = self.nx * 6 - self.dt_ocean = self.dt_irrad self.job_sgmt = f"{16:08}" self.num_sgmt = 1 self.post_NDS = 8 @@ -154,7 +146,6 @@ def hres(self, ocean_nx, ocean_ny): case "c360": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_ocean = self.dt_irrad self.dt_long = self.dt self.nx = 12 self.ny = self.nx * 6 @@ -168,7 +159,6 @@ def hres(self, ocean_nx, ocean_ny): case "c720": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_ocean = self.dt_irrad self.dt_long = 450 self.nx = 24 self.ny = self.nx * 6 @@ -183,7 +173,6 @@ def hres(self, ocean_nx, ocean_ny): case "c1440": self.dt_solar = 1800 self.dt_irrad = 1800 - self.dt_ocean = self.dt_irrad self.dt_long = 300 self.nx = 48 self.ny = self.nx * 6 @@ -198,7 +187,6 @@ def hres(self, ocean_nx, ocean_ny): case "c2880": self.dt_solar = 1800 self.dt_irrad = 1800 - self.dt_ocean = self.dt_irrad self.dt_long = 300 self.nx = 96 self.ny = self.nx * 6 @@ -214,7 +202,6 @@ def hres(self, ocean_nx, ocean_ny): case "c5760": self.dt_solar = 900 self.dt_irrad = 900 - self.dt_ocean = self.dt_irrad self.dt_long = 300 self.nx = 192 self.ny = self.nx * 6 @@ -230,7 +217,6 @@ def hres(self, ocean_nx, ocean_ny): case "c270": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_ocean = self.dt_irrad self.dt_long = self.dt self.nx = 18 self.ny = self.nx * 6 @@ -247,7 +233,6 @@ def hres(self, ocean_nx, ocean_ny): case "c540": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_ocean = self.dt_irrad self.dt_long = self.dt self.nx = 36 self.ny = self.nx * 6 * 2 @@ -264,7 +249,6 @@ def hres(self, ocean_nx, ocean_ny): case "c1080": self.dt_solar = 900 self.dt_irrad = 900 - self.dt_ocean = self.dt_irrad self.dt_long = 300 self.nx = 72 self.ny = self.nx * 6 * 2 @@ -281,7 +265,6 @@ def hres(self, ocean_nx, ocean_ny): case "c1536": self.dt_solar = 900 self.dt_irrad = 900 - self.dt_ocean = self.dt_irrad self.dt_long = 300 self.nx = 96 self.ny = self.nx * 6 @@ -298,7 +281,6 @@ def hres(self, ocean_nx, ocean_ny): case "c2160": self.dt_solar = 900 self.dt_irrad = 900 - self.dt_ocean = self.dt_irrad self.dt_long = 300 self.nx = 192 self.ny = self.nx * 6 * 2 @@ -312,8 +294,6 @@ def hres(self, ocean_nx, ocean_ny): self.stretch_factor = 2.5 self.res = 'CF2160x6C-SG001' - if answerdict["OM_name"].q_answer == "MIT": - self.dt_ocean = self.dt def set_microphysics(self): match self.microphysics: diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index fdb87cdf..aaf7a414 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -4,7 +4,7 @@ from gocart import gocart from env import answerdict, linkx from utility import envdict, pathdict, color -import math, os, shutil, tempfile, yaml, re +import math, os, shutil, tempfile, yaml, re, glob from pathlib import Path from jinja2 import Environment, FileSystemLoader, Undefined @@ -49,7 +49,7 @@ def __init__(self): def config_models(self): self.ocean.config() - self.atmos.config(self.ocean.nx, self.ocean.ny) + self.atmos.config(self.ocean.NX, self.ocean.NY) self.land.config() self.gocart.config() self.file_list.append(self.ocean.history_template) @@ -57,7 +57,7 @@ def config_models(self): # setup some variables idk def set_some_stuff(self): - if self.atmos.hist_im >= self.ocean.im: + if self.atmos.hist_im >= self.ocean.IM: self.interpolate_sst = True else: self.interpolate_sst = False @@ -199,12 +199,12 @@ def set_stuff(self): self.M2_replay_ana_location = f"{self.boundary_path}/merra2/data" # defines location of SST Boundary Conditions - oceanres = f"{self.ocean.im}x{self.ocean.jm}" + oceanres = f"{self.ocean.IM}x{self.ocean.JM}" if oceanres == "1440x720": self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/SST/{oceanres}" else: self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/realtime/@SSTNAME/{oceanres}" - if self.ocean.gridtype_abrv == "LL": + if self.ocean.gridtyp == "LL": self.sst_dir = "/nobackupp2/estrobac/geos5/SSTDIR" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" @@ -249,12 +249,12 @@ def set_stuff(self): # define location of SST Boundary Conditions - oceanres = f"{self.ocean.im}x{self.ocean.jm}" + oceanres = f"{self.ocean.IM}x{self.ocean.JM}" if oceanres == "1440x720": self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/SST/{oceanres}" else: self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/realtime/@SSTNAME/{oceanres}" - if self.ocean.gridtype_abrv == "LL": + if self.ocean.gridtyp == "LL": self.sst_dir = "/discover/nobackup/estrobac/geos5/SSTDIR" self.chem_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput_nc3" @@ -296,7 +296,7 @@ def set_stuff(self): self.replay_ana_expID = "REPLAY_UNSUPPORTED" self.replay_ana_location = "REPLAY_UNSUPPORTED" self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" - self.sst_dir = f"{self.boundary_path}/@SSTNAME/{self.ocean.im}x{self.ocean.jm}" + self.sst_dir = f"{self.boundary_path}/@SSTNAME/{self.ocean.IM}x{self.ocean.JM}" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" self.work_dir = os.environ.get('HOME') self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" @@ -331,7 +331,7 @@ def set_stuff(self): self.replay_ana_expID = "REPLAY_UNSUPPORTED" self.replay_ana_location = "REPLAY_UNSUPPORTED" self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" - self.sst_dir = f"{self.boundary_path}/@SSTNAME/{self.ocean.im}x{self.ocean.jm}" + self.sst_dir = f"{self.boundary_path}/@SSTNAME/{self.ocean.IM}x{self.ocean.JM}" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" self.work_dir = os.environ.get('HOME') self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" @@ -429,26 +429,33 @@ def copy_files_into_exp(self): self.copy_helper(f"{pathdict['install']}/post/post.rc", f"{self.exp_dir}/post.rc", "post.rc") # These files will be added if user chose to run coupled, regardless of ocean model selected. - if self.ocean.coupled == True: - self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/plotcon.j", f"{self.exp_dir}/plotcon.j", "plotocn.j") - self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/confon.py", f"{self.exp_dir}/__init__.py", "confocn.py") - self.file_list.extend(['input.nml', 'diag_table', 'plotocn.j', '__init__.py']) + if self.ocean.running_ocean == True and self.ocean.model != 'MIT': + self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/plotocn.j", f"{self.exp_dir}/plotocn.j", "plotocn.j") + self.copy_helper(f"{pathdict['install']}/coupled_diagnostics/g5lib/confocn.py", f"{self.exp_dir}/__init__.py", "confocn.py") + self.file_list.extend(['input.nml', 'diag_table','plotocn.j', '__init__.py']) if self.ocean.model == 'MOM5': - self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.im}x{self.ocean.jm}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") - self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.im}x{self.ocean.jm}/diag_table", f"{self.exp_dir}/diag_table.nml", "diag_table") - self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.im}x{self.ocean.jm}/field_table", f"{self.exp_dir}/field_table.nml", "field_table") self.file_list.append('field_table') + self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.IM}x{self.ocean.JM}/INPUT/input.nml", f"{self.exp_dir}/input.nml", "input.nml") + MOM5_path = os.path.join(pathdict['etc'], 'MOM5', 'geos5', f"{self.ocean.IM}x{self.ocean.JM}", 'INPUT', '*table') + files = glob.glob(MOM5_path) + for file in files: + file_name = os.path.basename(file) + self.copy_helper(file, f"{self.exp_dir}/{file_name}", file_name) elif self.ocean.model == 'MOM6': - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/MOM_input", f"{self.exp_dir}/MOM_input", "MOM_input") - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/MOM_override", f"{self.exp_dir}/MOM_override", "MOM_override") - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/diag_table", f"{self.exp_dir}/diag_table", "diag_table") - self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.im}x{self.ocean.jm}/field_table", f"{self.exp_dir}/field_table", "field_table") self.file_list.extend(['MOM_input', 'MOM_override', 'data_table']) + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/MOM_input", f"{self.exp_dir}/MOM_input", "MOM_input") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/MOM_override", f"{self.exp_dir}/MOM_override", "MOM_override") + self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") + MOM6_path = os.path.join(pathdict['etc'], 'MOM6', 'mom6_app', f"{self.ocean.IM}x{self.ocean.JM}", '*table') + files = glob.glob(MOM6_path) + for file in files: + file_name = os.path.basename(file) + self.copy_helper(file, f"{self.exp_dir}/{file_name}", file_name) + if self.ocean.seaice_model == 'CICE6': - self.copy_helper(f"{pathdict['etc']}/CICE6/cice6_app/{self.ocean.im}x{self.ocean.jm}/ice_in", f"{self.exp_dir}/ice_in") + self.copy_helper(f"{pathdict['etc']}/CICE6/cice6_app/{self.ocean.IM}x{self.ocean.JM}/ice_in", f"{self.exp_dir}/ice_in") self.file_list.append('ice_in') print(f"{color.GREEN}Done!{color.RESET}\n") @@ -566,14 +573,16 @@ def config_heartbeat(self): # With MOM5 we need to change dt lines in input.nml to # use $OCEAN_DT instead. NOTE: This regex assumes integer followed by comma if self.ocean.model == 'MOM5': + with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'r') as file: file_content = file.read() - - file_content = re.sub(r'(dt_cpld\s*=\s*)[0-9]+(\,)', r'\1'+self.atmos.DT_ocean+r'\2', file_content) - file_content = re.sub(r'(dt_atmos\s*=\s*)[0-9]+(\,)', r'\1'+self.atmos.DT_ocean+r'\2', file_content) - - with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'r') as file: + + file_content = re.sub(r'dt_cpld\s*=\s*.*(,)', rf"dt_cpld = {self.atmos.DT_ocean}\1", file_content) + file_content = re.sub(r'dt_atmos\s*=\s*.*(,)', rf"dt_atmos = {self.atmos.DT_ocean}\1", file_content) + + with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'w') as file: file.write(file_content) + # We also must change the MOM_override file to # have consistent DTs with the AGCM. So we use OCEAN_DT @@ -583,10 +592,10 @@ def config_heartbeat(self): with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'r') as file: file_content = file.read() - file_content = re.sub(r'(DT\s*=\s*).*(\,)', r'\1'+self.atmos.DT_ocean+r'\2', file_content) - file_content = re.sub(r'(DT_THERM\s*=\s*).*(\,)', r'\1'+self.atmos.DT_ocean+r'\2', file_content) + file_content = re.sub(r'DT\s*=\s*.*(,)', rf"DT = {self.atmos.DT_ocean}\1", file_content) + file_content = re.sub(r'DT_THERM\s*=\s*.*(,)', rf"DT_THERM = {self.atmos.DT_ocean}\1", file_content) - with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'r') as file: + with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'w') as file: file.write(file_content) @@ -669,9 +678,9 @@ def template(self): 'BASE_BIND_PATH': '', 'BOUNDARY_DIR': self.boundary_path, 'CHECKPOINT_TYPE': 'default', - 'OGCM_NX': self.ocean.nx, - 'OGCM_NY': self.ocean.ny, - 'OGCM_NPROCS': self.ocean.n_procs, + 'OGCM_NX': self.ocean.NX, + 'OGCM_NY': self.ocean.NY, + 'OGCM_NPROCS': self.ocean.nprocs, 'OBSERVER_FRQ': 0, 'DASTUNING': '#', 'COUPLED': self.ocean.coupled, @@ -679,8 +688,9 @@ def template(self): 'MOM5': self.ocean.MOM5, 'MOM6': self.ocean.MOM6, 'OCNMODEL': self.ocean.model, - 'CICE4': '#DELETE', - 'CICE6': '#DELETE', + 'CICE4': self.ocean.CICE4, + 'CICE6': self.ocean.CICE6, + 'HIST_CICE4': self.ocean.hist_CICE4, 'MIT': self.ocean.MIT, 'DATAOCEAN': self.ocean.data, 'OPS_SPECIES': self.gocart.ops_species, @@ -688,7 +698,7 @@ def template(self): 'MERRA2OX_SPECIES': self.gocart.MERRA2OX_species, 'HIST_GOCART': self.gocart.gocart_hist, 'LSM_PARMS': self.land.parameters, - 'OCEAN_NAME': self.ocean.model, + 'OCEAN_NAME': self.ocean.name, 'OCEAN_PRELOAD': self.ocean.preload, 'ana4replay.eta.%y4%m2%d2_%h2z.nc4': '/discover/nobackup/projects/gmao/merra2/data/ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4?g', 'REPLAY_ANA_EXPID': self.replay_ana_expID, @@ -714,7 +724,7 @@ def template(self): 'DT': self.atmos.dt, 'SOLAR_DT': self.atmos.dt_solar, 'IRRAD_DT': self.atmos.dt_irrad, - 'OCEAN_DT': self.atmos.dt_ocean, + 'OCEAN_DT': self.atmos.DT_ocean, 'LONG_DT': self.atmos.dt_long, 'NX': self.atmos.nx, 'NY': self.atmos.ny, @@ -735,11 +745,11 @@ def template(self): 'AGCM_IM': self.atmos.im, 'AGCM_JM': self.atmos.jm, 'AGCM_LM': self.atmos.lm, - 'OGCM_IM': self.ocean.im, - 'OGCM_JM': self.ocean.jm, - 'OGCM_LM': self.ocean.lm, - 'OGCM_NF': self.ocean.nf, - 'OGCM_GRID_TYPE': self.ocean.gridtype, + 'OGCM_IM': self.ocean.IM, + 'OGCM_JM': self.ocean.JM, + 'OGCM_LM': self.ocean.LM, + 'OGCM_NF': self.ocean.NF, + 'OGCM_GRID_TYPE': self.ocean.grid_type, 'BEG_DATE': self.begin_date, 'END_DATE': self.end_date, 'JOB_SGMT': self.job_sgmt, diff --git a/gcmpy/scripts/ocean.py b/gcmpy/scripts/ocean.py old mode 100755 new mode 100644 index 15d2eb10..2d7a3720 --- a/gcmpy/scripts/ocean.py +++ b/gcmpy/scripts/ocean.py @@ -1,255 +1,262 @@ -from env import answerdict +from env import answerdict from utility import color from datetime import date class ocean: - def __init__(self): - self.model = answerdict['OM_name'].q_answer - self.coupled = answerdict['OM_coupled'].q_answer - self.seaice_model = answerdict['OM_seaice_model'].q_answer - self.gridtype = '' - self.gridtype_abrv = '' - self.gridname = '' - self.data = '' - self.preload = '' - self.history_template = answerdict['history_template'].q_answer - self.im = None - self.jm = None - self.lm = answerdict['OM_vertical_res'].q_answer - self.imo = None - self.jmo = None - self.res = '' - self.tag = 'Reynolds' - self.sst_name = '' - self.sst_file = '' - self.ice_file = '' - self.kpar_file = '' - self.ostia = '' - self.out = '' - self.nx = None - self.ny = None - self.nf = None - self.latlon = '' - self.cube = '' - self.n_procs = None - self.MOM5 = '' - self.MOM6 = '' - self.MIT = '' - self.mpt_shepherd = '' - - - # for debugging purposes - def print_vars(self): - all_vars = vars(self) - for var_name, var_value in all_vars.items(): - print(f"{color.CYAN}{var_name}: {var_value}{color.RESET}") - - - def set_IMO(self): - self.imo = "%04d" % self.im - - def set_JMO(self): - self.jmo = "%04d" % self.jm - - def set_res(self): - hres = answerdict["OM_horizontal_res"].q_answer - if self.coupled == False and hres == "CS": - self.res = f"{self.gridtype_abrv}{self.imo}x6C" - elif self.coupled == False: - self.res = f"{self.gridtype_abrv}{self.imo}xPE{self.jmo}" - elif self.coupled == True: - self.res = f"{self.gridtype_abrv}{self.imo}x{self.gridtype_abrv}{self.jmo}" - # Testing at NAS shows that coupled runs *require* MPI_SHEPHERD=true - # to run. We believe this is due to LD_PRELOAD. For now we only set - # this for coupled runs. - self.mpt_shepherd = "setenv MPI_SHEPHERD true" - - def set_gridname(self): - if self.gridtype_abrv == "CF": - self.gridname = f"OC{self.im}x{self.jm}-{self.gridtype_abrv}" - elif self.model == "MIT": - self.gridname = f"{self.gridtype_abrv}{self.im}x{self.jm}-{self.gridtype_abrv}" - else: - self.gridname = f"PE{self.im}x{self.jm}-{self.gridtype_abrv}" + def __init__(ocean): + ocean.running_ocean = answerdict['OM_coupled'].q_answer + ocean.model = answerdict['OM_name'].q_answer + ocean.seaice_model = answerdict['OM_seaice_model'].q_answer + ocean.history_template = answerdict['history_template'].q_answer + ocean.LM = answerdict['OM_vertical_res'].q_answer + ocean.data_atmos = answerdict['OM_data_atmos'].q_answer + ocean.name = '' + ocean.preload = '' + ocean.seaice_name = '' + ocean.seaice_preload = '' + ocean.gridtyp = '' + - def set_kpar_file(self): - self.kpar_file = f"SEAWIFS_KPAR_mon_clim.{self.im}x{self.jm}" + def config(ocean): + if ocean.running_ocean == True: + ocean.set_coupled() + ocean.set_seaice() + ocean.set_preload() + ocean.set_data_atmosphere() + else: + ocean.set_uncoupled() - def coupled_hres(self): - if self.model == 'MOM5': - self.model = 'MOM' - self.preload = "env LD_PRELOAD=$GEOSDIR/lib/libmom.dylib" - mom5_warning = ( - ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" + + def set_coupled(ocean): + # NOTE: We use a CMake variable here because the shared library + # suffix is different on Linux and macOS. This is set by configure_file() + if ocean.model == 'MOM5': + ocean.name = 'MOM' + ocean.gridtyp = 'M5TP' + ocean.grid_type = 'Tripolar' + ocean.preload = 'env @PRELOAD_COMMAND=$GEOSDIR/lib/libmom@CMAKE_SHARED_LIBRARY_SUFFIX@' + ocean.MOM5 = '' + ocean.MOM6 = '#DELETE' + ocean.MIT = '#DELETE' + MOM5_warning = ( + "######################################################\n" "You have chosen to set up a coupled model experiment with MOM5.\n" "Be aware that such a set up is _known_ to have problems. See following for more details:\n" "https://github.com/GEOS-ESM/MOM5/issues/19\n" "If your intent is to help _fix_ above issue, your help is much appreciated. Thank you and good luck!\n" "Otherwise, until this above issue is _fixed_ you are on your own with above choice.\n" - "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" + "######################################################" ) - print(color.GREEN + mom5_warning + color.RESET) - elif self.model == 'MOM6': - self.preload = "env LD_PRELOAD=$GEOSDIR/lib/libmom6.dylib" - elif self.model == 'MIT': - self.gridtype_abrv = "llc" - - if self.model == 'MIT' and answerdict["OM_MIT_horizontal_res"].q_answer == 'cs32': - self.jm = 32 - self.im = self.jm * 6 - self.gridtype_abrv = "CM" - elif self.model == 'MIT' and answerdict["OM_MIT_horizontal_res"].q_answer == 'llc90': - self.gridtype_abrv = "LL" - if answerdict["AM_horizontal_res"].q_answer == "c48": - self.jm = 30 - self.im = self.jm * 96 - else: - self.jm = 15 - self.im = self.jm * 360 - elif self.model == 'MIT' and answerdict["OM_MIT_horizontal_res"].q_answer == 'llc1080': - self.gridtype_abrv = "LL" - self.jm = 60 - self.im = self.jm * 2880 - elif self.model == 'MIT' and answerdict["OM_MIT_horizontal_res"].q_answer == 'llc2160': - self.gridtype_abrv = "LL" - self.jm = 72 - self.im = self.jm * 7776 - elif self.model == "MOM" or self.model == "MOM6": - temp = answerdict["OM_MOM_horizontal_res"].q_answer.split() - self.im = int(temp[0]) - self.jm = int(temp[1]) - self.gridtype = "TM" - - - def coupled_vres(self): - if answerdict["AM_horizontal_res"].q_answer == "c12": - self.nx = 3 - self.ny = 2 - else: - self.nx = 36 - self.ny = 10 + print(color.GREEN + MOM5_warning + color.RESET) + ocean.NX = 36 + ocean.NY = 10 + resolution = answerdict['OM_MOM_horizontal_res'].q_answer.split() + ocean.IM = int(resolution[0]) + ocean.JM = int(resolution[1]) + elif ocean.model == 'MOM6': + ocean.name = 'MOM6' + ocean.gridtyp = 'M6TP' + ocean.grid_type = 'Tripolar' + ocean.preload = 'env @PRELOAD_COMMAND=\\$GEOSDIR/lib/libmom6@CMAKE_SHARED_LIBRARY_SUFFIX@' + ocean.MOM5 = '#DELETE' + ocean.MOM6 = '' + ocean.MIT = '#DELETE' + ocean.set_MOM6_resolution() + elif ocean.model == 'MIT': + ocean.name = 'MIT' + ocean.grid_type = 'llc' + ocean.gridtyp = 'MITLLC' + ocean.MOM5 = '#DELETE' + ocean.MOM6 = '#DELETE' + ocean.MIT = '' + ocean.JM = 15 + ocean.IM = ocean.jm * 360 + ocean.NX = 360 + ocean.NY = 1 + #ocean.gridspec = 'mit.ascii' <-- dead code - self.n_procs = self.nx*self.ny - - if self.model == "MOM" or self.model == "MOM6": - self.gridtype = "Tripolar" - elif self.model == "MIT": - if self.gridtype_abrv == "CM": - self.nx = 6 - self.ny = 1 - elif answerdict["AM_horizontal_res"].q_answer == 'c48': - self.nx = 96 - self.ny = 1 - elif answerdict["AM_horizontal_res"].q_answer == 'c90': - self.nx = 360 - self.ny = 1 - elif answerdict["AM_horizontal_res"].q_answer == 'c720': - self.nx = 2880 - self.ny = 1 - elif answerdict["AM_horizontal_res"].q_answer == 'c1440': - self.nx = 7776 - self.ny = 1 - - - def uncoupled_hres(self): + ocean.coupled = '' + IMO = '%04d' % ocean.IM + JMO = '%04d' % ocean.JM + ocean.res = f"{ocean.gridtyp}{IMO}x{JMO}" + ocean.tag = 'Reynolds' + ocean.sst_name = '#DELETE' + ocean.sst_file = '#DELETE' + ocean.ice_file = '#DELETE' + ocean.kpar_file = f"SEAWIFS_KPAR_mon_clim.{ocean.IM}x{ocean.JM}" + ocean.ostia = '#DELETE' + ocean.out = '#DELETE' + ocean.latlon = '' + ocean.cube = '#DELETE' + ocean.data = '#DELETE' + ocean.mpt_shepherd = 'setenv MPI_SHEPHERD true' + ocean.NF = 1 + + ocean.nprocs = ocean.NX * ocean.NY # This might be bugged(!) + ocean.set_gridname() + + + def set_uncoupled(ocean): + #rename this to 'uncoupled_hres' + hr_code = answerdict['OM_horizontal_res'].q_answer todays_date = date.today() - match answerdict["OM_horizontal_res"].q_answer: - case "o1": - temp_res = "360 180" - self.im, self.jm = map(int, temp_res.split()) - self.gridtype = "LatLon" - self.nf = 1 - self.tag = "Reynolds" - self.sst_name = "SST" - self.out = "360x180" - self.sst_file = f"dataoceanfile_MERRA_sst_1971-current.{self.im}x{self.jm}.LE" - self.ice_file = f"dataoceanfile_MERRA_fraci_1971-current.{self.im}x{self.jm}.LE" - self.set_kpar_file() - self.gridtype_abrv = "DE" - self.latlon = "" - self.cube = "#DELETE" - self.ostia = "#DELETE" - self.data = "" - case "o2": - temp_res = "1440 720" - self.im, self.jm = map(int, temp_res.split()) - self.gridtype = "LatLon" - self.nf = 1 - self.tag = "MERRA-2" - self.sst_name = "MERRA2" - self.out = "1440x720" - self.sst_file = f"dataoceanfile_MERRA2_SST.{self.im}x{self.jm}.{todays_date.year}.data" - self.ice_file = f"dataoceanfile_MERRA2_ICE.{self.im}x{self.jm}.{todays_date.year}.data" - self.set_kpar_file() - self.gridtype_abrv = "DE" - self.latlon = "" - self.cube = "#DELETE" - self.ostia = "" - self.data = "" - case "o3": - temp_res = "2880 1440" - self.im, self.jm = map(int, temp_res.split()) - self.gridtype = "LatLon" - self.nf = 1 - self.tag = "Ostia" - self.sst_name = "OSTIA_REYNOLDS" - self.out = "2880x1440" - self.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{OGCM_IM}x{OGCM_JM}.{todays_date.year}.data" - self.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{OGCM_IM}x{OGCM_JM}.{todays_date.year}.data" - self.set_kpar_file() - self.gridtype_abrv = "DE" - self.latlon = "" - self.cube = "#DELETE" - self.ostia = "" - self.data = "" - case "CS": - if int(answerdict["AM_horizontal_res"].q_answer[1:]) >= 90: - self.im = int(answerdict["AM_horizontal_res"].q_answer[1:]) - self.jm = self.im * 6 - self.gridtype = "Cubed-Sphere" - self.nf = 6 - self.tag = "Ostia" - self.sst_name = "OSTIA_REYNOLDS" - self.out = "CS" - self.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{self.im}x{self.jm}.{todays_date.year}.data" - self.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{self.im}x{self.jm}.{todays_date.year}.data" - self.set_kpar_file() - self.gridtype_abrv = "CF" - self.latlon = "#DELETE" - self.cube = "" - self.ostia = "" - self.data = "#DELETE" - else: - print(color.RED + "ERROR: Cubed-Sphere Ocean with " + color.BLUE + \ - answerdict["AM_horizontal_res"].q_answer + color.RED + \ - " is not currently supported. Must be c90 or higher!") - exit(1) - - self.set_IMO() - self.set_JMO() - self.set_res() - self.lm = 34 - self.model = f"Data Ocean ({answerdict['AM_horizontal_res'].q_answer})" - self.coupled = "#DELETE" - self.MOM5 = "#DELETE" - self.MOM6 = "#DELETE" - self.MIT = "#DELETE" - - - - # ocean model driver - def config(self): - if answerdict["OM_coupled"].q_answer == True: - self.coupled_hres() - self.coupled_vres() + + if hr_code == 'o1': + ocean.IM = 360 + ocean.JM = 180 + ocean.grid_type = 'LatLon' + ocean.NF = 1 + ocean.tag = 'Reynolds' + ocean.sst_name = 'SST' + ocean.out = '360x180' + ocean.sst_file = f"dataoceanfile_MERRA_sst_1971-current.{ocean.IM}x{ocean.JM}.LE" + ocean.ice_file = f"dataoceanfile_MERRA_fraci_1971-current.{ocean.IM}x{ocean.JM}.LE" + ocean.kpar_file = f"SEAWIFS_KPAR_mon_clim.{ocean.IM}x{ocean.JM}" + ocean.gridtyp = 'DE' + ocean.latlon = '' + ocean.cube = '#DELETE' + ocean.ostia = '#DELETE' + ocean.data = '' + elif hr_code == 'o2': + ocean.IM = 1440 + ocean.JM = 720 + ocean.grid_type = 'LatLon' + ocean.NF = 1 + ocean.tag = 'MERRA-2' + ocean.sst_name = 'MERRA2' + ocean.out = '1440x720' + ocean.sst_file = f"dataoceanfile_MERRA2_SST.{ocean.IM}x{ocean.JM}.\\{todays_date.year}.data" + ocean.ice_file = f"dataoceanfile_MERRA2_ICE.{ocean.IM}x{ocean.JM}.\\{todays_date.year}.data" + ocean.kpar_file = f"SEAWIFS_KPAR_mon_clim.{ocean.IM}x{ocean.JM}" + ocean.gridtyp = 'DE' + ocean.latlon = '' + ocean.cube = '#DELETE' + ocean.ostia = '' + ocean.data = '' + elif hr_code == 'o3': + ocean.IM = 2880 + ocean.JM = 1440 + ocean.grid_type = 'LatLon' + ocean.NF = 1 + ocean.tag = 'Ostia' + ocean.sst_name = 'OSTIA_REYNOLDS' + ocean.out = '2880x1440' + ocean.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{ocean.IM}x{ocean.JM}.\\{todays_date.year}.data" + ocean.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{ocean.IM}x{ocean.JM}.\\{todays_date.year}.data" + ocean.kpar_file = f"SEAWIFS_KPAR_mon_clim.{ocean.IM}x{ocean.JM}" + ocean.gridtyp = 'DE' + ocean.latlon = '' + ocean.cube = '#DELETE' + ocean.ostia = '' + ocean.data = '' + elif hr_code == 'cs': + # need to add input validation for this case + ocean.IM = int(answerdict['AM_horizontal_res'].q_answer[1:]) + ocean.JM = ocean.IM * 6 + ocean.grid_type = 'Cubed-Sphere' + ocean.NF = 6 + ocean.tag = 'Ostia' + ocean.sst_name = 'OSTIA_REYNOLDS' + ocean.out = 'CS' + ocean.sst_file = f"dataoceanfile_OSTIA_REYNOLDS_SST.{ocean.IM}x{ocean.JM}.\\{todays_date.year}.data" + ocean.ice_file = f"dataoceanfile_OSTIA_REYNOLDS_ICE.{ocean.IM}x{ocean.JM}.\\{todays_date.year}.data" + ocean.kpar_file = f"SEAWIFS_KPAR_mon_clim.{ocean.IM}x{ocean.JM}" + ocean.gridtyp = 'CF' + ocean.latlon = '#DELETE' + ocean.cube = '' + ocean.ostia = '' + ocean.data = '#DELETE' + + IMO = '%04d' % ocean.IM + JMO = '%04d' % ocean.JM + if hr_code == 'cs': + ocean.res = f"CF{IMO}x6C" else: - self.uncoupled_hres() + ocean.res = f"DE{IMO}xPE{JMO}" + #ocean.data = #THIS IS WILL OVERWRITE THE BLOCK ABOVE + ocean.name = '' + ocean.preload = '' + ocean.coupled = '#DELETE' + ocean.MOM5 = '#DELETE' + ocean.MOM6 = '#DELETE' + ocean.MIT = '#DELETE' + ocean.CICE4 = '#DELETE' + ocean.CICE6 = '#DELETE' + ocean.hist_CICE4 = '#DELETE' + ocean.model = f"Data Ocean ({hr_code})" + ocean.NX = '' + ocean.NY = '' + ocean.nprocs = '' + ocean.mpt_shepherd = '' + ocean.set_gridname() + + + + + def set_MOM6_resolution(ocean): + # For MOM6 we currently have only 3 allowed ocean resolutions based on the + # atmospheric resolution. The allowed are: + # + # Atm Res Atm NXxNY Atm IMxJM Ocean NXxNY Ocean IMxJM Ocean LM + # ------- --------- --------- ----------- ----------- -------- + # c12 1x6 12x72 3x2 72x36 50 + # c90 5x36 90x540 90x2 540x458 50 + # c180 30x36 180x1080 36x30 1440x1080 75 + # + # See https://github.com/GEOS-ESM/GEOSgcm/wiki/Coupled-model-configurations-(GEOS-MOM6) - self.set_gridname() + atmos_res = answerdict['AM_horizontal_res'].q_answer + if atmos_res == 'c12': + ocean.NX = 3 + ocean.NY = 2 + ocean.IM = 72 + ocean.JM = 36 + ocean.LM = 50 + elif atmos_res == 'c90': + ocean.NX = 90 + ocean.NY = 2 + ocean.IM = 540 + ocean.JM = 458 + ocean.LM = 50 + elif atmos_res == 'c180': + ocean.NX = 36 + ocean.NY = 30 + ocean.IM = 1440 + ocean.JM = 1080 + ocean.LM = 75 + def set_preload(ocean): + ocean.preload = f"{ocean.preload}:{ocean.seaice_preload}" + def set_seaice(ocean): + if ocean.seaice_model == 'CICE4': + ocean.seaice_preload = '$GEOSDIR/lib/libCICE4@CMAKE_SHARED_LIBRARY_SUFFIX@' + ocean.CICE4 = '' + ocean.CICE6 = '#DELETE' + ocean.hist_CICE4 = '' + elif ocean.seaice_model == 'CICE6': + ocean.seaice_preload = '$GEOSDIR/lib/libcice6@CMAKE_SHARED_LIBRARY_SUFFIX@' + ocean.CICE4 = '#DELETE' + ocean.CICE6 = '' + ocean.hist_CICE4 = '#DELETE' + def set_data_atmosphere(ocean): + if ocean.data_atmos == True: + ocean.modelatm = '#DELETE' + ocean.use_data_ATM4OCN = '.TRUE.' + else: + ocean.modelatm = '' + ocean.use_data_ATM4OCN = '.FALSE.' + + def set_gridname(ocean): + if ocean.gridtyp == 'CF': + ocean.gridname = f"OC{ocean.IM}x{ocean.JM}-{ocean.gridtyp}" + elif ocean.model == 'MIT': + ocean.gridname = f"{ocean.gridtyp}{ocean.IM}x{ocean.JM}-{ocean.gridtyp}" + else: + ocean.gridname = f"PE{ocean.IM}x{ocean.JM}-{ocean.gridtyp}" + diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index 06681057..637a0931 100755 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -37,8 +37,6 @@ def processor_choices(answerdict, i): @staticmethod def MIT_hres_choices(answerdict, i): - # This is a dumb case, but these are the only known ocean resolutions that work - # with these atmosphere resolutions, so we will only give the users these choices if i == "OM_MIT_horizontal_res": if answerdict["AM_horizontal_res"].q_answer == "c720": answerdict[i].q_choices = ["llc1080 (1/12-deg, Lat-Lon-Cube)"] @@ -60,6 +58,12 @@ def OM_hres_valid(answerdict, i): print(color.RED + "please enter exactly 2 numbers separated by a space! (int int)\n") answerdict[i].load_question(answerdict) + @staticmethod + def seaice_choices(answerdict, i): + if i == 'OM_seaice_model' and answerdict['OM_name'] == 'MOM6': + answerdict[i].q_choices = ['CICE6'] + + @staticmethod def heartbeat_default(answerdict, i): if i == "heartbeat": @@ -111,25 +115,17 @@ def heartbeat_valid(answerdict, i): @staticmethod def history_template_default(answerdict, i): if i == "history_template": - - match answerdict["OM_name"]: - case "MOM5": - answerdict[i].q_default = "HISTORY.AOGCM-MOM5.rc.tmpl" - case "MOM6": - answerdict[i].q_default = "HISTORY.AOGCM.rc.tmpl" - case "MIT": - answerdict[i].q_default = "HISTORY.AOGCM_MITgcm.rc.tmpl" - case _: - answerdict[i].q_default = "HISTORY.AGCM.rc.tmpl" - - ''' - @staticmethod - def history_template_valid(answerdict, i): - if i == "history_template": - while not os.path.exists(answerdict[i].q_answer): - print(f"Error: Could not find {color.RED}{answerdict[i]}{color.RESET}") - answerdict[i].load_question(answerdict) - ''' + + if answerdict['OM_name'].q_answer == 'MOM5': + answerdict[i].q_default = 'HISTORY.AOGCM-MOM5.rc.tmpl' + elif answerdict['OM_name'].q_answer == "MOM6": + answerdict[i].q_default = 'HISTORY.AOGCM.rc.tmpl' + elif answerdict['OM_name'].q_answer == 'MIT': + answerdict[i].q_default = 'HISTORY.AOGCM_MITgcm.rc.tmpl' + elif answerdict['OM_data_atmos'].q_answer == True: + answerdict[i].q_default == 'HISTORY.DATAATM.rc.tmpl' + else: + answerdict[i].q_default = 'HISTORY.AGCM.rc.tmpl' @staticmethod def exp_dir_default(answerdict, i): @@ -209,6 +205,7 @@ def process(): handle.processor_choices(answerdict,i) handle.MIT_hres_choices(answerdict, i) handle.MOM_hres_default(answerdict, i) + handle.seaice_choices(answerdict, i) handle.heartbeat_default(answerdict, i) handle.history_template_default(answerdict, i) handle.exp_dir_default(answerdict, i) diff --git a/gcmpy/yaml/atmospheric_model.yaml b/gcmpy/yaml/atmospheric_model.yaml index 719d1bd4..6cce1db2 100755 --- a/gcmpy/yaml/atmospheric_model.yaml +++ b/gcmpy/yaml/atmospheric_model.yaml @@ -4,6 +4,7 @@ AM_horizontal_res: choices: ['c12 -- 8 deg (750.0 km)', 'c24 -- 4 deg (375.0 km)', 'c48 -- 2 deg (187.5 km)', 'c90 -- 1 deg (100.0 km)', 'c180 -- 1/2 deg ( 50.0 km)', 'c360 -- 1/4 deg ( 25.0 km)', 'c720 -- 1/8 deg ( 12.5 km)', 'c1440 - 1/16 deg ( 6.25 km)', 'c2880 - 1/32 deg ( 3.125 km)', 'c5760 - 1/64 deg ( 1.5625 km)','c270 -- (16.0 -100 km)', 'c540 -- ( 8.0 - 50 km)', 'c1080 - ( 4.0 - 25 km)', 'c1536 - ( 2.0 - 20 km)', 'c2160 - ( 2.0 - 12 km)'] default_answer: '' follows_up: '' + answer: 'c12' AM_vertical_res: type: 'select' diff --git a/gcmpy/yaml/ocean_model.yaml b/gcmpy/yaml/ocean_model.yaml index 91c69f32..480845b5 100755 --- a/gcmpy/yaml/ocean_model.yaml +++ b/gcmpy/yaml/ocean_model.yaml @@ -70,5 +70,13 @@ OM_seaice_model: choices: ['CICE4', 'CICE6'] default_answer: '' follows_up: - - ['OM_coupled', ['True']] + - ['OM_coupled', [True]] + +OM_data_atmos: + type: 'confirm' + prompt: 'Do you wish to run Data Atmosphere?' + choices: '' + default_answer: False + follows_up: + - ['OM_coupled', [True]] # ---------------------------------------------------------------------------------------------- From 62bcafa03c71dc0f046246e0ac4261f07b7e33de Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 9 Apr 2025 12:21:16 -0400 Subject: [PATCH 17/37] gcm_v12 update --- .gitignore | 4 +- AGCM.rc.tmpl | 386 +++++++----- fvcore_layout.rc | 35 +- gcm_forecast.tmpl | 124 +++- gcm_run.j | 215 ++++--- gcm_setup | 578 ++++++++++-------- .../__pycache__/atmosphere.cpython-311.pyc | Bin 0 -> 12957 bytes .../__pycache__/atmosphere.cpython-312.pyc | Bin 0 -> 11934 bytes gcmpy/scripts/__pycache__/env.cpython-311.pyc | Bin 0 -> 5587 bytes gcmpy/scripts/__pycache__/env.cpython-312.pyc | Bin 0 -> 4807 bytes .../generate_question.cpython-311.pyc | Bin 0 -> 3146 bytes .../generate_question.cpython-312.pyc | Bin 0 -> 2995 bytes .../__pycache__/gocart.cpython-311.pyc | Bin 0 -> 3188 bytes .../__pycache__/gocart.cpython-312.pyc | Bin 0 -> 2697 bytes .../scripts/__pycache__/land.cpython-311.pyc | Bin 0 -> 3096 bytes .../scripts/__pycache__/land.cpython-312.pyc | Bin 0 -> 2660 bytes .../scripts/__pycache__/ocean.cpython-311.pyc | Bin 0 -> 11172 bytes .../scripts/__pycache__/ocean.cpython-312.pyc | Bin 0 -> 11210 bytes .../process_questions.cpython-311.pyc | Bin 0 -> 14604 bytes .../process_questions.cpython-312.pyc | Bin 0 -> 11971 bytes .../__pycache__/utility.cpython-311.pyc | Bin 0 -> 4163 bytes .../__pycache__/utility.cpython-312.pyc | Bin 0 -> 3860 bytes gcmpy/scripts/atmosphere.py | 166 +++-- gcmpy/scripts/env.py | 30 +- gcmpy/scripts/gcm_setup.py | 46 +- gcmpy/scripts/generate_question.py | 6 +- gcmpy/scripts/gocart.py | 13 +- gcmpy/scripts/land.py | 20 +- gcmpy/scripts/ocean.py | 4 +- gcmpy/scripts/process_questions.py | 243 +++++--- gcmpy/yaml/atmospheric_model.yaml | 14 +- gcmpy/yaml/gocart.yaml | 8 +- gcmpy/yaml/land_model.yaml | 10 +- 33 files changed, 1151 insertions(+), 751 deletions(-) create mode 100644 gcmpy/scripts/__pycache__/atmosphere.cpython-311.pyc create mode 100644 gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/env.cpython-311.pyc create mode 100644 gcmpy/scripts/__pycache__/env.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/generate_question.cpython-311.pyc create mode 100644 gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/gocart.cpython-311.pyc create mode 100644 gcmpy/scripts/__pycache__/gocart.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/land.cpython-311.pyc create mode 100644 gcmpy/scripts/__pycache__/land.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/ocean.cpython-311.pyc create mode 100644 gcmpy/scripts/__pycache__/ocean.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/process_questions.cpython-311.pyc create mode 100644 gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc create mode 100644 gcmpy/scripts/__pycache__/utility.cpython-311.pyc create mode 100644 gcmpy/scripts/__pycache__/utility.cpython-312.pyc diff --git a/.gitignore b/.gitignore index b25c15b8..d4f31ef1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -*~ +gcmpy/sync.sh +gcmpy/jinjafy.py + diff --git a/AGCM.rc.tmpl b/AGCM.rc.tmpl index d7cb41a0..c2b344e5 100644 --- a/AGCM.rc.tmpl +++ b/AGCM.rc.tmpl @@ -1,12 +1,26 @@ # Atmospheric Model Configuration Parameters # ------------------------------------------ +# Some rules of thumb when changing processor counts: +# +# 1) Start from the NX/NY that come from gcm_setup +# 2) The gcm will not run with AGCM_IM/NX or AGCM_JM/NY/6 less than or equal to 3 +# 3) if you want more cores, double NY (for 2x), then double NX(for 4x) and so on... +# 4) if you want fewer cores, half NX (for 0.5), then half NY for (0.25) and so on... +# 5) when you hit an odd number we need to get more creative +# 6) if you have questions send Bill Putman a Teams message NX: {{ NX }} NY: {{ NY }} IOSERVER_NODES: {{ NUM_OSERVER_NODES }} NUM_BACKEND_PES: {{ NUM_BACKEND_PES }} +DATAATM.GRID_TYPE: {{ GRID_TYPE }} +DATAATM.GRIDNAME: {{ AGCM_GRIDNAME }} +DATAATM.NF: {{ AGCM_NF }} +DATAATM.LM: {{ AGCM_LM }} +DATAATM.IM_WORLD: {{ AGCM_IM }} + AGCM_IM: {{ AGCM_IM }} AGCM_JM: {{ AGCM_JM }} AGCM_LM: {{ AGCM_LM }} @@ -23,24 +37,34 @@ AGCM.IM_WORLD: {{ AGCM_IM }} {{ CONUS }} AGCM.TARGET_LAT: 39.5 {{ CONUS }} AGCM.TARGET_LON: -98.35 +########################################################### +# debug options +# ---------------------------------------- +#DEBUG_DYN: .TRUE. +#DEBUG_GWD: .TRUE. +#DEBUG_MST: .TRUE. +#DEBUG_TRB: .TRUE. +#DEBUG_SYNCTQ: .TRUE. +########################################################### + ########################################################### # long physics DT options +# use extreme caution when adjusing these +# the defaults are most ideal # ---------------------------------------- ADJUST_DT: .FALSE. -CHEMISTRY_RUN_AT_INTERVAL_START: .TRUE. -CHEMISTRY_DT: {{ LONG_DT }} +GOCART2G_DT: {{ LONG_DT }} GOCART_DT: {{ LONG_DT }} HEMCO_DT: {{ LONG_DT }} +ACHEM_DT: {{ LONG_DT }} GF_DT: {{ LONG_DT }} -UW_DT: {{ LONG_DT }} +UW_DT: {{ LONG_DT }} ########################################################### ########################################################### # dynamics options # ---------------------------------------- DYCORE: {{ DYCORE }} -{{ FV_HWT }} FV3_CONFIG: HWT -AdvCore_Advection: 0 ########################################################### ########################################################### @@ -65,14 +89,12 @@ ORBIT_ANAL2B: .TRUE. # GFDL_1M microphysics options # ---------------------------------------- {{ GFDL_1M_ }}CLDMICR_OPTION: GFDL_1M -{{ GFDL_1M_ }}HYDROSTATIC: {{ GFDL_HYDRO }} ########################################################### ########################################################### # MGB2_2M microphysics options # ---------------------------------------- {{ MGB2_2M_ }}CLDMICR_OPTION: MGB2_2M -{{ MGB2_2M_ }}MGVERSION: @MGVERSION ########################################################### ########################################################### @@ -85,7 +107,6 @@ SHALLOW_OPTION: UW # convection scheme options # ---------------------------------------- CONVPAR_OPTION: {{ CONVPAR_OPTION }} -#USE_GF2020: 1 # Convective plumes to be activated (1 true, 0 false) DEEP: 1 SHALLOW: 0 @@ -102,23 +123,23 @@ CLOSURE_CONGESTUS: 3 ########################################################### # TRB/GWD Parameterization # ------------------------ -{{ FV_HWT }} RAYLEIGH_TAU1: 0.0 +NCAR_NRDG: {{ NCAR_NRDG }} ########################################################### - {{ HIST_GOCART }}########################################################### - {{ HIST_GOCART }}# Enable wet scavenging - {{ HIST_GOCART }}# NOTE: this section should be commented out when running gocart.data - {{ HIST_GOCART }}MCHEMTRI_increments:: - {{ HIST_GOCART }}DU::DU default - {{ HIST_GOCART }}SS::SS default - {{ HIST_GOCART }}SU::SO4 default - {{ HIST_GOCART }}CA.bc::CA.bcphilic default - {{ HIST_GOCART }}CA.br::CA.brphilic default - {{ HIST_GOCART }}CA.oc::CA.ocphilic default - {{ HIST_GOCART }}NI::NO3an1 "NI::NO3an2,NI::NO3an3" - {{ HIST_GOCART }}PCHEM::OX default - {{ HIST_GOCART }}:: - {{ HIST_GOCART }}########################################################### +{{ HIST_GOCART }}########################################################### +{{ HIST_GOCART }}# Enable wet scavenging +{{ HIST_GOCART }}# NOTE: this section should be commented out when running gocart.data +{{ HIST_GOCART }}MCHEMTRI_increments:: +{{ HIST_GOCART }}DU::DU default +{{ HIST_GOCART }}SS::SS default +{{ HIST_GOCART }}SU::SO4 default +{{ HIST_GOCART }}CA.bc::CA.bcphilic default +{{ HIST_GOCART }}CA.br::CA.brphilic default +{{ HIST_GOCART }}CA.oc::CA.ocphilic default +{{ HIST_GOCART }}NI::NO3an1 "NI::NO3an2,NI::NO3an3" +{{ HIST_GOCART }}PCHEM::OX default +{{ HIST_GOCART }}:: +{{ HIST_GOCART }}########################################################### ########################################################### # Ocean Model Configuration Parameters @@ -314,34 +335,6 @@ RECORD_REF_TIME: >>>REFTIME<<< >>>FCSTIME<<< # ASSIMILATION_CYCLE: nnnnnn # (Default: 21600) # IAU_DIGITAL_FILTER: YES or NO # (Default: YES ) -# Typical MERRA-2 Regular REPLAY Configuration -# -------------------------------------------- -#M2 REPLAY_ANA_EXPID: MERRA-2 -#M2 REPLAY_ANA_LOCATION: {{ M2_REPLAY_ANA_LOCATION }} -#M2 REPLAY_MODE: Regular -#M2 REPLAY_FILE: ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4 -# ----------------------------------------------------------------- - -# ANA EXPID and LOCATION used for REPLAY -# -------------------------------------- -#X_EXP REPLAY_ANA_EXPID: @ANA_EXPID -#X_EXP REPLAY_ANA_LOCATION: /discover/nobackup/projects/gmao/dadev/dao_it/archive/@ANA_EXPID -#X_EXP REPLAY_MODE: Regular -#X_EXP REPLAY_FILE: ana/Y%y4/M%m2/@ANA_EXPID.ana.eta.%y4%m2%d2_%h2%n2z.nc4 -#X_EXP REPLAY_FILE_FREQUENCY: 7200 - -# Regular REPLAY to ERA5 -# ---------------------- -#ERA5 REPLAY_MODE: Regular -#ERA5 REPLAY_FILE_FREQUENCY: 21600 -#ERA5 REPLAY_FILE_REFERENCE_TIME: 000000 -#ERA5 REPLAY_ANA_EXPID: era5 -#ERA5 REPLAY_ANA_LOCATION: /gpfsm/dnb78s1/projects/p18/sdrabenh/valdat/era5/ana -#ERA5 REPLAY_FILE: /gpfsm/dnb78s1/projects/p18/sdrabenh/valdat/era5/ana/Y%y4/M%m2/era5_eta2eta_L137.%y4%m2%d2_%h2z.nc4 -#ERA5 REPLAY_O3: NO -#ERA5 REPLAY_DAMPBEG: 500.0 -#ERA5 REPLAY_DAMPEND: 5000.0 - # Typical Exact REPLAY Configuration # ---------------------------------- # REPLAY_MODE: Exact @@ -357,7 +350,50 @@ RECORD_REF_TIME: >>>REFTIME<<< >>>FCSTIME<<< # REPLAY_FILE09: ana/Y%y4/M%m2/{{ REPLAY_ANA_EXPID }}.ana09.eta.%y4%m2%d2_%h2z.nc4 # REPLAY_FILE_FREQUENCY: 10800 # REPLAY_FILE_REFERENCE_TIME: 000000 + +# MERRA-2 Regular REPLAY Configuration +# -------------------------------------------- +#M2 REPLAY_ANA_EXPID: MERRA-2 +#M2 REPLAY_ANA_LOCATION: @M2_REPLAY_ANA_LOCATION +#M2 REPLAY_MODE: Regular +#M2 REPLAY_FILE: ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4 +#M2 MKIAU_JCAP: 62 + +# GEOS-IT Regular REPLAY Configuration +# -------------------------------------------- +#IT REPLAY_ANA_EXPID: GEOS-IT +#IT REPLAY_ANA_LOCATION: /discover/nobackup/projects/gmao/geos-it/dao_ops/archive/d5294_geosit_jan18 +#IT REPLAY_MODE: Regular +#IT REPLAY_FILE: ana/Y%y4/M%m2/d5294_geosit_jan18.ana.eta.%y4%m2%d2_%h2%n2z.nc4 +#IT MKIAU_JCAP: 62 + +# 4dvar ANA EXPID and LOCATION used for REPLAY +# -------------------------------------- +#X_EXP REPLAY_ANA_EXPID: @ANA_EXPID +#X_EXP REPLAY_ANA_LOCATION: /discover/nobackup/projects/gmao/dadev/dao_it/archive/@ANA_EXPID +#X_EXP REPLAY_MODE: Regular +#X_EXP REPLAY_FILE: ana/Y%y4/M%m2/@ANA_EXPID.ana.eta.%y4%m2%d2_%h2%n2z.nc4 +#X_EXP REPLAY_FILE_FREQUENCY: 7200 +# Regular REPLAY to GEOS-FP +# ------------------------- +#FP REPLAY_ANA_EXPID: f5295_fp +#FP REPLAY_ANA_LOCATION: /discover/nobackup/projects/gmao/geos_fp_arch/f5295_fp +#FP REPLAY_MODE: Regular +#FP REPLAY_FILE: ana/Y%y4/M%m2/f5295_fp.ana.eta.%y4%m2%d2_%h2%n2z.nc4 + +# Regular REPLAY to ERA5 +# ---------------------- +#ERA5 REPLAY_MODE: Regular +#ERA5 REPLAY_FILE_FREQUENCY: 21600 +#ERA5 REPLAY_FILE_REFERENCE_TIME: 000000 +#ERA5 REPLAY_ANA_EXPID: era5 +#ERA5 REPLAY_ANA_LOCATION: /css/era5 +#ERA5 REPLAY_FILE: ana/L137/Y%y4/M%m2/era5-L137.ana.eta.%y4%m2%d2_%h2z.nc4 +#ERA5 REPLAY_O3: NO +#ERA5 MKIAU_JCAP: 62 +#ERA5 REPLAY_DAMPBEG: 500.0 +#ERA5 REPLAY_DAMPEND: 5000.0 # 4DIAU (recreate analysis tendency on the fly) # --------------------------------------------- @@ -579,123 +615,123 @@ MAPL_ENABLE_BOOTSTRAP: {{ BOOT }} # Required AGCM Model Restart Files # --------------------------------- -DYN_INTERNAL_RESTART_FILE: fvcore_internal_rst -DYN_INTERNAL_CHECKPOINT_FILE: fvcore_internal_checkpoint -DYN_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -DYN_INTERNAL_HEADER: 1 +{{ MODELATM }}DYN_INTERNAL_RESTART_FILE: fvcore_internal_rst +{{ MODELATM }}DYN_INTERNAL_CHECKPOINT_FILE: fvcore_internal_checkpoint +{{ MODELATM }}DYN_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}DYN_INTERNAL_HEADER: 1 -GWD_INTERNAL_RESTART_FILE: gwd_internal_rst -GWD_INTERNAL_CHECKPOINT_FILE: gwd_internal_checkpoint -GWD_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}GWD_INTERNAL_RESTART_FILE: gwd_internal_rst +{{ MODELATM }}GWD_INTERNAL_CHECKPOINT_FILE: gwd_internal_checkpoint +{{ MODELATM }}GWD_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -LAKE_INTERNAL_RESTART_FILE: lake_internal_rst -LAKE_INTERNAL_CHECKPOINT_FILE: lake_internal_checkpoint -LAKE_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}LAKE_INTERNAL_RESTART_FILE: lake_internal_rst +{{ MODELATM }}LAKE_INTERNAL_CHECKPOINT_FILE: lake_internal_checkpoint +{{ MODELATM }}LAKE_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -LANDICE_INTERNAL_RESTART_FILE: landice_internal_rst -LANDICE_INTERNAL_CHECKPOINT_FILE: landice_internal_checkpoint -LANDICE_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}LANDICE_INTERNAL_RESTART_FILE: landice_internal_rst +{{ MODELATM }}LANDICE_INTERNAL_CHECKPOINT_FILE: landice_internal_checkpoint +{{ MODELATM }}LANDICE_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -CATCH_INTERNAL_RESTART_FILE: catch_internal_rst -CATCH_INTERNAL_CHECKPOINT_FILE: catch_internal_checkpoint -CATCH_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}CATCH_INTERNAL_RESTART_FILE: catch_internal_rst +{{ MODELATM }}CATCH_INTERNAL_CHECKPOINT_FILE: catch_internal_checkpoint +{{ MODELATM }}CATCH_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -CATCHCNCLM40_INTERNAL_RESTART_FILE: catchcn_internal_rst -CATCHCNCLM40_INTERNAL_CHECKPOINT_FILE: catchcn_internal_checkpoint -CATCHCNCLM40_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}CATCHCNCLM40_INTERNAL_RESTART_FILE: catchcn_internal_rst +{{ MODELATM }}CATCHCNCLM40_INTERNAL_CHECKPOINT_FILE: catchcn_internal_checkpoint +{{ MODELATM }}CATCHCNCLM40_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -MOIST_INTERNAL_RESTART_FILE: moist_internal_rst -MOIST_INTERNAL_CHECKPOINT_FILE: moist_internal_checkpoint -MOIST_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}MOIST_INTERNAL_RESTART_FILE: moist_internal_rst +{{ MODELATM }}MOIST_INTERNAL_CHECKPOINT_FILE: moist_internal_checkpoint +{{ MODELATM }}MOIST_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} # Boot-Strapable AGCM Model Restart Files # --------------------------------------- -AIAU_IMPORT_RESTART_FILE: aiau_import_rst -AIAU_IMPORT_CHECKPOINT_FILE: aiau_import_checkpoint -AIAU_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}AIAU_IMPORT_RESTART_FILE: aiau_import_rst +{{ MODELATM }}AIAU_IMPORT_CHECKPOINT_FILE: aiau_import_checkpoint +{{ MODELATM }}AIAU_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -GWD_IMPORT_RESTART_FILE: gwd_import_rst -GWD_IMPORT_CHECKPOINT_FILE: gwd_import_checkpoint -GWD_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}GWD_IMPORT_RESTART_FILE: gwd_import_rst +{{ MODELATM }}GWD_IMPORT_CHECKPOINT_FILE: gwd_import_checkpoint +{{ MODELATM }}GWD_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -MOIST_IMPORT_RESTART_FILE: moist_import_rst -MOIST_IMPORT_CHECKPOINT_FILE: moist_import_checkpoint -MOIST_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}MOIST_IMPORT_RESTART_FILE: moist_import_rst +{{ MODELATM }}MOIST_IMPORT_CHECKPOINT_FILE: moist_import_checkpoint +{{ MODELATM }}MOIST_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} SURFACE_IMPORT_RESTART_FILE: surf_import_rst SURFACE_IMPORT_CHECKPOINT_FILE: surf_import_checkpoint SURFACE_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -SOLAR_INTERNAL_RESTART_FILE: solar_internal_rst -SOLAR_INTERNAL_CHECKPOINT_FILE: solar_internal_checkpoint -SOLAR_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}SOLAR_INTERNAL_RESTART_FILE: solar_internal_rst +{{ MODELATM }}SOLAR_INTERNAL_CHECKPOINT_FILE: solar_internal_checkpoint +{{ MODELATM }}SOLAR_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -IRRAD_INTERNAL_RESTART_FILE: irrad_internal_rst -IRRAD_INTERNAL_CHECKPOINT_FILE: irrad_internal_checkpoint -IRRAD_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}IRRAD_INTERNAL_RESTART_FILE: irrad_internal_rst +{{ MODELATM }}IRRAD_INTERNAL_CHECKPOINT_FILE: irrad_internal_checkpoint +{{ MODELATM }}IRRAD_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -TURBULENCE_INTERNAL_RESTART_FILE: turb_internal_rst -TURBULENCE_INTERNAL_CHECKPOINT_FILE: turb_internal_checkpoint -TURBULENCE_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}TURBULENCE_INTERNAL_RESTART_FILE: turb_internal_rst +{{ MODELATM }}TURBULENCE_INTERNAL_CHECKPOINT_FILE: turb_internal_checkpoint +{{ MODELATM }}TURBULENCE_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -TURBULENCE_IMPORT_RESTART_FILE: turb_import_rst -TURBULENCE_IMPORT_CHECKPOINT_FILE: turb_import_checkpoint -TURBULENCE_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}TURBULENCE_IMPORT_RESTART_FILE: turb_import_rst +{{ MODELATM }}TURBULENCE_IMPORT_CHECKPOINT_FILE: turb_import_checkpoint +{{ MODELATM }}TURBULENCE_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -PCHEM_INTERNAL_RESTART_FILE: pchem_internal_rst -PCHEM_INTERNAL_CHECKPOINT_FILE: pchem_internal_checkpoint -PCHEM_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}PCHEM_INTERNAL_RESTART_FILE: pchem_internal_rst +{{ MODELATM }}PCHEM_INTERNAL_CHECKPOINT_FILE: pchem_internal_checkpoint +{{ MODELATM }}PCHEM_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -H2O_INTERNAL_RESTART_FILE: h2o_internal_rst -H2O_INTERNAL_CHECKPOINT_FILE: h2o_internal_checkpoint -H2O_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}H2O_INTERNAL_RESTART_FILE: h2o_internal_rst +{{ MODELATM }}H2O_INTERNAL_CHECKPOINT_FILE: h2o_internal_checkpoint +{{ MODELATM }}H2O_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} # Chemistry/AEROSOL Model Restart Files # ------------------------------------- -GOCART_IMPORT_RESTART_FILE: gocart_import_rst -GOCART_IMPORT_CHECKPOINT_FILE: gocart_import_checkpoint -GOCART_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}GOCART_IMPORT_RESTART_FILE: gocart_import_rst +{{ MODELATM }}GOCART_IMPORT_CHECKPOINT_FILE: gocart_import_checkpoint +{{ MODELATM }}GOCART_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -GOCART_INTERNAL_RESTART_FILE: gocart_internal_rst -GOCART_INTERNAL_CHECKPOINT_FILE: gocart_internal_checkpoint -GOCART_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}GOCART_INTERNAL_RESTART_FILE: gocart_internal_rst +{{ MODELATM }}GOCART_INTERNAL_CHECKPOINT_FILE: gocart_internal_checkpoint +{{ MODELATM }}GOCART_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -GOCART.data_INTERNAL_RESTART_FILE: gocartdata_internal_rst -GOCART.data_INTERNAL_CHECKPOINT_FILE: gocartdata_internal_checkpoint -GOCART.data_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}GOCART.data_INTERNAL_RESTART_FILE: gocartdata_internal_rst +{{ MODELATM }}GOCART.data_INTERNAL_CHECKPOINT_FILE: gocartdata_internal_checkpoint +{{ MODELATM }}GOCART.data_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -DU_INTERNAL_RESTART_FILE: du_internal_rst -DU_INTERNAL_CHECKPOINT_FILE: du_internal_checkpoint -DU_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}DU_INTERNAL_RESTART_FILE: du_internal_rst +{{ MODELATM }}DU_INTERNAL_CHECKPOINT_FILE: du_internal_checkpoint +{{ MODELATM }}DU_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -SS_INTERNAL_RESTART_FILE: ss_internal_rst -SS_INTERNAL_CHECKPOINT_FILE: ss_internal_checkpoint -SS_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}SS_INTERNAL_RESTART_FILE: ss_internal_rst +{{ MODELATM }}SS_INTERNAL_CHECKPOINT_FILE: ss_internal_checkpoint +{{ MODELATM }}SS_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -CA.oc_INTERNAL_RESTART_FILE: caoc_internal_rst -CA.oc_INTERNAL_CHECKPOINT_FILE: caoc_internal_checkpoint -CA.oc_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}CA.oc_INTERNAL_RESTART_FILE: caoc_internal_rst +{{ MODELATM }}CA.oc_INTERNAL_CHECKPOINT_FILE: caoc_internal_checkpoint +{{ MODELATM }}CA.oc_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -CA.bc_INTERNAL_RESTART_FILE: cabc_internal_rst -CA.bc_INTERNAL_CHECKPOINT_FILE: cabc_internal_checkpoint -CA.bc_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}CA.bc_INTERNAL_RESTART_FILE: cabc_internal_rst +{{ MODELATM }}CA.bc_INTERNAL_CHECKPOINT_FILE: cabc_internal_checkpoint +{{ MODELATM }}CA.bc_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -CA.br_INTERNAL_RESTART_FILE: cabr_internal_rst -CA.br_INTERNAL_CHECKPOINT_FILE: cabr_internal_checkpoint -CA.br_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}CA.br_INTERNAL_RESTART_FILE: cabr_internal_rst +{{ MODELATM }}CA.br_INTERNAL_CHECKPOINT_FILE: cabr_internal_checkpoint +{{ MODELATM }}CA.br_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -NI_INTERNAL_RESTART_FILE: ni_internal_rst -NI_INTERNAL_CHECKPOINT_FILE: ni_internal_checkpoint -NI_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}NI_INTERNAL_RESTART_FILE: ni_internal_rst +{{ MODELATM }}NI_INTERNAL_CHECKPOINT_FILE: ni_internal_checkpoint +{{ MODELATM }}NI_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -SU_INTERNAL_RESTART_FILE: su_internal_rst -SU_INTERNAL_CHECKPOINT_FILE: su_internal_checkpoint -SU_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}SU_INTERNAL_RESTART_FILE: su_internal_rst +{{ MODELATM }}SU_INTERNAL_CHECKPOINT_FILE: su_internal_checkpoint +{{ MODELATM }}SU_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -CARMA_INTERNAL_RESTART_FILE: carma_internal_rst -CARMA_INTERNAL_CHECKPOINT_FILE: carma_internal_checkpoint -CARMA_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}CARMA_INTERNAL_RESTART_FILE: carma_internal_rst +{{ MODELATM }}CARMA_INTERNAL_CHECKPOINT_FILE: carma_internal_checkpoint +{{ MODELATM }}CARMA_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} #STRATCHEM_INTERNAL_RESTART_FILE: stratchem_internal_rst #STRATCHEM_INTERNAL_CHECKPOINT_FILE: stratchem_internal_checkpoint @@ -721,29 +757,29 @@ CARMA_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} #GEOSCHEMCHEM_IMPORT_CHECKPOINT_FILE: geoschemchem_import_checkpoint #GEOSCHEMCHEM_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -MAM_INTERNAL_RESTART_FILE: mam_internal_rst -MAM_INTERNAL_CHECKPOINT_FILE: mam_internal_checkpoint -MAM_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}MAM_INTERNAL_RESTART_FILE: mam_internal_rst +{{ MODELATM }}MAM_INTERNAL_CHECKPOINT_FILE: mam_internal_checkpoint +{{ MODELATM }}MAM_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -ACHEM_INTERNAL_RESTART_FILE: achem_internal_rst -ACHEM_INTERNAL_CHECKPOINT_FILE: achem_internal_checkpoint -ACHEM_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}ACHEM_INTERNAL_RESTART_FILE: achem_internal_rst +{{ MODELATM }}ACHEM_INTERNAL_CHECKPOINT_FILE: achem_internal_checkpoint +{{ MODELATM }}ACHEM_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -TR_INTERNAL_RESTART_FILE: tr_internal_rst -TR_INTERNAL_CHECKPOINT_FILE: tr_internal_checkpoint -TR_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}TR_INTERNAL_RESTART_FILE: tr_internal_rst +{{ MODELATM }}TR_INTERNAL_CHECKPOINT_FILE: tr_internal_checkpoint +{{ MODELATM }}TR_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -TR_IMPORT_RESTART_FILE: tr_import_rst -TR_IMPORT_CHECKPOINT_FILE: tr_import_checkpoint -TR_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}TR_IMPORT_RESTART_FILE: tr_import_rst +{{ MODELATM }}TR_IMPORT_CHECKPOINT_FILE: tr_import_checkpoint +{{ MODELATM }}TR_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -HEMCO_INTERNAL_RESTART_FILE: hemco_internal_rst -HEMCO_INTERNAL_CHECKPOINT_FILE: hemco_internal_checkpoint -HEMCO_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}HEMCO_INTERNAL_RESTART_FILE: hemco_internal_rst +{{ MODELATM }}HEMCO_INTERNAL_CHECKPOINT_FILE: hemco_internal_checkpoint +{{ MODELATM }}HEMCO_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -HEMCO_IMPORT_RESTART_FILE: hemco_import_rst -HEMCO_IMPORT_CHECKPOINT_FILE: hemco_import_checkpoint -HEMCO_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +{{ MODELATM }}HEMCO_IMPORT_RESTART_FILE: hemco_import_rst +{{ MODELATM }}HEMCO_IMPORT_CHECKPOINT_FILE: hemco_import_checkpoint +{{ MODELATM }}HEMCO_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} #OH_INTERNAL_RESTART_FILE: oh_internal_rst #OH_INTERNAL_CHECKPOINT_FILE: oh_internal_checkpoint @@ -786,6 +822,32 @@ SEAICETHERMO_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} {{ COUPLED }}OCEAN_INTERNAL_CHECKPOINT_FILE: ocean_internal_checkpoint {{ COUPLED }}OCEAN_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +# GIGATRAJ RUN CONFIG +# ------------------------- +#GIGATRAJ_INTERNAL_RESTART_FILE: gigatraj_internal_rst +#GIGATRAJ_INTERNAL_CHECKPOINT_FILE: gigatraj_internal_checkpoint +#GIGATRAJ_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} +GIGATRAJ_REGRID_TO_LATLON: NO +#GIGATRAJ_PARCELS_FILE: parcels.nc4 +# time interval (minutes) for integration. Default is heart beat and it must be a multiple of heart beat. +# format hhmmss +# GIGATRAJ_INTEGRATE_DT: +# time interval to rebalance the parcels, i.e, the process keeps its own parcels +# format hhmmss +GIGATRAJ_REBALANCE_DT: 001500 +# time interval to write output +# format hhmmss +GIGATRAJ_OUTPUT_DT: 003000 +# format :: comp[%%bundle]%field[|alias], [] is optional +GIGATRAJ_VERTICAL_COORD: DYN%PL|P +#GIGATRAJ_VERTICAL_COORD: DYN%TH|Theta +#GIGATRAJ_VERTICAL_COORD: DYN%ZL|PAlt +# using ";" to separate fields. NO blank space between chars +# format :: comp[%%bundle]%field[|alias], [] is optional +GIGATRAJ_EXTRA_FIELDS: DYN%TH|Theta;DYN%ZL|PAlt +#GIGATRAJ_EXTRA_FIELDS: DYN%PL|P;DYN%ZL|PAlt +#GIGATRAJ_EXTRA_FIELDS: DYN%PL|P;DYN%TH|Theta + # IGNI Restart Files # ------------------ #IGNI_INTERNAL_RESTART_FILE: igni_internal_rst @@ -805,9 +867,9 @@ TILING_FILE: tile.bin VISDF_FILE: visdf.dat NIRDF_FILE: nirdf.dat LNFM_FILE: lnfm.data -{{ COUPLED }} ROUTING_FILE: runoff.bin +{{ MODELATM }}{{ COUPLED }} ROUTING_FILE: runoff.bin -VEGDYN_INTERNAL_RESTART_FILE: vegdyn.data +{{ MODELATM }}VEGDYN_INTERNAL_RESTART_FILE: vegdyn.data KPAR_FILE: SEAWIFS_KPAR_mon_clim.data @@ -837,8 +899,14 @@ HCFC22_FRIENDLIES: DYNAMICS:TURBULENCE:MOIST # Set RADIATION Parameterizations # ------------------------------- -USE_RRTMG_IRRAD: 1.0 -USE_RRTMG_SORAD: 1.0 +USE_RRTMGP_IRRAD: 1.0 +USE_RRTMGP_SORAD: 1.0 +RRTMGP_GAS_LW: ExtData/g5gcm/radiation/RRTMGP/v1.8/rrtmgp-gas-lw-g128.nc +RRTMGP_GAS_SW: ExtData/g5gcm/radiation/RRTMGP/v1.8/rrtmgp-gas-sw-g112.nc +RRTMGP_CLOUD_OPTICS_LW: ExtData/g5gcm/radiation/RRTMGP/v1.8/rrtmgp-clouds-lw.nc +RRTMGP_CLOUD_OPTICS_SW: ExtData/g5gcm/radiation/RRTMGP/v1.8/rrtmgp-clouds-sw.nc + +SOLAR_LB_MAX_PASSES: 10 ISOLVAR: 2 USE_NRLSSI2: .TRUE. SOLAR_CYCLE_FILE_NAME: ExtData/g5gcm/solar/NRLSSI2.txt @@ -850,13 +918,6 @@ SOLAR_CYCLE_FILE_NAME: ExtData/g5gcm/solar/NRLSSI2.txt NUM_BANDS: 30 -#USE_RRTMGP_IRRAD: 1.0 -#USE_RRTMGP_SORAD: 1.0 -#RRTMGP_GAS_LW: /discover/nobackup/pnorris/RRTMGP-data.v1.8/rrtmgp-data/rrtmgp-gas-lw-g128.nc -#RRTMGP_GAS_SW: /discover/nobackup/pnorris/RRTMGP-data.v1.8/rrtmgp-data/rrtmgp-gas-sw-g112.nc -#RRTMGP_CLOUD_OPTICS_LW: /discover/nobackup/pnorris/RRTMGP-data.v1.8/rrtmgp-data/rrtmgp-clouds-lw.nc -#RRTMGP_CLOUD_OPTICS_SW: /discover/nobackup/pnorris/RRTMGP-data.v1.8/rrtmgp-data/rrtmgp-clouds-sw.nc - DIURNAL_BIOMASS_BURNING: yes RATS_PROVIDER: {{ RATS_PROVIDER }} # options: PCHEM, GMICHEM, STRATCHEM (Radiatively active tracers) @@ -915,6 +976,7 @@ USE_WAVES: 0 {{ COUPLED }} # ---------------- {{ COUPLED }} USE_DATASEA:0 {{ COUPLED }} OCEAN_NAME: {{ OCEAN_NAME }} +{{ COUPLED }} USE_DATA_ATM4OCN: {{ USE_DATA_ATM4OCN }} {{ COUPLED }} USE_DATASEAICE:0 {{ COUPLED }} steady_state_ocean: 0 {{ COUPLED }} OCEAN_PICE_SCALING: 0.0 diff --git a/fvcore_layout.rc b/fvcore_layout.rc index 398dd8b5..edce70ef 100644 --- a/fvcore_layout.rc +++ b/fvcore_layout.rc @@ -1,12 +1,10 @@ &fv_core_nml - {{ FV_HYDRO }} - range_warn = .T. + range_warn = .F. fv_debug = .F. {{ FV_SCHMIDT }} {{ FV_STRETCH_FAC }} {{ FV_TARGET_LON }} {{ FV_TARGET_LAT }} - compute_coords_locally = .false. / &main_nml @@ -21,40 +19,11 @@ &fms_nml print_memory_usage=.true. - domains_stack_size = 24000000 + domains_stack_size = 12000000 clock_grain='MODULE', clock_flags='DETAILED', / &gfdl_cloud_microphysics_nml - sedi_transport = .true. - do_evap = .false. - do_subl = .false. - do_qa = .false. - tau_l2v = 300. - tau_i2v = 300. - tau_s2v = 300. - tau_g2v = 300. - tau_revp = 300. - tau_frz = 300. - dw_land = 0.05 - dw_ocean = 0.10 - rh_inc = 0.30 - rh_inr = 0.30 - qi0_crt = 8.0E-5 - qs0_crt = 1.0e-3 - c_psaci = 0.05 - c_pgacs = 0.01 - c_paut = 1.0 - c_cracw = 1.0 - {{ GFDL_PROG_CCN }} - {{ GFDL_USE_CCN }} - ccn_l = 300. - ccn_o = 100. - z_slope_liq = .true. - z_slope_ice = .true. - fix_negative = .true. - icloud_f = 3 - mp_time = 150. / diff --git a/gcm_forecast.tmpl b/gcm_forecast.tmpl index 9520df3f..3cfddd7d 100755 --- a/gcm_forecast.tmpl +++ b/gcm_forecast.tmpl @@ -79,8 +79,64 @@ set hour = `echo $time0 | cut -c1-2` set fdate = ${date0}_${hour}z setenv FCSTDIR $EXPDIR/forecasts/${FCST_LABL}_$fdate -setenv SCRDIR $FCSTDIR/scratch -if (! -e $SCRDIR ) mkdir -p $SCRDIR +mkdir -p $FCSTDIR + +# Handling of TSE_TMPDIR +# ---------------------- +# +# TSE_TMPDIR only exists at NCCS so first we check if it is defined + +if ( $?TSE_TMPDIR ) then + + # Next, we might not want to always use TSE_TMPDIR as the scratch + # if we need a permanent scratch directory for debugging or other + # purposes. So we can set a flag USE_TSE_TMPDIR to TRUE if we want + # and we default to TRUE + + set USE_TSE_TMPDIR = TRUE + + # If we want to use TSE_TMPDIR as the scratch, we create a scratch + # directory under TSE_TMPDIR and link it to SCRDIR + + if ( $USE_TSE_TMPDIR == TRUE ) then + + # Finally, we should be careful as there is a possibility we + # could collide if two runs use the same TSE_TMPDIR (for example + # a packable job). So we use $SLURM_JOB_ID and, if defined, + # $SLURM_ARRAY_TASK_ID to create a unique scratch directory + + set TSE_TMPDIR_NAME = $SLURM_JOB_ID + + setenv SCRDIR $TSE_TMPDIR/$TSE_TMPDIR_NAME/scratch + + if (-e $FCSTDIR/scratch ) /bin/rm -rf $FCSTDIR/scratch + if (-e $SCRDIR ) /bin/rm -rf $SCRDIR + mkdir -p $SCRDIR + ln -s $SCRDIR $FCSTDIR/scratch + + else + + # If USE_TSE_TMPDIR is FALSE, we create a scratch directory + # as we did before under the experiment directory + + setenv SCRDIR $FCSTDIR/scratch + if (-e $SCRDIR ) /bin/rm -rf $SCRDIR + mkdir -p $SCRDIR + + endif # USE_TSE_TMPDIR + +else + + # If TSE_TMPDIR is not defined, we are not at NCCS and we have to + # act as we did before and create a scratch directory under the + # experiment directory + + setenv SCRDIR $FSCTDIR/scratch + if (-e $SCRDIR ) /bin/rm -rf $SCRDIR + mkdir -p $SCRDIR + +endif # is TSE_TMPDIR defined + cd $SCRDIR /bin/rm -rf * @@ -274,6 +330,7 @@ GRID_LABELS: PC${HIST_IM}x${HIST_JM}-DC geosgcm_fcst.levels: 1000 975 950 925 900 850 800 750 700 600 500 400 300 250 200 150 100 70 50 30 10 7 5 3 1, geosgcm_fcst.fields: 'PHIS' , 'AGCM' , 'SLP' , 'DYN' , + 'W' , 'DYN' , 'U;V' , 'DYN' , 'T' , 'DYN' , 'PS' , 'DYN' , @@ -282,6 +339,9 @@ GRID_LABELS: PC${HIST_IM}x${HIST_JM}-DC 'Q' , 'MOIST' , 'QV' , 'QITOT' , 'AGCM' , 'QI' , 'QLTOT' , 'AGCM' , 'QL' , + 'QRTOT' , 'AGCM' , 'QR' , + 'QSTOT' , 'AGCM' , 'QS' , + 'QGTOT' , 'AGCM' , 'QG' , 'RH2' , 'MOIST' , 'RH' , 'O3' , 'CHEMISTRY' , :: @@ -306,14 +366,18 @@ GRID_LABELS: PC${HIST_IM}x${HIST_JM}-DC 'FRACI' , 'SURFACE' , 'frseaice' , 'PS' , 'DYN' , 'ps' , 'DELP' , 'DYN' , 'delp' , + 'DELZ' , 'DYN' , 'delz' , + 'W' , 'DYN' , 'w' , 'U;V' , 'DYN' , 'u;v' , 'TV' , 'DYN' , 'tv' , + 'T' , 'DYN' , 't' , 'Q' , 'MOIST' , 'sphu' , 'O3PPMV' , 'CHEMISTRY' , 'ozone' , 'QITOT' , 'AGCM' , 'qitot' , 'QLTOT' , 'AGCM' , 'qltot' , 'QRTOT' , 'MOIST' , 'qrtot' , 'QSTOT' , 'MOIST' , 'qstot' , + 'QGTOT' , 'MOIST' , 'qgtot' , :: _EOF_ @@ -359,10 +423,10 @@ setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} setenv EMISSIONS {{ EMISSIONS }} chmod +x linkbcs -{{ GCMRUN_CATCHCN }}set LSM_CHOICE = `grep LSM_CHOICE: AGCM.rc | cut -d':' -f2` -{{ GCMRUN_CATCHCN }}if ($LSM_CHOICE == 2) then -{{ GCMRUN_CATCHCN }} grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc -{{ GCMRUN_CATCHCN }}endif +@GCMRUN_CATCHCNset LSM_CHOICE = `grep LSM_CHOICE: AGCM.rc | cut -d':' -f2` +@GCMRUN_CATCHCNif ($LSM_CHOICE == 2) then +@GCMRUN_CATCHCN grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc +@GCMRUN_CATCHCNendif ####################################################################### # Get Executable and RESTARTS @@ -402,7 +466,10 @@ end set month = `echo $nymd0 | cut -c5-6` if( $CYCLED == .TRUE. ) then - /bin/ln -s $EXPDIR/restarts/*${nymd0}_${hour}*z.* . + foreach rst ( $rst_files ) + /bin/cp $EXPDIR/restarts/*${nymd0}_${hour}*z.* . & + end + wait $GEOSBIN/stripname ${EXPID}. $GEOSBIN/stripname _checkpoint.${nymd0}_${hour}\* _rst # Format if written from RECORD_FREQUENCY $GEOSBIN/stripname .e${nymd0}_${hour}\* # Format if decorated by gcm_run.j @@ -420,11 +487,6 @@ end # /bin/rm irrad_internal_rst endif -# Get proper ridge scheme GWD internal restart -# -------------------------------------------- -/bin/rm gwd_internal_rst -/bin/cp {{ GWDRSDIR }}/gwd_internal_c${AGCM_IM} gwd_internal_rst - # Re-Create Proper CAP.rc # ----------------------- cp CAP.rc CAP.rc.orig @@ -536,6 +598,18 @@ if( $AGCM_LM != 72 ) then cp $file dummy cat dummy | sed -e "s|/L72/|/L${AGCM_LM}/|g" | sed -e "s|z72|z${AGCM_LM}|g" > $file end + + # We have to do something special for L186. By default all of the GOCART emissions have: + # pressure_lid_in_hPa: 0.01 + # which is the pressure lid in hPa for all other GEOS vertical levels. But L186 has a lid + # at 0.00025 Pa. So we need to change this value in the GOCART emissions files for L186. + if ( $AGCM_LM == 186 ) then + set files = `/bin/ls *.rc` + foreach file ($files) + cp $file dummy + cat dummy | sed -e '/pressure_lid_in_hPa:/c\pressure_lid_in_hPa: 2.5e-6' > $file + end + endif endif # Rename big ExtData files that are not needed @@ -590,18 +664,30 @@ endif # ------------------------------- # UNCOMMENT THE LINES BELOW IF RUNNING RRTMGP # -#set instance_files = `/bin/ls -1 *_instance*.rc` -#foreach instance ($instance_files) -# /bin/mv $instance $instance.tmp -# cat $instance.tmp | sed -e '/RRTMG/ s#RRTMG#RRTMGP#' > $instance -# /bin/rm $instance.tmp -#end +set instance_files = `/bin/ls -1 *_instance*.rc` +foreach instance ($instance_files) + /bin/mv $instance $instance.tmp + cat $instance.tmp | sed -e '/\bRRTMG\b/ s#RRTMG#RRTMGP#' > $instance + /bin/rm $instance.tmp +end # Link Boundary Conditions for Appropriate Date # --------------------------------------------- setenv YEAR $yearc ./linkbcs +if ( ! -e gwd_internal_rst ) then + echo "WARNING: gwd_internal_rst not found. Setting NCAR_NRDG to 0" + # Now, if the user has already set an NCAR_NRDG value, we need to + # change it to 0. If they haven't set it, we need to add it to the + # AGCM.rc file. + if ( `grep -c "NCAR_NRDG:" AGCM.rc` == 0 ) then + echo "NCAR_NRDG: 0" >> AGCM.rc + else + sed -i '/NCAR_NRDG:/c\NCAR_NRDG: 0' AGCM.rc + endif +endif + if (! -e tile.bin) then $GEOSBIN/binarytile.x tile.data tile.bin {{ MOM5 }} $GEOSBIN/binarytile.x tile_hist.data tile_hist.bin @@ -842,3 +928,5 @@ $RUN_CMD 1 $GEOSUTIL/bin/stats.x -fcst $fcst_files \ @ NFCST = $NFCST + 1 set date = `$GEOSUTIL/post/tick $date0 $time0 86400` end + +# vi: ft=tcsh diff --git a/gcm_run.j b/gcm_run.j index aa32e48b..858e0614 100755 --- a/gcm_run.j +++ b/gcm_run.j @@ -68,12 +68,70 @@ if (! -e $EXPDIR/plot ) mkdir -p $EXPDIR/plot if( $GCMEMIP == TRUE ) then if (! -e $EXPDIR/restarts/$RSTDATE ) mkdir -p $EXPDIR/restarts/$RSTDATE - setenv SCRDIR $EXPDIR/scratch.$RSTDATE + set SCRDIR_NAME = scratch.$RSTDATE else - setenv SCRDIR $EXPDIR/scratch + set SCRDIR_NAME = scratch endif -if (! -e $SCRDIR ) mkdir -p $SCRDIR +# Handling of TSE_TMPDIR +# ---------------------- +# +# TSE_TMPDIR only exists at NCCS so first we check if it is defined + +if ( $?TSE_TMPDIR ) then + + # Next, we might not want to always use TSE_TMPDIR as the scratch + # if we need a permanent scratch directory for debugging or other + # purposes. So we can set a flag USE_TSE_TMPDIR to TRUE if we want + # and we default to TRUE + + set USE_TSE_TMPDIR = TRUE + + # If we want to use TSE_TMPDIR as the scratch, we create a scratch + # directory under TSE_TMPDIR and link it to SCRDIR + + if ( $USE_TSE_TMPDIR == TRUE ) then + + # Finally, we should be careful as there is a possibility we + # could collide if two runs use the same TSE_TMPDIR (for example + # a packable job). So we use $SLURM_JOB_ID and, if defined, + # $SLURM_ARRAY_TASK_ID to create a unique scratch directory + + set TSE_TMPDIR_NAME = $SLURM_JOB_ID + if ( $?SLURM_ARRAY_TASK_ID ) then + set TSE_TMPDIR_NAME = ${TSE_TMPDIR_NAME}_${SLURM_ARRAY_TASK_ID} + endif + + setenv SCRDIR $TSE_TMPDIR/$TSE_TMPDIR_NAME/$SCRDIR_NAME + + if ( -e $EXPDIR/$SCRDIR_NAME || -l $EXPDIR/$SCRDIR_NAME ) /bin/rm -rf $EXPDIR/$SCRDIR_NAME + if ( -e $SCRDIR ) /bin/rm -rf $SCRDIR + mkdir -p $SCRDIR + ln -s $SCRDIR $EXPDIR/$SCRDIR_NAME + + else + + # If USE_TSE_TMPDIR is FALSE, we create a scratch directory + # as we did before under the experiment directory + + setenv SCRDIR $EXPDIR/$SCRDIR_NAME + if (-e $SCRDIR ) /bin/rm -rf $SCRDIR + mkdir -p $SCRDIR + endif # USE_TSE_TMPDIR + +else + + # If TSE_TMPDIR is not defined, we are not at NCCS and we have to + # act as we did before and create a scratch directory under the + # experiment directory + + setenv SCRDIR $EXPDIR/$SCRDIR_NAME + if (-e $SCRDIR ) /bin/rm -rf $SCRDIR + mkdir -p $SCRDIR + +endif # is TSE_TMPDIR defined + +cd $SCRDIR ####################################################################### # Set Experiment Run Parameters @@ -176,24 +234,16 @@ awk '{$1=$1};1' < CAP.rc.orig > CAP.rc set year = `echo $RSTDATE | cut -d_ -f1 | cut -b1-4` set month = `echo $RSTDATE | cut -d_ -f1 | cut -b5-6` -{{ EMIP_OLDLAND }}# Copy MERRA-2 Restarts -{{ EMIP_OLDLAND }}# --------------------- -{{ EMIP_NEWLAND }}# Copy Jason-3_4 REPLAY MERRA-2 NewLand Restarts -{{ EMIP_NEWLAND }}# ---------------------------------------------- -cp /discover/nobackup/projects/gmao/g6dev/ltakacs/{{ EMIP_MERRA2 }}/restarts/AMIP/M${month}/restarts.${year}${month}.tar . -tar xf restarts.${year}${month}.tar -/bin/rm restarts.${year}${month}.tar -{{ EMIP_OLDLAND }}/bin/rm MERRA2*bin - - -{{ EMIP_OLDLAND }}# Regrid MERRA-2 Restarts -{{ EMIP_OLDLAND }}# ----------------------- -{{ EMIP_NEWLAND }}# Regrid Jason-3_4 REPLAY MERRA-2 NewLand Restarts -{{ EMIP_NEWLAND }}# ------------------------------------------------ -set RSTID = `/bin/ls *catch* | cut -d. -f1` -set day = `/bin/ls *catch* | cut -d. -f3 | awk 'match($0,/[0-9]{8}/) {print substr($0,RSTART+6,2)}'` -$GEOSBIN/remap_restarts.py command_line -np -ymdh ${year}${month}${day}21 -grout C${AGCM_IM} -levsout ${AGCM_LM} -out_dir . -rst_dir . -expid $RSTID -bcvin {{ EMIP_BCS_IN }} -oceanin 1440x720 -nobkg -lbl -nolcv -bcvout {{ LSMBCS }} -rs 3 -oceanout {{ OCEANOUT }} -in_bc_base @BC_BASE -out_bc_base @BC_BASE -{{ EMIP_OLDLAND }}/bin/rm $RSTID.*.bin +# Copy Restarts from v11.5.2 REPLAY to MERRA-2 +# ---------------------------------------------- +ln -s /discover/nobackup/projects/gmao/geos_itv/sdrabenh/REMIP_Experiments/v11.5.2_L072_C180_M2_REMIP/restarts/restarts.e${year}${month}10_21z.tar . +tar -xvf restarts.e${year}${month}10_21z.tar --wildcards "*_internal_rst*" + +# Regrid v11.5.2 Restarts +# ------------------------------------------------ +set RSTID = `/bin/ls *catch* | /bin/grep -Po '^.*(?=\.\w+_rst\.)'` +set day = `/bin/ls *catch* | /bin/grep -Po '(?<=\d{6})\d{2}(?=_21z)'` +$GEOSBIN/remap_restarts.py command_line -np -ymdh ${year}${month}${day}21 -grout C${AGCM_IM} -levsout ${AGCM_LM} -out_dir . -rst_dir . -expid $RSTID -bcvin NL3 -oceanin 1440x720 -in_bc_base /discover/nobackup/projects/gmao/bcs_shared/fvInput/ExtData/esm/tiles -newid regrid -nobkg -nolcv -bcvout @LSMBCS -rs 3 -oceanout @OCEANOUT -out_bc_base @BC_BASE set IMC = $AGCM_IM if( $IMC < 10 ) then @@ -204,15 +254,12 @@ else if($IMC < 1000) then set IMC = 0$IMC endif -set chk_type = `/usr/bin/file -Lb --mime-type C${AGCM_IM}[cef]_${RSTID}.*catch*` +set chk_type = `ls -1 regrid.catch*_internal_rst.${year}${month}${day}_21z.nc4 | xargs /usr/bin/file -Lb --mime-type ` if( "$chk_type" =~ "application/octet-stream" ) set ext = bin if( "$chk_type" =~ "application/x-hdf" ) set ext = nc4 -$GEOSBIN/stripname C${AGCM_IM}{{ OCEANOUT }}_${RSTID}. -$GEOSBIN/stripname .${year}${month}${day}_21z.$ext.{{ LSMBCS }}.{{ ATMOStag }}_{{ OCEANtag }} -{{ EMIP_OLDLAND }}/bin/mv gocart_internal_rst gocart_internal_rst.merra2 -{{ EMIP_OLDLAND }}$GEOSBIN/gogo.x -s $RSTID.Chem_Registry.rc.${year}${month}${day}_21z -t $EXPDIR/RC/Chem_Registry.rc -i gocart_internal_rst.merra2 -o gocart_internal_rst -r C${AGCM_IM} -l ${AGCM_LM} - +$GEOSBIN/stripname regrid. +$GEOSBIN/stripname .${year}${month}${day}_21z.$ext # Create CAP.rc and cap_restart # ----------------------------- @@ -241,16 +288,20 @@ cat CAP.tmp | sed -e "s?$oldstring?$newstring?g" > CAP.rc endif +set GIGATRAJ = `grep '^\s*GIGATRAJ_PARCELS_FILE:' AGCM.rc | cut -d: -f2` + ####################################################################### # Move to Scratch Directory and Copy RC Files from Home Directory ####################################################################### cd $SCRDIR /bin/rm -rf * - cp -f $EXPDIR/RC/* . cp $EXPDIR/cap_restart . cp $EXPDIR/linkbcs . +if ($GIGATRAJ != "") then + cp $EXPDIR/$GIGATRAJ . +endif cp -f $HOMDIR/*.rc . cp -f $HOMDIR/*.nml . cp -f $HOMDIR/*.yaml . @@ -327,10 +378,10 @@ setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} setenv EMISSIONS {{ EMISSIONS }} chmod +x linkbcs -{{ GCMRUN_CATCHCN }}set LSM_CHOICE = `grep LSM_CHOICE: AGCM.rc | cut -d':' -f2` -{{ GCMRUN_CATCHCN }}if ($LSM_CHOICE == 2) then -{{ GCMRUN_CATCHCN }} grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc -{{ GCMRUN_CATCHCN }}endif +@GCMRUN_CATCHCNset LSM_CHOICE = `grep LSM_CHOICE: AGCM.rc | cut -d':' -f2` +@GCMRUN_CATCHCNif ($LSM_CHOICE == 2) then +@GCMRUN_CATCHCN grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc +@GCMRUN_CATCHCNendif ####################################################################### # Setup executable ####################################################################### @@ -520,7 +571,8 @@ end # ----------------------- set USE_WAVES = `grep '^\s*USE_WAVES:' AGCM.rc| cut -d: -f2` set wavemodel = `cat WGCM.rc | grep "wave_model:" | cut -d "#" -f1 | cut -d ":" -f 2 | sed 's/\s//g'` -set wavewatch = `$USE_WAVES != 0 && $wavemodel == "WW3"` +set wavewatch = 0 +if (($USE_WAVES != 0) && ($wavemodel == "WW3") ) set wavewatch = 1 # Copy Restarts to Scratch Directory # ---------------------------------- @@ -541,20 +593,8 @@ else endif wait -# Get proper ridge scheme GWD internal restart -# -------------------------------------------- -if ( $rst_by_face == YES ) then - echo "WARNING: The generated gwd_internal_face_x_rst are used" - #foreach n (1 2 3 4 5 6) - #/bin/rm gwd_internal_face_${n}_rst - #/bin/cp {{ GWDRSDIR }}/gwd_internal_c${AGCM_IM}_face_${n} gwd_internal_face_${n}_rst - #end -else - /bin/rm gwd_internal_rst - /bin/cp {{ GWDRSDIR }}/gwd_internal_c${AGCM_IM} gwd_internal_rst -endif -{{ COUPLED }} /bin/mkdir INPUT -{{ COUPLED }} cp $EXPDIR/RESTART/* INPUT +@COUPLED /bin/mkdir INPUT +@COUPLED cp $EXPDIR/RESTART/* INPUT # Copy and Tar Initial Restarts to Restarts Directory # --------------------------------------------------- @@ -756,6 +796,7 @@ if( $AGCM_LM != 72 ) then cp $file dummy cat dummy | sed -e "s|/L72/|/L${AGCM_LM}/|g" | sed -e "s|z72|z${AGCM_LM}|g" > $file end + endif # Rename big ExtData files that are not needed @@ -810,18 +851,40 @@ endif # ------------------------------- # UNCOMMENT THE LINES BELOW IF RUNNING RRTMGP # -#set instance_files = `/bin/ls -1 *_instance*.rc` -#foreach instance ($instance_files) -# /bin/mv $instance $instance.tmp -# cat $instance.tmp | sed -e '/RRTMG/ s#RRTMG#RRTMGP#' > $instance -# /bin/rm $instance.tmp -#end +set instance_files = `/bin/ls -1 *_instance*.rc` +foreach instance ($instance_files) + /bin/mv $instance $instance.tmp + cat $instance.tmp | sed -e '/\bRRTMG\b/ s#RRTMG#RRTMGP#' > $instance + /bin/rm $instance.tmp +end # Link Boundary Conditions for Appropriate Date # --------------------------------------------- setenv YEAR $yearc ./linkbcs +# Get proper ridge scheme GWD internal restart +# -------------------------------------------- +if ( $rst_by_face == YES ) then + echo "WARNING: The generated gwd_internal_face_x_rst are used" + #foreach n (1 2 3 4 5 6) + #/bin/rm gwd_internal_face_${n}_rst + #/bin/cp @GWDRSDIR/gwd_internal_c${AGCM_IM}_face_${n} gwd_internal_face_${n}_rst + #end +else + if (! -e gwd_internal_rst) then + echo "WARNING: gwd_internal_rst not found. Setting NCAR_NRDG to 0" + # Now, if the user has already set an NCAR_NRDG value, we need to + # change it to 0. If they haven't set it, we need to add it to the + # AGCM.rc file. + if ( `grep -c "NCAR_NRDG:" AGCM.rc` == 0 ) then + echo "NCAR_NRDG: 0" >> AGCM.rc + else + sed -i '/NCAR_NRDG:/c\NCAR_NRDG: 0' AGCM.rc + endif + endif +endif + if (! -e tile.bin) then $GEOSBIN/binarytile.x tile.data tile.bin endif @@ -1041,6 +1104,13 @@ endif # Set OMP_NUM_THREADS # ------------------- setenv OMP_NUM_THREADS 1 +if ($OMP_NUM_THREADS > 1) then + setenv OMP_STACKSIZE 16M + setenv KMP_AFFINITY compact + echo OMP_STACKSIZE $OMP_STACKSIZE + echo KMP_AFFINITY $KMP_AFFINITY +endif +echo OMP_NUM_THREADS $OMP_NUM_THREADS # Run GEOSgcm.x # ------------- @@ -1189,8 +1259,9 @@ set restarts = `/bin/ls -1 *_rst` # ---------------------------------------------------- set restarts = `/bin/ls -1 $EXPID.*_rst.${edate}.${GCMVER}.${BCTAG}_${BCRSLV}.*` foreach restart ($restarts) -cp $restart ${EXPDIR}/restarts +cp $restart ${EXPDIR}/restarts & end +wait # Remove EXPID from RESTART name # ------------------------------ @@ -1246,20 +1317,20 @@ end {{ COUPLED }} # ------------------------- {{ MOM5 }} set dsets="ocean_month" {{ MOM6 }} set dsets="ocean_state prog_z sfc_ave forcing" -{{ MOM5 }} foreach dset ( $dsets ) -{{ MOM5 }} set num = `/bin/ls -1 $dset.nc | wc -l` -{{ MOM5 }} if($num != 0) then -{{ MOM5 }} if(! -e $EXPDIR/MOM_Output) mkdir -p $EXPDIR/MOM_Output -{{ MOM5 }} /bin/mv $SCRDIR/$dset.nc $EXPDIR/MOM_Output/$dset.${edate}.nc -{{ MOM5 }} endif -{{ MOM5 }} end -{{ MOM6 }} foreach dset ( $dsets ) -{{ MOM6 }} set num = `/bin/ls -1 $dset.nc | wc -l` -{{ MOM6 }} if($num != 0) then -{{ MOM6 }} if(! -e $EXPDIR/MOM_Output) mkdir -p $EXPDIR/MOM_Output -{{ MOM6 }} /bin/mv $SCRDIR/$dset.nc $EXPDIR/MOM_Output/$dset.${edate}.nc -{{ MOM6 }} endif -{{ MOM6 }} end +{{ MOM5 }} foreach dset ( $dsets ) +{{ MOM5 }} set num = `/bin/ls -1 $dset.nc | wc -l` +{{ MOM5 }} if($num != 0) then +{{ MOM5 }} if(! -e $EXPDIR/MOM_Output) mkdir -p $EXPDIR/MOM_Output +{{ MOM5 }} /bin/mv $SCRDIR/$dset.nc $EXPDIR/MOM_Output/$dset.${edate}.nc +{{ MOM5 }} endif +{{ MOM5 }} end +{{ MOM6 }} foreach dset ( $dsets ) +{{ MOM6 }} set num = `/bin/ls -1 $dset.nc | wc -l` +{{ MOM6 }} if($num != 0) then +{{ MOM6 }} if(! -e $EXPDIR/MOM_Output) mkdir -p $EXPDIR/MOM_Output +{{ MOM6 }} /bin/mv $SCRDIR/$dset.nc $EXPDIR/MOM_Output/$dset.${edate}.nc +{{ MOM6 }} endif +{{ MOM6 }} end {{ CICE6 }} # CICE6-Specific Output Files {{ CICE6 }} # ------------------------- @@ -1276,6 +1347,8 @@ end # Run Post-Processing and Forecasts ####################################################################### +if ($rc == 0) then + $GEOSUTIL/post/gcmpost.script -source $EXPDIR -movefiles if( $FSEGMENT != 00000000 ) then @@ -1294,6 +1367,8 @@ if( $FSEGMENT != 00000000 ) then endif endif +endif + ####################################################################### # Update Iteration Counter ####################################################################### @@ -1307,6 +1382,10 @@ else @ counter = ${NUM_SGMT} + 1 endif +if ($rc != 0) then + @ counter = ${NUM_SGMT} + 1 +endif + end # end of segment loop; remain in $SCRDIR ####################################################################### diff --git a/gcm_setup b/gcm_setup index 62ea226a..73870682 100755 --- a/gcm_setup +++ b/gcm_setup @@ -37,20 +37,17 @@ setenv ARCH `uname -s` setenv NODE `uname -n` if ($ARCH == Darwin) then - set FINDPATH = realpath set PRELOAD_COMMAND = 'DYLD_INSERT_LIBRARIES' set LD_LIBRARY_PATH_CMD = 'DYLD_LIBRARY_PATH' # On macOS we seem to need to call mpirun directly and not use esma_mpirun # For some reason SIP does not let the libraries be preloaded set RUN_CMD = 'mpirun -np ' else - set FINDPATH = 'readlink -f' set PRELOAD_COMMAND = 'LD_PRELOAD' set LD_LIBRARY_PATH_CMD = 'LD_LIBRARY_PATH' set RUN_CMD = '$GEOSBIN/esma_mpirun -np ' endif -set GCMSETUP = `$FINDPATH $0` -set BINDIR = `dirname $GCMSETUP` +set BINDIR = `pwd -L` set GEOSDEF = `dirname $BINDIR` set ETCDIR = ${GEOSDEF}/etc @@ -176,7 +173,7 @@ endif ####################################################################### # Get MPI stack from CMake -set MPI_STACK = intelmpi +set MPI_STACK = @MPI_STACK@ ####################################################################### # Enter Experiment Specific Run Parameters @@ -245,6 +242,7 @@ echo " ${C2}c90 -- 1 deg (${C1}100.0 km${C2}) ${CN}" echo " ${C2}c180 -- 1/2 deg (${C1} 50.0 km${C2}) ${CN}" echo " ${C2}c360 -- 1/4 deg (${C1} 25.0 km${C2}) ${CN} " echo " ${C2}c720 -- 1/8 deg (${C1} 12.5 km${C2}) ${CN}" +echo " ${C2}c1120 - 1/12 deg (${C1} 8.0 km${C2}) ${CN}" echo " ${C2}c1440 - 1/16 deg (${C1} 6.25 km${C2}) ${CN}" echo " ${C2}c2880 - 1/32 deg (${C1} 3.125 km${C2}) ${CN}" echo " ${C2}c5760 - 1/64 deg (${C1} 1.5625 km${C2}) ${CN}" @@ -265,6 +263,7 @@ if( $HRCODE != 'c12' & \ $HRCODE != 'c180' & \ $HRCODE != 'c360' & \ $HRCODE != 'c720' & \ + $HRCODE != 'c1120' & \ $HRCODE != 'c1440' & \ $HRCODE != 'c2880' & \ $HRCODE != 'c5760' & \ @@ -296,10 +295,10 @@ endif set LATLON_AGCM = "#DELETE" set CUBE_AGCM = "" -echo "Enter the Atmospheric Model ${C1}Vertical Resolution${CN}: ${C2}LM${CN} (Default: 72)" +echo "Enter the Atmospheric Model ${C1}Vertical Resolution${CN}: ${C2}LM${CN} (Default: 181)" set AGCM_LM = $< if( .$AGCM_LM == . ) then - set AGCM_LM = 72 + set AGCM_LM = 181 endif @@ -309,13 +308,13 @@ endif ASKMP: -echo "Enter Choice for Atmospheric Model ${C1}Microphysics${CN}: (Default: BACM_1M)" +echo "Enter Choice for Atmospheric Model ${C1}Microphysics${CN}: (Default: GFDL_1M)" echo " ${C2}BACM_1M -- 3-phase 1-moment Bacmeister et al${CN}" echo " ${C2}GFDL_1M -- 6-phase 1-moment Geophysical Fluid Dynamics Laboratory${CN}" echo " ${C2}MGB2_2M -- 5 or 6-phase 2-moment Morrison & Gettleman${CN}" set CLDMICRO = $< if( .$CLDMICRO == . ) then - set CLDMICRO = "BACM_1M" + set CLDMICRO = "GFDL_1M" else set CLDMICRO = `echo $CLDMICRO | tr "[:lower:]" "[:upper:]"` if( "$CLDMICRO" != "BACM_1M" & \ @@ -327,39 +326,6 @@ else endif endif - -####################################################################### -# Test to see if using hydrostatic or non-hydrostatic atmosphere -####################################################################### - -ASKHYDRO: - -set DEFAULT_HYDROSTATIC = TRUE - -echo "Use ${C1}Hydrostatic Atmosphere${CN}? (Default: ${C2}${DEFAULT_HYDROSTATIC}${CN})" -set USE_HYDROSTATIC = $< - -if( .$USE_HYDROSTATIC == . ) then - set USE_HYDROSTATIC = $DEFAULT_HYDROSTATIC -else - set USE_HYDROSTATIC = `echo $USE_HYDROSTATIC | tr "[:lower:]" "[:upper:]"` - if( $USE_HYDROSTATIC == "Y" | \ - $USE_HYDROSTATIC == "YES" | \ - $USE_HYDROSTATIC == "T" | \ - $USE_HYDROSTATIC == "TRUE" ) set USE_HYDROSTATIC = TRUE - if( $USE_HYDROSTATIC == "N" | \ - $USE_HYDROSTATIC == "NO" | \ - $USE_HYDROSTATIC == "F" | \ - $USE_HYDROSTATIC == "FALSE" ) set USE_HYDROSTATIC = FALSE - - if( "$USE_HYDROSTATIC" != "TRUE" & "$USE_HYDROSTATIC" != "FALSE" ) then - echo - echo "Use ${C1}Hydrostatic Atmosphere${CN} must be set equal to ${C2}TRUE/YES${CN} or ${C2}FALSE/NO${CN}!" - goto ASKHYDRO - endif -endif - - ####################################################################### # Test to see if you want to use ioserver ####################################################################### @@ -369,7 +335,10 @@ ASKIOS: if( $HRCODE == 'c180' | \ $HRCODE == 'c360' | \ $HRCODE == 'c720' | \ + $HRCODE == 'c1120' | \ $HRCODE == 'c1440' | \ + $HRCODE == 'c2880' | \ + $HRCODE == 'c5760' | \ $HRCODE == 'c270' | \ $HRCODE == 'c540' | \ $HRCODE == 'c1080' | \ @@ -418,11 +387,12 @@ ASKPROC: if ( $SITE == 'NCCS' ) then - set BUILT_ON_SLES15 = + set BUILT_ON_SLES15 = @BUILT_ON_SLES15@ if ("$BUILT_ON_SLES15" == "TRUE") then echo "Enter the ${C1}Processor Type${CN} you wish to run on:" echo " ${C2}mil (Milan)${CN} (default)" + echo " ${C2}cas (Cascade Lake)${CN}" echo " " set MODEL = `echo $<` set MODEL = `echo $MODEL | tr "[:upper:]" "[:lower:]"` @@ -430,15 +400,18 @@ if ( $SITE == 'NCCS' ) then set MODEL = 'mil' endif - if( $MODEL != 'mil' ) goto ASKPROC + if( $MODEL != 'mil' & \ + $MODEL != 'cas' ) goto ASKPROC if ($MODEL == 'mil') then - # We save a couple processes for the kernel - set NCPUS_PER_NODE = 126 + # For even division, use 120 cores per node + set NCPUS_PER_NODE = 120 + else if ($MODEL == 'cas') then + # For even division, use 40 cores per node + set NCPUS_PER_NODE = 40 endif else echo "Enter the ${C1}Processor Type${CN} you wish to run on:" - echo " ${C2}sky (Skylake)${CN}" echo " ${C2}cas (Cascade Lake) (default)${CN}" echo " " set MODEL = `echo $<` @@ -447,19 +420,11 @@ if ( $SITE == 'NCCS' ) then set MODEL = 'cas' endif - if( $MODEL != 'sky' & \ - $MODEL != 'cas' ) goto ASKPROC + if( $MODEL != 'cas' ) goto ASKPROC - if ($MODEL == 'sky') then + if ($MODEL == 'cas') then + # We use 40 of 46 cores per node for even division set NCPUS_PER_NODE = 40 - else if ($MODEL == 'cas') then - # NCCS currently recommends that users do not run with - # 48 cores per node on SCU16 due to OS issues and - # recommends that CPU-intensive works run with 46 or less - # cores. As 45 is a multiple of 3, it's the best value - # that doesn't waste too much - #set NCPUS_PER_NODE = 48 - set NCPUS_PER_NODE = 45 endif endif @@ -468,9 +433,9 @@ else if ( $SITE == 'NAS' ) then echo "Enter the ${C1}Processor Type${CN} you wish to run on:" echo " ${C2}has (Haswell)${CN}" echo " ${C2}bro (Broadwell)${CN}" - echo " ${C2}sky (Skylake)${CN} (default)" + echo " ${C2}sky (Skylake)${CN}" echo " ${C2}cas (Cascade Lake)${CN}" - echo " ${C2}rom (AMD Rome)${CN}" + echo " ${C2}rom (AMD Rome)${CN} (Default)" echo " ${C2}mil (AMD Milan)${CN}" echo " " echo " NOTE Due to how FV3 is compiled by default, Sandy Bridge" @@ -479,7 +444,7 @@ else if ( $SITE == 'NAS' ) then set MODEL = `echo $<` set MODEL = `echo $MODEL | tr "[:upper:]" "[:lower:]"` if ( .$MODEL == .) then - set MODEL = 'sky' + set MODEL = 'rom' endif if( $MODEL != 'has' & \ @@ -505,15 +470,18 @@ else if ( $SITE == 'NAS' ) then if ($MODEL == 'has') then set NCPUS_PER_NODE = 24 else if ($MODEL == 'bro') then - set NCPUS_PER_NODE = 28 + # we use 24 of 28 cores per node for even division + set NCPUS_PER_NODE = 24 else if ($MODEL == 'sky_ele') then set NCPUS_PER_NODE = 40 else if ($MODEL == 'cas_ait') then set NCPUS_PER_NODE = 40 else if ($MODEL == 'rom_ait') then - set NCPUS_PER_NODE = 128 + # we use 120 of 128 cores per node for even division + set NCPUS_PER_NODE = 120 else if ($MODEL == 'mil_ait') then - set NCPUS_PER_NODE = 128 + # we use 120 of 128 cores per node for even division + set NCPUS_PER_NODE = 120 endif else if( $SITE == 'AWS' | $SITE == 'Azure' ) then @@ -622,18 +590,18 @@ if( $OGCM == TRUE ) then if ( "$OCNMODEL" == "MOM5" ) then set OCEAN_NAME="MOM" set OGRIDTYP = "M5TP" - set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=$GEOSDIR/lib/libmom.so' + set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=$GEOSDIR/lib/libmom@CMAKE_SHARED_LIBRARY_SUFFIX@' set MOM5="" set MOM6 = "#DELETE" set DEFAULT_HISTORY_TEMPLATE="HISTORY.AOGCM-MOM5.rc.tmpl" - set mom5_warning=">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nYou (user) have chosen to set up a coupled model experiment with MOM5.\nBe aware that such a set up is _known_ to have problems. See following for more details.\nhttps://github.com/GEOS-ESM/MOM5/issues/19\nIf your intent is to help _fix_ above issue, your help is much appreciated. Thank you and good luck!\nOtherwise, until this above issue is _fixed_ you are on your own with above choice.\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" + set mom5_warning="######################################################\nYou (user) have chosen to set up a coupled model experiment with MOM5.\nBe aware that such a set up is _known_ to have problems. See following for more details.\nhttps://github.com/GEOS-ESM/MOM5/issues/19\nIf your intent is to help _fix_ above issue, your help is much appreciated. Thank you and good luck!\nOtherwise, until this above issue is _fixed_ you are on your own with above choice.\n######################################################" echo "\033[31;5m"${mom5_warning}"\033[0m" set MIT = "#DELETE" else if ( "$OCNMODEL" == "MOM6" ) then set OCEAN_NAME="MOM6" set OGRIDTYP = "M6TP" - set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=\$GEOSDIR/lib/libmom6.so' + set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=\$GEOSDIR/lib/libmom6@CMAKE_SHARED_LIBRARY_SUFFIX@' set MOM6="" set MOM5 = "#DELETE" set DEFAULT_HISTORY_TEMPLATE="HISTORY.AOGCM.rc.tmpl" @@ -769,13 +737,13 @@ if( $OGCM == TRUE ) then # suffix is different on Linux and macOS. This is set by configure_file() if ( $SEAICEMODEL == "CICE4" ) then set SEAICE_NAME="CICE4" - set SEAICE_PRELOAD = '$GEOSDIR/lib/libCICE4.so' + set SEAICE_PRELOAD = '$GEOSDIR/lib/libCICE4@CMAKE_SHARED_LIBRARY_SUFFIX@' set CICE4="" set CICE6 = "#DELETE" set HIST_CICE4 = "" else if ( $SEAICEMODEL == "CICE6" ) then set SEAICE_NAME="CICE6" - set SEAICE_PRELOAD = '$GEOSDIR/lib/libcice6.so' + set SEAICE_PRELOAD = '$GEOSDIR/lib/libcice6@CMAKE_SHARED_LIBRARY_SUFFIX@' set CICE6="" set CICE4 = "#DELETE" set HIST_CICE4 = "#DELETE" @@ -821,12 +789,31 @@ else # OGCM = FALSE (Data Ocean Resolution) # ------------------------------------ DORSLV: - echo "Enter the ${C1}Data_Ocean Horizontal Resolution ${CN}code: ${C2}o1${CN} (1 -deg, 360x180 Reynolds) Default" + + # We have two different default ocean resolutions based on the atmospheric resolution + # if LOW_ATM_RES is TRUE, we use o1 (Reynolds) as the default + # if LOW_ATM_RES is FALSE, we use CS (Cubed-Sphere OSTIA) as the default + + if( $LOW_ATM_RES == 'TRUE') then + set DEFAULT_HRCODE = 'o1' + set O1_DEFAULT = ' (Default)' + set CS_DEFAULT = '' + else + set DEFAULT_HRCODE = 'CS' + set O1_DEFAULT = '' + set CS_DEFAULT = ' (Default)' + set DEFAULT_HRCODE = 'CS' + endif + echo "Enter the ${C1}Data_Ocean Horizontal Resolution ${CN}code: ${C2}o1${CN} (1 -deg, 360x180 Reynolds)${O1_DEFAULT}" echo " ${C2}o2${CN} (1/4-deg, 1440x720 MERRA-2)" echo " ${C2}o3${CN} (1/8-deg, 2880x1440 OSTIA)" - echo " ${C2}CS${CN} (Cubed-Sphere OSTIA)" + echo " ${C2}CS${CN} (Cubed-Sphere OSTIA)${CS_DEFAULT}" + # We also note that the Reynolds ocean does not exist past 2022 + echo "" + echo "NOTE: The Reynolds ocean resolution is only available up to 2022" + set HRCODE = `echo $<` - if( .$HRCODE == . ) set HRCODE = o1 + if( .$HRCODE == . ) set HRCODE = $DEFAULT_HRCODE set HRCODE = `echo $HRCODE | tr "[:upper:]" "[:lower:]"` if( $HRCODE != 'o1' & \ @@ -888,30 +875,29 @@ else set DATAOCEAN = "" endif if( $HRCODE == 'cs' ) then - if( $LOW_ATM_RES == 'FALSE') then - set OGCM_IM = `echo $AGCM_IM | cut -b2-` - set OGCM_JM = `expr $OGCM_IM \* 6` - set Resolution = `echo $OGCM_IM $OGCM_JM` - set OGCM_IM = $Resolution[1] - set OGCM_JM = $Resolution[2] - set OGCM_GRID_TYPE = Cubed-Sphere - set OGCM_NF = 6 - set LATLON_OGCM = "#DELETE" - set CUBE_OGCM = "" - set DATAOCEAN = "#DELETE" - - set OCEAN_TAG = Ostia - set SSTNAME = OSTIA_REYNOLDS - set OCEANOUT = "CS" - set SSTFILE = dataoceanfile_OSTIA_REYNOLDS_SST.${OGCM_IM}x${OGCM_JM}.\${YEAR}.data - set ICEFILE = dataoceanfile_OSTIA_REYNOLDS_ICE.${OGCM_IM}x${OGCM_JM}.\${YEAR}.data - set KPARFILE = SEAWIFS_KPAR_mon_clim.${OGCM_IM}x${OGCM_JM} - set OGRIDTYP = "CF" - set OSTIA = "" - else + if( $LOW_ATM_RES == 'TRUE') then echo "Error: Cubed-Sphere Ocean with ${AGCM_IM} not currently supported. Must be c90 or higher" exit 7 endif + set OGCM_IM = `echo $AGCM_IM | cut -b2-` + set OGCM_JM = `expr $OGCM_IM \* 6` + set Resolution = `echo $OGCM_IM $OGCM_JM` + set OGCM_IM = $Resolution[1] + set OGCM_JM = $Resolution[2] + set OGCM_GRID_TYPE = Cubed-Sphere + set OGCM_NF = 6 + set LATLON_OGCM = "#DELETE" + set CUBE_OGCM = "" + set DATAOCEAN = "#DELETE" + + set OCEAN_TAG = Ostia + set SSTNAME = OSTIA_REYNOLDS + set OCEANOUT = "CS" + set SSTFILE = dataoceanfile_OSTIA_REYNOLDS_SST.${OGCM_IM}x${OGCM_JM}.\${YEAR}.data + set ICEFILE = dataoceanfile_OSTIA_REYNOLDS_ICE.${OGCM_IM}x${OGCM_JM}.\${YEAR}.data + set KPARFILE = SEAWIFS_KPAR_mon_clim.${OGCM_IM}x${OGCM_JM} + set OGRIDTYP = "CF" + set OSTIA = "" endif set IMO = ${OGCM_IM} @@ -958,6 +944,44 @@ else set OGCM_NPROCS = "" endif +# Check for Data Atmosphere +#-------------------------- +set DATA_ATMOS = FALSE +set MODELATM = "" +set USE_DATA_ATM4OCN = .FALSE. + +if( $OGCM == "TRUE" ) then + +DATATMOS: + echo "Do you wish to run ${C1}Data Atmosphere${CN}? (Default: ${C2}NO${CN} or ${C2}FALSE${CN})" + set DATA_ATMOS = $< + if (.$DATA_ATMOS == .) then + set DATA_ATMOS = FALSE + else + set DATA_ATMOS = `echo $DATA_ATMOS | tr "[:lower:]" "[:upper:]"` + if ($DATA_ATMOS == "Y" | \ + $DATA_ATMOS == "YES" | \ + $DATA_ATMOS == "T" | \ + $DATA_ATMOS == "TRUE" ) set DATA_ATMOS = TRUE + if ($DATA_ATMOS == "N" | \ + $DATA_ATMOS == "NO" | \ + $DATA_ATMOS == "F" | \ + $DATA_ATMOS == "FALSE") set DATA_ATMOS = FALSE + if ($DATA_ATMOS != TRUE & $DATA_ATMOS != FALSE) then + echo + echo "Please answer ${C2}YES${CN} or ${C2}NO${CN}!" + goto DATATMOS + endif + endif + + if ($DATA_ATMOS == TRUE) then + set MODELATM = "#DELETE" + set USE_DATA_ATM4OCN = .TRUE. + + set DEFAULT_HISTORY_TEMPLATE = "HISTORY.DATAATM.rc.tmpl" + endif +endif + # Set DEFAULT SHMEM Parameter # --------------------------- set USE_SHMEM = 0 @@ -980,11 +1004,11 @@ endif # Default Run Parameters # ---------------------- if( $AGCM_IM == "c12" ) then - set DT = 1800 + set DT = 3600 + set LONG_DT = 3600 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = $DT + set OCEAN_DT = 3600 set AGCM_IM = 12 set AGCM_JM = `expr $AGCM_IM \* 6` # C12 MOM6 should be 1x6 to match the default 3x2 ocean layout @@ -994,7 +1018,6 @@ if( $AGCM_IM == "c12" ) then set NX = 2 endif set NY = `expr $NX \* 6` - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set JOB_SGMT = 00000015 @@ -1004,15 +1027,14 @@ if( $AGCM_IM == "c12" ) then endif if( $AGCM_IM == "c24" ) then set DT = 1800 + set LONG_DT = 3600 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = $DT + set OCEAN_DT = 3600 set AGCM_IM = 24 set AGCM_JM = `expr $AGCM_IM \* 6` set NX = 4 set NY = `expr $NX \* 6` - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set JOB_SGMT = 00000015 @@ -1021,16 +1043,15 @@ if( $AGCM_IM == "c24" ) then set POST_NDS = 4 endif if( $AGCM_IM == "c48" ) then - set DT = 1800 + set DT = 1200 + set LONG_DT = 3600 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = $DT + set OCEAN_DT = 3600 set AGCM_IM = 48 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 4 + set NX = 6 set NY = `expr $NX \* 6` - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = 180 set HIST_JM = 91 set JOB_SGMT = 00000015 @@ -1040,9 +1061,9 @@ if( $AGCM_IM == "c48" ) then endif if( $AGCM_IM == "c90" ) then set DT = 900 + set LONG_DT = 1800 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set LONG_DT = $DT set AGCM_IM = 90 set AGCM_JM = `expr $AGCM_IM \* 6` if( $OGCM == TRUE ) then @@ -1059,11 +1080,10 @@ if( $AGCM_IM == "c90" ) then endif set OCEAN_DT = $DT else - set NX = 3 + set NX = 10 set NY = `expr $NX \* 6` - set OCEAN_DT = $IRRAD_DT + set OCEAN_DT = 3600 endif - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set JOB_SGMT = 00000032 @@ -1073,9 +1093,9 @@ if( $AGCM_IM == "c90" ) then endif if( $AGCM_IM == "c180" ) then set DT = 600 + set LONG_DT = 1200 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set LONG_DT = $DT set AGCM_IM = 180 set AGCM_JM = `expr $AGCM_IM \* 6` if( $OGCM == TRUE ) then @@ -1089,11 +1109,10 @@ if( $AGCM_IM == "c180" ) then endif set OCEAN_DT = $DT else - set NX = 6 + set NX = 20 set NY = `expr $NX \* 6` - set OCEAN_DT = $IRRAD_DT + set OCEAN_DT = 3600 endif - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 2 @@ -1104,15 +1123,14 @@ if( $AGCM_IM == "c180" ) then endif if( $AGCM_IM == "c360" ) then set DT = 450 + set LONG_DT = 900 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = $DT + set OCEAN_DT = 3600 set AGCM_IM = 360 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 12 + set NX = 30 set NY = `expr $NX \* 6` - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 4 @@ -1123,15 +1141,14 @@ if( $AGCM_IM == "c360" ) then endif if( $AGCM_IM == "c720" ) then set DT = 300 + set LONG_DT = 600 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = $DT + set OCEAN_DT = 3600 set AGCM_IM = 720 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 24 + set NX = 40 set NY = `expr $NX \* 6` - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 @@ -1141,17 +1158,35 @@ if( $AGCM_IM == "c720" ) then set POST_NDS = 16 set USE_SHMEM = 1 endif +if( $AGCM_IM == "c1120" ) then + set DT = 300 + set LONG_DT = 600 + set SOLAR_DT = 3600 + set IRRAD_DT = 3600 + set OCEAN_DT = 3600 + set AGCM_IM = 1120 + set AGCM_JM = `expr $AGCM_IM \* 6` + set NX = 60 + set NY = `expr $NX \* 6` + set HIST_IM = `expr $AGCM_IM \* 4` + set HIST_JM = `expr $AGCM_IM \* 2 + 1` + set NUM_READERS = 6 + set JOB_SGMT = 00000005 + set NUM_SGMT = 1 + set ATMOS_RES = CF1120x6C + set POST_NDS = 16 + set USE_SHMEM = 1 +endif if( $AGCM_IM == "c1440" ) then - set DT = 150 + set DT = 225 + set LONG_DT = 450 set SOLAR_DT = 1800 set IRRAD_DT = 1800 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = 300 + set OCEAN_DT = 1800 set AGCM_IM = 1440 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 48 + set NX = 80 set NY = `expr $NX \* 6` - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 @@ -1162,16 +1197,15 @@ if( $AGCM_IM == "c1440" ) then set USE_SHMEM = 1 endif if( $AGCM_IM == "c2880" ) then - set DT = 75 + set DT = 150 + set LONG_DT = 300 set SOLAR_DT = 1800 set IRRAD_DT = 1800 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = 300 + set OCEAN_DT = 1800 set AGCM_IM = 2880 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 96 - set NY = `expr $NX \* 6 \* 2` - set HYDROSTATIC = $USE_HYDROSTATIC + set NX = 80 + set NY = `expr $NX \* 6` set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 @@ -1184,16 +1218,15 @@ if( $AGCM_IM == "c2880" ) then set CONVPAR_OPTION = NONE endif if( $AGCM_IM == "c5760" ) then - set DT = 45 - set SOLAR_DT = 900 - set IRRAD_DT = 900 - set OCEAN_DT = $IRRAD_DT + set DT = 75 set LONG_DT = 300 + set SOLAR_DT = 1800 + set IRRAD_DT = 1800 + set OCEAN_DT = 1800 set AGCM_IM = 5760 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 192 + set NX = 80 set NY = `expr $NX \* 6` - set HYDROSTATIC = $USE_HYDROSTATIC set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 @@ -1210,15 +1243,14 @@ set CONUS = '#' set STRETCH_FACTOR = "" if( $AGCM_IM == "c270" ) then set DT = 600 + set LONG_DT = 1200 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = $DT + set OCEAN_DT = 3600 set AGCM_IM = 270 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 8 - set NY = `expr $NX \* 6 \* 2` - set HYDROSTATIC = $USE_HYDROSTATIC + set NX = 20 + set NY = `expr $NX \* 6` set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 @@ -1232,15 +1264,14 @@ if( $AGCM_IM == "c270" ) then endif if( $AGCM_IM == "c540" ) then set DT = 300 + set LONG_DT = 600 set SOLAR_DT = 3600 set IRRAD_DT = 3600 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = $DT + set OCEAN_DT = 3600 set AGCM_IM = 540 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 14 - set NY = `expr $NX \* 6 \* 2` - set HYDROSTATIC = $USE_HYDROSTATIC + set NX = 30 + set NY = `expr $NX \* 6` set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 @@ -1254,15 +1285,14 @@ if( $AGCM_IM == "c540" ) then endif if( $AGCM_IM == "c1080" ) then set DT = 150 - set SOLAR_DT = 900 - set IRRAD_DT = 900 - set OCEAN_DT = $IRRAD_DT set LONG_DT = 300 + set SOLAR_DT = 1800 + set IRRAD_DT = 1800 + set OCEAN_DT = 1800 set AGCM_IM = 1080 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 22 - set NY = `expr $NX \* 6 \* 2` - set HYDROSTATIC = $USE_HYDROSTATIC + set NX = 40 + set NY = `expr $NX \* 6` set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 @@ -1276,37 +1306,35 @@ if( $AGCM_IM == "c1080" ) then endif if( $AGCM_IM == "c1536" ) then set DT = 75 + set LONG_DT = 300 set SOLAR_DT = 900 set IRRAD_DT = 900 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = 300 + set OCEAN_DT = 900 set AGCM_IM = 1536 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 36 - set NY = `expr $NX \* 6 \* 2` - set HYDROSTATIC = $USE_HYDROSTATIC + set NX = 60 + set NY = `expr $NX \* 6` set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 - set JOB_SGMT = 00000005 + set JOB_SGMT = 00000001 set NUM_SGMT = 1 set ATMOS_RES = CF1536x6C-SG002 - set POST_NDS = 16 + set POST_NDS = 32 set USE_SHMEM = 1 set CONUS = '' set STRETCH_FACTOR = 3.0 endif if( $AGCM_IM == "c2160" ) then - set DT = 60 + set DT = 75 + set LONG_DT = 300 set SOLAR_DT = 900 set IRRAD_DT = 900 - set OCEAN_DT = $IRRAD_DT - set LONG_DT = 300 + set OCEAN_DT = 900 set AGCM_IM = 2160 set AGCM_JM = `expr $AGCM_IM \* 6` - set NX = 40 - set NY = `expr $NX \* 6 \* 2` - set HYDROSTATIC = $USE_HYDROSTATIC + set NX = 80 + set NY = `expr $NX \* 6` set HIST_IM = `expr $AGCM_IM \* 4` set HIST_JM = `expr $AGCM_IM \* 2 + 1` set NUM_READERS = 6 @@ -1318,6 +1346,27 @@ if( $AGCM_IM == "c2160" ) then set CONUS = '' set STRETCH_FACTOR = 2.5 endif +if( $AGCM_IM == "c4320" ) then + set DT = 30 + set LONG_DT = 300 + set SOLAR_DT = 900 + set IRRAD_DT = 900 + set OCEAN_DT = 900 + set AGCM_IM = 4320 + set AGCM_JM = `expr $AGCM_IM \* 6` + set NX = 80 + set NY = `expr $NX \* 6` + set HIST_IM = `expr $AGCM_IM \* 4` + set HIST_JM = `expr $AGCM_IM \* 2 + 1` + set NUM_READERS = 6 + set JOB_SGMT = 00000001 + set NUM_SGMT = 1 + set ATMOS_RES = CF4320x6C + set POST_NDS = 32 + set USE_SHMEM = 1 + set CONUS = '' + set STRETCH_FACTOR = 2.5 +endif set OGCM_IS_FCST = 0 set FVCUBED = "" @@ -1348,7 +1397,7 @@ set JOB_SGMT = "$JOB_SGMT 000000" ####################################################################### -# Setting for Microphysics & Hydrostatic Mode # +# Setting for Microphysics # ####################################################################### set BACM_1M_ = "#" @@ -1366,10 +1415,6 @@ if ( "$CLDMICRO" == "MGB2_2M" ) then set MGB2_2M_ = "" endif -set GFDL_HYDRO = ".TRUE." -set GFDL_PROG_CCN = "prog_ccn = .true." -set GFDL_USE_CCN = "use_ccn = .true." - # BACM_1M and GFDL do not use WSUB_CLIM, so this eliminates a regrid if ( "$CLDMICRO" == "BACM_1M" | "$CLDMICRO" == "GFDL_1M" ) then set MP_TURN_OFF_WSUB_EXTDATA = "" @@ -1377,21 +1422,6 @@ else set MP_TURN_OFF_WSUB_EXTDATA = "#DELETE#" endif -# Settings for fvcore_layout.rc -if ( "$USE_HYDROSTATIC" == "TRUE" ) then - set FV_MAKENH = "Make_NH = .F." - set FV_HYDRO = "hydrostatic = .T." - set FV_HWT = '#' -else - set FV_MAKENH = "Make_NH = .T." - set FV_HYDRO = "hydrostatic = .F." - if ( "$CLDMICRO" == "GFDL_1M" ) then - set GFDL_HYDRO = ".FALSE." - endif - # Enable FV3_CONFIG: HWT when running non-hydrostatic - set FV_HWT = '' -endif - if ($CONUS == '#') then set SCHMIDT = "do_schmidt = .false." set STRETCH_FAC = "stretch_fac = 1.0" @@ -1402,8 +1432,6 @@ else set STRETCH_FAC = "stretch_fac = $STRETCH_FACTOR" set TARGET_LON = "target_lon = -98.35" set TARGET_LAT = "target_lat = 39.5" - # Always enable FV3_CONFIG: HWT for CONUS - set FV_HWT = '' endif ####################################################################### @@ -1413,9 +1441,26 @@ endif # Enter Land Surface Model Boundary Conditions # ----------------------------------------------------------- LSM_BCS: -echo "Enter the choice of ${C1} Land Surface Boundary Conditions${CN} using: ${C2}ICA${CN} (Icarus), ${C2}NL3${CN} (Default: Icarus-NLv3), or ${C2}v12${CN}" + +# If we are running DATA_ATMOS, we can skip the Land bits, but we must still fill +# things out with something. So we use the default Land settings. + +if ($DATA_ATMOS == TRUE) then + set LSM_BCS = "NL3" + set LSM_CHOICE = 1 + set LSM_BCS = "NL3" + set LSM_PARMS = "" + set EMIP_BCS_IN = "NL3" + set EMIP_OLDLAND = "#DELETE" + set EMIP_NEWLAND = "" + set EMIP_MERRA2 = "MERRA2_NewLand" + set HIST_CATCHCN = "#DELETE" + set GCMRUN_CATCHCN = "#DELETE" +else + +echo "Enter the choice of ${C1}Land Surface Boundary Conditions${CN} using: ${C2}ICA${CN} (Icarus), ${C2}NL3${CN} (Icarus-NLv3), or ${C2}v13${CN} (Default)" set LSM_BCS = $< -if( .$LSM_BCS == . ) set LSM_BCS = "NL3" +if( .$LSM_BCS == . ) set LSM_BCS = "v13" if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "ica" ) then set LSM_BCS = "ICA" set LSM_PARMS = "#DELETE" @@ -1423,6 +1468,7 @@ if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "ica" ) then set EMIP_OLDLAND = "" set EMIP_NEWLAND = "#DELETE" set EMIP_MERRA2 = "MERRA2" + set GWD_IN_BCS = "FALSE" else if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "nl3" ) then set LSM_BCS = "NL3" set LSM_PARMS = "" @@ -1430,16 +1476,18 @@ else if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "nl3" ) then set EMIP_OLDLAND = "#DELETE" set EMIP_NEWLAND = "" set EMIP_MERRA2 = "MERRA2_NewLand" -else if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "v12" ) then - set LSM_BCS = "v12" + set GWD_IN_BCS = "FALSE" +else if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "v13" ) then + set LSM_BCS = "v13" set LSM_PARMS = "" set EMIP_BCS_IN = "NL3" set EMIP_OLDLAND = "#DELETE" set EMIP_NEWLAND = "" set EMIP_MERRA2 = "MERRA2_NewLand" + set GWD_IN_BCS = "TRUE" else echo - echo "${C1} Land Surface Boundary Conditions${CN} must be set equal to ${C2}ICA (Icarus)${CN}, ${C2}NL3 (Icarus-NLv3)${CN}, or ${C2}v12${CN}!" + echo "${C1} Land Surface Boundary Conditions${CN} must be set equal to ${C2}ICA (Icarus)${CN}, ${C2}NL3 (Icarus-NLv3)${CN}, or ${C2}v13${CN}!" goto LSM_BCS endif @@ -1456,13 +1504,16 @@ if( $LSM_CHOICE != 1 & $LSM_CHOICE != 2 ) then else echo endif -if( $LSM_CHOICE == 1 ) then +if( $LSM_CHOICE == 1 ) then set HIST_CATCHCN = "#DELETE" set GCMRUN_CATCHCN = "#DELETE" -else if( $LSM_CHOICE == 2 ) then +else if( $LSM_CHOICE == 2 ) then set HIST_CATCHCN = "" set GCMRUN_CATCHCN = "" endif + +endif # DATA_ATMOS + ####################################################################### # Check for AEROSOL/Chemistry Models ####################################################################### @@ -1470,6 +1521,24 @@ endif # Check for GOCART # ---------------- GOCART: + +# If we are running DATA_ATMOS, we can skip the GOCART bits, but we must still fill +# things out with something. So we use the climatological aerosols settings so +# the sed scripts don't get confused. +if ($DATA_ATMOS == TRUE) then + set GOKART = FALSE + set DATA_DRIVEN = FALSE + set AERO_PROVIDER = GOCART2G + set EMISSIONS = "" + set GOCART = "#" + set HIST_GOCART = "" + set OPS_SPECIES = "#" + set CMIP_SPECIES = "#" + set MERRA2OX_SPECIES = "#" + set PCHEM_CLIM_YEARS = "" + set OX_RELAXTIME = 0.0 +else + echo "Do you wish to run ${C1}GOCART${CN} with ${C2}Actual${CN} or ${C2}Climatological${CN} Aerosols? (Enter: ${C2}A${CN} (Default) or ${C2}C${CN})" set DATA_DRIVEN = $< if( .$DATA_DRIVEN == . ) set DATA_DRIVEN = A @@ -1538,6 +1607,7 @@ EMISSIONS: set OX_RELAXTIME = 259200. endif +endif # DATA_ATMOS # RATS Provider # ------------- @@ -1670,6 +1740,12 @@ else set NUM_BACKEND_PES = 0 endif +# For OpenMP regression testing, we need a variable that is half +# the number of CPUs per node and also two times the number of nodes +set NODES_TWICE = `expr $NODES \* 2` +set NCPUS_PER_NODE_HALF = `expr $NCPUS_PER_NODE / 2` + + # Here we need to convert POST_NDS to total tasks. Using 16 cores # per task as a good default @ POST_NPES = $POST_NDS * 16 @@ -1706,6 +1782,7 @@ if( $SITE == 'NAS' ) then setenv RUN_Q "PBS -q ${QTYPE}" # batch queue name for gcm_run.j setenv RUN_P "PBS -l select=${NODES}:ncpus=${NCPUS_PER_NODE}:mpiprocs=${NCPUS_PER_NODE}:model=${MODEL}" # PE Configuration for gcm_run.j setenv RUN_FP "PBS -l select=24:ncpus=${NCPUS_PER_NODE}:mpiprocs=${NCPUS_PER_NODE}:model=${MODEL}" # PE Configuration for gcm_forecast.j + setenv REGRESS_P "PBS -l select=${NODES_TWICE}:ncpus=${NCPUS_PER_NODE_HALF}:mpiprocs=${NCPUS_PER_NODE_HALF}:model=${MODEL}" # PE Configuration for gcm_regress.j setenv POST_Q "PBS -q normal" # batch queue name for gcm_post.j setenv PLOT_Q "PBS -q normal" # batch queue name for gcm_plot.j setenv MOVE_Q "PBS -q normal" # batch queue name for gcm_moveplot.j @@ -1753,6 +1830,7 @@ else if( $SITE == 'NCCS' ) then setenv RUN_Q "SBATCH --constraint=${MODEL}" # batch queue name for gcm_run.j setenv RUN_P "SBATCH --nodes=${NODES} --ntasks-per-node=${NCPUS_PER_NODE}" # PE Configuration for gcm_run.j setenv RUN_FP "SBATCH --nodes=${NODES} --ntasks-per-node=${NCPUS_PER_NODE}" # PE Configuration for gcm_forecast.j + setenv REGRESS_P "SBATCH --nodes=${NODES_TWICE} --ntasks-per-node=${NCPUS_PER_NODE_HALF}" # PE Configuration for gcm_regress.j setenv POST_Q "SBATCH --constraint=${MODEL}" # batch queue name for gcm_post.j setenv PLOT_Q "SBATCH --constraint=${MODEL}" # batch queue name for gcm_plot.j setenv MOVE_Q "SBATCH --partition=datamove" # batch queue name for gcm_moveplot.j @@ -1797,6 +1875,7 @@ else if( $SITE == 'AWS' | $SITE == 'Azure' ) then setenv RUN_Q "SBATCH --constraint=${MODEL}" # batch queue name for gcm_run.j setenv RUN_P "SBATCH --nodes=${NODES} --ntasks-per-node=${NCPUS_PER_NODE}" # PE Configuration for gcm_run.j setenv RUN_FP "SBATCH --nodes=${NODES} --ntasks-per-node=${NCPUS_PER_NODE}" # PE Configuration for gcm_forecast.j + setenv REGRESS_P "SBATCH --nodes=${NODES_TWICE} --ntasks-per-node=${NCPUS_PER_NODE_HALF}" # PE Configuration for gcm_regress.j setenv POST_Q NULL # batch queue name for gcm_post.j setenv PLOT_Q NULL # batch queue name for gcm_plot.j setenv MOVE_Q NULL # batch queue name for gcm_moveplot.j @@ -1815,7 +1894,7 @@ else if( $SITE == 'AWS' | $SITE == 'Azure' ) then setenv SSTDIR ${BOUNDARY_DIR}/@SSTNAME/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions setenv CHMDIR ${BOUNDARY_DIR}/fvInput_nc3 # locations of Aerosol Chemistry BCs - setenv WRKDIR /home/$LOGNAME # user work directory + setenv WRKDIR $HOME # user work directory setenv COUPLEDIR ${BOUNDARY_DIR}/bcs_shared/make_bcs_inputs/ocean # Coupled Ocean/Atmos Forcing setenv GWDRSDIR ${BOUNDARY_DIR}/GWD_RIDGE # Location of GWD_RIDGE files @@ -1835,6 +1914,7 @@ else setenv RUN_Q NULL # batch queue name for gcm_run.j setenv RUN_P NULL # PE Configuration for gcm_run.j setenv RUN_FP NULL # PE Configuration for gcm_forecast.j + setenv REGRESS_P NULL # PE Configuration for gcm_regress.j setenv POST_Q NULL # batch queue name for gcm_post.j setenv PLOT_Q NULL # batch queue name for gcm_plot.j setenv MOVE_Q NULL # batch queue name for gcm_moveplot.j @@ -1853,7 +1933,7 @@ else setenv SSTDIR ${BOUNDARY_DIR}/@SSTNAME/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions setenv CHMDIR ${BOUNDARY_DIR}/fvInput_nc3 # locations of Aerosol Chemistry BCs - setenv WRKDIR /home/$LOGNAME # user work directory + setenv WRKDIR $HOME # user work directory setenv COUPLEDIR ${BOUNDARY_DIR}/bcs_shared/make_bcs_inputs/ocean # Coupled Ocean/Atmos Forcing setenv GWDRSDIR ${BOUNDARY_DIR}/GWD_RIDGE # Location of GWD_RIDGE files set NX = 1 @@ -2188,9 +2268,6 @@ endif else if( $MPI_STACK == intelmpi ) then cat > $HOMDIR/SETENV.commands << EOF -setenv I_MPI_ADJUST_ALLREDUCE 12 -setenv I_MPI_ADJUST_GATHERV 3 - # This flag prints out the Intel MPI state. Uncomment if needed #setenv I_MPI_DEBUG 9 EOF @@ -2200,7 +2277,27 @@ EOF # specific compared to the above adjustments if ( $SITE == 'NCCS' ) then +# Some flags we know work on SLES15 and Milan (see below) +# For safety, we keep the old SLES12 flags for that system +# +# NOTE: When Cascade Lake is on SLES15, the following flags +# might need to be Milan only + +if ("$BUILT_ON_SLES15" == "TRUE") then cat >> $HOMDIR/SETENV.commands << EOF +setenv I_MPI_ADJUST_ALLREDUCE 12 +setenv I_MPI_ADJUST_GATHERV 3 + +setenv I_MPI_FABRICS shm:ofi +setenv I_MPI_OFI_PROVIDER psm3 +EOF + +else + +cat >> $HOMDIR/SETENV.commands << EOF +setenv I_MPI_ADJUST_ALLREDUCE 12 +setenv I_MPI_ADJUST_GATHERV 3 + setenv I_MPI_SHM_HEAP_VSIZE 512 setenv PSM2_MEMORY large EOF @@ -2216,40 +2313,20 @@ EOF endif # if NOT Singularity -# Testing by Bill Putman found these to be -# useful flags with Intel MPI on SLES15 on the -# Milan nodes. -# Note 1: Testing by NCCS shows the PSM3 provider -# runs on the Infiniband fabric. Tests show it runs -# up to C720. -# Note 2: When the Cascade Lakes are moved to -# SLES15, these will need to be Milan-only flags -# as Intel MPI will probably work just fine with -# Intel chips. -if ("$BUILT_ON_SLES15" == "TRUE") then -cat >> $HOMDIR/SETENV.commands << EOF -setenv I_MPI_FALLBACK 0 -setenv I_MPI_FABRICS ofi -setenv I_MPI_OFI_PROVIDER psm3 -setenv I_MPI_ADJUST_SCATTER 2 -setenv I_MPI_ADJUST_SCATTERV 2 -setenv I_MPI_ADJUST_GATHER 2 -setenv I_MPI_ADJUST_GATHERV 3 -setenv I_MPI_ADJUST_ALLGATHER 3 -setenv I_MPI_ADJUST_ALLGATHERV 3 -setenv I_MPI_ADJUST_ALLREDUCE 12 -setenv I_MPI_ADJUST_REDUCE 10 -setenv I_MPI_ADJUST_BCAST 11 -setenv I_MPI_ADJUST_REDUCE_SCATTER 4 -setenv I_MPI_ADJUST_BARRIER 9 -EOF - endif # if SLES15 endif # if NCCS endif # if mpi +# Check for gwd_internal for Ridge Scheme + +# For ICA and NL3 the gwd files are in a non-bcs location +# and may or may not exist. If they don't we set NCAR_NRDG to 0 +set NCAR_NRDG = 16 +if ( $GWD_IN_BCS == FALSE ) then + if ( ! -e $GWDRSDIR/gwd_internal_c${AGCM_IM} ) set NCAR_NRDG = 0 +endif ####################################################################### # Create Local Scripts and Resource Files @@ -2273,6 +2350,7 @@ s?{{ RUN_T }}?$RUN_T?g s?{{ RUN_P }}?$RUN_P?g s?{{ RUN_FP }}?$RUN_FP?g s?{{ RUN_Q }}?$RUN_Q?g +s?{{ REGRESS_P }}?$REGRESS_P?g s?{{ POST_N }}?$POST_N?g s?{{ POST_T }}?$POST_T?g s?{{ POST_P }}?$POST_P?g @@ -2303,6 +2381,7 @@ s?{{ KPARFILE }}?$KPARFILE?g s?{{ CHMDIR }}?$CHMDIR?g s?{{ COUPLEDIR }}?$COUPLEDIR?g s?{{ GWDRSDIR }}?$GWDRSDIR?g +s?{{ NCAR_NRDG }}?$NCAR_NRDG?g s?{{ EXPDIR }}?$EXPDIR?g s?{{ EXPDSC }}?$EXPDSC?g s?{{ HOMDIR }}?$HOMDIR?g @@ -2364,11 +2443,11 @@ s?{{ OCEAN_NAME }}?$OCEAN_NAME?g s?{{ OCEAN_PRELOAD }}?$OCEAN_PRELOAD?g s?{{ _4DIAUDAS }}?#DELETE?g -s?{{ REGULAR_REPLAY }}?#?g s?{{ REGULAR_REPLAY_GMAO }}?#?g s?{{ REGULAR_REPLAY_NCEP }}?#DELETE?g s?{{ REGULAR_REPLAY_ECMWF }}?#DELETE?g -s?{{ ana4replay.eta.%y4%m2%d2_%h2z.nc4 }}?/discover/nobackup/projects/gmao/merra2/data/ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4?g +s?{{ REGULAR_REPLAY }}?#?g +s?ana4replay.eta.%y4%m2%d2_%h2z.nc4?/discover/nobackup/projects/gmao/merra2/data/ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4?g s?{{ REPLAY_ANA_EXPID }}?$REPLAY_ANA_EXPID?g s?{{ REPLAY_ANA_LOCATION }}?$REPLAY_ANA_LOCATION?g @@ -2429,7 +2508,6 @@ s/{{ JOB_SGMT }}/${JOB_SGMT}/g s/{{ NUM_SGMT }}/${NUM_SGMT}/g s/{{ CONUS }}/${CONUS}/g -s/{{ FV_HWT }}/${FV_HWT}/g s/{{ CONVPAR_OPTION }}/${CONVPAR_OPTION}/g s/{{ STRETCH_FACTOR }}/${STRETCH_FACTOR}/g @@ -2457,9 +2535,12 @@ s?{{ MGB2_2M_ }}?$MGB2_2M_?g s?{{ PRELOAD_COMMAND }}?$PRELOAD_COMMAND?g s?{{ LD_LIBRARY_PATH_CMD }}?$LD_LIBRARY_PATH_CMD?g -s?{{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}?$LD_LIBRARY_PATH_CMD?g +s?{{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}?${LD_LIBRARY_PATH_CMD}?g s?{{ RUN_CMD }}?$RUN_CMD?g +s?{{ MODELATM }}?$MODELATM?g +s?{{ USE_DATA_ATM4OCN }}?$USE_DATA_ATM4OCN?g + EOF # Added FV3/GFDL-MP Specific Parameters @@ -2467,16 +2548,10 @@ EOF cat >> $HOMDIR/sedfile << EOF -s^{{ HYDROSTATIC }}^$HYDROSTATIC^g s?{{ FV_SCHMIDT }}?$SCHMIDT?g s?{{ FV_STRETCH_FAC }}?$STRETCH_FAC?g s?{{ FV_TARGET_LON }}?$TARGET_LON?g s?{{ FV_TARGET_LAT }}?$TARGET_LAT?g -s?{{ FV_MAKENH }}?$FV_MAKENH?g -s?{{ FV_HYDRO }}?$FV_HYDRO?g -s?{{ GFDL_PROG_CCN }}?$GFDL_PROG_CCN?g -s?{{ GFDL_USE_CCN }}?$GFDL_USE_CCN?g -s?{{ GFDL_HYDRO }}?$GFDL_HYDRO?g EOF @@ -2598,19 +2673,11 @@ foreach rsname ($RSNAMES) set test = `eval echo \$$rsname` if( $test == FALSE ) then foreach type ($RSTYPES) - set TMPCMD = `mktemp` set string = ${name}_${type} - /bin/rm -f $LOCDIR/$FILE.tmp - /bin/mv -f $LOCDIR/$FILE $LOCDIR/$FILE.tmp - echo cat $LOCDIR/$FILE.tmp \| awk \'\{if \( \$1 \~ \"${string}\" \) \ - \{sub \( \/${string}\/ ,\"\#${string}\" \)\;print\} else print\}\' \> $LOCDIR/$FILE > $TMPCMD - chmod +x $TMPCMD - $TMPCMD - /bin/rm -f $TMPCMD + sed -i -e "s/${string}/#${string}/g" $LOCDIR/$FILE end endif end -/bin/rm -f $LOCDIR/$FILE.tmp # Delete or Enable EXP Configuration Variables @@ -2822,8 +2889,8 @@ if( -e $HOMDIR/sedfile ) /bin/rm $HOMDIR/sedfile # NOTE: This variable is set at CMake time depending on # how the build was configured. -set INSTALL_TARFILE = FALSE -set TARFILE_NAME = "GEOSgcm.tar.gz" +set INSTALL_TARFILE = @CFG_INSTALL_SOURCE_TARFILE@ +set TARFILE_NAME = "@CMAKE_PROJECT_NAME@.tar.gz" if ( $INSTALL_TARFILE == "TRUE" ) then @@ -3204,8 +3271,11 @@ echo "" /bin/rm $NEWEXPFILES /bin/rm $COPYSCRIPT /bin/rm $SEDFILE -/bin/rm $TMPHIST -/bin/rm -rf $TMPOCEANDIR +# TMPHIST and TMPOCEANDIR are not defined if cloning +if ( $KLONE == "FALSE" ) then + /bin/rm -f $TMPHIST + /bin/rm -rf $TMPOCEANDIR +endif # ------------------------ # Cloned Experiment Source @@ -3213,8 +3283,8 @@ echo "" # NOTE: This variable is set at CMake time depending on # how the build was configured. -set INSTALL_TARFILE = FALSE -set TARFILE_NAME = "GEOSgcm.tar.gz" +set INSTALL_TARFILE = @CFG_INSTALL_SOURCE_TARFILE@ +set TARFILE_NAME = "@CMAKE_PROJECT_NAME@.tar.gz" if ( $INSTALL_TARFILE == "TRUE" ) then diff --git a/gcmpy/scripts/__pycache__/atmosphere.cpython-311.pyc b/gcmpy/scripts/__pycache__/atmosphere.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86c585b54d334dc7c848a91f1baa268b540f4e3a GIT binary patch literal 12957 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 literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/env.cpython-311.pyc b/gcmpy/scripts/__pycache__/env.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6f433e7631bbfa04fa558e41d8a8c1f423c6d42e GIT binary patch literal 5587 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 literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/env.cpython-312.pyc b/gcmpy/scripts/__pycache__/env.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f54cf81cd4a8cdd7c7197bd908b3c282d662ddc1 GIT binary patch literal 4807 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 Tf9<5m{m9`_p8i`Sh423Xi#vw+ literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/generate_question.cpython-311.pyc b/gcmpy/scripts/__pycache__/generate_question.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62a6cdb1259e05db3aeab66920b83343e3bf8c8f GIT binary patch literal 3146 zcmbVO&2JM&6rcUDli+L;aJEgvM*;;Aw+I6v{ZfHef>0#nP!d2&q1(l~Nt~?h&CDi{ z)RY`Jm?~9KFUgTs6sX7_KqU@6^iZi6J934!5)x9?LvN-*J#cB?oAs`73=-<|?wfh@ z=FOXZ@6B&~M^QEqpx=yt#{X<4THv%jjtnTW8KT-R5b{rrEUZxGmFKaw3~bnhd*!Ii}B8j@vq|jb$w>dx>c? zHqO>F?2<`gC7GGl7=u? z#*ZHx8Xixkh;M<${5h`#^4bd+4!cOERSh*u=Yuh{KRBa_eNc9yViL&!<9gl>G4Z`Yn=*gsMJEl=hGGka=m_FLUP1!_t#sV#yn%~?I^_sE^CbJ)aLEIzlrO1{F zkz2aU{qL0ek5-7N^m110h~H2OJ@ImM>vFmj-BXGV6y7^gh~o3BSvWUdNbtv+tq^iq zI3_+NBrObj&5#I#!{RydZyY>_Qnk4tS}57#hY~awYE5}_&+@_LgB6JnK8|+X7$~<# z^A6nvJFQDH9wMIPK}aAb`6diBQck!Hsk|4YlZgfy#*zp|3}K2F4?XMz2a}LVo=#j3 z=GKlcnGEJQSh-c241i-rybYH30_&T2_8RCmjNA)GuZWqS>UJbmchq0EBRs&IUbdr^ zbrAcCzQ3sR9eSZ}ej%Xqb-ocwIIXM$@mKVHsLpp&)%StA?+)U;&UcWB|M%S-!Vv&D zVO7MM6Rzx-mmRosntW_+p7kyt(``y-Gh->5jtO)N*tlW9Rx|0u1khA5S+;d&BGyI` zNI2lS5g!kAI!8C-Fo$6LCU?Vh?P5bW8u|v1U{iD(&g?W0*aN@jQ}&|w>98Eoqh+HvVVaskV=?zbbfR7tEY0*yre^c;so-V2*C3U1`^THh#)RRT^WJx{wP(8J(o+_%R zOX}(T;Nz}s{!PL`CJ_tcy@mI$rnwt5EuA%HEbO;x5K-OoG;|}Tgy*>rdOs3w%psWK zjm{b7j(r4dA^26qrqI?330PM+)L9_`>+A^iR7fN9R>y^t@CM|A*jgtHHU8s)l9uQj zpi24^(Gt%MR?8X%wnUugbPkSJDM#v&vtII1lXU{}a{Tn|{I(wBsA!1Qi%?EbG??FP zTc*y;Uax?Aoe8touj=h1G0BxIGvi9kp>9)(F+8=!)(^hS!moYz!}t@c?ufO3x=-4t2r3+Q2+}oD9__W*NmJ zNHO?SM#d|MuUzl#S@Q>8IUc45VID?-eG9B234%~2EerftCYuWWQzi!rFM29+NRTV7 fy9Fq>M)m~9p4Jp2LP&rQX=G1u?CA>>{0sjB6lt%T literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc b/gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4d5b6bbefaa6fbaaabb988d15eaacaf38caba86 GIT binary patch literal 2995 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 DzX(Im literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/land.cpython-311.pyc b/gcmpy/scripts/__pycache__/land.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34fb53eca1316cd57f783c837743f17e7ce31941 GIT binary patch literal 3096 zcmb_e&2JM&6rcUFH(uL;KnVGuP!ddCXf_a9XiBM2ViHi|R7t3c+iK-_oUmZ8!|o*L^4TSuOM0JRj&DJ^CtP)Bnmmyg$!Ew0fGkjJ^2pr+bAfdt? zLdA8SkjL@0(LW1 z{7n|S*+_*YqIvH@MWE0U8%B4XCFy0Bwrkf(`(7dKS*L!`t)4q!lvMT1C|@1rucPET z3bN@ArpL03G$n9ea@+}xj%YM#C$*%V%~=ypLx0jvUC*Ws+Y#c!y^cIQu4QvHopBDp zZZbD((4@JbrE&(b9m&% zC+hUfl$BMfG1=RzTGsXC&0Nk@2VyEX`Z?EtV6=a-S5Co|! zb4)rb^Cz%@GWW`vkR`GX)MJlxn_J=@cobTyj&;~Pt`cN`e0AzeDF561ZNc`+j}Y4{ zK0cgr~Viev;}V;mFEqR)~Cjk?%Va^*Q2P66!?K?Q|BF8B;fG z6J0oB|Fw&8M;eQb$0nkpi9aAmhBRtSK?c+eC^M%4cXP?iY}!J-BQVT16b>+BOnkA? z%`{qPi~}HGO#v*Er~6v&i$C<;>&wff&JzzW{Cr`fv$xpUTP9q?Am`#n@NjQl(eDrD>iNVtP? zm3DNJ^3W8#yuGeDF-b2oR02IO3)Bacmq9%JI&Xf@8@9WeH*83?R)~?*niWdcyvacQ zUvCX>*joU6*S#C7E+y^=m-{ci@OKWxhGP>kM;IJAV}{^-9iQ7{E}7UEov=%3@$~#K zHYH*1RPRL8Z|;GI=3ay*gnbD65t;#Gj9o>mMFD)7|qN^;nHW z1+x+N*d)vrgq=waVOqWWX|c&mwa4oPHA@3<6W({feN*WwC|#wl>{HItZx^B zI5D@0Lc6*dQVSu~6J^N+QMOh@%YG8>0io9<;xq7$iFg3(?y(N6TIc6b&O65K(mUnY zfpYOEZ>k_>;(P8o9v}Q!n9`>g6?QHz@i7Qm#{u9#ZX-+`HKPIyo+y^!7)@(B4J~8pStN} Sh=Y)J!#~LT_azUQ^Zx*muA4Xj literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/land.cpython-312.pyc b/gcmpy/scripts/__pycache__/land.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad7859f922b23a66917e2f8877231eeba6c35d49 GIT binary patch literal 2660 zcmb_eO>7fK6rTOFH~vW=KnOo6)S)TMpMg+7QAHIc#!!-tlz;?Q+m+*8!iM$Q>~4Z= zB@zb?i4+N{R!SsPDV!S0rPoT8dTKAdkd%mM1gD<3(d1BxQ{S8QuH#5hsp?36^WK~H z=FQIc&5VCfCSwFz_Vo3!U!#QliAK=GnzC^clzE~PowG=h%W)j)yu}xVoWK#DWQi`^ zC%X8Q_cL;0MN%TK(NH)V%iHc7HnI{IxaXQKII(MJs z1f2&d;`}*D7ePjJ31qYqQKD3|^0rtmy(|2m1uO0G8A+7HP0xhyBJPZ-l=GXlC7JbS+ZS9l(>V-qVgTh-*77V8Nz76rLl6}$rlaJa9kQUie^~@uV&gb z!Hkln<5t!z+qlatKX5QJJluPlHeb3ta#btjy~3@cVS992wr_Cwnp*cf;i%{u)=d}j zIQaIn^jP_(TTJWrXm@wob#LWwmr71Ln;9AzD-_eF?Rt63N{^a$8tifz{h=3kXNHlPA&;1=S=xb*`lz^#yXQ{-t)pXR2x@sJ%j zgWsOk`hN1|CxmnVwOEuI!k$=OB5h*mt8>rP6R_By&{}oi_BzfR4rzWRRK- z?4eDlP3El$!^OOV(45^E9AlHQ@M?<>AkNMl+abWc0s`>bv3o)Mre{W8>pc4Xg~u2E z=!nz;Cv zfbk9<&IWM8gMSvFn1@3>4iQ_M&fPvth;vBi;h=`_vBMZ%0lEldA%rXvzm+vz+I+w( z@2V21Rl%9+RU%;3tKbUiRWPz%B??wZjdxa&|KBP=lqQu5m-~9(Mmzg61DUHCDr5)G zI7l-ZsoesCI?zp3^O8^Dy=u%+2}}GySXJ zPi}v3efIjou9f5mEM{{G%)ml})U*FJ6>1 zc_;oN!@rGjGMI?y$g=uO4Vv^c{sXR|VlC+cVpF_p@cIij1!u zUagu&V;Vm36BghKdWM^z*$81|(9?;$$jnU?8Q*t_7*c@8JW`C{?H}M(DtiC` literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/ocean.cpython-311.pyc b/gcmpy/scripts/__pycache__/ocean.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b5a5f8bc4d38b6bf08394eb0b7478845b750c54b GIT binary patch literal 11172 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 PKxZpmyFnEL(y{*oVd#Q` literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc b/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb95fccc5e78159ad68f97c614717b3769576b5a GIT binary patch literal 11971 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 JefGx!_dl7nfs_CM literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/__pycache__/utility.cpython-312.pyc b/gcmpy/scripts/__pycache__/utility.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4358525d4379b95fc1d91083613f168c2eccd8ab GIT binary patch literal 3860 zcmd5mZMCC0K7N^v)KY=x>MrgGfWwro@u8O5nYJCcPWYZvUAyAoGg za@n`bL}Uz91$?l96gj#=4M>L`EclWD0h0fai?%9IVd0_$ddf|*0tCpZGjB<1r4TBb zQy;M3dv9jm?96ax-ty~sTqH0y{t;Y!4y%9TrZqy%#r{@+kjF$NDrXScn>m?d`+yt> zkSU@D9uPJ74CHXgK}HJ!jc?OJI+1yJ!U3X@rEX8skI$MLEv$yeVGU9}e!jO}dg+HW zJn;&UpK%@!_K{;W^mWt_K@Fa`l?bDI?kve*OI(kt@ol7Ub!8FJh5nH2~KV&}( zl*f>PnB{Un<>a6mkV9%v=GBlKR(Uz1hGjvG$Wc|0MKvnNR8j7NC$7dG5V>3J0!-B7 z>28-VnubXmeE*$G7t3t=Ih!tc)1|jO;+QvG@TQ-Y8=?L?9)bX@-z*nf)}ggnX+e1Q z4S>hQ2K2^Kvj$sxoPFF@P5amlSl=gzKDn?@pt(eeIkL&+(;8#7o z=H_y@)0`WsDt5_2Q>E{(XBMjqRym_q?p?T$v8(K*B5?*7S1z07|6DK}xJZe12t-rVS zo|8EL^n{Zb`GWs4_Ib=nT-g$??1LEj|A-;Q=(eKBPtE3Xc`5*jMv)FNT+j{8iy@5x zsTBky9}WUiumF8Q`1sMsPv+OPGWpZ7^iU%&Zm1^p-`wO zWvx(f#X_NMsx<@GU4_E$YKqb1gm2By-kOGAc=CgZyeniUW`Bh%8UYR!uzj_0KZF4We96!DfaMja~8ao&E>%j3BHk2upHXsx?Ae1*?xX!1; zuBfdPwW_U~73+{L9#jP3+5ZdEWw*=HZkOH?8gOLT?UGVCY>rq?YJg#o6<;TQi1B%b zVTKWg0>da`t4(vn#`IxB6%VL&l8)tFac*+<#;x1=iJ4sE?69OrmS)$gl2>rjf=MO2 zq)Awr($wUPC^m%XyrnE^m!(Ehx?{31D2B9PD2u-V?$xLSV`Rk8E6ccIV;VQj;vQX* z^ongt+DcWUdReR3lB!d!Xq&VyHpZIAExoc>GZYH7E=hBmErCgMKH9-)v2i*ojg;V( zCC#X|-YCtL%#WlR8rm2Y#TyIo(htpLO_dbGtZ2i`siu##RM}Aie`$ zmrbg{AqYTO!Jm3qsv4SNX;RUw*h3of1+*%^7J*J zrvvm1OcaZClXHV*Yti2gPf$g-G>DK!3+?zce$rlAqn!lKgE9+0C|S%N7C#Z63tj)k zi7bd8x?J0a1EV<(IflJ~jl+)7K_I4s^fXLvl39n=w=HI#(l>zX_p{G)V?lvi(&s4D zRI4vF9X%p3gnCW^pr^^d3+Ei++(z+l!q6dyfq!VQUo8Zr$D~f!4drF#k@Sodp*||L zY9r}0qe;uaX$wQJN_K=UmK^zXgyJnt@k5iIKsbkhHqsFUJanW6SezJOqqI%}JRmPZ z0^jrEWB@<_*cUlI?v)LTYNYw?;PUKK!VT4xvf&2d+ro`BKQ!E+W*6N^vqQQ3y_#;Q zjaMyN%uH0PhF)YHz{>oxDNz8b8}n@%XHXW(oN6ja%}m@Zv^UT>3-j>V;zscRTc%@f zz_i?;RkvKBYA7~#8Lts|CTo=su@BI*;Gi2`1nWLhDgGaGBhW1I7Is5Rrd~M`p6`Wm z@5a7HCqNiW%(@P^8{|0dpXB9j^741#BzJX>0DL!eii__NfZb~(7GI6*00=v&vwu3X zo?c7;`KPPG!&e;g(oSk%eQ<4XJ+qd1`o?FMoT01RscXPH<&fSMZ+LBZW974mGx&?I z&TpqCfP2y*JuR+x@@;46%64iTczu6J9A;hI%xtGFA9X1_{gANXFjsJE#r2xDCucVLV(|-VH+&KCG literal 0 HcmV?d00001 diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py index 9e015eb1..70957640 100755 --- a/gcmpy/scripts/atmosphere.py +++ b/gcmpy/scripts/atmosphere.py @@ -3,7 +3,7 @@ class atmosphere: def __init__(self): - self.use_SHMEM = False + self.use_SHMEM = 0 self.force_das = "#" self.force_gcm = "#" self.num_readers = 1 @@ -11,7 +11,7 @@ def __init__(self): self.dt = answerdict['heartbeat'].q_answer self.dt_solar = None self.dt_irrad = None - self.DT_ocean = answerdict['heartbeat'].q_answer + self.dt_ocean = answerdict['heartbeat'].q_answer self.dt_long = None self.lm = int(answerdict['AM_vertical_res'].q_answer) self.im = int(answerdict['AM_horizontal_res'].q_answer[1:]) @@ -67,7 +67,8 @@ def hres(self, ocean_nx, ocean_ny): case "c12": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = self.dt + self.dt_long = 3600 + self.dt_ocean = 3600 if answerdict["OM_name"].q_answer == "MOM6": self.nx = 1 else: @@ -80,10 +81,12 @@ def hres(self, ocean_nx, ocean_ny): self.ny_convert = 6 self.res = 'CF0012x6C' + case "c24": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = self.dt + self.dt_long = 3600 + self.dt_ocean = 3600 self.nx = 4 self.ny = self.nx * 6 self.job_sgmt = f"{15:08}" @@ -96,8 +99,9 @@ def hres(self, ocean_nx, ocean_ny): case "c48": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = self.dt - self.nx = 4 + self.dt_long = 3600 + self.dt_ocean = 3600 + self.nx = 6 self.ny = self.nx * 6 self.im_hist = 180 self.jm_hist = 91 @@ -111,17 +115,21 @@ def hres(self, ocean_nx, ocean_ny): case "c90": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = self.dt - match answerdict["OM_name"].q_answer: - case "MIT": - self.nx = 10 - self.ny = 36 - case "MOM5","MOM6": - self.nx = ocean_nx - self.ny = ocean_ny - case _: - self.nx = 3 - self.ny = self.nx * 6 + self.dt_long = 1800 + self.dt_ocean = self.dt + if answerdict['OM_name'].q_answer == 'MIT': + self.nx = 10 + self.ny = 36 + elif answerdict['OM_name'].q_answer == 'MOM5': + self.nx = ocean_nx + self.ny = ocean_ny + elif answerdict['OM_name'].q_answer == 'MOM6': + self.nx = 5 + self.ny = 36 + else: + self.nx = 10 + self.ny = self.nx * 6 + self.dt_ocean = 3600 self.job_sgmt = f"{32:08}" self.num_sgmt = 4 self.post_NDS = 8 @@ -130,13 +138,18 @@ def hres(self, ocean_nx, ocean_ny): case "c180": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = self.dt - if answerdict["OM_coupled"].q_answer == True: + self.dt_long = 1200 + self.dt_ocean = self.dt + if answerdict['OM_name'].q_answer == 'MOM6': + self.nx = 30 + self.ny = 36 + elif answerdict['OM_name'].q_answer == 'MOM5' or answerdict['OM_name'].q_answer == 'MIT': self.nx = ocean_nx self.ny = ocean_ny else: - self.nx = 6 + self.nx = 20 self.ny = self.nx * 6 + self.dt_ocean = 3600 self.job_sgmt = f"{16:08}" self.num_sgmt = 1 self.post_NDS = 8 @@ -146,8 +159,9 @@ def hres(self, ocean_nx, ocean_ny): case "c360": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = self.dt - self.nx = 12 + self.dt_long = 900 + self.dt_ocean = 4600 + self.nx = 30 self.ny = self.nx * 6 self.num_readers = 4 self.job_sgmt = f"{5:08}" @@ -159,36 +173,54 @@ def hres(self, ocean_nx, ocean_ny): case "c720": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 450 - self.nx = 24 + self.dt_long = 600 + self.dt_ocean = 3600 + self.nx = 40 self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{5:08}" self.num_sgmt = 1 self.post_NDS = 16 self.nx_convert = 8 - self.use_SHMEM = True + self.use_SHMEM = 1 self.res = 'CF0720x6C' + case "1120": + self.dt_solar = 3600 + self.dt_irrad = 3600 + self.dt_long = 600 + self.dt_ocean = 3600 + self.nx = 60 + self.ny = self.nx * 6 + self.num_readers = 6 + self.job_sgmt = f"{5:08}" + self.num_sgmt = 1 + self.post_NDS = 16 + self.nx_convert = 8 + self.use_SHMEM = 1 + self.res = 'CF1120x6C' + case "c1440": self.dt_solar = 1800 self.dt_irrad = 1800 - self.dt_long = 300 - self.nx = 48 + self.dt_long = 450 + self.dt_ocean = 1800 + self.nx = 80 self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 self.nx_convert = 8 - self.use_SHMEM = True + self.use_SHMEM = 1 self.res = 'CF1440x6C' case "c2880": self.dt_solar = 1800 self.dt_irrad = 1800 self.dt_long = 300 - self.nx = 96 + self.dt_ocean = 1800 + self.nx = 80 self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{1:08}" @@ -200,10 +232,11 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF2880x6C' case "c5760": - self.dt_solar = 900 - self.dt_irrad = 900 + self.dt_solar = 1800 + self.dt_irrad = 1800 self.dt_long = 300 - self.nx = 192 + self.dt_ocean = 1800 + self.nx = 80 self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{1:08}" @@ -217,15 +250,16 @@ def hres(self, ocean_nx, ocean_ny): case "c270": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = self.dt - self.nx = 18 - self.ny = self.nx * 6 + self.dt_long = 1200 + self.dt_ocean = 3600 + self.nx = 20 + self.ny = self.nx * 6 * 2 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 self.nx_convert = 8 - self.use_SHMEM = True + self.use_SHMEM = 1 self.conus = "" self.stretch_factor = 2.5 self.res = 'CF0270x6C-SG001' @@ -233,31 +267,33 @@ def hres(self, ocean_nx, ocean_ny): case "c540": self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = self.dt - self.nx = 36 + self.dt_long = 600 + self.dt_ocean = 3600 + self.nx = 30 self.ny = self.nx * 6 * 2 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 self.nx_convert = 8 - self.use_SHMEM = True + self.use_SHMEM = 1 self.conus = "" self.stretch_factor = 2.5 self.res = 'CF0540x6C-SG001' case "c1080": - self.dt_solar = 900 - self.dt_irrad = 900 + self.dt_solar = 1800 + self.dt_irrad = 1800 self.dt_long = 300 - self.nx = 72 + self.dt_ocean = 1800 + self.nx = 40 self.ny = self.nx * 6 * 2 self.num_readers = 6 self.job_sgmt = f"{1:08}" self.num_sgmt = 1 self.post_NDS = 32 self.nx_convert = 8 - self.use_SHMEM = True + self.use_SHMEM = 1 self.conus = "" self.stretch_factor = 2.5 self.res = 'CF1080x6C-SG001' @@ -266,14 +302,15 @@ def hres(self, ocean_nx, ocean_ny): self.dt_solar = 900 self.dt_irrad = 900 self.dt_long = 300 - self.nx = 96 + self.dt_ocean = 900 + self.nx = 60 self.ny = self.nx * 6 self.num_readers = 6 self.job_sgmt = f"{5:08}" self.num_sgmt = 1 self.post_NDS = 16 self.nx_convert = 8 - self.use_SHMEM = True + self.use_SHMEM = 1 self.conus = "" self.stretch_factor = 3.0 self.res = 'CF1536x6C-SG002' @@ -282,18 +319,37 @@ def hres(self, ocean_nx, ocean_ny): self.dt_solar = 900 self.dt_irrad = 900 self.dt_long = 300 - self.nx = 192 + self.dt_ocean = 900 + self.nx = 80 self.ny = self.nx * 6 * 2 self.num_readers = 6 self.job_sgmt = f"{5:08}" self.num_sgmt = 1 self.post_NDS = 32 self.nx_convert = 8 - self.use_SHMEM = True + self.use_SHMEM = 1 self.conus = "" self.stretch_factor = 2.5 self.res = 'CF2160x6C-SG001' + case 'c4320': + self.dt_solar = 900 + self.dt_irrad = 900 + self.dt_long = 300 + self.dt_ocean = 900 + self.nx = 80 + self.ny = self.nx * 6 * 2 + self.num_readers = 6 + self.job_sgmt = f"{5:08}" + self.num_sgmt = 1 + self.post_NDS = 32 + self.nx_convert = 8 + self.use_SHMEM = 1 + self.conus = "" + self.stretch_factor = 2.5 + self.res = 'CF4320x6C' + + def set_microphysics(self): match self.microphysics: @@ -310,19 +366,6 @@ def set_turnoff_wsub(self): else: self.MP_turnoff_wsub = "" - # settings for fvcore_layour.rc - def set_fvcore_layout(self): - if self.use_hydrostatic == True: - self.FV_make_NH = "Make_NH = .F." - self.FV_hydro = "hydrostatic = .T." - self.FV_hwt = '#' - else: - self.FV_make_NH = "Make_NH = .T." - self.FV_hydro = "hydrostatic = .F." - self.FV_hwt = '' - if self.microphysics == "MGB2_2M": - self.FV_hydro = ".FALSE." - def set_conus(self): if self.conus == "#": self.schmidt = "do_schmidt = .false." @@ -331,7 +374,7 @@ def set_conus(self): self.target_lat = "target_lat = -90.0" else: self.schmidt = "do_schmidt = .true." - self.FV_stretch_fac = "stretch_fac = $STRETCH_FACTOR" + self.FV_stretch_fac = f"stretch_fac = {self.stretch_factor}" self.target_lon = "target_lon = -98.35" self.target_lat = "target_lat = 39.5" self.FV_hwt = '' @@ -346,6 +389,5 @@ def set_wsub_extdata(self): def config(self, ocean_nx, ocean_ny): self.hres(ocean_nx, ocean_ny) self.set_microphysics() - self.set_fvcore_layout() self.set_conus() self.set_wsub_extdata() diff --git a/gcmpy/scripts/env.py b/gcmpy/scripts/env.py index e80ee7bb..f700df6c 100755 --- a/gcmpy/scripts/env.py +++ b/gcmpy/scripts/env.py @@ -74,31 +74,29 @@ # Set Number of CPUs per Node ####################################################################### if envdict['site'] == 'NCCS': - # NOTE: in the current version of gcm_setup, we never build on - # SLES15, so milan nodes are not an option for NCCS. - if answerdict['processor'].q_answer == 'sky': - envdict['n_CPUs'] = 40 - elif answerdict['processor'].q_answer == 'cas': - ''' - NCCS currently recommends that users do not run with - 48 cores per n_CPUs on SCU16 due to OS issues and - recommends that CPU-intensive works run with 46 or less - cores. As 45 is a multiple of 3, it's the best value - that doesn't waste too much - ''' - envdict['n_CPUs'] = 45 + ''' + NCCS currently recommends that users do not run with + 48 cores per n_CPUs on SCU16 due to OS issues and + recommends that CPU-intensive works run with 46 or less + cores. As 45 is a multiple of 3, it's the best value + that doesn't waste too much + ''' + envdict['n_CPUs'] = 40 elif envdict['site'] == 'NAS': if answerdict['processor'].q_answer == 'has': envdict['n_CPUs'] = 24 elif answerdict['processor'].q_answer == 'bro': - envdict['n_CPUs'] = 28 + envdict['n_CPUs'] = 24 elif answerdict['processor'].q_answer == 'sky': + answerdict['processor'].q_answer = 'sky_ele' envdict['n_CPUs'] = 40 elif answerdict['processor'].q_answer == 'cas': + answerdict['processor'].q_answer = 'cas_ait' envdict['n_CPUs'] = 40 - else: - envdict['n_CPUs'] = 128 + elif answerdict['processor'].q_answer == 'rom' or answerdict['processor'].q_answer == 'mil': + answerdict['processor'].q_answer += '_ait' + envdict['n_CPUs'] = 120 elif envdict['site'] == 'AWS' or envdict['site'] == 'AZURE': # Because we do not know the name of the model or the number of CPUs diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index aaf7a414..f831f762 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -127,7 +127,6 @@ def set_stuff(self): self.archive_n = f"{answerdict['experiment_id'].q_answer[:200]}_ARCH" # ARCHIVE Job Name self.regress_n = f"{answerdict['experiment_id'].q_answer[:200]}_RGRS" # REGRESS Job Name - # Here we need to convert POST_NDS to total tasks. Using 16 cores # per task as a good default post_npes = self.atmos.post_NDS * 16 @@ -150,6 +149,7 @@ def set_stuff(self): run_q - Batch queue name for gcm_run.j run_p - PE Configuration for gcm_run.j run_fp - PE Configuration for gcm_forecast.j + regress_p - PE Configuration for gcm_regress.j post_q - Batch queue name for gcm_post.j plot_q - Batch queue name for gcm_plot.j move_q - Batch queue name for gcm_moveplot.j @@ -183,7 +183,8 @@ def set_stuff(self): self.archive_t = "8:00:00" self.run_q = f"PBS -q normal" self.run_p = f"PBS -l select={self.nodes}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" - self.run_fp = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" + self.run_fp = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" + self.regress_p = f"PBS -l select={self.nodes * 2}:ncpus=${NCPUS_PER_NODE_HALF}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer / 2}" self.post_q = "PBS -q normal" self.plot_q = "PBS -q normal" self.move_q = "PBS -q normal" @@ -233,6 +234,7 @@ def set_stuff(self): self.run_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" self.run_fp = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + self.regress_p = f"SBATCH --nodes={self.nodes * 2} --ntasks-per-node={envdict['n_CPUs'] / 2}" self.post_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.plot_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.move_q = "SBATCH --partition=datamove" @@ -283,6 +285,7 @@ def set_stuff(self): self.run_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" self.run_fp = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + self.regress_p = f"SBATCH --nodes={self.nodes * 2} --ntasks-per-node={envdict['n_CPUs'] / 2}" self.post_q = "NULL" self.plot_q = "NULL" self.move_q = "NULL" @@ -318,6 +321,7 @@ def set_stuff(self): self.run_q = "NULL" self.run_p = "NULL" self.run_fp = "NULL" + self.regress_p = "NULL" self.post_q = "NULL" self.plot_q = "NULL" self.move_q = "NULL" @@ -345,6 +349,15 @@ def set_stuff(self): self.n_backend_pes = 0 + # For ICA and NL3 the gwd files are in a non-bcs location + # and may or may not exist. If they don't we set NCAR_NRDG to 0 + self.NCAR_NRDG = 16 + if self.land.gwd_in_bcs == False and not os.path.exists(f"{self.gwdrs_dir}/gwd_internal_c{self.atmos.im}"): + self.NCAR_NRDG = 0 + + + + # mainly used to create .{*}root files and/or populate them def create_dotfile(self, path, content): try: @@ -503,7 +516,11 @@ def mod_RC_dir_for_pchem(self): # file in the RC dir and modify the atmos.lm values for file_name in os.listdir(rc_dir): file_path = os.path.join(rc_dir, file_name) - + + # ignore the subdirectories in RC/ + if not os.path.isfile(file_path): + continue + with open(file_path, 'r') as file: file_content = file.read() @@ -577,8 +594,8 @@ def config_heartbeat(self): with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'r') as file: file_content = file.read() - file_content = re.sub(r'dt_cpld\s*=\s*.*(,)', rf"dt_cpld = {self.atmos.DT_ocean}\1", file_content) - file_content = re.sub(r'dt_atmos\s*=\s*.*(,)', rf"dt_atmos = {self.atmos.DT_ocean}\1", file_content) + file_content = re.sub(r'dt_cpld\s*=\s*.*(,)', rf"dt_cpld = {self.atmos.dt_ocean}\1", file_content) + file_content = re.sub(r'dt_atmos\s*=\s*.*(,)', rf"dt_atmos = {self.atmos.dt_ocean}\1", file_content) with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'w') as file: file.write(file_content) @@ -592,8 +609,8 @@ def config_heartbeat(self): with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'r') as file: file_content = file.read() - file_content = re.sub(r'DT\s*=\s*.*(,)', rf"DT = {self.atmos.DT_ocean}\1", file_content) - file_content = re.sub(r'DT_THERM\s*=\s*.*(,)', rf"DT_THERM = {self.atmos.DT_ocean}\1", file_content) + file_content = re.sub(r'DT\s*=\s*.*(,)', rf"DT = {self.atmos.dt_ocean}\1", file_content) + file_content = re.sub(r'DT_THERM\s*=\s*.*(,)', rf"DT_THERM = {self.atmos.dt_ocean}\1", file_content) with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'w') as file: file.write(file_content) @@ -624,6 +641,7 @@ def template(self): 'RUN_T': self.run_t, 'RUN_P': self.run_p, 'RUN_FP': self.run_fp, + 'REGRESS_P': self.regress_p, 'RUN_Q': self.run_q, 'POST_N': self.post_n, 'POST_T': self.post_t, @@ -655,6 +673,7 @@ def template(self): 'CHMDIR': self.chem_dir, 'COUPLEDIR': self.coupled_dir, 'GWDRSDIR': self.gwdrs_dir, + 'NCAR_NRDG': self.NCAR_NRDG, 'EXPDIR': self.exp_dir, 'EXPDSC': answerdict['experiment_description'].q_answer, 'HOMDIR': self.exp_dir, @@ -710,6 +729,8 @@ def template(self): 'AERO_PROVIDER': self.gocart.aero_provider, 'OANA_PROVIDER': 'PCHEM', 'EMISSIONS': self.gocart.emissions, + 'CH4_PROVIDER': self.gocart.ch4_provider, + 'CO2_PROVIDER': self.gocart.c02_provider, 'DYCORE': 'FV3', 'AGCM_GRIDNAME': self.atmos.gridname, 'OGCM_GRIDNAME': self.ocean.gridname, @@ -724,7 +745,7 @@ def template(self): 'DT': self.atmos.dt, 'SOLAR_DT': self.atmos.dt_solar, 'IRRAD_DT': self.atmos.dt_irrad, - 'OCEAN_DT': self.atmos.DT_ocean, + 'OCEAN_DT': self.atmos.dt_ocean, 'LONG_DT': self.atmos.dt_long, 'NX': self.atmos.nx, 'NY': self.atmos.ny, @@ -755,7 +776,6 @@ def template(self): 'JOB_SGMT': self.job_sgmt, 'NUM_SGMT': self.atmos.num_sgmt, 'CONUS': self.atmos.conus, - 'FV_HWT': self.atmos.FV_hwt, 'CONVPAR_OPTION': self.atmos.convpar_option, 'STRETCH_FACTOR': self.atmos.stretch_factor, 'INTERPOLATE_SST': self.interpolate_sst, @@ -777,16 +797,12 @@ def template(self): 'PRELOAD_COMMAND': envdict['preload_command'], 'LD_LIBRARY_PATH_CMD': envdict['ld_library_path_command'], 'RUN_CMD': envdict['run_command'], - 'HYDROSTATIC': self.atmos.use_hydrostatic, + 'MODELATM': self.ocean.modelatm, + 'USE_DATA_ATM4OCN': self.ocean.use_data_ATM4OCN, 'FV_SCHMIDT': self.atmos.schmidt, 'FV_STRETCH_FAC': self.atmos.FV_stretch_fac, 'FV_TARGET_LON': self.atmos.target_lon, 'FV_TARGET_LAT': self.atmos.target_lat, - 'FV_MAKENH': self.atmos.FV_make_NH, - 'FV_HYDRO': self.atmos.FV_hydro, - 'GFDL_PROG_CCN': self.atmos.GFDL_prog_ccn, - 'GFDL_USE_CCN': self.atmos.GFDL_use_ccn, - 'GFDL_HYDRO': self.atmos.GFDL_hydro, 'FORCEDAS': self.atmos.force_das, 'FORCEGCM': self.atmos.force_gcm, 'HIST_CICE4': '#DELETE', diff --git a/gcmpy/scripts/generate_question.py b/gcmpy/scripts/generate_question.py index e2efbe20..7d34913e 100755 --- a/gcmpy/scripts/generate_question.py +++ b/gcmpy/scripts/generate_question.py @@ -24,17 +24,17 @@ def __init__(self, q_name, q_type, q_prompt, q_choices, q_default, q_follows_up) def should_ask(self, answerdict): if self.q_follows_up: for prev_question, accepted_answers in self.q_follows_up: - if answerdict[prev_question].q_answer in accepted_answers or ('any' in accepted_answers and answerdict[prev_question].q_answer != None): + if answerdict[prev_question].q_answer in accepted_answers or ('any' in accepted_answers and answerdict[prev_question].q_answer != None) or ('was_not_asked' in accepted_answers): return True return False return True # loads the questionary api based on yaml configurations - def load_question(self, answerdict): + def load_question(self, question): # check if the yaml entry should be skipped - if not self.should_ask(answerdict): + if not self.should_ask(question): return # if should_ask() returns true, call correct questionary API diff --git a/gcmpy/scripts/gocart.py b/gcmpy/scripts/gocart.py index e64e6166..46133be6 100755 --- a/gcmpy/scripts/gocart.py +++ b/gcmpy/scripts/gocart.py @@ -3,8 +3,13 @@ class gocart: def __init__(self): - self.aerosol = answerdict["gocart_aerosols"].q_answer - self.emissions = f"{answerdict['gocart_emission'].q_answer}_EMISSIONS" + # Gocart questions are skipped if data atmosphere is turned on. Use defaults + if answerdict['OM_data_atmos'].q_answer == True: + self.aerosol = 'Actual' + self.emissions = 'OPS_EMISSIONS' + else: + self.aerosol = answerdict["gocart_aerosols"].q_answer + self.emissions = f"{answerdict['gocart_emission'].q_answer}_EMISSIONS" self.data_driven = None self.ops_species = '#' self.cmip_species = '#' @@ -16,6 +21,10 @@ def __init__(self): self.aero_provider = 'GOCART2G' self.rats_provider = 'PCHEM' + # Additional RATS settings for specific GHGs + self.ch4_provider = 'none' + self.c02_provider = 'none' + # for debugging purposes def print_vars(self): all_vars = vars(self) diff --git a/gcmpy/scripts/land.py b/gcmpy/scripts/land.py index 7e3059a5..8fafd97c 100755 --- a/gcmpy/scripts/land.py +++ b/gcmpy/scripts/land.py @@ -3,8 +3,13 @@ class land: def __init__(self): - self.model = answerdict["LS_model"].q_answer - self.bcs = answerdict["LS_boundary_conditions"].q_answer + # If data atmosphere is enabled, land questions are skipped. Use default values. + if answerdict['OM_data_atmos'].q_answer == True: + self.model = "Catchment" + self.bcs = "NL3" + else: + self.model = answerdict["LS_model"].q_answer + self.bcs = answerdict["LS_boundary_conditions"].q_answer self.parameters = '' self.emip_bcs_in = '' self.emip_oldland = '' @@ -25,19 +30,22 @@ def set_bcs(self): self.emip_bcs_in = "GM4" self.emip_oldland = "" self.emip_newland = "#DELETE" - self.emip_MERRA2 = "MERRA2" + self.emip_MERRA2 = "MERRA2" + self.gwd_in_bcs = False elif self.bcs == "NL3": self.parameters = "" self.emip_bcs_in = "NL3" self.emip_oldland = "#DELETE" self.emip_newland = "" - self.emip_MERRA2 = "MERRA2_NewLand" - elif self.bcs == "v12": + self.emip_MERRA2 = "MERRA2_NewLand" + self.gwd_in_bcs = False + elif self.bcs == "v13": self.parameters = "" self.emip_bcs_in = "NL3" self.emip_oldland = "#DELETE" self.emip_newland = "" - self.emip_MERRA2 = "MERRA2_NewLand" + self.emip_MERRA2 = "MERRA2_NewLand" + self.gwd_in_bcs = True def set_catchment(self): diff --git a/gcmpy/scripts/ocean.py b/gcmpy/scripts/ocean.py index 2d7a3720..b9dbaecb 100644 --- a/gcmpy/scripts/ocean.py +++ b/gcmpy/scripts/ocean.py @@ -25,6 +25,7 @@ def config(ocean): ocean.set_data_atmosphere() else: ocean.set_uncoupled() + ocean.set_data_atmosphere() def set_coupled(ocean): @@ -149,7 +150,7 @@ def set_uncoupled(ocean): ocean.cube = '#DELETE' ocean.ostia = '' ocean.data = '' - elif hr_code == 'cs': + elif hr_code == 'CS': # need to add input validation for this case ocean.IM = int(answerdict['AM_horizontal_res'].q_answer[1:]) ocean.JM = ocean.IM * 6 @@ -176,6 +177,7 @@ def set_uncoupled(ocean): #ocean.data = #THIS IS WILL OVERWRITE THE BLOCK ABOVE ocean.name = '' ocean.preload = '' + ocean.LM = 34 ocean.coupled = '#DELETE' ocean.MOM5 = '#DELETE' ocean.MOM6 = '#DELETE' diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index 637a0931..98afdd9b 100755 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -22,41 +22,78 @@ def experiment_desc(answerdict, i): print(color.RED + "The experiment description must be different from the ID!") answerdict[i].load_question(answerdict) + @staticmethod + def io_server_defualt(answerdict, i): + if i != 'io_server': + return + match answerdict['AM_horizontal_res'].q_answer: + case 'c180' | 'c360' | 'c720' | 'c1120' | 'c1440' | 'c2880' | 'c5760' | 'c270' | 'c540' | 'c1080' | 'c1536' | 'c2160': + answerdict[i].q_default = True + case _: + answerdict[i].q_default = False + + @staticmethod def processor_choices(answerdict, i): - if i == "processor": - if envdict["site"] == "NCCS": - answerdict[i].q_choices = ["cas", "sky"] - elif envdict["site"] == "NAS": - answerdict[i].q_choices = ["sky", "has", "bro", "cas", "rom", "mil"] - else: - exit(1) + if i != "processor": + return + + if envdict["site"] == "NCCS": + answerdict[i].q_choices = ["cas"] + elif envdict["site"] == "NAS": + answerdict[i].q_choices = ["rom", "sky", "has", "bro", "cas", "mil"] + else: + exit(1) + + print(color.GREEN + "NOTE Due to how FV3 is compiled by default, Sandy Bridge\n" + \ + "and Ivy Bridge are not supported by current GEOS" + color.RESET) + + @staticmethod + def OM_horizontal_res_default(answerdict, i): + if i != 'OM_horizontal_res': + return + + # The default ocean resolution is based on the atmospheric resolution + match answerdict['AM_horizontal_res'].q_answer: + case 'c12' | 'c24' | 'c48': + answerdict[i].q_choices = ['o1 (1 -deg, 360x180 Reynolds)', \ + 'o2 (1/4-deg, 1440x720 MERRA-2)', \ + 'o3 (1/8-deg, 2880x1440 OSTIA)'] + case _: + answerdict[i].q_choices = ['CS (Cubed-Sphere OSTIA)', \ + 'o1 (1 -deg, 360x180 Reynolds)', \ + 'o2 (1/4-deg, 1440x720 MERRA-2)', \ + 'o3 (1/8-deg, 2880x1440 OSTIA)'] - print(color.GREEN + "NOTE Due to how FV3 is compiled by default, Sandy Bridge\n" + \ - "and Ivy Bridge are not supported by current GEOS" + color.RESET) @staticmethod def MIT_hres_choices(answerdict, i): - if i == "OM_MIT_horizontal_res": - if answerdict["AM_horizontal_res"].q_answer == "c720": - answerdict[i].q_choices = ["llc1080 (1/12-deg, Lat-Lon-Cube)"] - elif answerdict["AM_horizontal_res"].q_answer == "c1440": - answerdict[i].q_choices = ["llc2160 (1/24-deg, Lat-Lon-Cube)"] + if i != "OM_MIT_horizontal_res": + return + if answerdict["AM_horizontal_res"].q_answer == "c720": + answerdict[i].q_choices = ["llc1080 (1/12-deg, Lat-Lon-Cube)"] + elif answerdict["AM_horizontal_res"].q_answer == "c1440": + answerdict[i].q_choices = ["llc2160 (1/24-deg, Lat-Lon-Cube)"] @staticmethod def MOM_hres_default(answerdict, i): - if i == "OM_MOM_horizontal_res" and \ - answerdict["OM_name"].q_answer == "MOM6" and \ - answerdict["AM_horizontal_res"].q_answer == "c12": + if i != "OM_MOM_horizontal_res": + return + if answerdict["OM_name"].q_answer == "MOM6" and answerdict["AM_horizontal_res"].q_answer == "c12": answerdict[i].q_default = "72 36" + ''' + THIS METHOD IS BUGGED FOR NOW @staticmethod def OM_hres_valid(answerdict, i): - if i == "OM_MOM_horizontal_res" and answerdict[i].q_answer != None: - #input validation using regex - while not re.match(r"^\d+\s\d+$", answerdict[i].q_answer): - print(color.RED + "please enter exactly 2 numbers separated by a space! (int int)\n") - answerdict[i].load_question(answerdict) + if i != "OM_MOM_horizontal_res": + return + + #input validation using regex + while not re.match(r"^\d+\s\d+$", answerdict[i].q_answer): + print(color.RED + "please enter exactly 2 numbers separated by a space! (int int)\n") + answerdict[i].load_question(answerdict) + ''' @staticmethod def seaice_choices(answerdict, i): @@ -66,96 +103,105 @@ def seaice_choices(answerdict, i): @staticmethod def heartbeat_default(answerdict, i): - if i == "heartbeat": - ''' - Default heartbeat is determined by atmospheric resolution. - Of course, this just the recommended value. The user can - enter whatever value they like - ''' - heartbeat = "" - match answerdict["AM_horizontal_res"].q_answer: - case "c12" | "c24" | "c48" | "c90": - heartbeat = "1800" - case "c180": - heartbeat = "900" - case "c360": - heartbeat = "450" - case "c720": - heartbeat = "225" - case "c1440": - heartbeat = "75" - case "c5760": - heartbeat = "30" - case "c270" | "c540": - heartbeat = "600" - case "c1080": - heartbeat = "150" - case "c1536": - heartbeat = "75" - case "c2160": - heartbeat = "60" - - - # Per W. Putman recommendation, set heartbeat to 450s anytime BACM_1M is selected - # ((IMPORTANT: default must be type string)) - if answerdict["AM_microphysics"].q_answer == "BACM_1M": - heartbeat = "450" - - answerdict[i].q_default = heartbeat + if i != "heartbeat": + return + ''' + Default heartbeat is determined by atmospheric resolution. + Of course, this just the recommended value. The user can + enter whatever value they like + ''' + heartbeat = "" + match answerdict["AM_horizontal_res"].q_answer: + case 'c12': + heartbeat = 3600 + case 'c24': + heartbeat = 1800 + case 'c48': + heartbeat = 1200 + case 'c90': + heartbeat = 900 + case 'c180' | 'c270': + heartbeat = 600 + case 'c360': + heartbeat = 450 + case 'c720' | 'c1120' | 'c540': + heartbeat = 300 + case 'c1440': + heartbeat = 225 + case 'c2880' | 'c1080': + heartbeat = 150 + case 'c5760' | 'c1536' | 'c2160': + heartbeat = 75 + case 'c4320': + heartbeat = 30 + + + # Per W. Putman recommendation, set heartbeat to 450s anytime BACM_1M is selected + if answerdict["AM_microphysics"].q_answer == "BACM_1M": + heartbeat = 450 + + # ((IMPORTANT: default must be type string due to some limitation in questionary)) + answerdict[i].q_default = str(heartbeat) @staticmethod def heartbeat_valid(answerdict, i): - if i == "heartbeat": - # input validation using regex - while not re.match(r"^\d+$", answerdict[i].q_answer): - print(f"{color.RED}please enter exactly 1 number!{color.RESET}") - answerdict[i].load_question(answerdict) + if i != "heartbeat": + return + # input validation using regex + while not re.match(r"^\d+$", answerdict[i].q_answer): + print(f"{color.RED}please enter exactly 1 number!{color.RESET}") + answerdict[i].load_question(answerdict) @staticmethod def history_template_default(answerdict, i): - if i == "history_template": + if i != "history_template": + return - if answerdict['OM_name'].q_answer == 'MOM5': - answerdict[i].q_default = 'HISTORY.AOGCM-MOM5.rc.tmpl' - elif answerdict['OM_name'].q_answer == "MOM6": - answerdict[i].q_default = 'HISTORY.AOGCM.rc.tmpl' - elif answerdict['OM_name'].q_answer == 'MIT': - answerdict[i].q_default = 'HISTORY.AOGCM_MITgcm.rc.tmpl' - elif answerdict['OM_data_atmos'].q_answer == True: - answerdict[i].q_default == 'HISTORY.DATAATM.rc.tmpl' - else: - answerdict[i].q_default = 'HISTORY.AGCM.rc.tmpl' + if answerdict['OM_name'].q_answer == 'MOM5': + answerdict[i].q_default = 'HISTORY.AOGCM-MOM5.rc.tmpl' + elif answerdict['OM_name'].q_answer == "MOM6": + answerdict[i].q_default = 'HISTORY.AOGCM.rc.tmpl' + elif answerdict['OM_name'].q_answer == 'MIT': + answerdict[i].q_default = 'HISTORY.AOGCM_MITgcm.rc.tmpl' + elif answerdict['OM_data_atmos'].q_answer == True: + answerdict[i].q_default == 'HISTORY.DATAATM.rc.tmpl' + else: + answerdict[i].q_default = 'HISTORY.AGCM.rc.tmpl' @staticmethod def exp_dir_default(answerdict, i): - if i == "exp_dir": - root = f"{os.environ.get('HOME')}/.EXPDIRroot" - if os.path.exists(root): - try: - with open(root, "r") as file: - answerdict[i].q_default = f"{file.read().strip()}/{answerdict['experiment_id'].q_answer}" - except Exception as e: - print(f"An error occurred while reading {color.BLUE}.EXPDIRroot{color.RESET}: {str(e)}") - elif envdict['site'] in ['NAS','NCCS']: - answerdict[i].q_default = f"/{'discover/' if envdict['site'] == 'NCCS' else ''}nobackup/{os.environ.get('LOGNAME')}/{answerdict['experiment_id'].q_answer}" - else: - answerdict[i].q_default = f"{os.environ.get('HOME')}/{answerdict['experiment_id']}" + if i != "exp_dir": + return + + root = f"{os.environ.get('HOME')}/.EXPDIRroot" + if os.path.exists(root): + try: + with open(root, "r") as file: + answerdict[i].q_default = f"{file.read().strip()}/{answerdict['experiment_id'].q_answer}" + except Exception as e: + print(f"An error occurred while reading {color.BLUE}.EXPDIRroot{color.RESET}: {str(e)}") + elif envdict['site'] in ['NAS','NCCS']: + answerdict[i].q_default = f"/{'discover/' if envdict['site'] == 'NCCS' else ''}nobackup/{os.environ.get('LOGNAME')}/{answerdict['experiment_id'].q_answer}" + else: + answerdict[i].q_default = f"{os.environ.get('HOME')}/{answerdict['experiment_id']}" @staticmethod def exp_dir_valid(answerdict, i): - if i == "home_dir" or i == "exp_dir": - while os.path.basename(answerdict[i].q_answer) != answerdict['experiment_id'].q_answer: - print(f"{color.RED}This directory MUST point to the experiment ID: {color.BLUE}{answerdict['experiment_id'].q_answer}{color.RED}!{color.RESET}") - answerdict[i].load_question(answerdict) + if i != "home_dir" or i != "exp_dir": + return + while os.path.basename(answerdict[i].q_answer) != answerdict['experiment_id'].q_answer: + print(f"{color.RED}This directory MUST point to the experiment ID: {color.BLUE}{answerdict['experiment_id'].q_answer}{color.RED}!{color.RESET}") + answerdict[i].load_question(answerdict) @staticmethod def group_root_default(answerdict, i): - if i == "group_root": - groups = subprocess.check_output('groups', shell=True).decode('utf-8').strip() - answerdict[i].q_default = groups.split()[0] + if i != "group_root": + return + groups = subprocess.check_output('groups', shell=True).decode('utf-8').strip() + answerdict[i].q_default = groups.split()[0] @@ -196,13 +242,15 @@ def process(): yaml_questions[i]["choices"], \ yaml_questions[i]["default_answer"],\ yaml_questions[i]["follows_up"]) - + answerdict[i] = temp # if the question properties need to dynamically change at # runtime call handle function BEFORE load_question() - handle.processor_choices(answerdict,i) + handle.io_server_defualt(answerdict, i) + handle.processor_choices(answerdict, i) + handle.OM_horizontal_res_default(answerdict, i) handle.MIT_hres_choices(answerdict, i) handle.MOM_hres_default(answerdict, i) handle.seaice_choices(answerdict, i) @@ -211,14 +259,13 @@ def process(): handle.exp_dir_default(answerdict, i) # prompts the user with the question - answerdict[i].load_question(answerdict) + answerdict[i].load_question(answerdict) # input validation and other post processing goes here, # AFTER load_question() call handle.experiment_desc(answerdict, i) - handle.OM_hres_valid(answerdict, i) + # handle.OM_hres_valid(answerdict, i) handle.heartbeat_valid(answerdict, i) - #handle.history_template_valid(answerdict, i) handle.exp_dir_valid(answerdict, i) # strips the first word from every select type question diff --git a/gcmpy/yaml/atmospheric_model.yaml b/gcmpy/yaml/atmospheric_model.yaml index 6cce1db2..34fec4e8 100755 --- a/gcmpy/yaml/atmospheric_model.yaml +++ b/gcmpy/yaml/atmospheric_model.yaml @@ -1,22 +1,22 @@ AM_horizontal_res: type: 'select' prompt: 'Select the atmospheric models HORIZONTAL resolution:' - choices: ['c12 -- 8 deg (750.0 km)', 'c24 -- 4 deg (375.0 km)', 'c48 -- 2 deg (187.5 km)', 'c90 -- 1 deg (100.0 km)', 'c180 -- 1/2 deg ( 50.0 km)', 'c360 -- 1/4 deg ( 25.0 km)', 'c720 -- 1/8 deg ( 12.5 km)', 'c1440 - 1/16 deg ( 6.25 km)', 'c2880 - 1/32 deg ( 3.125 km)', 'c5760 - 1/64 deg ( 1.5625 km)','c270 -- (16.0 -100 km)', 'c540 -- ( 8.0 - 50 km)', 'c1080 - ( 4.0 - 25 km)', 'c1536 - ( 2.0 - 20 km)', 'c2160 - ( 2.0 - 12 km)'] + choices: ['c12 -- 8 deg (750.0 km)', 'c24 -- 4 deg (375.0 km)', 'c48 -- 2 deg (187.5 km)', 'c90 -- 1 deg (100.0 km)', 'c180 -- 1/2 deg ( 50.0 km)', 'c360 -- 1/4 deg ( 25.0 km)', 'c720 -- 1/8 deg ( 12.5 km)', 'c1120 -- 1/12 deg ( 8.0 km)', 'c1440 - 1/16 deg ( 6.25 km)','c270 -- (16.0 -100 km)', 'c540 -- ( 8.0 - 50 km)', 'c1080 - ( 4.0 - 25 km)', 'c1536 - ( 2.0 - 20 km)', 'c2160 - ( 2.0 - 12 km)'] default_answer: '' follows_up: '' - answer: 'c12' + answer: '' AM_vertical_res: - type: 'select' + type: 'text' prompt: 'Enter the atmospheric models VERTICAL resolution:' - choices: ['72', '91', '137', '181'] - default_answer: '' + choices: '' + default_answer: '181' follows_up: '' AM_microphysics: type: 'select' prompt: 'Select the Atmospheric Model Microphysics:' - choices: ['BACM_1M -- 3-phase 1-moment Bacmeister et al', 'GFDL_1M -- 6-phase 1-moment Geophysical Fluid Dynamics Laboratory', 'MGB2_2M -- 5 or 6-phase 2-moment Morrison & Gettleman'] + choices: ['GFDL_1M -- 6-phase 1-moment Geophysical Fluid Dynamics Laboratory', 'BACM_1M -- 3-phase 1-moment Bacmeister et al', 'MGB2_2M -- 5 or 6-phase 2-moment Morrison & Gettleman'] default_answer: '' follows_up: '' @@ -38,7 +38,7 @@ io_server: type: 'confirm' prompt: 'Would you like to IOSERVER?' choices: '' - default_answer: False + default_answer: '' follows_up: '' diff --git a/gcmpy/yaml/gocart.yaml b/gcmpy/yaml/gocart.yaml index f7c681ff..5eeae936 100755 --- a/gcmpy/yaml/gocart.yaml +++ b/gcmpy/yaml/gocart.yaml @@ -3,11 +3,15 @@ gocart_aerosols: prompt: 'Do you wish to run GOCART with Actual or Climatological Aersols?' choices: ['Actual', 'Climatological'] default_answer: '' - follows_up: '' + follows_up: + - ['OM_data_atmos', [False]] + - ['OM_data_atmos', ['was_not_asked']] gocart_emission: type: 'select' prompt: 'Select the GOCART Emission Files to use:' choices: ['AMIP', 'OPS'] default_answer: '' - follows_up: '' + follows_up: + - ['OM_data_atmos', [False]] + - ['OM_data_atmos', ['was_not_asked']] diff --git a/gcmpy/yaml/land_model.yaml b/gcmpy/yaml/land_model.yaml index 7972cbfb..cb5efe1b 100755 --- a/gcmpy/yaml/land_model.yaml +++ b/gcmpy/yaml/land_model.yaml @@ -1,13 +1,17 @@ LS_boundary_conditions: type: 'select' prompt: 'Select the Land Surface Boundary Conditions:' - choices: ['NL3', 'ICA', 'v12'] + choices: ['v13', 'NL3', 'ICA'] default_answer: '' - follows_up: '' + follows_up: + - ['OM_data_atmos', [False]] + - ['OM_data_atmos', ['was_not_asked']] LS_model: type: 'select' prompt: 'Select the Land Surface Model:' choices: ['Catchment', 'CatchmentCN-CLM4.0 (CN_CLM40)'] default_answer: '' - follows_up: '' + follows_up: + - ['OM_data_atmos', [False]] + - ['OM_data_atmos', ['was_not_asked']] From 5320e33eb0fa9d7df564d3cad25a4c37d4aa2f7b Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Thu, 10 Apr 2025 11:19:14 -0400 Subject: [PATCH 18/37] fixed CMakeLists.txt and updated gitignore --- .gitignore | 176 ++++++++++++++++++ gcmpy/scripts/CMakeLists.txt | 2 +- .../__pycache__/atmosphere.cpython-311.pyc | Bin 12957 -> 0 bytes .../__pycache__/atmosphere.cpython-312.pyc | Bin 11934 -> 0 bytes gcmpy/scripts/__pycache__/env.cpython-311.pyc | Bin 5587 -> 0 bytes gcmpy/scripts/__pycache__/env.cpython-312.pyc | Bin 4807 -> 0 bytes .../generate_question.cpython-311.pyc | Bin 3146 -> 0 bytes .../generate_question.cpython-312.pyc | Bin 2995 -> 0 bytes .../__pycache__/gocart.cpython-311.pyc | Bin 3188 -> 0 bytes .../__pycache__/gocart.cpython-312.pyc | Bin 2697 -> 0 bytes .../scripts/__pycache__/land.cpython-311.pyc | Bin 3096 -> 0 bytes .../scripts/__pycache__/land.cpython-312.pyc | Bin 2660 -> 0 bytes .../scripts/__pycache__/ocean.cpython-311.pyc | Bin 11172 -> 0 bytes .../scripts/__pycache__/ocean.cpython-312.pyc | Bin 11210 -> 0 bytes .../process_questions.cpython-311.pyc | Bin 14604 -> 0 bytes .../process_questions.cpython-312.pyc | Bin 11971 -> 0 bytes .../__pycache__/utility.cpython-311.pyc | Bin 4163 -> 0 bytes .../__pycache__/utility.cpython-312.pyc | Bin 3860 -> 0 bytes gcmpy/scripts/test_generate_question.py | 9 - 19 files changed, 177 insertions(+), 10 deletions(-) delete mode 100644 gcmpy/scripts/__pycache__/atmosphere.cpython-311.pyc delete mode 100644 gcmpy/scripts/__pycache__/atmosphere.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/env.cpython-311.pyc delete mode 100644 gcmpy/scripts/__pycache__/env.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/generate_question.cpython-311.pyc delete mode 100644 gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/gocart.cpython-311.pyc delete mode 100644 gcmpy/scripts/__pycache__/gocart.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/land.cpython-311.pyc delete mode 100644 gcmpy/scripts/__pycache__/land.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/ocean.cpython-311.pyc delete mode 100644 gcmpy/scripts/__pycache__/ocean.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/process_questions.cpython-311.pyc delete mode 100644 gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc delete mode 100644 gcmpy/scripts/__pycache__/utility.cpython-311.pyc delete mode 100644 gcmpy/scripts/__pycache__/utility.cpython-312.pyc delete mode 100644 gcmpy/scripts/test_generate_question.py diff --git a/.gitignore b/.gitignore index d4f31ef1..0d547507 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,179 @@ gcmpy/sync.sh gcmpy/jinjafy.py +####################### generic ######################### + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +#uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc diff --git a/gcmpy/scripts/CMakeLists.txt b/gcmpy/scripts/CMakeLists.txt index 440db4ac..20693139 100644 --- a/gcmpy/scripts/CMakeLists.txt +++ b/gcmpy/scripts/CMakeLists.txt @@ -4,7 +4,7 @@ set (programs generate_question.py gocart.py land.py - model.py + gcm_setup.py ocean.py process_questions.py utility.py diff --git a/gcmpy/scripts/__pycache__/atmosphere.cpython-311.pyc b/gcmpy/scripts/__pycache__/atmosphere.cpython-311.pyc deleted file mode 100644 index 86c585b54d334dc7c848a91f1baa268b540f4e3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12957 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 diff --git a/gcmpy/scripts/__pycache__/env.cpython-311.pyc b/gcmpy/scripts/__pycache__/env.cpython-311.pyc deleted file mode 100644 index 6f433e7631bbfa04fa558e41d8a8c1f423c6d42e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5587 zcmcgvO>7&-72f4?$>oyzA@y(lt*jqQQDiEX<2bS_Tb5`^wnVw4mBfS-g5r)O%H)#S zB_)|~QKoQFCQwnfaACGcQ6UH%8RSe04`;_tXqeoQ6i%REC6cL|>0$uQw7zDXac z_YFRS{-%6JcpJiW#N;zY%sz93@i7sL&q5aQtdF%2Jms_UMxPDdH3kCJB67X1yctjP z&65D-; zP;7BVvK<_? zvfS!@k%_N83sX9#@tK&q5~c|e>&<1<4n+Ce4>I%h6`r-<1J8b}dlzGQM|FRv_1hA_ zLKr;o&CY?i3UD>1GMZph!~d*rW3_(&4}E<{s=WGCYtfPFs8`zSYlrA{@J+V~zIpnP z@2Xcpez*AA1*eX01$^6c@kapP!ndRL4SYJ}Zm(B?Tr<;Sh9xNea5PA>cj+StLL0x?B!TR;?@;-cD31Q~@ z_vMhnH_yZmJQe@XXX1~Q@QwUnHO7CS!+`~)@YiZog{DLMl3u9BJVVkSs!LkT+;HV7F_+B z_*2#UyiEA|P~Uf{PriQCzcWy&O_}F=t7Vq;;z|5hU1>-{u=Wx!5t4D!uti-XHc67W z2Hyo3|DcyZ$NC6yK=)0xM_+ly7lB+K+}DDx)&k2Fwl<04E{D8wy5yCMa0>BPddN2f z-Wghdp)Bp`o))fvj>A8&jss;KaUSunR%?3Ldw}_`Hdn9a%XZrNahN%S^MgMN+>dl_ z0=RQJM|uhV{61oGA90})F*NlUyT?6b)XYfO;6uT<#>4{gHJzh_(Qs7MShN*Hv3Mvd zNEbCzFd7RX{xQCmJpKlrq-kU%91?C^P1cNzNFiZ05e|r<_)R>%hQhI=VPq}YG8K(P z0s_wg5^(`>HGv{RoI9Glc$5>Oaqhc5A__)Vg-{al$2r!E5SNewt7x3nj6#%0nlT^- z*E9;ngGsY@?yBp!7}Q8nGfJU2O0pLwy{_pw4-5wPFI8X#KEU{Beu?w$GNkQY;ui5{ z%}>Z%WE@7y&j#@taTij1yOt-s#C_6zpVX*GEOg(X8IF%?R6MXM;oAboeLdk^jjc!# zCoe3IjX5Q0EpQ_m6`eD#Mek}b;tUB=JP-~$mqUUR`mvi%DJX_wamfiGI3BzCwdL$8 z63|vmoDlI%WgLDIKBoVIzZ4;xMxkYbDe0HNRI=Esq+bG(7&2()XbcIUpk`c)1-C?8 zK)%1-Vm*iv@m)~F7qgPZBEDMby6WT%o~clnIVm$IvsAj_w^aHFu!ow6uTr3}F@&{c zLP8vcffMofS7Ra@fmkTGc0!|J3`aK-i;MWOsTti0pX#rX2ku+Tl%WW z*S#7&>09!+l1Er?NC+bCW;6jAj5skN2$1evRN#_h`e-B}#W@MZx%e95_Lbmp-uH6R z6%MP2fue-ME60<)F0fS8!9pUk3~U(_10E;zIH#GH+?U;pue&vRJ|rZzk~K~&*cpr^ zLc&TkIpXqo7CqzKk`P!9BQ750L=+c8XajgqqFU~8%`_blH$y_QeSg^vA-XAmJ;60N zBf)q=L|W7IwfSlPoZIX2T=mb-UGPkL=3HK_E+(RIG{F0V#j~v0bzBi}&3|R`>a5lh z=KbN&vKSC=`f(X4W0O`K(1gH^2r*8x0#}~VSlH`|$2Gq=Ijz+JUnwuy)`t(xg*mqq zNs)lRLdejInjs1Smu^Z>vBH7)N>q$!_LA5AZzqtXS1ipCds{On;-N6qBoUu=(TE9+ zi3!KpTE>FX8jVZYmd2nhIDU5V#hJfw*3DRyQ;Xikim8 zM95yfCTR{a5RyfZGW++(faNh<#A1G#yHx7oDN7gG;#%!yqGQ;RP=-Z zvga0Eq6p{1h_+y>x=11%50!+2k(veY5FiX~a7W{Fkysc-5M(Q_FS}3ZM^-=eUo&ST zQ9cny6Cw}R;le77f?o?1Ns=njDnGBOM3-D{DsftVUQ-E&Ty6!Eg)|m8!cv=}Rck|v zQCmA@qN%_Twx;x}8SkApvVrV!cKOcrob{+;Jz5}GlG90QN@c9+3)|+*={(aeGwo`9 zW13FWDqE9Y-aeM`=h;4)?Ngb~oyI)VFYB#5`9_}Yl-bUmh8@p`ExXenbnkQnFwH7V zXO8Jsm~L5bkC=Wu)-Mm7e=zny{M#$JflCE~bd%HM7X*1srgd)IO; z=aiOn4;pd~m*Q|ebX>|iF6A8aievtv!;^P-a*nHt;`ZjR zZoPLaJG-;={^IWST-~@*H~z^~jy2ml>1kW@y>8SK zzLN1~yeiG6gQ@GO>)EEvSY}MMHK&5Ay%B7s->HQ(sclVrwteqj-@cw=3-yH2nm%>= zTxKOtb;wjl!C<19LM_qOo|;L|=8R3y9?`b+Yq$MbI!|}Xbf;>zXNDDXmtsD)`*Pkq zDw{{uj;^#h!{nGYXsV?lb6K%)ie+ebDQ`I;TTVQ8e)wdX&76TOQkcOX6uh_opj|n& zpqzS5_WARt{PHQk$~g3`WM&X{+r5}$P83PWkP)Ke}O+?#J)~d7)%0up4>!Q-S_^{QR zZ}sL{mz36}11AHpg@f+JcNSH1ZF=MOPqWAJ<{sJHQ!tt=t*X5#)0m0o>;sB@pgaus59Rn^5{DGUhCktM4h$fYjkS`2sKe3X_Ae zr*Ti7JbC&sXj$I^QQ0@)y_)0BDBPL!OlCG`>y&Ms zPt-c7Xy1E(2FhoemTOvzYDA83(|eu3?DXLe6+Z*4v|=kptX#8K-u_>I#%J3tx^;Emn6M z@oD3TyN3FVv;qHFjnQp4e`cpJ-$-Jup diff --git a/gcmpy/scripts/__pycache__/env.cpython-312.pyc b/gcmpy/scripts/__pycache__/env.cpython-312.pyc deleted file mode 100644 index f54cf81cd4a8cdd7c7197bd908b3c282d662ddc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4807 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 Tf9<5m{m9`_p8i`Sh423Xi#vw+ diff --git a/gcmpy/scripts/__pycache__/generate_question.cpython-311.pyc b/gcmpy/scripts/__pycache__/generate_question.cpython-311.pyc deleted file mode 100644 index 62a6cdb1259e05db3aeab66920b83343e3bf8c8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3146 zcmbVO&2JM&6rcUDli+L;aJEgvM*;;Aw+I6v{ZfHef>0#nP!d2&q1(l~Nt~?h&CDi{ z)RY`Jm?~9KFUgTs6sX7_KqU@6^iZi6J934!5)x9?LvN-*J#cB?oAs`73=-<|?wfh@ z=FOXZ@6B&~M^QEqpx=yt#{X<4THv%jjtnTW8KT-R5b{rrEUZxGmFKaw3~bnhd*!Ii}B8j@vq|jb$w>dx>c? zHqO>F?2<`gC7GGl7=u? z#*ZHx8Xixkh;M<${5h`#^4bd+4!cOERSh*u=Yuh{KRBa_eNc9yViL&!<9gl>G4Z`Yn=*gsMJEl=hGGka=m_FLUP1!_t#sV#yn%~?I^_sE^CbJ)aLEIzlrO1{F zkz2aU{qL0ek5-7N^m110h~H2OJ@ImM>vFmj-BXGV6y7^gh~o3BSvWUdNbtv+tq^iq zI3_+NBrObj&5#I#!{RydZyY>_Qnk4tS}57#hY~awYE5}_&+@_LgB6JnK8|+X7$~<# z^A6nvJFQDH9wMIPK}aAb`6diBQck!Hsk|4YlZgfy#*zp|3}K2F4?XMz2a}LVo=#j3 z=GKlcnGEJQSh-c241i-rybYH30_&T2_8RCmjNA)GuZWqS>UJbmchq0EBRs&IUbdr^ zbrAcCzQ3sR9eSZ}ej%Xqb-ocwIIXM$@mKVHsLpp&)%StA?+)U;&UcWB|M%S-!Vv&D zVO7MM6Rzx-mmRosntW_+p7kyt(``y-Gh->5jtO)N*tlW9Rx|0u1khA5S+;d&BGyI` zNI2lS5g!kAI!8C-Fo$6LCU?Vh?P5bW8u|v1U{iD(&g?W0*aN@jQ}&|w>98Eoqh+HvVVaskV=?zbbfR7tEY0*yre^c;so-V2*C3U1`^THh#)RRT^WJx{wP(8J(o+_%R zOX}(T;Nz}s{!PL`CJ_tcy@mI$rnwt5EuA%HEbO;x5K-OoG;|}Tgy*>rdOs3w%psWK zjm{b7j(r4dA^26qrqI?330PM+)L9_`>+A^iR7fN9R>y^t@CM|A*jgtHHU8s)l9uQj zpi24^(Gt%MR?8X%wnUugbPkSJDM#v&vtII1lXU{}a{Tn|{I(wBsA!1Qi%?EbG??FP zTc*y;Uax?Aoe8touj=h1G0BxIGvi9kp>9)(F+8=!)(^hS!moYz!}t@c?ufO3x=-4t2r3+Q2+}oD9__W*NmJ zNHO?SM#d|MuUzl#S@Q>8IUc45VID?-eG9B234%~2EerftCYuWWQzi!rFM29+NRTV7 fy9Fq>M)m~9p4Jp2LP&rQX=G1u?CA>>{0sjB6lt%T diff --git a/gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc b/gcmpy/scripts/__pycache__/generate_question.cpython-312.pyc deleted file mode 100644 index a4d5b6bbefaa6fbaaabb988d15eaacaf38caba86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2995 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 DzX(Im diff --git a/gcmpy/scripts/__pycache__/land.cpython-311.pyc b/gcmpy/scripts/__pycache__/land.cpython-311.pyc deleted file mode 100644 index 34fb53eca1316cd57f783c837743f17e7ce31941..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3096 zcmb_e&2JM&6rcUFH(uL;KnVGuP!ddCXf_a9XiBM2ViHi|R7t3c+iK-_oUmZ8!|o*L^4TSuOM0JRj&DJ^CtP)Bnmmyg$!Ew0fGkjJ^2pr+bAfdt? zLdA8SkjL@0(LW1 z{7n|S*+_*YqIvH@MWE0U8%B4XCFy0Bwrkf(`(7dKS*L!`t)4q!lvMT1C|@1rucPET z3bN@ArpL03G$n9ea@+}xj%YM#C$*%V%~=ypLx0jvUC*Ws+Y#c!y^cIQu4QvHopBDp zZZbD((4@JbrE&(b9m&% zC+hUfl$BMfG1=RzTGsXC&0Nk@2VyEX`Z?EtV6=a-S5Co|! zb4)rb^Cz%@GWW`vkR`GX)MJlxn_J=@cobTyj&;~Pt`cN`e0AzeDF561ZNc`+j}Y4{ zK0cgr~Viev;}V;mFEqR)~Cjk?%Va^*Q2P66!?K?Q|BF8B;fG z6J0oB|Fw&8M;eQb$0nkpi9aAmhBRtSK?c+eC^M%4cXP?iY}!J-BQVT16b>+BOnkA? z%`{qPi~}HGO#v*Er~6v&i$C<;>&wff&JzzW{Cr`fv$xpUTP9q?Am`#n@NjQl(eDrD>iNVtP? zm3DNJ^3W8#yuGeDF-b2oR02IO3)Bacmq9%JI&Xf@8@9WeH*83?R)~?*niWdcyvacQ zUvCX>*joU6*S#C7E+y^=m-{ci@OKWxhGP>kM;IJAV}{^-9iQ7{E}7UEov=%3@$~#K zHYH*1RPRL8Z|;GI=3ay*gnbD65t;#Gj9o>mMFD)7|qN^;nHW z1+x+N*d)vrgq=waVOqWWX|c&mwa4oPHA@3<6W({feN*WwC|#wl>{HItZx^B zI5D@0Lc6*dQVSu~6J^N+QMOh@%YG8>0io9<;xq7$iFg3(?y(N6TIc6b&O65K(mUnY zfpYOEZ>k_>;(P8o9v}Q!n9`>g6?QHz@i7Qm#{u9#ZX-+`HKPIyo+y^!7)@(B4J~8pStN} Sh=Y)J!#~LT_azUQ^Zx*muA4Xj diff --git a/gcmpy/scripts/__pycache__/land.cpython-312.pyc b/gcmpy/scripts/__pycache__/land.cpython-312.pyc deleted file mode 100644 index ad7859f922b23a66917e2f8877231eeba6c35d49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2660 zcmb_eO>7fK6rTOFH~vW=KnOo6)S)TMpMg+7QAHIc#!!-tlz;?Q+m+*8!iM$Q>~4Z= zB@zb?i4+N{R!SsPDV!S0rPoT8dTKAdkd%mM1gD<3(d1BxQ{S8QuH#5hsp?36^WK~H z=FQIc&5VCfCSwFz_Vo3!U!#QliAK=GnzC^clzE~PowG=h%W)j)yu}xVoWK#DWQi`^ zC%X8Q_cL;0MN%TK(NH)V%iHc7HnI{IxaXQKII(MJs z1f2&d;`}*D7ePjJ31qYqQKD3|^0rtmy(|2m1uO0G8A+7HP0xhyBJPZ-l=GXlC7JbS+ZS9l(>V-qVgTh-*77V8Nz76rLl6}$rlaJa9kQUie^~@uV&gb z!Hkln<5t!z+qlatKX5QJJluPlHeb3ta#btjy~3@cVS992wr_Cwnp*cf;i%{u)=d}j zIQaIn^jP_(TTJWrXm@wob#LWwmr71Ln;9AzD-_eF?Rt63N{^a$8tifz{h=3kXNHlPA&;1=S=xb*`lz^#yXQ{-t)pXR2x@sJ%j zgWsOk`hN1|CxmnVwOEuI!k$=OB5h*mt8>rP6R_By&{}oi_BzfR4rzWRRK- z?4eDlP3El$!^OOV(45^E9AlHQ@M?<>AkNMl+abWc0s`>bv3o)Mre{W8>pc4Xg~u2E z=!nz;Cv zfbk9<&IWM8gMSvFn1@3>4iQ_M&fPvth;vBi;h=`_vBMZ%0lEldA%rXvzm+vz+I+w( z@2V21Rl%9+RU%;3tKbUiRWPz%B??wZjdxa&|KBP=lqQu5m-~9(Mmzg61DUHCDr5)G zI7l-ZsoesCI?zp3^O8^Dy=u%+2}}GySXJ zPi}v3efIjou9f5mEM{{G%)ml})U*FJ6>1 zc_;oN!@rGjGMI?y$g=uO4Vv^c{sXR|VlC+cVpF_p@cIij1!u zUagu&V;Vm36BghKdWM^z*$81|(9?;$$jnU?8Q*t_7*c@8JW`C{?H}M(DtiC` diff --git a/gcmpy/scripts/__pycache__/ocean.cpython-311.pyc b/gcmpy/scripts/__pycache__/ocean.cpython-311.pyc deleted file mode 100644 index b5a5f8bc4d38b6bf08394eb0b7478845b750c54b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11172 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 PKxZpmyFnEL(y{*oVd#Q` diff --git a/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc b/gcmpy/scripts/__pycache__/process_questions.cpython-312.pyc deleted file mode 100644 index eb95fccc5e78159ad68f97c614717b3769576b5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11971 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 JefGx!_dl7nfs_CM diff --git a/gcmpy/scripts/__pycache__/utility.cpython-312.pyc b/gcmpy/scripts/__pycache__/utility.cpython-312.pyc deleted file mode 100644 index 4358525d4379b95fc1d91083613f168c2eccd8ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3860 zcmd5mZMCC0K7N^v)KY=x>MrgGfWwro@u8O5nYJCcPWYZvUAyAoGg za@n`bL}Uz91$?l96gj#=4M>L`EclWD0h0fai?%9IVd0_$ddf|*0tCpZGjB<1r4TBb zQy;M3dv9jm?96ax-ty~sTqH0y{t;Y!4y%9TrZqy%#r{@+kjF$NDrXScn>m?d`+yt> zkSU@D9uPJ74CHXgK}HJ!jc?OJI+1yJ!U3X@rEX8skI$MLEv$yeVGU9}e!jO}dg+HW zJn;&UpK%@!_K{;W^mWt_K@Fa`l?bDI?kve*OI(kt@ol7Ub!8FJh5nH2~KV&}( zl*f>PnB{Un<>a6mkV9%v=GBlKR(Uz1hGjvG$Wc|0MKvnNR8j7NC$7dG5V>3J0!-B7 z>28-VnubXmeE*$G7t3t=Ih!tc)1|jO;+QvG@TQ-Y8=?L?9)bX@-z*nf)}ggnX+e1Q z4S>hQ2K2^Kvj$sxoPFF@P5amlSl=gzKDn?@pt(eeIkL&+(;8#7o z=H_y@)0`WsDt5_2Q>E{(XBMjqRym_q?p?T$v8(K*B5?*7S1z07|6DK}xJZe12t-rVS zo|8EL^n{Zb`GWs4_Ib=nT-g$??1LEj|A-;Q=(eKBPtE3Xc`5*jMv)FNT+j{8iy@5x zsTBky9}WUiumF8Q`1sMsPv+OPGWpZ7^iU%&Zm1^p-`wO zWvx(f#X_NMsx<@GU4_E$YKqb1gm2By-kOGAc=CgZyeniUW`Bh%8UYR!uzj_0KZF4We96!DfaMja~8ao&E>%j3BHk2upHXsx?Ae1*?xX!1; zuBfdPwW_U~73+{L9#jP3+5ZdEWw*=HZkOH?8gOLT?UGVCY>rq?YJg#o6<;TQi1B%b zVTKWg0>da`t4(vn#`IxB6%VL&l8)tFac*+<#;x1=iJ4sE?69OrmS)$gl2>rjf=MO2 zq)Awr($wUPC^m%XyrnE^m!(Ehx?{31D2B9PD2u-V?$xLSV`Rk8E6ccIV;VQj;vQX* z^ongt+DcWUdReR3lB!d!Xq&VyHpZIAExoc>GZYH7E=hBmErCgMKH9-)v2i*ojg;V( zCC#X|-YCtL%#WlR8rm2Y#TyIo(htpLO_dbGtZ2i`siu##RM}Aie`$ zmrbg{AqYTO!Jm3qsv4SNX;RUw*h3of1+*%^7J*J zrvvm1OcaZClXHV*Yti2gPf$g-G>DK!3+?zce$rlAqn!lKgE9+0C|S%N7C#Z63tj)k zi7bd8x?J0a1EV<(IflJ~jl+)7K_I4s^fXLvl39n=w=HI#(l>zX_p{G)V?lvi(&s4D zRI4vF9X%p3gnCW^pr^^d3+Ei++(z+l!q6dyfq!VQUo8Zr$D~f!4drF#k@Sodp*||L zY9r}0qe;uaX$wQJN_K=UmK^zXgyJnt@k5iIKsbkhHqsFUJanW6SezJOqqI%}JRmPZ z0^jrEWB@<_*cUlI?v)LTYNYw?;PUKK!VT4xvf&2d+ro`BKQ!E+W*6N^vqQQ3y_#;Q zjaMyN%uH0PhF)YHz{>oxDNz8b8}n@%XHXW(oN6ja%}m@Zv^UT>3-j>V;zscRTc%@f zz_i?;RkvKBYA7~#8Lts|CTo=su@BI*;Gi2`1nWLhDgGaGBhW1I7Is5Rrd~M`p6`Wm z@5a7HCqNiW%(@P^8{|0dpXB9j^741#BzJX>0DL!eii__NfZb~(7GI6*00=v&vwu3X zo?c7;`KPPG!&e;g(oSk%eQ<4XJ+qd1`o?FMoT01RscXPH<&fSMZ+LBZW974mGx&?I z&TpqCfP2y*JuR+x@@;46%64iTczu6J9A;hI%xtGFA9X1_{gANXFjsJE#r2xDCucVLV(|-VH+&KCG diff --git a/gcmpy/scripts/test_generate_question.py b/gcmpy/scripts/test_generate_question.py deleted file mode 100644 index b4a4219d..00000000 --- a/gcmpy/scripts/test_generate_question.py +++ /dev/null @@ -1,9 +0,0 @@ -import unittest -import generate_question as gq - -class testGenereateQuestion(unittest.TestCase): - def test_should_ask(self): - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file From db7ea6c3d5d848fb6c04129bf089fdb3b0ad58aa Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Thu, 10 Apr 2025 15:15:46 -0400 Subject: [PATCH 19/37] Fixed some template variables still using old format + SSTNAME gets templated properly --- AGCM.rc.tmpl | 2 +- gcm_forecast.tmpl | 8 ++++---- gcm_run.j | 16 ++++++++-------- gcmpy/scripts/gcm_setup.py | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/AGCM.rc.tmpl b/AGCM.rc.tmpl index c2b344e5..13d550e9 100644 --- a/AGCM.rc.tmpl +++ b/AGCM.rc.tmpl @@ -354,7 +354,7 @@ RECORD_REF_TIME: >>>REFTIME<<< >>>FCSTIME<<< # MERRA-2 Regular REPLAY Configuration # -------------------------------------------- #M2 REPLAY_ANA_EXPID: MERRA-2 -#M2 REPLAY_ANA_LOCATION: @M2_REPLAY_ANA_LOCATION +#M2 REPLAY_ANA_LOCATION: {{ M2_REPLAY_ANA_LOCATION }} #M2 REPLAY_MODE: Regular #M2 REPLAY_FILE: ana/MERRA2_all/Y%y4/M%m2/MERRA2.ana.eta.%y4%m2%d2_%h2z.nc4 #M2 MKIAU_JCAP: 62 diff --git a/gcm_forecast.tmpl b/gcm_forecast.tmpl index 3cfddd7d..9e061f82 100755 --- a/gcm_forecast.tmpl +++ b/gcm_forecast.tmpl @@ -423,10 +423,10 @@ setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} setenv EMISSIONS {{ EMISSIONS }} chmod +x linkbcs -@GCMRUN_CATCHCNset LSM_CHOICE = `grep LSM_CHOICE: AGCM.rc | cut -d':' -f2` -@GCMRUN_CATCHCNif ($LSM_CHOICE == 2) then -@GCMRUN_CATCHCN grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc -@GCMRUN_CATCHCNendif +{{ GCMRUN_CATCHCN }}set LSM_CHOICE = `grep LSM_CHOICE: AGCM.rc | cut -d':' -f2` +{{ GCMRUN_CATCHCN }}if ($LSM_CHOICE == 2) then +{{ GCMRUN_CATCHCN }} grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc +{{ GCMRUN_CATCHCN }}endif ####################################################################### # Get Executable and RESTARTS diff --git a/gcm_run.j b/gcm_run.j index 858e0614..635ccc93 100755 --- a/gcm_run.j +++ b/gcm_run.j @@ -243,7 +243,7 @@ tar -xvf restarts.e${year}${month}10_21z.tar --wildcards "*_internal_rst*" # ------------------------------------------------ set RSTID = `/bin/ls *catch* | /bin/grep -Po '^.*(?=\.\w+_rst\.)'` set day = `/bin/ls *catch* | /bin/grep -Po '(?<=\d{6})\d{2}(?=_21z)'` -$GEOSBIN/remap_restarts.py command_line -np -ymdh ${year}${month}${day}21 -grout C${AGCM_IM} -levsout ${AGCM_LM} -out_dir . -rst_dir . -expid $RSTID -bcvin NL3 -oceanin 1440x720 -in_bc_base /discover/nobackup/projects/gmao/bcs_shared/fvInput/ExtData/esm/tiles -newid regrid -nobkg -nolcv -bcvout @LSMBCS -rs 3 -oceanout @OCEANOUT -out_bc_base @BC_BASE +$GEOSBIN/remap_restarts.py command_line -np -ymdh ${year}${month}${day}21 -grout C${AGCM_IM} -levsout ${AGCM_LM} -out_dir . -rst_dir . -expid $RSTID -bcvin NL3 -oceanin 1440x720 -in_bc_base /discover/nobackup/projects/gmao/bcs_shared/fvInput/ExtData/esm/tiles -newid regrid -nobkg -nolcv -bcvout {{ LSMBCS }} -rs 3 -oceanout {{ OCEANOUT }} -out_bc_base @BC_BASE set IMC = $AGCM_IM if( $IMC < 10 ) then @@ -378,10 +378,10 @@ setenv BCRSLV {{ ATMOStag }}_{{ OCEANtag }} setenv EMISSIONS {{ EMISSIONS }} chmod +x linkbcs -@GCMRUN_CATCHCNset LSM_CHOICE = `grep LSM_CHOICE: AGCM.rc | cut -d':' -f2` -@GCMRUN_CATCHCNif ($LSM_CHOICE == 2) then -@GCMRUN_CATCHCN grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc -@GCMRUN_CATCHCNendif +{{ GCMRUN_CATCHCN }}set LSM_CHOICE = `grep LSM_CHOICE: AGCM.rc | cut -d':' -f2` +{{ GCMRUN_CATCHCN }}if ($LSM_CHOICE == 2) then +{{ GCMRUN_CATCHCN }} grep -v "'CNFROOTC'" HISTORY.rc > Hist_tmp.rc && mv Hist_tmp.rc HISTORY.rc +{{ GCMRUN_CATCHCN }}endif ####################################################################### # Setup executable ####################################################################### @@ -593,8 +593,8 @@ else endif wait -@COUPLED /bin/mkdir INPUT -@COUPLED cp $EXPDIR/RESTART/* INPUT +{{ COUPLED }} /bin/mkdir INPUT +{{ COUPLED }} cp $EXPDIR/RESTART/* INPUT # Copy and Tar Initial Restarts to Restarts Directory # --------------------------------------------------- @@ -869,7 +869,7 @@ if ( $rst_by_face == YES ) then echo "WARNING: The generated gwd_internal_face_x_rst are used" #foreach n (1 2 3 4 5 6) #/bin/rm gwd_internal_face_${n}_rst - #/bin/cp @GWDRSDIR/gwd_internal_c${AGCM_IM}_face_${n} gwd_internal_face_${n}_rst + #/bin/cp {{ GWDRSDIR }}/gwd_internal_c${AGCM_IM}_face_${n} gwd_internal_face_${n}_rst #end else if (! -e gwd_internal_rst) then diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index f831f762..2268ad53 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -204,7 +204,7 @@ def set_stuff(self): if oceanres == "1440x720": self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/SST/{oceanres}" else: - self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/realtime/@SSTNAME/{oceanres}" + self.sst_dir = f"{self.boundary_path}/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{oceanres}" if self.ocean.gridtyp == "LL": self.sst_dir = "/nobackupp2/estrobac/geos5/SSTDIR" @@ -255,7 +255,7 @@ def set_stuff(self): if oceanres == "1440x720": self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/SST/{oceanres}" else: - self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/realtime/@SSTNAME/{oceanres}" + self.sst_dir = f"{os.environ.get('SHARE')}/gmao_ops/fvInput/g5gcm/bcs/realtime/{self.ocean.sst_name}/{oceanres}" if self.ocean.gridtyp == "LL": self.sst_dir = "/discover/nobackup/estrobac/geos5/SSTDIR" @@ -299,7 +299,7 @@ def set_stuff(self): self.replay_ana_expID = "REPLAY_UNSUPPORTED" self.replay_ana_location = "REPLAY_UNSUPPORTED" self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" - self.sst_dir = f"{self.boundary_path}/@SSTNAME/{self.ocean.IM}x{self.ocean.JM}" + self.sst_dir = f"{self.boundary_path}/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" self.work_dir = os.environ.get('HOME') self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" @@ -335,7 +335,7 @@ def set_stuff(self): self.replay_ana_expID = "REPLAY_UNSUPPORTED" self.replay_ana_location = "REPLAY_UNSUPPORTED" self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" - self.sst_dir = f"{self.boundary_path}/@SSTNAME/{self.ocean.IM}x{self.ocean.JM}" + self.sst_dir = f"{self.boundary_path}/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" self.work_dir = os.environ.get('HOME') self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" From b4a94fc2ef45fff23aedec1842474789c57968e2 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Wed, 7 May 2025 08:44:54 -0400 Subject: [PATCH 20/37] Move @ to braces --- AGCM.rc.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AGCM.rc.tmpl b/AGCM.rc.tmpl index 8e3cd33f..5d8a53a1 100644 --- a/AGCM.rc.tmpl +++ b/AGCM.rc.tmpl @@ -804,7 +804,7 @@ SURFACE_IMPORT_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} #RRG_INTERNAL_RESTART_FILE: rrg_internal_rst #RRG_INTERNAL_CHECKPOINT_FILE: rrg_internal_checkpoint -#RRG_INTERNAL_CHECKPOINT_TYPE: @CHECKPOINT_TYPE +#RRG_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} # OCEAN Model Restart Files # ------------------------- @@ -869,7 +869,7 @@ GIGATRAJ_EXTRA_FIELDS: DYN%TH|Theta;DYN%ZL|PAlt # ------------------------- #GIGATRAJ_INTERNAL_RESTART_FILE: gigatraj_internal_rst #GIGATRAJ_INTERNAL_CHECKPOINT_FILE: gigatraj_internal_checkpoint -#GIGATRAJ_INTERNAL_CHECKPOINT_TYPE: @CHECKPOINT_TYPE +#GIGATRAJ_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} GIGATRAJ_REGRID_TO_LATLON: NO #GIGATRAJ_PARCELS_FILE: parcels.nc4 # time interval (minutes) for integration. Default is heart beat and it must be a multiple of heart beat. From d2ed1c958beb73a7cfa5f256a27f5dabcdf2b95d Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Wed, 7 May 2025 10:13:07 -0400 Subject: [PATCH 21/37] Fix bad merge again --- AGCM.rc.tmpl | 36 ----- gcm_regress.j | 72 +++++----- gcm_run.j | 5 + gcmpy/scripts/atmosphere.py | 3 +- gcmpy/scripts/env.py | 7 +- gcmpy/scripts/gcm_setup.py | 213 ++++++++++++++--------------- gcmpy/scripts/process_questions.py | 40 +++--- gcmpy/yaml/atmospheric_model.yaml | 7 - gcmpy/yaml/mpi_config.yaml | 28 +--- linkbcs.tmpl | 10 +- 10 files changed, 174 insertions(+), 247 deletions(-) diff --git a/AGCM.rc.tmpl b/AGCM.rc.tmpl index 5d8a53a1..26723a5a 100644 --- a/AGCM.rc.tmpl +++ b/AGCM.rc.tmpl @@ -38,16 +38,6 @@ AGCM.IM_WORLD: {{ AGCM_IM }} {{ CONUS }} AGCM.TARGET_LAT: 39.5 {{ CONUS }} AGCM.TARGET_LON: -98.35 -########################################################### -# debug options -# ---------------------------------------- -#DEBUG_DYN: .TRUE. -#DEBUG_GWD: .TRUE. -#DEBUG_MST: .TRUE. -#DEBUG_TRB: .TRUE. -#DEBUG_SYNCTQ: .TRUE. -########################################################### - ########################################################### # debug options # ---------------------------------------- @@ -865,32 +855,6 @@ GIGATRAJ_EXTRA_FIELDS: DYN%TH|Theta;DYN%ZL|PAlt #GIGATRAJ_EXTRA_FIELDS: DYN%PL|P;DYN%ZL|PAlt #GIGATRAJ_EXTRA_FIELDS: DYN%PL|P;DYN%TH|Theta -# GIGATRAJ RUN CONFIG -# ------------------------- -#GIGATRAJ_INTERNAL_RESTART_FILE: gigatraj_internal_rst -#GIGATRAJ_INTERNAL_CHECKPOINT_FILE: gigatraj_internal_checkpoint -#GIGATRAJ_INTERNAL_CHECKPOINT_TYPE: {{ CHECKPOINT_TYPE }} -GIGATRAJ_REGRID_TO_LATLON: NO -#GIGATRAJ_PARCELS_FILE: parcels.nc4 -# time interval (minutes) for integration. Default is heart beat and it must be a multiple of heart beat. -# format hhmmss -# GIGATRAJ_INTEGRATE_DT: -# time interval to rebalance the parcels, i.e, the process keeps its own parcels -# format hhmmss -GIGATRAJ_REBALANCE_DT: 001500 -# time interval to write output -# format hhmmss -GIGATRAJ_OUTPUT_DT: 003000 -# format :: comp[%%bundle]%field[|alias], [] is optional -GIGATRAJ_VERTICAL_COORD: DYN%PL|P -#GIGATRAJ_VERTICAL_COORD: DYN%TH|Theta -#GIGATRAJ_VERTICAL_COORD: DYN%ZL|PAlt -# using ";" to separate fields. NO blank space between chars -# format :: comp[%%bundle]%field[|alias], [] is optional -GIGATRAJ_EXTRA_FIELDS: DYN%TH|Theta;DYN%ZL|PAlt -#GIGATRAJ_EXTRA_FIELDS: DYN%PL|P;DYN%ZL|PAlt -#GIGATRAJ_EXTRA_FIELDS: DYN%PL|P;DYN%TH|Theta - # IGNI Restart Files # ------------------ #IGNI_INTERNAL_RESTART_FILE: igni_internal_rst diff --git a/gcm_regress.j b/gcm_regress.j index 87b492ba..6ed5a75c 100755 --- a/gcm_regress.j +++ b/gcm_regress.j @@ -5,7 +5,7 @@ ####################################################################### #{{ BATCH_TIME }}{{ RUN_T }} -#{{ RUN_P }} +#{{ REGRESS_P }} #{{ BATCH_JOBNAME }}{{ REGRESS_N }} #{{ RUN_Q }} #{{ BATCH_GROUP }} @@ -870,12 +870,12 @@ if ( $RUN_OPENMP == TRUE) then cp $EXPDIR/$rst $EXPDIR/regress end - @COUPLED /bin/rm -rf INPUT - @COUPLED /bin/mkdir INPUT - @COUPLED cp $EXPDIR/RESTART/* INPUT + {{ COUPLED }} /bin/rm -rf INPUT + {{ COUPLED }} /bin/mkdir INPUT + {{ COUPLED }} cp $EXPDIR/RESTART/* INPUT - @COUPLED # restore original input.nml - @COUPLED /bin/mv input.nml.orig input.nml + {{ COUPLED }} # restore original input.nml + {{ COUPLED }} /bin/mv input.nml.orig input.nml /bin/rm cap_restart echo $nymd0 $nhms0 > cap_restart @@ -901,17 +901,17 @@ if ( $RUN_OPENMP == TRUE) then /bin/mv AGCM.rc AGCM.tmp cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc - @COUPLED set oldstring = `cat AGCM.rc | grep "^ *OGCM.NX:"` - @COUPLED set newstring = "OGCM.NX: ${OGCM_NX0}" - @COUPLED /bin/mv AGCM.rc AGCM.tmp - @COUPLED cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc - @COUPLED set oldstring = `cat AGCM.rc | grep "^ *OGCM.NY:"` - @COUPLED set newstring = "OGCM.NY: ${OGCM_NY0}" - @COUPLED /bin/mv AGCM.rc AGCM.tmp - @COUPLED cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc + {{ COUPLED }} set oldstring = `cat AGCM.rc | grep "^ *OGCM.NX:"` + {{ COUPLED }} set newstring = "OGCM.NX: ${OGCM_NX0}" + {{ COUPLED }} /bin/mv AGCM.rc AGCM.tmp + {{ COUPLED }} cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc + {{ COUPLED }} set oldstring = `cat AGCM.rc | grep "^ *OGCM.NY:"` + {{ COUPLED }} set newstring = "OGCM.NY: ${OGCM_NY0}" + {{ COUPLED }} /bin/mv AGCM.rc AGCM.tmp + {{ COUPLED }} cat AGCM.tmp | sed -e "s?$oldstring?$newstring?g" > AGCM.rc - @MOM5sed -r -i -e "/^ *layout/ s#= ([0-9]+),*([0-9]+)#= ${OGCM_NX0},${OGCM_NY0}#" input.nml - @MOM6sed -r -i -e "s/#override LAYOUT = 3, 2/#override LAYOUT = ${OGCM_NX0}, ${OGCM_NY0}/g" MOM_override + {{ MOM5 }}sed -r -i -e "/^ *layout/ s#= ([0-9]+),*([0-9]+)#= ${OGCM_NX0},${OGCM_NY0}#" input.nml + {{ MOM6 }}sed -r -i -e "s/#override LAYOUT = 3, 2/#override LAYOUT = ${OGCM_NX0}, ${OGCM_NY0}/g" MOM_override setenv YEAR `cat cap_restart | cut -c1-4` ./linkbcs @@ -934,7 +934,7 @@ if ( $RUN_OPENMP == TRUE) then echo "=== Running OpenMP test of duration ${test_duration_step5} with NX = $NX0 and NY = $NY0 starting at $nymd0 $nhms0 ===" - @OCEAN_PRELOAD $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' + {{ OCEAN_PRELOAD }} $RUN_CMD $NPES ./GEOSgcm.x --logging_config 'logging.yaml' set date = `cat cap_restart` set nymde4 = $date[1] @@ -951,7 +951,7 @@ if ( $RUN_OPENMP == TRUE) then /bin/mv -v $chk ${chk}.${nymde1}_${nhmse1}.5 end - @MOM6/bin/mv -v RESTART/MOM.res.nc MOM.res.nc.5 + {{ MOM6 }}/bin/mv -v RESTART/MOM.res.nc MOM.res.nc.5 # Move history as well set hist_file_names = `ls -1 ${EXPID}.test_collection.*.nc4` @@ -1268,24 +1268,24 @@ if ($RUN_OPENMP == TRUE) then endif end - @MOM6# check MOM.res.nc (MOM6 restart) - @MOM6set file1 = MOM.res.nc.2 - @MOM6set file2 = MOM.res.nc.5 - @MOM6if( -e $file1 && -e $file2 ) then - @MOM6 set check = true - @MOM6 if( $check == true ) then - @MOM6 echo Comparing "MOM6 restarts" - @MOM6 cmp $file1 $file2 - @MOM6 if( $status == 0 ) then - @MOM6 echo OpenMP Success! - @MOM6 echo " " - @MOM6 else - @MOM6 echo OpenMP Failed! - @MOM6 echo " " - @MOM6 set openmp_pass = false - @MOM6 endif - @MOM6 endif - @MOM6endif + {{ MOM6 }}# check MOM.res.nc (MOM6 restart) + {{ MOM6 }}set file1 = MOM.res.nc.2 + {{ MOM6 }}set file2 = MOM.res.nc.5 + {{ MOM6 }}if( -e $file1 && -e $file2 ) then + {{ MOM6 }} set check = true + {{ MOM6 }} if( $check == true ) then + {{ MOM6 }} echo Comparing "MOM6 restarts" + {{ MOM6 }} cmp $file1 $file2 + {{ MOM6 }} if( $status == 0 ) then + {{ MOM6 }} echo OpenMP Success! + {{ MOM6 }} echo " " + {{ MOM6 }} else + {{ MOM6 }} echo OpenMP Failed! + {{ MOM6 }} echo " " + {{ MOM6 }} set openmp_pass = false + {{ MOM6 }} endif + {{ MOM6 }} endif + {{ MOM6 }}endif echo "=== Comparing replay checkpoint files from 6-hour ${NX0}x${NY0} run with restarts from 6-hour OpenMP:2 ${NX0}x${NY0} run ===" diff --git a/gcm_run.j b/gcm_run.j index af461277..a2f1655f 100755 --- a/gcm_run.j +++ b/gcm_run.j @@ -1138,6 +1138,11 @@ else endif echo GEOSgcm Run Status: $rc +# Reset OpenMP Threads to 1 +setenv OMP_NUM_THREADS 1 +./strip GWD_GridComp.rc +sed -i -e "s|TRUE|FALSE|g" GWD_GridComp.rc + {{ MIT }} # --------------------------------------------------- {{ MIT }} # For MITgcm restarts - after running GEOSgcm.x {{ MIT }} # --------------------------------------------------- diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py index 70957640..8b212dd1 100755 --- a/gcmpy/scripts/atmosphere.py +++ b/gcmpy/scripts/atmosphere.py @@ -19,7 +19,6 @@ def __init__(self): self.nx = None self.ny = None self.nf = 6 - self.use_hydrostatic = answerdict["use_hydrostatic"].q_answer self.microphysics = answerdict["AM_microphysics"].q_answer self.hist_im = self.im * 4 self.hist_jm = self.im * 2 + 1 @@ -385,7 +384,7 @@ def set_wsub_extdata(self): else: self.mp_turn_off_wsub_extdata = '#DELETE#' - + def config(self, ocean_nx, ocean_ny): self.hres(ocean_nx, ocean_ny) self.set_microphysics() diff --git a/gcmpy/scripts/env.py b/gcmpy/scripts/env.py index f700df6c..babf5e2a 100755 --- a/gcmpy/scripts/env.py +++ b/gcmpy/scripts/env.py @@ -81,7 +81,10 @@ cores. As 45 is a multiple of 3, it's the best value that doesn't waste too much ''' - envdict['n_CPUs'] = 40 + if answerdict['processor'].q_answer == 'cas': + envdict['n_CPUs'] = 40 + elif answerdict['processor'].q_answer == 'mil': + envdict['n_CPUs'] = 120 elif envdict['site'] == 'NAS': if answerdict['processor'].q_answer == 'has': @@ -142,5 +145,5 @@ envdict['preload_command'] = 'LD_PRELOAD' envdict['ld_library_path_command'] = 'LD_LIBRARY_PATH' envdict['run_command'] = '$GEOSBIN/esma_mpirun -np ' - + diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index 2268ad53..d8453e37 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -28,22 +28,22 @@ def __init__(self): self.n_oserver_nodes = None self.n_backend_pes = None self.n_nodes = None - self.exp_dir = answerdict['exp_dir'].q_answer + self.exp_dir = answerdict['exp_dir'].q_answer self.restart_by_oserver = 'NO' - self.gcm_version = Path(f"{pathdict['etc']}/.AGCM_VERSION").read_text() + self.gcm_version = Path(f"{pathdict['etc']}/.AGCM_VERSION").read_text() self.file_list = ['gcm_run.j', - 'gcm_post.j', - 'gcm_archive.j', - 'gcm_regress.j', - 'gcm_plot.tmpl', - 'gcm_quickplot.csh', - 'gcm_moveplot.j', - 'gcm_forecast.tmpl', + 'gcm_post.j', + 'gcm_archive.j', + 'gcm_regress.j', + 'gcm_plot.tmpl', + 'gcm_quickplot.csh', + 'gcm_moveplot.j', + 'gcm_forecast.tmpl', 'gcm_forecast.setup', - 'gcm_emip.setup', - 'CAP.rc.tmpl', - 'AGCM.rc.tmpl', - 'logging.yaml', + 'gcm_emip.setup', + 'CAP.rc.tmpl', + 'AGCM.rc.tmpl', + 'logging.yaml', 'fvcore_layout.rc', 'linkbcs.tmpl'] @@ -64,7 +64,7 @@ def set_some_stuff(self): self.bcs_res = f"{self.atmos.res}_{self.ocean.res}" self.tile_data = f"{self.atmos.res}_{self.ocean.res}_Pfafstetter.til" self.tile_bin = f"{self.atmos.res}_{self.ocean.res}_Pfafstetter.TIL" - self.job_sgmt = f"{self.atmos.job_sgmt} 000000" + self.job_sgmt = f"{self.atmos.job_sgmt} 000000" # setup experiment nodes @@ -80,10 +80,10 @@ def set_nodes(self): # Next the number of frontend PEs is 10% of the model PEs n_frontend_pes = math.ceil(model_npes * 0.1) - # Now we roughly figure out the number of collections in the HISTORY.rc + # Now we roughly figure out the number of collections in the HISTORY.rc n_hist_collections = 0 with open(f"{pathdict['etc']}/{answerdict['history_template'].q_answer}", 'r') as file: - in_collections = False + in_collections = False for line in file: if line.split(' ', 1)[0] == "COLLECTIONS:": in_collections = True @@ -101,7 +101,7 @@ def set_nodes(self): # The number of backend PEs is the number of history collections divided by the number of oserver nodes n_backend_pes = math.ceil(n_hist_collections / n_oserver_nodes) - + # multigroup requires at least two backend pes if (n_backend_pes < 2): n_backend_pes = 2 @@ -113,8 +113,6 @@ def set_nodes(self): self.n_oserver_nodes = 0 self.n_backend_pes = 0 - - def set_stuff(self): self.set_nodes() # Longer job names are now supported with SLURM and PBS. Limits seem to be 1024 characters with SLURM @@ -123,7 +121,7 @@ def set_stuff(self): self.run_fn = f"{answerdict['experiment_id'].q_answer[:200]}_FCST" # Forecast Job Name self.post_n = f"{answerdict['experiment_id'].q_answer[:200]}_POST" # POST Job Name self.plot_n = f"{answerdict['experiment_id'].q_answer[:200]}_PLT" # PLOT Job Name - self.move_n = f"{answerdict['experiment_id'].q_answer[:200]}_PLT" # MOVE Job Name + self.move_n = f"{answerdict['experiment_id'].q_answer[:200]}_MOVE" # MOVE Job Name self.archive_n = f"{answerdict['experiment_id'].q_answer[:200]}_ARCH" # ARCHIVE Job Name self.regress_n = f"{answerdict['experiment_id'].q_answer[:200]}_RGRS" # REGRESS Job Name @@ -170,29 +168,29 @@ def set_stuff(self): ''' if envdict['site'] == "NAS": - self.batch_cmd = "qsub" - self.batch_group = "PBS -W group_list=" - self.batch_time = "PBS -l walltime=" - self.batch_jobname = "PBS -N" - self.batch_outputname = "PBS -o " - self.batch_joinouterr = "PBS -j oe -k oed" - self.run_ft = "6:00:00" - self.run_t = "8:00:00" - self.post_t = "8:00:00" - self.plot_t = "8:00:00" - self.archive_t = "8:00:00" - self.run_q = f"PBS -q normal" - self.run_p = f"PBS -l select={self.nodes}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" - self.run_fp = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" - self.regress_p = f"PBS -l select={self.nodes * 2}:ncpus=${NCPUS_PER_NODE_HALF}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer / 2}" - self.post_q = "PBS -q normal" - self.plot_q = "PBS -q normal" + self.batch_cmd = "qsub" + self.batch_group = "PBS -W group_list=" + self.batch_time = "PBS -l walltime=" + self.batch_jobname = "PBS -N" + self.batch_outputname = "PBS -o " + self.batch_joinouterr = "PBS -j oe -k oed" + self.run_ft = "6:00:00" + self.run_t = "8:00:00" + self.post_t = "8:00:00" + self.plot_t = "8:00:00" + self.archive_t = "8:00:00" + self.run_q = f"PBS -q normal" + self.run_p = f"PBS -l select={self.nodes}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" + self.run_fp = f"PBS -l select=24:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" + self.regress_p = f"PBS -l select={self.nodes * 2}:ncpus={envdict['n_CPUSs'] // 2}:mpiprocs={envdict['n_CPUs'] // 2}:model={answerdict['processor'].q_answer}" + self.post_q = "PBS -q normal" + self.plot_q = "PBS -q normal" self.move_q = "PBS -q normal" self.archive_q = "PBS -q normal" self.post_p = f"PBS -l select={NPCUS}:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" self.plot_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs=1:model={answerdict['processor'].q_answer}" self.archive_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" - self.move_p = "PBS -l select=1:ncpus=1" + self.move_p = "PBS -l select=1:ncpus=1" self.boundary_path = "/nobackup/gmao_SIteam/ModelData" self.bcs_dir = f"{self.boundary_path}/bcs/{self.land.bcs}/{self.land.bcs}_{self.ocean.tag}" self.replay_ana_expID = "ONLY_MERRA2_SUPPORTED" @@ -209,15 +207,15 @@ def set_stuff(self): self.sst_dir = "/nobackupp2/estrobac/geos5/SSTDIR" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" - self.work_dir = f"/nobackup/{os.environ.get('LOGNAME')}" + self.work_dir = f"/nobackup/{os.environ.get('LOGNAME')}" self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" # Coupled Ocean/Atmos Forcing if self.ocean.model == "MIT": self.coupled_dir = "/nobackupp2/estrobac/geos5/GRIDDIR" else: - self.coupled_dir = f"{boundary_path}/aogcm" - + self.coupled_dir = f"{self.boundary_path}/aogcm" + elif envdict['site'] == "NCCS": self.batch_cmd = "sbatch" @@ -227,14 +225,14 @@ def set_stuff(self): self.batch_outputname = "SBATCH --output=" self.batch_joinouterr = "DELETE" self.run_ft = "06:00:00" - self.run_t = "12:00:00" - self.post_t = "8:00:00" - self.plot_t = "12:00:00" + self.run_t = "12:00:00" + self.post_t = "8:00:00" + self.plot_t = "12:00:00" self.archive_t = "2:00:00" self.run_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" self.run_fp = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" - self.regress_p = f"SBATCH --nodes={self.nodes * 2} --ntasks-per-node={envdict['n_CPUs'] / 2}" + self.regress_p = f"SBATCH --nodes={self.nodes * 2} --ntasks-per-node={envdict['n_CPUs'] // 2}" self.post_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.plot_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" self.move_q = "SBATCH --partition=datamove" @@ -270,8 +268,8 @@ def set_stuff(self): self.coupled_dir = f"{self.boundary_path}/bcs_shared/make_bcs_inputs/ocean" - elif envdict['site'] == "AWS" or envdict['SITE'] == "Azure": - self.batch_cmd = "sbatch" + elif envdict['site'] == "AWS" or envdict['site'] == "Azure": + self.batch_cmd = "sbatch" self.batch_group = "#DELETE" self.batch_time = "SBATCH --time=" self.batch_jobname = "SBATCH --job-name=" @@ -283,9 +281,9 @@ def set_stuff(self): self.plot_t = "12:00:00" self.archive_t = "1:00:00" self.run_q = f"SBATCH --constraint={answerdict['processor'].q_answer}" - self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" + self.run_p = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" self.run_fp = f"SBATCH --nodes={self.nodes} --ntasks-per-node={envdict['n_CPUs']}" - self.regress_p = f"SBATCH --nodes={self.nodes * 2} --ntasks-per-node={envdict['n_CPUs'] / 2}" + self.regress_p = f"SBATCH --nodes={self.nodes * 2} --ntasks-per-node={envdict['n_CPUs'] // 2}" self.post_q = "NULL" self.plot_q = "NULL" self.move_q = "NULL" @@ -308,8 +306,8 @@ def set_stuff(self): else: # These are defaults for the desktop self.batch_cmd = "sbatch" - self.batch_group = "SBATCH --account=" - self.batch_time = "SBATCH --time=" + self.batch_group = "SBATCH --account=" + self.batch_time = "SBATCH --time=" self.batch_jobname = "SBATCH --job-name=" self.batch_outputname = "SBATCH --output=" self.batch_joinouterr = "DELETE" @@ -337,10 +335,11 @@ def set_stuff(self): self.M2_replay_ana_location = "REPLAY_UNSUPPORTED" self.sst_dir = f"{self.boundary_path}/{self.ocean.sst_name}/{self.ocean.IM}x{self.ocean.JM}" self.chem_dir = f"{self.boundary_path}/fvInput_nc3" - self.work_dir = os.environ.get('HOME') + self.work_dir = os.environ.get('HOME') self.gwdrs_dir = f"{self.boundary_path}/GWD_RIDGE" self.coupled_dir = f"{self.boundary_path}/aogcm" + if envdict['site'] == 'GMAO.desktop': # By default on desktop, just ignore IOSERVER for now self.atmos.NX = 1 self.atmos.NY = 6 @@ -354,7 +353,7 @@ def set_stuff(self): self.NCAR_NRDG = 16 if self.land.gwd_in_bcs == False and not os.path.exists(f"{self.gwdrs_dir}/gwd_internal_c{self.atmos.im}"): self.NCAR_NRDG = 0 - + @@ -378,7 +377,7 @@ def RC_setup(self): # Make the experiment directory and the RC directory inside of it RC_dir = os.path.join(self.exp_dir, 'RC') - + # Delete the destination directory if it exists if os.path.exists(RC_dir): shutil.rmtree(RC_dir) @@ -410,34 +409,23 @@ def mpistacksettings(self): # retrieve config from correlating mpi setting being used self.mpi_config = mpidict.get(envdict['mpi']) - # These are options determined to be useful at NCCS - # Not setting generally as they are more fabric/cluster - # specific compared to the above adjustments - if envdict['site'] == 'NCCS': - self.mpi_config += "\nsetenv I_MPI_SHM_HEAP_VSIZE 512 \ - \nsetenv PSM2_MEMORY large" - - # as of right now, sigularity is not an option so this will always be added - self.mpi_config += "\nsetenv I_MPI_EXTRA_FILESYSTEM 1 \ - \nsetenv I_MPI_EXTRA_FILESYSTEM_FORCE gpfs" - - - ####################################################################### - # Create directories and copy files over + # Create directories and copy files over ####################################################################### # A little helper function for copying files and displaying the info to the user def copy_helper(self, src, destination, filename): - shutil.copy(src, destination) - print(f"Creating {color.RED}{filename}{color.RESET} for Experiment: {answerdict['experiment_id'].q_answer}") + if os.path.exists(src): + shutil.copy(src, destination) + print(f"Creating {color.RED}{filename}{color.RESET} for Experiment: {answerdict['experiment_id'].q_answer}") def copy_files_into_exp(self): print("\n\n\n") for file in self.file_list: - self.copy_helper(f"{pathdict['GEOSgcm_App']}/{file}", f"{self.exp_dir}/{file}", file) - + self.copy_helper(f"{pathdict['install']}/bin/{file}", f"{self.exp_dir}/{file}", file) + self.copy_helper(f"{pathdict['install']}/etc/{file}", f"{self.exp_dir}/{file}", file) + self.copy_helper(f"{pathdict['install']}/post/plot.rc", f"{self.exp_dir}/plot.rc", "plot.rc") self.copy_helper(f"{pathdict['install']}/post/post.rc", f"{self.exp_dir}/post.rc", "post.rc") @@ -452,7 +440,7 @@ def copy_files_into_exp(self): self.copy_helper(f"{pathdict['etc']}/MOM5/geos5/{self.ocean.IM}x{self.ocean.JM}/INPUT/input.nml", f"{self.exp_dir}/input.nml", "input.nml") MOM5_path = os.path.join(pathdict['etc'], 'MOM5', 'geos5', f"{self.ocean.IM}x{self.ocean.JM}", 'INPUT', '*table') files = glob.glob(MOM5_path) - for file in files: + for file in files: file_name = os.path.basename(file) self.copy_helper(file, f"{self.exp_dir}/{file_name}", file_name) elif self.ocean.model == 'MOM6': @@ -463,12 +451,12 @@ def copy_files_into_exp(self): self.copy_helper(f"{pathdict['etc']}/MOM6/mom6_app/{self.ocean.IM}x{self.ocean.JM}/input.nml", f"{self.exp_dir}/input.nml", "input.nml") MOM6_path = os.path.join(pathdict['etc'], 'MOM6', 'mom6_app', f"{self.ocean.IM}x{self.ocean.JM}", '*table') files = glob.glob(MOM6_path) - for file in files: + for file in files: file_name = os.path.basename(file) self.copy_helper(file, f"{self.exp_dir}/{file_name}", file_name) if self.ocean.seaice_model == 'CICE6': - self.copy_helper(f"{pathdict['etc']}/CICE6/cice6_app/{self.ocean.IM}x{self.ocean.JM}/ice_in", f"{self.exp_dir}/ice_in") + self.copy_helper(f"{pathdict['etc']}/CICE6/cice6_app/{self.ocean.IM}x{self.ocean.JM}/ice_in", f"{self.exp_dir}/ice_in") self.file_list.append('ice_in') print(f"{color.GREEN}Done!{color.RESET}\n") @@ -478,18 +466,18 @@ def copy_files_into_exp(self): # Produce Final script and .rc files ####################################################################### - # THIS WHOLE SECTION IS WILDLY OUT OF DATE, HOWEVER I KEPT IT AS IT WAS + # THIS WHOLE SECTION IS WILDLY OUT OF DATE, HOWEVER I KEPT IT AS IT WAS # IN THE ORIGINAL SCRIPT FOR NOW def restarts(self): # comment or un-comment restarts based on exp configuration # --------------------------------------------------------- - rsnames = {'H2O': False, + rsnames = {'H2O': False, 'MAM': False, 'CARMA': False, 'GMICHEM': False, 'STRATCHEM': False} rstypes = ['INTERNAL','IMPORT'] - + with open(f"{answerdict['exp_dir'].q_answer}/AGCM.rc.tmpl", 'r') as file: file_content = file.read() @@ -509,10 +497,10 @@ def restarts(self): def mod_RC_dir_for_pchem(self): if self.atmos.lm == 72: return - + rc_dir = f"{answerdict['exp_dir'].q_answer}/RC" - - # if atmospheric vertical resolution != 72, we loop through every + + # if atmospheric vertical resolution != 72, we loop through every # file in the RC dir and modify the atmos.lm values for file_name in os.listdir(rc_dir): file_path = os.path.join(rc_dir, file_name) @@ -527,10 +515,10 @@ def mod_RC_dir_for_pchem(self): file_content = file_content.replace("/L72/", f"/L{self.atmos.lm}/") file_content = file_content.replace("z72", f"z{self.atmos.lm}") file_content = file_content.replace("_72_", f"_{self.atmos.lm}_") - + with open(file_path, 'w') as file: file.write(file_content) - + # configure pchem and TR in GEOS_ChemGridComp.rc def config_chemGridComp(self): if self.gocart.rats_provider == 'PCHEM': @@ -545,7 +533,7 @@ def config_chemGridComp(self): # we always enable TR and gocart file_content = re.sub(r'(ENABLE_PCHEM:\s*\.).*(\.)', r'\1'+pchem+r'\2', file_content) file_content = re.sub(r'(ENABLE_TR:\s*\.).*(\.)', r'\1TRUE\2', file_content) - file_content = re.sub(r'(ENABLE_GOCART_DATA:\s*\.).*(\.)', r'\1TRUE\2', file_content) + file_content = re.sub(r'(ENABLE_GOCART_DATA:\s*\.).*(\.)', r'\1FALSE\2', file_content) with open(chemgridcomp, 'w') as file: file.write(file_content) @@ -556,6 +544,7 @@ def config_surfaceGridComp(self): with open(surfacegridcomp, 'r') as file: file_content = file.read() + file_content = re.sub(r'# GEOSagcm=>', r' ', file_content) if self.land.model == 'CatchmentCN-CLM4.0': file_content = re.sub(r'(LAND_PARAMS:\s*).*', r'\1CN_CLM40', file_content) @@ -580,7 +569,7 @@ def config_gocartGridComp(self): file_content = re.sub(r'(ACTIVE_INSTANCES_CA:\s*)CA.oc', r'\1CA.oc.data', file_content) file_content = re.sub(r'(ACTIVE_INSTANCES_CA:\s*)CA.bc', r'\1CA.bc.data', file_content) file_content = re.sub(r'(ACTIVE_INSTANCES_CA:\s*)CA.br', r'\1CA.br.data', file_content) - + with open(gocartgridcomp, 'w') as file: file.write(file_content) @@ -590,16 +579,16 @@ def config_heartbeat(self): # With MOM5 we need to change dt lines in input.nml to # use $OCEAN_DT instead. NOTE: This regex assumes integer followed by comma if self.ocean.model == 'MOM5': - + with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'r') as file: file_content = file.read() - + file_content = re.sub(r'dt_cpld\s*=\s*.*(,)', rf"dt_cpld = {self.atmos.dt_ocean}\1", file_content) file_content = re.sub(r'dt_atmos\s*=\s*.*(,)', rf"dt_atmos = {self.atmos.dt_ocean}\1", file_content) - + with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'w') as file: file.write(file_content) - + # We also must change the MOM_override file to # have consistent DTs with the AGCM. So we use OCEAN_DT @@ -628,7 +617,7 @@ def cleanup(self, file_path): - def template(self): + def template(self): # this dictionary holds template values for the default jinja2 delimiter "{{ val }}" jinja_dict = { 'SETENVS': self.mpi_config, @@ -654,12 +643,12 @@ def template(self): 'PLOT_Q': self.plot_q, 'MOVE_Q': self.move_q, 'MOVE_P': self.move_p, - 'ARCHIVE_N': self.archive_n, + 'ARCHIVE_N': self.archive_n, 'ARCHIVE_T': self.archive_t, 'ARCHIVE_P': self.archive_p, 'ARCHIVE_Q': self.archive_q, 'REGRESS_N': self.regress_n, - 'BCSDIR': self.bcs_dir, + 'BCSDIR': self.bcs_dir, 'SSTDIR': self.sst_dir, 'SSTNAME': self.ocean.sst_name, 'OCEANOUT': self.ocean.out, @@ -667,18 +656,18 @@ def template(self): 'EMIP_BCS_IN': self.land.emip_bcs_in, 'EMIP_MERRA2': self.land.emip_MERRA2, 'BCSTAG': self.ocean.tag, - 'SSTFILE': self.ocean.sst_file, - 'ICEFILE': self.ocean.ice_file, + 'SSTFILE': self.ocean.sst_file, + 'ICEFILE': self.ocean.ice_file, 'KPARFILE': self.ocean.kpar_file, - 'CHMDIR': self.chem_dir, + 'CHMDIR': self.chem_dir, 'COUPLEDIR': self.coupled_dir, 'GWDRSDIR': self.gwdrs_dir, 'NCAR_NRDG': self.NCAR_NRDG, 'EXPDIR': self.exp_dir, 'EXPDSC': answerdict['experiment_description'].q_answer, 'HOMDIR': self.exp_dir, - 'BATCH_GROUP': self.batch_group, - 'BATCH_TIME': self.batch_time, + 'BATCH_GROUP': self.batch_group+answerdict['group_root'].q_answer, + 'BATCH_TIME': self.batch_time, 'BATCH_CMD': self.batch_cmd, 'BATCH_JOBNAME': self.batch_jobname, 'BATCH_OUTPUTNAME': self.batch_outputname, @@ -691,7 +680,7 @@ def template(self): 'GEOSUTIL': pathdict['install'], 'SINGULARITY_BUILD': '#DELETE', 'NATIVE_BUILD': '', - 'MPT_SHEPHERD': self.ocean.mpt_shepherd, + 'MPT_SHEPHERD': self.ocean.mpt_shepherd, 'SINGULARITY_SANDBOX': '', 'REAL_BIND_PATH': '', 'BASE_BIND_PATH': '', @@ -699,18 +688,18 @@ def template(self): 'CHECKPOINT_TYPE': 'default', 'OGCM_NX': self.ocean.NX, 'OGCM_NY': self.ocean.NY, - 'OGCM_NPROCS': self.ocean.nprocs, + 'OGCM_NPROCS': self.ocean.nprocs, 'OBSERVER_FRQ': 0, 'DASTUNING': '#', - 'COUPLED': self.ocean.coupled, + 'COUPLED': self.ocean.coupled, 'CLDMICRO': self.atmos.microphysics, 'MOM5': self.ocean.MOM5, 'MOM6': self.ocean.MOM6, - 'OCNMODEL': self.ocean.model, + 'OCNMODEL': self.ocean.model, 'CICE4': self.ocean.CICE4, 'CICE6': self.ocean.CICE6, 'HIST_CICE4': self.ocean.hist_CICE4, - 'MIT': self.ocean.MIT, + 'MIT': self.ocean.MIT, 'DATAOCEAN': self.ocean.data, 'OPS_SPECIES': self.gocart.ops_species, 'CMIP_SPECIES': self.gocart.cmip_species, @@ -732,12 +721,12 @@ def template(self): 'CH4_PROVIDER': self.gocart.ch4_provider, 'CO2_PROVIDER': self.gocart.c02_provider, 'DYCORE': 'FV3', - 'AGCM_GRIDNAME': self.atmos.gridname, + 'AGCM_GRIDNAME': self.atmos.gridname, 'OGCM_GRIDNAME': self.ocean.gridname, 'OGCM_IS_FCST': '0', 'BOOT': 'YES', 'BCSRES': self.bcs_res, - 'OCEANtag': self.ocean.res, + 'OCEANtag': self.ocean.res, 'ATMOStag': self.atmos.res, 'RES_DATELINE': self.atmos.res_dateline, 'TILEDATA': self.tile_data, @@ -754,7 +743,7 @@ def template(self): 'NUM_OSERVER_NODES': self.n_oserver_nodes, 'NUM_BACKEND_PES': self.n_backend_pes, 'RESTART_BY_OSERVER': self.restart_by_oserver, - 'NCPUS_PER_NODE': envdict['n_CPUs'], + 'NCPUS_PER_NODE': envdict['n_CPUs'], 'NUM_READERS': self.atmos.num_readers, 'NUM_WRITERS': self.atmos.num_writers, 'LATLON_AGCM': self.atmos.latlon, @@ -778,7 +767,7 @@ def template(self): 'CONUS': self.atmos.conus, 'CONVPAR_OPTION': self.atmos.convpar_option, 'STRETCH_FACTOR': self.atmos.stretch_factor, - 'INTERPOLATE_SST': self.interpolate_sst, + 'INTERPOLATE_SST': self.interpolate_sst, 'HIST_IM': self.atmos.hist_im, 'HIST_JM': self.atmos.hist_jm, 'ISCCP_SATSIM': 1, @@ -804,7 +793,7 @@ def template(self): 'FV_TARGET_LON': self.atmos.target_lon, 'FV_TARGET_LAT': self.atmos.target_lat, 'FORCEDAS': self.atmos.force_das, - 'FORCEGCM': self.atmos.force_gcm, + 'FORCEGCM': self.atmos.force_gcm, 'HIST_CICE4': '#DELETE', 'FVCUBED': '', 'HIST_CATCHCN': self.land.HIST_catchment, @@ -817,11 +806,11 @@ def template(self): 'REGULAR_REPLAY_NCEP': '#DELETE', 'REGULAR_REPLAY_ECMWF': '#DELETE' } - + exp_dir = answerdict['exp_dir'].q_answer - # this is an edge-case that can't be handled with jinja2 + # this is an edge-case that can't be handled with jinja2 for file in self.file_list: with open(f"{exp_dir}/{file}", 'r') as tmpl: file_content = tmpl.read() @@ -829,12 +818,12 @@ def template(self): file_content = re.sub(r'[ \t]*RECORD_', r'#RECORD_', file_content) with open(f"{exp_dir}/{file}", 'w') as tmpl: - tmpl.write(file_content) + tmpl.write(file_content) # this block handles the default case for jinja templating default_env = Environment( loader=FileSystemLoader(exp_dir) - ) + ) for file in self.file_list: template = default_env.get_template(file) content = template.render(jinja_dict) @@ -855,7 +844,7 @@ def organize_exp_dir(self): sub_dirs = ['archive', 'forecasts', 'plot', 'post' , 'regress'] for i in sub_dirs: os.makedirs(os.path.join(exp_dir, i), exist_ok=True) - + # archive dir shutil.move(f"{exp_dir}/gcm_archive.j", f"{exp_dir}/archive/gcm_archive.j") diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index 98afdd9b..7ac88e00 100755 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -3,7 +3,7 @@ from utility import envdict, pathdict, color """ -This class handles special cases where a question"s properties need to be checked/dynamically +This class handles special cases where a question"s properties need to be checked/dynamically changed at runtime based on certain conditions (e.g. input validation) """ class handle: @@ -11,7 +11,7 @@ class handle: @staticmethod def select_type(answerdict, i): if answerdict[i].q_type == "select" and answerdict[i].q_answer != None: - # as of right now, we only want the first word of every select-type question. + # as of right now, we only want the first word of every select-type question. # If that changes it's probably best to delete this function. answerdict[i].q_answer = answerdict[i].q_answer.split(None, 1)[0] @@ -39,15 +39,15 @@ def processor_choices(answerdict, i): return if envdict["site"] == "NCCS": - answerdict[i].q_choices = ["cas"] + answerdict[i].q_choices = ["mil", "cas"] elif envdict["site"] == "NAS": - answerdict[i].q_choices = ["rom", "sky", "has", "bro", "cas", "mil"] + print(color.GREEN + "NOTE Due to how FV3 is compiled by default, Sandy Bridge\n" + \ + "and Ivy Bridge are not supported by current GEOS" + color.RESET) + + answerdict[i].q_choices = ["rom", "mil", "sky", "cas", "bro", "has"] else: exit(1) - print(color.GREEN + "NOTE Due to how FV3 is compiled by default, Sandy Bridge\n" + \ - "and Ivy Bridge are not supported by current GEOS" + color.RESET) - @staticmethod def OM_horizontal_res_default(answerdict, i): if i != 'OM_horizontal_res': @@ -83,8 +83,8 @@ def MOM_hres_default(answerdict, i): answerdict[i].q_default = "72 36" ''' - THIS METHOD IS BUGGED FOR NOW - @staticmethod + THIS METHOD IS BUGGED FOR NOW + @staticmethod def OM_hres_valid(answerdict, i): if i != "OM_MOM_horizontal_res": return @@ -107,15 +107,15 @@ def heartbeat_default(answerdict, i): return ''' Default heartbeat is determined by atmospheric resolution. - Of course, this just the recommended value. The user can + Of course, this just the recommended value. The user can enter whatever value they like ''' heartbeat = "" match answerdict["AM_horizontal_res"].q_answer: case 'c12': - heartbeat = 3600 - case 'c24': heartbeat = 1800 + case 'c24': + heartbeat = 1200 case 'c48': heartbeat = 1200 case 'c90': @@ -157,7 +157,7 @@ def heartbeat_valid(answerdict, i): def history_template_default(answerdict, i): if i != "history_template": return - + if answerdict['OM_name'].q_answer == 'MOM5': answerdict[i].q_default = 'HISTORY.AOGCM-MOM5.rc.tmpl' elif answerdict['OM_name'].q_answer == "MOM6": @@ -173,7 +173,7 @@ def history_template_default(answerdict, i): def exp_dir_default(answerdict, i): if i != "exp_dir": return - + root = f"{os.environ.get('HOME')}/.EXPDIRroot" if os.path.exists(root): try: @@ -185,7 +185,7 @@ def exp_dir_default(answerdict, i): answerdict[i].q_default = f"/{'discover/' if envdict['site'] == 'NCCS' else ''}nobackup/{os.environ.get('LOGNAME')}/{answerdict['experiment_id'].q_answer}" else: answerdict[i].q_default = f"{os.environ.get('HOME')}/{answerdict['experiment_id']}" - + @staticmethod def exp_dir_valid(answerdict, i): @@ -196,7 +196,7 @@ def exp_dir_valid(answerdict, i): answerdict[i].load_question(answerdict) - @staticmethod + @staticmethod def group_root_default(answerdict, i): if i != "group_root": return @@ -242,8 +242,8 @@ def process(): yaml_questions[i]["choices"], \ yaml_questions[i]["default_answer"],\ yaml_questions[i]["follows_up"]) - - answerdict[i] = temp + + answerdict[i] = temp # if the question properties need to dynamically change at @@ -251,7 +251,7 @@ def process(): handle.io_server_defualt(answerdict, i) handle.processor_choices(answerdict, i) handle.OM_horizontal_res_default(answerdict, i) - handle.MIT_hres_choices(answerdict, i) + handle.MIT_hres_choices(answerdict, i) handle.MOM_hres_default(answerdict, i) handle.seaice_choices(answerdict, i) handle.heartbeat_default(answerdict, i) @@ -267,7 +267,7 @@ def process(): # handle.OM_hres_valid(answerdict, i) handle.heartbeat_valid(answerdict, i) handle.exp_dir_valid(answerdict, i) - + # strips the first word from every select type question handle.select_type(answerdict, i) diff --git a/gcmpy/yaml/atmospheric_model.yaml b/gcmpy/yaml/atmospheric_model.yaml index 34fec4e8..2423b30a 100755 --- a/gcmpy/yaml/atmospheric_model.yaml +++ b/gcmpy/yaml/atmospheric_model.yaml @@ -27,13 +27,6 @@ heartbeat: default_answer: '' follows_up: '' -use_hydrostatic: - type: 'confirm' - prompt: 'Use Hydrostatic Amtosphere?' - choices: '' - default_answer: True - follows_up: '' - io_server: type: 'confirm' prompt: 'Would you like to IOSERVER?' diff --git a/gcmpy/yaml/mpi_config.yaml b/gcmpy/yaml/mpi_config.yaml index df537070..f00d5051 100755 --- a/gcmpy/yaml/mpi_config.yaml +++ b/gcmpy/yaml/mpi_config.yaml @@ -55,31 +55,5 @@ NCCS: | # These are options determined to be useful at NCCS # Not setting generally as they are more fabric/cluster # specific compared to the above adjustments - setenv I_MPI_SHM_HEAP_VSIZE 512 - setenv PSM2_MEMORY large - -BUILT_ON_SLE15: | - # Testing by Bill Putman found these to be - # useful flags with Intel MPI on SLES15 on the - # Milan nodes. - # Note 1: Testing by NCCS shows the PSM3 provider - # runs on the Infiniband fabric. Tests show it runs - # up to C720. - # Note 2: When the Cascade Lakes are moved to - # SLES15, these will need to be Milan-only flags - # as Intel MPI will probably work just fine with - # Intel chips. - setenv I_MPI_FALLBACK 0 - setenv I_MPI_FABRICS ofi + setenv I_MPI_FABRICS shm:ofi setenv I_MPI_OFI_PROVIDER psm3 - setenv I_MPI_ADJUST_SCATTER 2 - setenv I_MPI_ADJUST_SCATTERV 2 - setenv I_MPI_ADJUST_GATHER 2 - setenv I_MPI_ADJUST_GATHERV 3 - setenv I_MPI_ADJUST_ALLGATHER 3 - setenv I_MPI_ADJUST_ALLGATHERV 3 - setenv I_MPI_ADJUST_ALLREDUCE 12 - setenv I_MPI_ADJUST_REDUCE 10 - setenv I_MPI_ADJUST_BCAST 11 - setenv I_MPI_ADJUST_REDUCE_SCATTER 4 - setenv I_MPI_ADJUST_BARRIER 9 diff --git a/linkbcs.tmpl b/linkbcs.tmpl index eb5192e3..355095a6 100644 --- a/linkbcs.tmpl +++ b/linkbcs.tmpl @@ -65,13 +65,13 @@ set MERRA2OX_SPECIES = "#" /bin/ln -sf $BCSDIR/TOPO/TOPO_{{ ATMOStag }}/smoothed/topo_TRB_var_{{ AGCM_IM }}x{{ AGCM_JM }}.data topo_trbvar.data # Handle gwd_internal_rst -if ( -e $BCSDIR/TOPO/TOPO_@ATMOStag/smoothed/gwd_internal_rst ) then +if ( -e $BCSDIR/TOPO/TOPO_{{ ATMOStag }}/smoothed/gwd_internal_rst ) then echo "Found gwd_internal_rst in bcsdir. Copying to scratch directory" - /bin/cp -vf $BCSDIR/TOPO/TOPO_@ATMOStag/smoothed/gwd_internal_rst gwd_internal_rst -else if (-e @GWDRSDIR/gwd_internal_c@AGCM_IM) then - echo "Found gwd_internal_c@AGCM_IM. Copying to scratch directory" + /bin/cp -vf $BCSDIR/TOPO/TOPO_{{ ATMOStag }}/smoothed/gwd_internal_rst gwd_internal_rst +else if (-e {{ GWDRSDIR }}/gwd_internal_c{{ AGCM_IM }}) then + echo "Found gwd_internal_c{{ AGCM_IM }}. Copying to scratch directory" /bin/rm gwd_internal_rst - /bin/cp @GWDRSDIR/gwd_internal_c@AGCM_IM gwd_internal_rst + /bin/cp {{ GWDRSDIR }}/gwd_internal_c{{ AGCM_IM }} gwd_internal_rst endif {{ COUPLED }}cp $HOMDIR/*_table . From ba0eb573249481256eae816df3a9067c61a6ca80 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 14 May 2025 14:14:05 -0400 Subject: [PATCH 22/37] fixed out_bc_base not being templated in gcm_run.j --- gcmpy/scripts/gcm_setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index d8453e37..ea124545 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -192,6 +192,7 @@ def set_stuff(self): self.archive_p = f"PBS -l select=1:ncpus={envdict['n_CPUs']}:mpiprocs={envdict['n_CPUs']}:model={answerdict['processor'].q_answer}" self.move_p = "PBS -l select=1:ncpus=1" self.boundary_path = "/nobackup/gmao_SIteam/ModelData" + self.bc_base = f"{self.boundary_path}/bcs_shared/fvInput/ExtData/esm/tiles" self.bcs_dir = f"{self.boundary_path}/bcs/{self.land.bcs}/{self.land.bcs}_{self.ocean.tag}" self.replay_ana_expID = "ONLY_MERRA2_SUPPORTED" self.replay_ana_location = "ONLY_MERRA2_SUPPORTED" @@ -242,7 +243,8 @@ def set_stuff(self): self.archive_p = "SBATCH --ntasks=1" self.move_p = "SBATCH --ntasks=1" self.boundary_path = "/discover/nobackup/projects/gmao" - self.bcs_dir = f"{self.boundary_path}/bcs_shared/fvInput/ExtData/esm/tiles/{self.land.bcs}" + self.bc_base = f"{boundary_path}/bcs_shared/fvInput/ExtData/esm/tiles" + self.bcs_dir = f"{self.bc_base}/{self.land.bcs}" self.replay_ana_expID = "x0039" self.replay_ana_location = f"{self.boundary_path}/g6dev/ltakacs/x0039" self.M2_replay_ana_location = f"{self.boundary_path}/merra2/data" @@ -293,6 +295,7 @@ def set_stuff(self): self.archive_p = "SBATCH --ntasks=1" self.move_p = "SBATCH --ntasks=1" self.boundary_path = "/ford1/share/gmao_SIteam/ModelData" + self.bc_base = f"{self.boundary_path}/bcs_shared/fvInput/ExtData/esm/tiles" self.bcs_dir = f"{self.boundary_path}/bcs/{self.land.bcs}_{self.ocean.tag}" self.replay_ana_expID = "REPLAY_UNSUPPORTED" self.replay_ana_location = "REPLAY_UNSUPPORTED" @@ -329,6 +332,7 @@ def set_stuff(self): self.archive_p = "NULL" self.move_p = "NULL" self.boundary_path = "/ford1/share/gmao_SIteam/ModelData" + self.bc_base = f"{self.boundary_path}/bcs_shared/fvInput/ExtData/esm/tiles" self.bcs_dir = f"{self.boundary_path}/bcs/{self.land.bcs} /{self.land.bcs}_{self.ocean.tag}" self.replay_ana_expID = "REPLAY_UNSUPPORTED" self.replay_ana_location = "REPLAY_UNSUPPORTED" @@ -684,6 +688,7 @@ def template(self): 'SINGULARITY_SANDBOX': '', 'REAL_BIND_PATH': '', 'BASE_BIND_PATH': '', + 'BC_BASE': self.bc_base, 'BOUNDARY_DIR': self.boundary_path, 'CHECKPOINT_TYPE': 'default', 'OGCM_NX': self.ocean.NX, From 42fb65fe92111b4eaa73ac4c7debed8e6b68e577 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Wed, 28 May 2025 11:55:49 -0400 Subject: [PATCH 23/37] Add several_tries and new PSM env to python --- gcm_setup | 2 +- gcmpy/scripts/gcm_setup.py | 8 +++++++- gcmpy/yaml/mpi_config.yaml | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/gcm_setup b/gcm_setup index db4f9e63..562f88d7 100755 --- a/gcm_setup +++ b/gcm_setup @@ -2459,7 +2459,7 @@ s/{{ USE_IOSERVER }}/$USE_IOSERVER/g s/{{ NUM_OSERVER_NODES }}/$NUM_OSERVER_NODES/g s/{{ NUM_BACKEND_PES }}/$NUM_BACKEND_PES/g s/{{ RESTART_BY_OSERVER }}/$RESTART_BY_OSERVER/g -s^{{ SEVERAL_TRIES }}^$SEVERAL_TRIES#g +s^{{ SEVERAL_TRIES }}^$SEVERAL_TRIES^g s/{{ NCPUS_PER_NODE }}/$NCPUS_PER_NODE/g s/{{ NUM_READERS }}/$NUM_READERS/g s/{{ NUM_WRITERS }}/$NUM_WRITERS/g diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index ea124545..653f964e 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -30,6 +30,7 @@ def __init__(self): self.n_nodes = None self.exp_dir = answerdict['exp_dir'].q_answer self.restart_by_oserver = 'NO' + self.several_tries = '' self.gcm_version = Path(f"{pathdict['etc']}/.AGCM_VERSION").read_text() self.file_list = ['gcm_run.j', 'gcm_post.j', @@ -410,6 +411,11 @@ def mpistacksettings(self): if envdict['mpi'] == 'openmpi' or envdict['mpi'] == 'mvapich': self.restart_by_oserver = 'YES' + # NAS recommends several_tries for MPT job issues + # https://www.nas.nasa.gov/hecc/support/kb/mpt-startup-failures-workarounds_526.html + if envdict['site'] == "NAS" and envdict['mpi'] == 'mpt': + self.several_tries = '/u/scicon/tools/bin/several_tries' + # retrieve config from correlating mpi setting being used self.mpi_config = mpidict.get(envdict['mpi']) @@ -799,13 +805,13 @@ def template(self): 'FV_TARGET_LAT': self.atmos.target_lat, 'FORCEDAS': self.atmos.force_das, 'FORCEGCM': self.atmos.force_gcm, - 'HIST_CICE4': '#DELETE', 'FVCUBED': '', 'HIST_CATCHCN': self.land.HIST_catchment, 'GCMRUN_CATCHCN': self.land.GCMRUN_catchment, 'EMIP_OLDLAND': self.land.emip_oldland, 'EMIP_NEWLAND': self.land.emip_newland, '_4DIAUDAS': '#DELETE', + 'SEVERAL_TRIES': self.several_tries, 'REGULAR_REPLAY': '#', 'REGULAR_REPLAY_GMAO': '#', 'REGULAR_REPLAY_NCEP': '#DELETE', diff --git a/gcmpy/yaml/mpi_config.yaml b/gcmpy/yaml/mpi_config.yaml index f00d5051..d8c5371f 100755 --- a/gcmpy/yaml/mpi_config.yaml +++ b/gcmpy/yaml/mpi_config.yaml @@ -57,3 +57,4 @@ NCCS: | # specific compared to the above adjustments setenv I_MPI_FABRICS shm:ofi setenv I_MPI_OFI_PROVIDER psm3 + setenv FI_PSM3_CONN_TIMEOUT 120 From 1152b0fb4640a9e0416c3c475869a8ac60791830 Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 23 Jul 2025 03:23:52 -0400 Subject: [PATCH 24/37] big gcm_v12 update --- gcm_setup | 33 ++++------ gcmpy/CMakeLists.txt | 16 ----- gcmpy/scripts/CMakeLists.txt | 12 +--- gcmpy/scripts/env.py | 18 +---- gcmpy/scripts/gcm_setup.py | 101 ++++++++++++++++++++--------- gcmpy/scripts/ocean.py | 7 +- gcmpy/scripts/process_questions.py | 21 ++---- gcmpy/yaml/CMakeLists.txt | 10 +-- gcmpy/yaml/mpi_config.yaml | 26 ++++++-- gcmpy/yaml/ocean_model.yaml | 4 +- 10 files changed, 120 insertions(+), 128 deletions(-) mode change 100755 => 100644 gcm_setup diff --git a/gcm_setup b/gcm_setup old mode 100755 new mode 100644 index 562f88d7..40177912 --- a/gcm_setup +++ b/gcm_setup @@ -581,7 +581,7 @@ if( $OGCM == TRUE ) then else if ( "$OCNMODEL" == "MOM6" ) then set OCEAN_NAME="MOM6" set OGRIDTYP = "M6TP" - set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=\$GEOSDIR/lib/libmom6@CMAKE_SHARED_LIBRARY_SUFFIX@' + set OCEAN_PRELOAD = 'env @PRELOAD_COMMAND=$GEOSDIR/lib/libmom6@CMAKE_SHARED_LIBRARY_SUFFIX@' set MOM6="" set MOM5 = "#DELETE" set DEFAULT_HISTORY_TEMPLATE="HISTORY.AOGCM.rc.tmpl" @@ -694,13 +694,13 @@ if( $OGCM == TRUE ) then # Seaice Model # ----------- SEAICEMODEL: - echo "Choose a ${C1}Seaice Model${CN}: (Default: ${C2}CICE4${CN})" + echo "Choose a ${C1}Seaice Model${CN}: (Default: ${C2}CICE6${CN})" echo " ${C2}CICE4${CN}" echo " ${C2}CICE6${CN}" set SEAICEMODEL = $< if ( .$SEAICEMODEL == . ) then - set SEAICEMODEL = "CICE4" + set SEAICEMODEL = "CICE6" else set SEAICEMODEL = `echo $SEAICEMODEL | tr "[:lower:]" "[:upper:]"` @@ -1436,6 +1436,7 @@ if ($DATA_ATMOS == TRUE) then set EMIP_MERRA2 = "MERRA2_NewLand" set HIST_CATCHCN = "#DELETE" set GCMRUN_CATCHCN = "#DELETE" + set GWD_IN_BCS = "FALSE" else echo "Enter the choice of ${C1}Land Surface Boundary Conditions${CN} using: ${C2}ICA${CN} (Icarus), ${C2}NL3${CN} (Icarus-NLv3), or ${C2}v13${CN} (Default)" @@ -1786,7 +1787,7 @@ if( $SITE == 'NAS' ) then if( ${OGCM_IM}x${OGCM_JM} == "1440x720" ) then setenv SSTDIR ${BOUNDARY_DIR}/fvInput/g5gcm/bcs/SST/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions else - setenv SSTDIR ${BOUNDARY_DIR}/fvInput/g5gcm/bcs/realtime/@SSTNAME/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions + setenv SSTDIR ${BOUNDARY_DIR}/fvInput/g5gcm/bcs/realtime/${SSTNAME}/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions endif if (${OGRIDTYP} == "MITLLC") then setenv SSTDIR /nobackupp2/estrobac/geos5/SSTDIR @@ -1834,7 +1835,7 @@ else if( $SITE == 'NCCS' ) then if( ${OGCM_IM}x${OGCM_JM} == "1440x720" ) then setenv SSTDIR $SHARE/gmao_ops/fvInput/g5gcm/bcs/SST/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions else - setenv SSTDIR $SHARE/gmao_ops/fvInput/g5gcm/bcs/realtime/@SSTNAME/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions + setenv SSTDIR $SHARE/gmao_ops/fvInput/g5gcm/bcs/realtime/${SSTNAME}/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions endif setenv CHMDIR $SHARE/gmao_ops/fvInput_nc3 # locations of Aerosol Chemistry BCs setenv WRKDIR /discover/nobackup/$LOGNAME # user work directory @@ -1876,7 +1877,7 @@ else if( $SITE == 'AWS' | $SITE == 'Azure' ) then setenv REPLAY_ANA_LOCATION REPLAY_UNSUPPORTED # Default Analysis Location for REPLAY setenv M2_REPLAY_ANA_LOCATION REPLAY_UNSUPPORTED # Default Analysis Location for M2 REPLAY - setenv SSTDIR ${BOUNDARY_DIR}/@SSTNAME/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions + setenv SSTDIR ${BOUNDARY_DIR}/${SSTNAME}/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions setenv CHMDIR ${BOUNDARY_DIR}/fvInput_nc3 # locations of Aerosol Chemistry BCs setenv WRKDIR $HOME # user work directory setenv COUPLEDIR ${BOUNDARY_DIR}/bcs_shared/make_bcs_inputs/ocean # Coupled Ocean/Atmos Forcing @@ -1915,7 +1916,7 @@ else setenv REPLAY_ANA_LOCATION REPLAY_UNSUPPORTED # Default Analysis Location for REPLAY setenv M2_REPLAY_ANA_LOCATION REPLAY_UNSUPPORTED # Default Analysis Location for M2 REPLAY - setenv SSTDIR ${BOUNDARY_DIR}/@SSTNAME/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions + setenv SSTDIR ${BOUNDARY_DIR}/${SSTNAME}/${OGCM_IM}x${OGCM_JM} # location of SST Boundary Conditions setenv CHMDIR ${BOUNDARY_DIR}/fvInput_nc3 # locations of Aerosol Chemistry BCs setenv WRKDIR $HOME # user work directory setenv COUPLEDIR ${BOUNDARY_DIR}/bcs_shared/make_bcs_inputs/ocean # Coupled Ocean/Atmos Forcing @@ -2271,13 +2272,6 @@ EOF # specific compared to the above adjustments if ( $SITE == 'NCCS' ) then -# Some flags we know work on SLES15 and Milan (see below) -# For safety, we keep the old SLES12 flags for that system -# -# NOTE: When Cascade Lake is on SLES15, the following flags -# might need to be Milan only - -if ("$BUILT_ON_SLES15" == "TRUE") then cat >> $HOMDIR/SETENV.commands << EOF setenv I_MPI_ADJUST_ALLREDUCE 12 setenv I_MPI_ADJUST_GATHERV 3 @@ -2435,6 +2429,9 @@ s?{{ AERO_PROVIDER }}?$AERO_PROVIDER?g s?{{ OANA_PROVIDER }}?PCHEM?g s?{{ EMISSIONS }}?$EMISSIONS?g +s?{{ CH4_PROVIDER }}?$CH4_PROVIDER?g +s?{{ CO2_PROVIDER }}?$CO2_PROVIDER?g + s^{{ DYCORE }}^$DYCORE^g s^{{ AGCM_GRIDNAME }}^$AGCM_GRIDNAME^g s^{{ OGCM_GRIDNAME }}^$OGCM_GRIDNAME^g @@ -2459,7 +2456,7 @@ s/{{ USE_IOSERVER }}/$USE_IOSERVER/g s/{{ NUM_OSERVER_NODES }}/$NUM_OSERVER_NODES/g s/{{ NUM_BACKEND_PES }}/$NUM_BACKEND_PES/g s/{{ RESTART_BY_OSERVER }}/$RESTART_BY_OSERVER/g -s^{{ SEVERAL_TRIES }}^$SEVERAL_TRIES^g +s#{{ SEVERAL_TRIES }}#$SEVERAL_TRIES#g s/{{ NCPUS_PER_NODE }}/$NCPUS_PER_NODE/g s/{{ NUM_READERS }}/$NUM_READERS/g s/{{ NUM_WRITERS }}/$NUM_WRITERS/g @@ -2510,15 +2507,12 @@ s?{{ MGB2_2M_ }}?$MGB2_2M_?g s?{{ PRELOAD_COMMAND }}?$PRELOAD_COMMAND?g s?{{ LD_LIBRARY_PATH_CMD }}?$LD_LIBRARY_PATH_CMD?g -s?{{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}?${LD_LIBRARY_PATH_CMD}?g +s?{{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}?\{$LD_LIBRARY_PATH_CMD\}?g s?{{ RUN_CMD }}?$RUN_CMD?g s?{{ MODELATM }}?$MODELATM?g s?{{ USE_DATA_ATM4OCN }}?$USE_DATA_ATM4OCN?g -s?@MODELATM?$MODELATM?g -s?@USE_DATA_ATM4OCN?$USE_DATA_ATM4OCN?g - EOF # Added FV3/GFDL-MP Specific Parameters @@ -3350,3 +3344,4 @@ gcm_setup, a setup script for the GEOS GCM EOF exit 1 + diff --git a/gcmpy/CMakeLists.txt b/gcmpy/CMakeLists.txt index f90cd199..7dcf4dd1 100644 --- a/gcmpy/CMakeLists.txt +++ b/gcmpy/CMakeLists.txt @@ -2,19 +2,3 @@ add_subdirectory(scripts) add_subdirectory(yaml) -set (programs) - -install ( - PROGRAMS ${programs} - DESTINATION bin/gcmpy - ) - -# processed files -set (setup_scripts) - -foreach (file ${setup_scripts}) - configure_file(${file} ${file} @ONLY) - install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION bin/gcmpy) -endforeach () - - diff --git a/gcmpy/scripts/CMakeLists.txt b/gcmpy/scripts/CMakeLists.txt index 20693139..0e192ab0 100644 --- a/gcmpy/scripts/CMakeLists.txt +++ b/gcmpy/scripts/CMakeLists.txt @@ -10,15 +10,7 @@ set (programs utility.py ) -install ( - PROGRAMS ${programs} - DESTINATION bin/gcmpy/scripts - ) - -# processed files -set (setup_scripts) - -foreach (file ${setup_scripts}) +foreach (file ${programs}) configure_file(${file} ${file} @ONLY) - install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION bin/gcmpy) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION bin/gcmpy/scripts) endforeach () diff --git a/gcmpy/scripts/env.py b/gcmpy/scripts/env.py index babf5e2a..a8f5d419 100755 --- a/gcmpy/scripts/env.py +++ b/gcmpy/scripts/env.py @@ -44,31 +44,15 @@ ####################################################################### envdict['node'] = platform.node() envdict['arch'] = platform.system() -#print(f"{color.RED}{pathdict['bin']}{color.RESET}") envdict['site'] = open(os.path.join(pathdict['etc'], 'SITE.rc'), 'r').read().split()[-1] ####################################################################### # Test for Compiler and MPI Setup ####################################################################### # Extract BASEDIR tail -basedir = open(os.path.join(pathdict['etc'], 'BASEDIR.rc'), 'r').read().split()[-1] -mpi = os.path.split(basedir)[-1] - -# Map MPI dirname to correct MPI implementation -if any(tag in mpi for tag in ['openmpi','hpcx']): mpi = 'openmpi' -elif any(tag in mpi for tag in ['impi', 'intelmpi']): mpi = 'intelmpi' -elif 'mvapich2' in mpi: mpi = 'mvapich2' -elif 'mpich' in mpi: mpi = 'mpich' -elif 'mpt' in mpi: mpi = 'mpt' -else: mpi = 'intelmpi' -envdict['mpi'] = mpi -#print("MPI implementation is: " + color.GREEN + MPI) - +envdict['mpi'] = '@MPI_STACK@' answerdict = pq.process() -#for i in answerdict: -# print(answerdict[i].q_answer) - ####################################################################### # Set Number of CPUs per Node diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index 653f964e..bdf758e4 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -244,7 +244,7 @@ def set_stuff(self): self.archive_p = "SBATCH --ntasks=1" self.move_p = "SBATCH --ntasks=1" self.boundary_path = "/discover/nobackup/projects/gmao" - self.bc_base = f"{boundary_path}/bcs_shared/fvInput/ExtData/esm/tiles" + self.bc_base = f"{self.boundary_path}/bcs_shared/fvInput/ExtData/esm/tiles" self.bcs_dir = f"{self.bc_base}/{self.land.bcs}" self.replay_ana_expID = "x0039" self.replay_ana_location = f"{self.boundary_path}/g6dev/ltakacs/x0039" @@ -353,14 +353,6 @@ def set_stuff(self): self.n_backend_pes = 0 - # For ICA and NL3 the gwd files are in a non-bcs location - # and may or may not exist. If they don't we set NCAR_NRDG to 0 - self.NCAR_NRDG = 16 - if self.land.gwd_in_bcs == False and not os.path.exists(f"{self.gwdrs_dir}/gwd_internal_c{self.atmos.im}"): - self.NCAR_NRDG = 0 - - - # mainly used to create .{*}root files and/or populate them def create_dotfile(self, path, content): @@ -383,7 +375,7 @@ def RC_setup(self): # Make the experiment directory and the RC directory inside of it RC_dir = os.path.join(self.exp_dir, 'RC') - # Delete the destination directory if it exists + # Delete the directory if it exists already if os.path.exists(RC_dir): shutil.rmtree(RC_dir) @@ -407,17 +399,34 @@ def mpistacksettings(self): with open('../yaml/mpi_config.yaml') as file: mpidict = yaml.load(file, Loader=yaml.FullLoader) + # retrieve config from correlating mpi setting being used + self.mpi_config = mpidict.get(envdict['mpi']) + # restart by oserver if using openmpi or mvapich if envdict['mpi'] == 'openmpi' or envdict['mpi'] == 'mvapich': self.restart_by_oserver = 'YES' # NAS recommends several_tries for MPT job issues # https://www.nas.nasa.gov/hecc/support/kb/mpt-startup-failures-workarounds_526.html - if envdict['site'] == "NAS" and envdict['mpi'] == 'mpt': + if envdict['mpi'] == 'mpt': self.several_tries = '/u/scicon/tools/bin/several_tries' + # Testing at NAS shows that coupled runs *require* MPI_SHEPHERD=true + # to run. We believe this is due to LD_PRELOAD. For now we only set + # this for coupled runs. + if self.ocean.running_ocean == True: + self.ocean.mpt_shepherd = "setenv MPI_SHEPHERD true" + + if envdict['site'] == 'NCCS': + self.mpi_config += f"\n{mpidict.get('NCCS')}" + + # Check for gwd_internal for Ridge Scheme + # For ICA and NL3 the gwd files are in a non-bcs location + # and may or may not exist. If they don't we set NCAR_NRDG to 0 + self.NCAR_NRDG = 16 + if self.land.gwd_in_bcs == False and \ + not os.path.exists(f"{self.gwdrs_dir}/gwd_internal_c{self.atmos.im}"): + self.NCAR_NRDG = 0 - # retrieve config from correlating mpi setting being used - self.mpi_config = mpidict.get(envdict['mpi']) ####################################################################### @@ -466,7 +475,7 @@ def copy_files_into_exp(self): self.copy_helper(file, f"{self.exp_dir}/{file_name}", file_name) if self.ocean.seaice_model == 'CICE6': - self.copy_helper(f"{pathdict['etc']}/CICE6/cice6_app/{self.ocean.IM}x{self.ocean.JM}/ice_in", f"{self.exp_dir}/ice_in") + self.copy_helper(f"{pathdict['etc']}/CICE6/cice6_app/{self.ocean.IM}x{self.ocean.JM}/ice_in", f"{self.exp_dir}/ice_in", "ice_in") self.file_list.append('ice_in') print(f"{color.GREEN}Done!{color.RESET}\n") @@ -602,29 +611,60 @@ def config_heartbeat(self): # We also must change the MOM_override file to # have consistent DTs with the AGCM. So we use OCEAN_DT - # and change MOM_override to match. NOTE: This sed - # assumes floating point number with a decimal + # and change MOM_override to match. NOTE: This assumes + # floating point number with a decimal if self.ocean.model == 'MOM6': with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'r') as file: file_content = file.read() - file_content = re.sub(r'DT\s*=\s*.*(,)', rf"DT = {self.atmos.dt_ocean}\1", file_content) - file_content = re.sub(r'DT_THERM\s*=\s*.*(,)', rf"DT_THERM = {self.atmos.dt_ocean}\1", file_content) + file_content = re.sub(r'DT\s*=\s*.*', rf"DT = {self.atmos.dt_ocean}", file_content) + file_content = re.sub(r'DT_THERM\s*=\s*.*', rf"DT_THERM = {self.atmos.dt_ocean}", file_content) with open(f"{answerdict['exp_dir'].q_answer}/MOM_override", 'w') as file: file.write(file_content) + ####################################################################### + # Copy over Source Tarfile + ####################################################################### + def copy_src_tarfile(self): + bool_install_tarfile = '@CFG_INSTALL_SOURCE_TARFILE@' + tarfile_name = '@CMAKE_PROJECT_NAME@.tar.gz' + + if bool_install_tarfile != 'TRUE': + return + + src_dir = f"{self.exp_dir}/src" + tarfile_path = f"{pathdict['install']}/src/{tarfile_name}" + + # remove and recreate src directory + if src_dir.exists(): + shutil.rmtree(src_dir) + src_dir.mkdir(parents=True) + print(f"Copying build source code into {color.GREEN}{src_dir}{color.RESET}") + + if os.path.exists(tarfile_path): + shutil.copy(tarfile_path, src_dir) + else: + print(f"{tarfile_path} not found, yet CMake was asked to make and install a tarfile") + print("Something went wrong.") + + + # We create a RESTART dir if running ocean + def make_RESTART_dir(self): + if self.ocean.running_ocean == True: + os.makedirs(f"{self.exp_dir}/RESTART", exist_ok=True) + + # Templating helper function -- Removes lines marked with "#DELETE" def cleanup(self, file_path): with open(file_path, 'r') as file: content = file.read() - content = re.sub(r'.*#DELETE.*\n?', r'', content) + filtered_content = re.sub(r'(?m)^\s*#+DELETE\w*.*\n?', '', content) with open(file_path, 'w') as file: - file.write(content) - + file.write(filtered_content) def template(self): @@ -818,32 +858,29 @@ def template(self): 'REGULAR_REPLAY_ECMWF': '#DELETE' } - - exp_dir = answerdict['exp_dir'].q_answer - # this is an edge-case that can't be handled with jinja2 for file in self.file_list: - with open(f"{exp_dir}/{file}", 'r') as tmpl: + with open(f"{self.exp_dir}/{file}", 'r') as tmpl: file_content = tmpl.read() file_content = re.sub(r'[ \t]*RECORD_', r'#RECORD_', file_content) - with open(f"{exp_dir}/{file}", 'w') as tmpl: + with open(f"{self.exp_dir}/{file}", 'w') as tmpl: tmpl.write(file_content) # this block handles the default case for jinja templating default_env = Environment( - loader=FileSystemLoader(exp_dir) + loader=FileSystemLoader(self.exp_dir) ) for file in self.file_list: template = default_env.get_template(file) content = template.render(jinja_dict) - with open(f"{exp_dir}/{file}", 'w') as tmpl: + with open(f"{self.exp_dir}/{file}", 'w') as tmpl: tmpl.write(content) # remove #DELETE lines for file in self.file_list: - file_path = f"{exp_dir}/{file}" + file_path = f"{self.exp_dir}/{file}" self.cleanup(file_path) @@ -855,6 +892,8 @@ def organize_exp_dir(self): sub_dirs = ['archive', 'forecasts', 'plot', 'post' , 'regress'] for i in sub_dirs: os.makedirs(os.path.join(exp_dir, i), exist_ok=True) + self.copy_src_tarfile() + self.make_RESTART_dir() # archive dir shutil.move(f"{exp_dir}/gcm_archive.j", f"{exp_dir}/archive/gcm_archive.j") @@ -868,6 +907,10 @@ def organize_exp_dir(self): shutil.move(f"{exp_dir}/gcm_plot.tmpl", f"{exp_dir}/plot/gcm_plot.tmpl") shutil.move(f"{exp_dir}/gcm_quickplot.csh", f"{exp_dir}/plot/gcm_quickplot.csh") shutil.move(f"{exp_dir}/plot.rc", f"{exp_dir}/plot/plot.rc") + try: #only if using MOM ocean + shutil.move(f"{exp_dir}/plotocn.j", f"{exp_dir}/plot/plotocn.j") + except FileNotFoundError: + pass # post dir shutil.move(f"{exp_dir}/gcm_post.j", f"{exp_dir}/post/gcm_post.j") diff --git a/gcmpy/scripts/ocean.py b/gcmpy/scripts/ocean.py index b9dbaecb..5bfe9371 100644 --- a/gcmpy/scripts/ocean.py +++ b/gcmpy/scripts/ocean.py @@ -15,6 +15,7 @@ def __init__(ocean): ocean.seaice_name = '' ocean.seaice_preload = '' ocean.gridtyp = '' + ocean.mpt_shepherd = '' def config(ocean): @@ -58,7 +59,7 @@ def set_coupled(ocean): ocean.name = 'MOM6' ocean.gridtyp = 'M6TP' ocean.grid_type = 'Tripolar' - ocean.preload = 'env @PRELOAD_COMMAND=\\$GEOSDIR/lib/libmom6@CMAKE_SHARED_LIBRARY_SUFFIX@' + ocean.preload = 'env @PRELOAD_COMMAND=$GEOSDIR/lib/libmom6@CMAKE_SHARED_LIBRARY_SUFFIX@' ocean.MOM5 = '#DELETE' ocean.MOM6 = '' ocean.MIT = '#DELETE' @@ -74,7 +75,7 @@ def set_coupled(ocean): ocean.IM = ocean.jm * 360 ocean.NX = 360 ocean.NY = 1 - #ocean.gridspec = 'mit.ascii' <-- dead code + #ocean.gridspec = 'mit.ascii' <-- dead code(?) ocean.coupled = '' IMO = '%04d' % ocean.IM @@ -90,7 +91,6 @@ def set_coupled(ocean): ocean.latlon = '' ocean.cube = '#DELETE' ocean.data = '#DELETE' - ocean.mpt_shepherd = 'setenv MPI_SHEPHERD true' ocean.NF = 1 ocean.nprocs = ocean.NX * ocean.NY # This might be bugged(!) @@ -189,7 +189,6 @@ def set_uncoupled(ocean): ocean.NX = '' ocean.NY = '' ocean.nprocs = '' - ocean.mpt_shepherd = '' ocean.set_gridname() diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index 7ac88e00..a340ccfc 100755 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -1,4 +1,4 @@ -import yaml, re, os +import yaml, re, os, subprocess from generate_question import generateQuestion from utility import envdict, pathdict, color @@ -82,19 +82,6 @@ def MOM_hres_default(answerdict, i): if answerdict["OM_name"].q_answer == "MOM6" and answerdict["AM_horizontal_res"].q_answer == "c12": answerdict[i].q_default = "72 36" - ''' - THIS METHOD IS BUGGED FOR NOW - @staticmethod - def OM_hres_valid(answerdict, i): - if i != "OM_MOM_horizontal_res": - return - - #input validation using regex - while not re.match(r"^\d+\s\d+$", answerdict[i].q_answer): - print(color.RED + "please enter exactly 2 numbers separated by a space! (int int)\n") - answerdict[i].load_question(answerdict) - ''' - @staticmethod def seaice_choices(answerdict, i): if i == 'OM_seaice_model' and answerdict['OM_name'] == 'MOM6': @@ -200,8 +187,9 @@ def exp_dir_valid(answerdict, i): def group_root_default(answerdict, i): if i != "group_root": return - groups = subprocess.check_output('groups', shell=True).decode('utf-8').strip() - answerdict[i].q_default = groups.split()[0] + groups_output = subprocess.check_output(["groups"], text=True) + group_root = groups_output.strip().split()[0] + answerdict[i].q_default = group_root @@ -257,6 +245,7 @@ def process(): handle.heartbeat_default(answerdict, i) handle.history_template_default(answerdict, i) handle.exp_dir_default(answerdict, i) + handle.group_root_default(answerdict, i) # prompts the user with the question answerdict[i].load_question(answerdict) diff --git a/gcmpy/yaml/CMakeLists.txt b/gcmpy/yaml/CMakeLists.txt index 92e417d7..78c46fc7 100644 --- a/gcmpy/yaml/CMakeLists.txt +++ b/gcmpy/yaml/CMakeLists.txt @@ -1,4 +1,4 @@ -set (programs +set (files atmospheric_model.yaml directory_setup.yaml exp_setup.yaml @@ -9,14 +9,8 @@ set (programs ) install ( - PROGRAMS ${programs} + FILES ${files} DESTINATION bin/gcmpy/yaml ) -# processed files -set (setup_scripts) -foreach (file ${setup_scripts}) - configure_file(${file} ${file} @ONLY) - install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${file} DESTINATION bin/gcmpy) -endforeach () diff --git a/gcmpy/yaml/mpi_config.yaml b/gcmpy/yaml/mpi_config.yaml index d8c5371f..fb037626 100755 --- a/gcmpy/yaml/mpi_config.yaml +++ b/gcmpy/yaml/mpi_config.yaml @@ -1,6 +1,10 @@ +# Testing by Bill Putman determined some useful +# Open MPI parameters. Testing shows these work +# on both OSs at NCCS and on macOS openmpi: | # Turn off warning about TMPDIR on NFS setenv OMPI_MCA_shmem_mmap_enable_nfs_warning 0 + # pre-connect MPI procs on mpi_init setenv OMPI_MCA_mpi_preconnect_all 1 setenv OMPI_MCA_coll_tuned_bcast_algorithm 7 setenv OMPI_MCA_coll_tuned_scatter_algorithm 2 @@ -16,8 +20,6 @@ openmpi: | setenv OMPI_MCA_sharedfp "^lockedfile,individual" mvapich: | - # MVAPICH and GEOS has issues with restart writing. Having the - # oserver write them seems to...work setenv MV2_ENABLE_AFFINITY 0 setenv SLURM_DISTRIBUTION block setenv MV2_MPIRUN_TIMEOUT 100 @@ -26,19 +28,25 @@ mvapich: | mpt: | setenv MPI_COLL_REPRODUCIBLE setenv SLURM_DISTRIBUTION block + #setenv MPI_DISPLAY_SETTINGS 1 #setenv MPI_VERBOSE 1 + setenv MPI_MEMMAP_OFF unsetenv MPI_NUM_MEMORY_REGIONS setenv MPI_XPMEM_ENABLED yes unsetenv SUPPRESS_XPMEM_TRIM_THRESH + setenv MPI_LAUNCH_TIMEOUT 40 + setenv MPI_COMM_MAX 1024 setenv MPI_GROUP_MAX 1024 setenv MPI_BUFS_PER_PROC 256 + # For some reason, PMI_RANK is randomly set and interferes # with binarytile.x and other executables. unsetenv PMI_RANK + # Often when debugging on MPT, the traceback from Intel Fortran # is "absorbed" and only MPT's errors are displayed. To allow the # compiler's traceback to be displayed, uncomment this environment @@ -46,15 +54,19 @@ mpt: | #setenv FOR_IGNORE_EXCEPTIONS false intelmpi: | - setenv I_MPI_ADJUST_ALLREDUCE 12 - setenv I_MPI_ADJUST_GATHERV 3 # This flag prints out the Intel MPI state. Uncomment if needed #setenv I_MPI_DEBUG 9 +# These are options determined to be useful at NCCS +# Not setting generally as they are more fabric/cluster +# specific compared to the above adjustments +# NCCS: | - # These are options determined to be useful at NCCS - # Not setting generally as they are more fabric/cluster - # specific compared to the above adjustments + setenv I_MPI_ADJUST_ALLREDUCE 12 + setenv I_MPI_ADJUST_GATHERV 3 + setenv I_MPI_FABRICS shm:ofi setenv I_MPI_OFI_PROVIDER psm3 + + # This has been found to help with congestion setenv FI_PSM3_CONN_TIMEOUT 120 diff --git a/gcmpy/yaml/ocean_model.yaml b/gcmpy/yaml/ocean_model.yaml index 480845b5..96792b63 100755 --- a/gcmpy/yaml/ocean_model.yaml +++ b/gcmpy/yaml/ocean_model.yaml @@ -45,7 +45,7 @@ OM_MOM_horizontal_res: choices: '' default_answer: '360 200' follows_up: - - ['OM_name', ['MOM5', 'MOM6']] + - ['OM_name', ['MOM5']] OM_MIT_horizontal_res: type: 'select' @@ -67,7 +67,7 @@ OM_vertical_res: OM_seaice_model: type: 'select' prompt: 'Choose a seaice model:' - choices: ['CICE4', 'CICE6'] + choices: ['CICE6', 'CICE4'] default_answer: '' follows_up: - ['OM_coupled', [True]] From d02a7db473bbc69459e6949058c7c0e4b10442ab Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Wed, 23 Jul 2025 15:10:56 -0400 Subject: [PATCH 25/37] updated cmakelists for CFG_INSTALL_SOURCE_TARFILE --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e485887c..3a195fef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,3 @@ -add_subdirectory(gcmpy) - ecbuild_add_executable ( TARGET GEOSgcm.x SOURCES GEOSgcm.F90 @@ -79,3 +77,4 @@ endforeach () configure_file(.AGCM_VERSION .AGCM_VERSION @ONLY) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/.AGCM_VERSION DESTINATION etc) +add_subdirectory(gcmpy) From 67b54d9d09043388cd423ff1bb0f9fc8fac7f002 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 29 Jul 2025 12:24:46 -0400 Subject: [PATCH 26/37] Restore some missing changes --- gcm_run.j | 22 +++++++++++++++++++--- gcm_setup | 11 +++++------ gcmpy/scripts/land.py | 14 +++++++------- gcmpy/yaml/land_model.yaml | 6 +++--- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/gcm_run.j b/gcm_run.j index aacdada6..001057fd 100755 --- a/gcm_run.j +++ b/gcm_run.j @@ -37,6 +37,7 @@ setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH}:${GEOSDIR}/lib # We only add BASEDIR to the {{ LD_LIBRARY_PATH_CMD }} if BASEDIR is defined (i.e., not running with Spack) if ( $?BASEDIR ) then setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib + setenv PATH ${PATH}:${BASEDIR}/${ARCH}/bin endif setenv RUN_CMD "{{ RUN_CMD }}" @@ -463,9 +464,14 @@ chmod +x linkbcs {{ SINGULARITY_BUILD }} setenv GEOSEXE $GEOSBIN/GEOSgcm.x {{ SINGULARITY_BUILD }} endif -{{ NATIVE_BUILD }} echo "Copying $EXPDIR/GEOSgcm.x to $SCRDIR" -{{ NATIVE_BUILD }} echo "" -{{ NATIVE_BUILD }} /bin/cp $EXPDIR/GEOSgcm.x $SCRDIR/GEOSgcm.x +{{ NATIVE_BUILD }} if (-e $EXPDIR/GEOSgcm.x) then +{{ NATIVE_BUILD }} echo "Copying $EXPDIR/GEOSgcm.x to $SCRDIR" +{{ NATIVE_BUILD }} echo "" +{{ NATIVE_BUILD }} /bin/cp $EXPDIR/GEOSgcm.x $SCRDIR/GEOSgcm.x +{{ NATIVE_BUILD }} else +{{ NATIVE_BUILD }} echo "$EXPDIR/GEOSgcm.x not found. Please link or copy the executable to the experiment directory." +{{ NATIVE_BUILD }} exit 1 +{{ NATIVE_BUILD }} endif {{ NATIVE_BUILD }} setenv GEOSEXE $SCRDIR/GEOSgcm.x ####################################################################### @@ -895,6 +901,16 @@ endif #ln -sf $SSTDIR/dataoceanfile_MERRA2_SST.${OGCM_IM}x${OGCM_JM}.${yy}.data sst.data #ln -sf $SSTDIR/dataoceanfile_MERRA2_ICE.${OGCM_IM}x${OGCM_JM}.${yy}.data fraci.data +{{ CICE6 }} #detect exisistence of certain fields in CICE6 restart +{{ CICE6 }} ncdump -h INPUT/iced.nc | grep 'apnd' > /dev/null +{{ CICE6 }} if( $status == 0 ) then +{{ CICE6 }} echo 'pond state in restart, turn on restart flag if not already' +{{ CICE6 }} sed -i -E 's/^[[:space:]]*restart_pond_lvl[[:space:]]*=[[:space:]]*\.false\./ restart_pond_lvl = .true./' ice_in +{{ CICE6 }} else +{{ CICE6 }} echo 'pond state NOT in restart, turn off restart flag if already on' +{{ CICE6 }} sed -i -E 's/^[[:space:]]*restart_pond_lvl[[:space:]]*=[[:space:]]*\.true\./ restart_pond_lvl = .false./' ice_in +{{ CICE6 }} endif + ####################################################################### # Split Saltwater Restart if detected ####################################################################### diff --git a/gcm_setup b/gcm_setup index 40177912..c3aa0614 100644 --- a/gcm_setup +++ b/gcm_setup @@ -1439,9 +1439,9 @@ if ($DATA_ATMOS == TRUE) then set GWD_IN_BCS = "FALSE" else -echo "Enter the choice of ${C1}Land Surface Boundary Conditions${CN} using: ${C2}ICA${CN} (Icarus), ${C2}NL3${CN} (Icarus-NLv3), or ${C2}v13${CN} (Default)" +echo "Enter the choice of ${C1}Land Surface Boundary Conditions${CN} using: ${C2}ICA${CN} (Icarus), ${C2}NL3${CN} (Icarus-NLv3), or ${C2}v12${CN} (Default)" set LSM_BCS = $< -if( .$LSM_BCS == . ) set LSM_BCS = "v13" +if( .$LSM_BCS == . ) set LSM_BCS = "v12" if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "ica" ) then set LSM_BCS = "ICA" set LSM_PARMS = "#DELETE" @@ -1458,8 +1458,8 @@ else if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "nl3" ) then set EMIP_NEWLAND = "" set EMIP_MERRA2 = "MERRA2_NewLand" set GWD_IN_BCS = "FALSE" -else if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "v13" ) then - set LSM_BCS = "v13" +else if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "v12" ) then + set LSM_BCS = "v12" set LSM_PARMS = "" set EMIP_BCS_IN = "NL3" set EMIP_OLDLAND = "#DELETE" @@ -1468,7 +1468,7 @@ else if( `echo $LSM_BCS | tr '[:upper:]' '[:lower:]'` == "v13" ) then set GWD_IN_BCS = "TRUE" else echo - echo "${C1} Land Surface Boundary Conditions${CN} must be set equal to ${C2}ICA (Icarus)${CN}, ${C2}NL3 (Icarus-NLv3)${CN}, or ${C2}v13${CN}!" + echo "${C1} Land Surface Boundary Conditions${CN} must be set equal to ${C2}ICA (Icarus)${CN}, ${C2}NL3 (Icarus-NLv3)${CN}, or ${C2}v12${CN}!" goto LSM_BCS endif @@ -3344,4 +3344,3 @@ gcm_setup, a setup script for the GEOS GCM EOF exit 1 - diff --git a/gcmpy/scripts/land.py b/gcmpy/scripts/land.py index 8fafd97c..940d7158 100755 --- a/gcmpy/scripts/land.py +++ b/gcmpy/scripts/land.py @@ -10,11 +10,11 @@ def __init__(self): else: self.model = answerdict["LS_model"].q_answer self.bcs = answerdict["LS_boundary_conditions"].q_answer - self.parameters = '' + self.parameters = '' self.emip_bcs_in = '' self.emip_oldland = '' self.emip_newland = '' - self.emip_MERRA2 = '' + self.emip_MERRA2 = '' self.HIST_catchment = '' self.GCMRUN_catchment = '' @@ -25,12 +25,12 @@ def print_vars(self): print(f"{color.CYAN}{var_name}: {var_value}{color.RESET}") def set_bcs(self): - if self.bcs == "ICA": + if self.bcs == "ICA": self.parameters = "#DELETE" self.emip_bcs_in = "GM4" self.emip_oldland = "" self.emip_newland = "#DELETE" - self.emip_MERRA2 = "MERRA2" + self.emip_MERRA2 = "MERRA2" self.gwd_in_bcs = False elif self.bcs == "NL3": self.parameters = "" @@ -39,12 +39,12 @@ def set_bcs(self): self.emip_newland = "" self.emip_MERRA2 = "MERRA2_NewLand" self.gwd_in_bcs = False - elif self.bcs == "v13": + elif self.bcs == "v12": self.parameters = "" - self.emip_bcs_in = "NL3" + self.emip_bcs_in = "v12" self.emip_oldland = "#DELETE" self.emip_newland = "" - self.emip_MERRA2 = "MERRA2_NewLand" + self.emip_MERRA2 = "MERRA2_NewLand" self.gwd_in_bcs = True diff --git a/gcmpy/yaml/land_model.yaml b/gcmpy/yaml/land_model.yaml index cb5efe1b..95f28d17 100755 --- a/gcmpy/yaml/land_model.yaml +++ b/gcmpy/yaml/land_model.yaml @@ -1,9 +1,9 @@ LS_boundary_conditions: type: 'select' prompt: 'Select the Land Surface Boundary Conditions:' - choices: ['v13', 'NL3', 'ICA'] + choices: ['v12', 'NL3', 'ICA'] default_answer: '' - follows_up: + follows_up: - ['OM_data_atmos', [False]] - ['OM_data_atmos', ['was_not_asked']] @@ -12,6 +12,6 @@ LS_model: prompt: 'Select the Land Surface Model:' choices: ['Catchment', 'CatchmentCN-CLM4.0 (CN_CLM40)'] default_answer: '' - follows_up: + follows_up: - ['OM_data_atmos', [False]] - ['OM_data_atmos', ['was_not_asked']] From 6e321662425034eca08fc8492f0a813b20cce8b5 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 29 Jul 2025 12:28:23 -0400 Subject: [PATCH 27/37] Fix bad change --- gcmpy/scripts/land.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcmpy/scripts/land.py b/gcmpy/scripts/land.py index 940d7158..dbcd0a5f 100755 --- a/gcmpy/scripts/land.py +++ b/gcmpy/scripts/land.py @@ -41,7 +41,7 @@ def set_bcs(self): self.gwd_in_bcs = False elif self.bcs == "v12": self.parameters = "" - self.emip_bcs_in = "v12" + self.emip_bcs_in = "NL3" self.emip_oldland = "#DELETE" self.emip_newland = "" self.emip_MERRA2 = "MERRA2_NewLand" From 151eae1a64bbe427cb999a1c0e9ccae248d3a883 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 29 Jul 2025 12:50:33 -0400 Subject: [PATCH 28/37] Updates to history --- HISTORY.AGCM.rc.tmpl | 23 +++++---- HISTORY.AOGCM-MOM5.rc.tmpl | 4 ++ HISTORY.AOGCM.rc.tmpl | 4 ++ HISTORY.AOGCM_MITgcm.rc.tmpl | 4 ++ HISTORY.rc.tmpl | 93 ++++++++++++++++++------------------ 5 files changed, 73 insertions(+), 55 deletions(-) diff --git a/HISTORY.AGCM.rc.tmpl b/HISTORY.AGCM.rc.tmpl index a6bf313e..c9f1ee5e 100644 --- a/HISTORY.AGCM.rc.tmpl +++ b/HISTORY.AGCM.rc.tmpl @@ -209,15 +209,15 @@ PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} 'ASNOW' , 'SURFACE' , 'RADSRF' , 'RADIATION' , 'TBISCCP' , 'SATSIM' , - 'DBZ_MAX' , 'MOIST' , 'DBZMAX' , 'MAX' , - 'DBZ_TOP' , 'MOIST' , 'DBZTOP' , 'MAX' , - 'DBZ_1KM' , 'MOIST' , 'DBZ1KM' , 'MAX' , - 'DBZ_M10C' , 'MOIST' , 'DBZM10C' , 'MAX' , - 'UH25' , 'DYN' , 'UH25MX' , 'MAX' , - 'UH03' , 'DYN' , 'UH03MX' , 'MAX' , - 'SRH25' , 'DYN' , 'SRH25MX' , 'MAX' , - 'SRH03' , 'DYN' , 'SRH03MX' , 'MAX' , - 'SRH01' , 'DYN' , 'SRH01MX' , 'MAX' , + 'DBZ_MAX' , 'MOIST' , 'DBZMAX' , 'MAX' , + 'DBZ_TOP' , 'MOIST' , 'DBZTOP' , 'MAX' , + 'DBZ_1KM' , 'MOIST' , 'DBZ1KM' , 'MAX' , + 'DBZ_M10C' , 'MOIST' , 'DBZM10C' , 'MAX' , + 'UH25' , 'DYN' , 'UH25MX' , 'MAX' , + 'UH03' , 'DYN' , 'UH03MX' , 'MAX' , + 'SRH25' , 'DYN' , 'SRH25MX' , 'MAX' , + 'SRH03' , 'DYN' , 'SRH03MX' , 'MAX' , + 'SRH01' , 'DYN' , 'SRH01MX' , 'MAX' , 'FLNS' , 'IRRAD' , 'FLNSC' , 'IRRAD' , 'FLNSA' , 'IRRAD' , 'FLNSCNA' , @@ -343,6 +343,8 @@ PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} 'SWNDWTR' , 'SURFACE' , 'SWGNTWTR' , 'SWNDICE' , 'SURFACE' , 'SWGNTICE' , 'SNOWOCN' , 'SURFACE' , 'PRECSNOOCN' , + 'ICEFOCN' , 'SURFACE' , 'PRECICEOCN' , + 'SPTOTOCN' , 'SURFACE' , 'PRECSOLOCN' , 'RAINOCN' , 'SURFACE' , 'TAUXW;TAUYW' , 'SURFACE' , 'TAUXWTR;TAUYWTR', 'TAUXI;TAUYI' , 'SURFACE' , 'TAUXICE;TAUYICE', @@ -597,8 +599,11 @@ PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} geosgcm_budi.regrid_method: 'CONSERVE', geosgcm_budi.frequency: 030000 , geosgcm_budi.fields: 'TQV' , 'AGCM' , + 'TQG' , 'AGCM' , 'TQI' , 'AGCM' , 'TQL' , 'AGCM' , + 'TQR' , 'AGCM' , + 'TQS' , 'AGCM' , 'TOX' , 'AGCM' , 'MASS' , 'AGCM' , :: diff --git a/HISTORY.AOGCM-MOM5.rc.tmpl b/HISTORY.AOGCM-MOM5.rc.tmpl index 13b6d0b5..d222ef73 100644 --- a/HISTORY.AOGCM-MOM5.rc.tmpl +++ b/HISTORY.AOGCM-MOM5.rc.tmpl @@ -343,6 +343,8 @@ PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} 'SWNDWTR' , 'SURFACE' , 'SWGNTWTR' , 'SWNDICE' , 'SURFACE' , 'SWGNTICE' , 'SNOWOCN' , 'SURFACE' , 'PRECSNOOCN' , + 'ICEFOCN' , 'SURFACE' , 'PRECICEOCN' , + 'SPTOTOCN' , 'SURFACE' , 'PRECSOLOCN' , 'RAINOCN' , 'SURFACE' , 'TAUXW;TAUYW' , 'SURFACE' , 'TAUXWTR;TAUYWTR', 'TAUXI;TAUYI' , 'SURFACE' , 'TAUXICE;TAUYICE', @@ -1657,6 +1659,8 @@ PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} 'RAINOCN' , 'OPENWATER', 'AO_RAIN' , 'OPENWATER', 'SNOWOCN' , 'OPENWATER', + 'ICEFOCN' , 'OPENWATER', + 'SPTOTOCN' , 'OPENWATER', 'AO_SNOW' , 'OPENWATER', 'FRACI' , 'SEAICETHERMO', 'FRZMLT' , 'SEAICETHERMO', diff --git a/HISTORY.AOGCM.rc.tmpl b/HISTORY.AOGCM.rc.tmpl index 6dad102c..588a948e 100644 --- a/HISTORY.AOGCM.rc.tmpl +++ b/HISTORY.AOGCM.rc.tmpl @@ -340,6 +340,8 @@ PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} 'SWNDWTR' , 'SURFACE' , 'SWGNTWTR' , 'SWNDICE' , 'SURFACE' , 'SWGNTICE' , 'SNOWOCN' , 'SURFACE' , 'PRECSNOOCN' , + 'ICEFOCN' , 'SURFACE' , 'PRECICEOCN' , + 'SPTOTOCN' , 'SURFACE' , 'PRECSOLOCN' , 'RAINOCN' , 'SURFACE' , 'TAUXW;TAUYW' , 'SURFACE' , 'TAUXWTR;TAUYWTR', 'TAUXI;TAUYI' , 'SURFACE' , 'TAUXICE;TAUYICE', @@ -1582,6 +1584,8 @@ PC{{ HIST_IM }}x{{ HIST_JM }}-DC.LM: {{ AGCM_LM }} 'RAINOCN' , 'OPENWATER', 'AO_RAIN' , 'OPENWATER', 'SNOWOCN' , 'OPENWATER', + 'ICEFOCN' , 'OPENWATER', + 'SPTOTOCN' , 'OPENWATER', 'AO_SNOW' , 'OPENWATER', 'FRACI' , 'SEAICETHERMO', 'FRZMLT' , 'SEAICETHERMO', diff --git a/HISTORY.AOGCM_MITgcm.rc.tmpl b/HISTORY.AOGCM_MITgcm.rc.tmpl index 076b217f..291ea5f5 100755 --- a/HISTORY.AOGCM_MITgcm.rc.tmpl +++ b/HISTORY.AOGCM_MITgcm.rc.tmpl @@ -309,6 +309,8 @@ PC360x181-DC.GRIDNAME: PC360x181-DC 'SWNDWTR' , 'SURFACE' , 'SWGNTWTR' , 'SWNDICE' , 'SURFACE' , 'SWGNTICE' , 'SNOWOCN' , 'SURFACE' , 'PRECSNOOCN' , + 'ICEFOCN' , 'SURFACE' , 'PRECICEOCN' , + 'SPTOTOCN' , 'SURFACE' , 'PRECSOLOCN' , 'RAINOCN' , 'SURFACE' , 'TAUXW;TAUYW' , 'SURFACE' , 'TAUXWTR;TAUYWTR', 'TAUXI;TAUYI' , 'SURFACE' , 'TAUXICE;TAUYICE', @@ -1665,6 +1667,8 @@ PC360x181-DC.GRIDNAME: PC360x181-DC 'RAINOCN' , 'OPENWATER', 'AO_RAIN' , 'OPENWATER', 'SNOWOCN' , 'OPENWATER', + 'ICEFOCN' , 'OPENWATER', + 'SPTOTOCN' , 'OPENWATER', 'AO_SNOW' , 'OPENWATER', 'FRACI' , 'SEAICETHERMO', 'FRZMLT' , 'SEAICETHERMO', diff --git a/HISTORY.rc.tmpl b/HISTORY.rc.tmpl index 4afaebd4..a373baae 100644 --- a/HISTORY.rc.tmpl +++ b/HISTORY.rc.tmpl @@ -130,6 +130,8 @@ COLLECTIONS: 'inst3_3d_asm_Np-' 'bkg.eta' 'bkg.sfc' 'cbkg.eta' + 'bkg.lfo_inst' + 'bkg.lfo_tavg' 'vtx.mix' # 'vtx.prs' # 'prog.sfc+-' @@ -139,9 +141,6 @@ COLLECTIONS: 'inst3_3d_asm_Np-' # 'prog.eta+-' # 'traj.lcv' # 'ptrj.prs' -# predictor forcing files for land da coupling -# 'inst1_2d_lfo_Nx+-' -# 'tavg1_2d_lfo_Nx+-' # Forecast Files # 'inst3_3d_asm_Np+-' # 'inst3_3d_asm_Nv+-' @@ -1039,6 +1038,8 @@ COLLECTIONS: 'inst3_3d_asm_Np-' 'SWNDWTR' , 'SURFACE' , 'SWGNTWTR' , 'SWNDICE' , 'SURFACE' , 'SWGNTICE' , 'SNOWOCN' , 'SURFACE' , 'PRECSNOOCN' , + 'ICEFOCN' , 'SURFACE' , 'PRECICEOCN' , + 'SPTOTOCN' , 'SURFACE' , 'PRECSOLOCN' , 'RAINOCN' , 'SURFACE' , 'TAUXW;TAUYW' , 'SURFACE' , 'TAUXWTR;TAUYWTR' , 'TAUXI;TAUYI' , 'SURFACE' , 'TAUXICE;TAUYICE' , @@ -1097,6 +1098,8 @@ COLLECTIONS: 'inst3_3d_asm_Np-' 'SWNDWTR' , 'SURFACE' , 'SWGNTWTR' , 'SWNDICE' , 'SURFACE' , 'SWGNTICE' , 'SNOWOCN' , 'SURFACE' , 'PRECSNOOCN' , + 'ICEFOCN' , 'SURFACE' , 'PRECICEOCN' , + 'SPTOTOCN' , 'SURFACE' , 'PRECSOLOCN' , 'RAINOCN' , 'SURFACE' , 'TAUXW;TAUYW' , 'SURFACE' , 'TAUXWTR;TAUYWTR' , 'TAUXI;TAUYI' , 'SURFACE' , 'TAUXICE;TAUYICE' , @@ -1288,6 +1291,47 @@ COLLECTIONS: 'inst3_3d_asm_Np-' 'GOCART::CO2' , 'GOCART' , 'CO2' , :: +####################################################################### +# Ldas bkg forcing +####################################################################### + + bkg.lfo_tavg.format: 'CFIO' , + bkg.lfo_tavg.descr: '2d,1-Hourly,Time-Averaged,Single-Level,Land Surface Forcings' , + bkg.lfo_tavg.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , + bkg.lfo_tavg.mode: 'time-averaged' , + bkg.lfo_tavg.frequency: 010000 , + bkg.lfo_tavg.duration: 010000 , + bkg.lfo_tavg.ref_date: >>>IOBBKGD<<< , + bkg.lfo_tavg.ref_time: >>>IOBBKGT<<< , + bkg.lfo_tavg.end_date: >>>IOEBKGD<<< , + bkg.lfo_tavg.end_time: >>>IOEBKGT<<< , + bkg.lfo_tavg.fields: 'SLRSF' , 'SOLAR' , 'SWGDN' , + 'LWS' , 'IRRAD' , 'LWGAB' , + 'PCU' , 'SURFACE' , 'PRECCU' , + 'PLS' , 'SURFACE' , 'PRECLS' , + 'SNO' , 'SURFACE' , 'PRECSNO' , + 'DFPAR' , 'SOLAR' , 'PARDF' , + 'DRPAR' , 'SOLAR' , 'PARDR' , + :: + + bkg.lfo_inst.format: 'CFIO' , + bkg.lfo_inst.descr: '2d,1-Hourly,Instantaneous,Single-Level,Land Surface Forcings' , + bkg.lfo_inst.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , + bkg.lfo_inst.mode: 'instantaneous' , + bkg.lfo_inst.frequency: 010000 , + bkg.lfo_inst.duration: 010000 , + bkg.lfo_inst.ref_date: >>>IOBBKGD<<< , + bkg.lfo_inst.ref_time: >>>IOBBKGT<<< , + bkg.lfo_inst.end_date: >>>IOEBKGD<<< , + bkg.lfo_inst.end_time: >>>IOEBKGT<<< , + bkg.lfo_inst.fields: 'DZ' , 'DYN' , 'HLML' , + 'TA' , 'DYN' , 'TLML' , + 'QA' , 'DYN' , 'QLML' , + 'SPEED' , 'DYN' , 'SPEEDLML' , + 'PS' , 'DYN' , + :: + + ####################################################################### # Aerosols/Constituents ####################################################################### @@ -1981,49 +2025,6 @@ COLLECTIONS: 'inst3_3d_asm_Np-' 'ZLE' , 'DYN' , 'hght' , :: -####################################################################### -# predictor forcing files for land da coupling -####################################################################### - - tavg1_2d_lfo_Nx+-.format: 'CFIO' , - tavg1_2d_lfo_Nx+-.descr: '2d,1-Hourly,Time-Averaged,Single-Level,Land Surface Forcings' , -# tavg1_2d_lfo_Nx+-.nbits: 10 , - tavg1_2d_lfo_Nx+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , - tavg1_2d_lfo_Nx+-.mode: 'time-averaged' , - tavg1_2d_lfo_Nx+-.frequency: 010000 , - tavg1_2d_lfo_Nx+-.duration: 010000 , - tavg1_2d_lfo_Nx+-.ref_date: >>>IOBBKGD<<< , - tavg1_2d_lfo_Nx+-.ref_time: >>>IOBBKGT<<< , - tavg1_2d_lfo_Nx+-.end_date: >>>IOEBKGD<<< , - tavg1_2d_lfo_Nx+-.end_time: >>>IOEBKGT<<< , - tavg1_2d_lfo_Nx+-.fields: 'SLRSF' , 'SOLAR' , 'SWGDN' , - 'SWLAND' , 'SURFACE' , - 'LWS' , 'IRRAD' , 'LWGAB' , - 'PCU' , 'SURFACE' , 'PRECRAINCU' , - 'PLS' , 'SURFACE' , 'PRECRAINLS' , - 'SNO' , 'SURFACE' , 'PRECSNO' , - 'DFPAR' , 'SOLAR' , 'PARDF' , - 'DRPAR' , 'SOLAR' , 'PARDR' , - :: - - inst1_2d_lfo_Nx+-.format: 'CFIO' , - inst1_2d_lfo_Nx+-.descr: '2d,1-Hourly,Instantaneous,Single-Level,Land Surface Forcings' , -# inst1_2d_lfo_Nx+-.nbits: 10 , - inst1_2d_lfo_Nx+-.template: '%y4%m2%d2_%h2%n2z.>>>NCSUFFIX<<<' , - inst1_2d_lfo_Nx+-.mode: 'instantaneous' , - inst1_2d_lfo_Nx+-.frequency: 010000 , - inst1_2d_lfo_Nx+-.duration: 010000 , - inst1_2d_lfo_Nx+-.ref_date: >>>IOBBKGD<<< , - inst1_2d_lfo_Nx+-.ref_time: >>>IOBBKGT<<< , - inst1_2d_lfo_Nx+-.end_date: >>>IOEBKGD<<< , - inst1_2d_lfo_Nx+-.end_time: >>>IOEBKGT<<< , - inst1_2d_lfo_Nx+-.fields: 'DZ' , 'DYN' , 'HLML' , - 'TA' , 'DYN' , 'TLML' , - 'QA' , 'DYN' , 'QLML' , - 'SPEED' , 'DYN' , 'SPEEDLML' , - 'PS' , 'DYN' , - :: - ####################################################################### # Forecast Files ####################################################################### From 9177c7fa818d10f5e7ce6955457b60b1875b3ded Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 29 Jul 2025 12:59:52 -0400 Subject: [PATCH 29/37] Satisfy yamllint --- gcmpy/yaml/exp_setup.yaml | 2 +- gcmpy/yaml/gocart.yaml | 6 +++--- gcmpy/yaml/mpi_config.yaml | 4 ++-- gcmpy/yaml/ocean_model.yaml | 16 ++++++++-------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/gcmpy/yaml/exp_setup.yaml b/gcmpy/yaml/exp_setup.yaml index 82404a5d..a7d85a13 100755 --- a/gcmpy/yaml/exp_setup.yaml +++ b/gcmpy/yaml/exp_setup.yaml @@ -24,7 +24,7 @@ clone_experiment_path: prompt: 'Enter the location of the experiment you wish to clone (where gcm_run.j is located):' choices: '' default_answer: '' - follows_up: + follows_up: - ['clone_experiment', [True]] diff --git a/gcmpy/yaml/gocart.yaml b/gcmpy/yaml/gocart.yaml index 5eeae936..8c3e33c4 100755 --- a/gcmpy/yaml/gocart.yaml +++ b/gcmpy/yaml/gocart.yaml @@ -3,15 +3,15 @@ gocart_aerosols: prompt: 'Do you wish to run GOCART with Actual or Climatological Aersols?' choices: ['Actual', 'Climatological'] default_answer: '' - follows_up: + follows_up: - ['OM_data_atmos', [False]] - ['OM_data_atmos', ['was_not_asked']] gocart_emission: type: 'select' - prompt: 'Select the GOCART Emission Files to use:' + prompt: 'Select the GOCART Emission Files to use:' choices: ['AMIP', 'OPS'] default_answer: '' - follows_up: + follows_up: - ['OM_data_atmos', [False]] - ['OM_data_atmos', ['was_not_asked']] diff --git a/gcmpy/yaml/mpi_config.yaml b/gcmpy/yaml/mpi_config.yaml index fb037626..f2aaed6a 100755 --- a/gcmpy/yaml/mpi_config.yaml +++ b/gcmpy/yaml/mpi_config.yaml @@ -64,9 +64,9 @@ intelmpi: | NCCS: | setenv I_MPI_ADJUST_ALLREDUCE 12 setenv I_MPI_ADJUST_GATHERV 3 - + setenv I_MPI_FABRICS shm:ofi setenv I_MPI_OFI_PROVIDER psm3 - + # This has been found to help with congestion setenv FI_PSM3_CONN_TIMEOUT 120 diff --git a/gcmpy/yaml/ocean_model.yaml b/gcmpy/yaml/ocean_model.yaml index 96792b63..aea5ecab 100755 --- a/gcmpy/yaml/ocean_model.yaml +++ b/gcmpy/yaml/ocean_model.yaml @@ -2,13 +2,13 @@ # # question name: # question type: 'text/confirm/select/path' -# question prompt: 'ask your question' +# question prompt: 'ask your question' # choices: ['list', 'of', 'choices'] <----------(only for select type, otherwise leave blank) # default answer: 'default' <----------(optional/can be left blank) -# follows_up: <----------(optional/can be left blank. If you want to +# follows_up: <----------(optional/can be left blank. If you want to # -['prev question', ['answer1', 'answer2']] conditionally skip a question, add a list of # -['or other prev question', ['any']] tuples containing the question(s) it will follow up -# and the answer the user has to give in order for +# and the answer the user has to give in order for # this question to be asked. Multiple answers can be # an ask condition, or you can set the answer to 'any' # which will allow any answer given to show the question.) @@ -26,7 +26,7 @@ OM_horizontal_res: prompt: 'Select the Data_Ocean HORIZONTAL resolution:' choices: ['o1 (1 -deg, 360x180 Reynolds)', 'o2 (1/4-deg, 1440x720 MERRA-2)', 'o3 (1/8-deg, 2880x1440 OSTIA)', 'CS (Cubed-Sphere OSTIA)'] default_answer: '' - follows_up: + follows_up: - ['OM_coupled', [False]] # --------------------------------------------------------------------------------------------- @@ -36,7 +36,7 @@ OM_name: prompt: 'Choose an Ocean Model:' choices: ['MOM5', 'MOM6', 'MIT'] default_answer: '' - follows_up: + follows_up: - ['OM_coupled', [True]] OM_MOM_horizontal_res: @@ -44,7 +44,7 @@ OM_MOM_horizontal_res: prompt: 'Enter the Ocean Lat/Lon Horizontal Resolution (IM JM):' choices: '' default_answer: '360 200' - follows_up: + follows_up: - ['OM_name', ['MOM5']] OM_MIT_horizontal_res: @@ -52,7 +52,7 @@ OM_MIT_horizontal_res: prompt: 'Select the Data_Ocean HORIZONTAL resolution:' choices: ['llc90 (1-deg, Lat-Lon-Cube)', 'llc270 (1/3-deg, Lat-Lon-Cube)', 'cs32 (5-deg, cubed-sphere)'] default_answer: '' - follows_up: + follows_up: - ['OM_name', ['MIT']] OM_vertical_res: @@ -60,7 +60,7 @@ OM_vertical_res: prompt: 'Enter the Ocean Model VERTICAL resolution (LM):' choices: '' default_answer: '50' - follows_up: + follows_up: - ['OM_MOM_horizontal_res', ['any']] - ['OM_MIT_horizontal_res', ['any']] From f3a50fae7f5d65842bcf4900c892a93ed5eab323 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 29 Jul 2025 13:01:39 -0400 Subject: [PATCH 30/37] Trivial commit to test CI --- gcmpy/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/gcmpy/CMakeLists.txt b/gcmpy/CMakeLists.txt index 7dcf4dd1..a577c96c 100644 --- a/gcmpy/CMakeLists.txt +++ b/gcmpy/CMakeLists.txt @@ -1,4 +1,3 @@ # cp (makes exe) add_subdirectory(scripts) add_subdirectory(yaml) - From d84d2f02a749a18abe94e625acb4d28aa5ee92df Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 29 Jul 2025 13:12:44 -0400 Subject: [PATCH 31/37] Make scm like gcm --- scm_run.j | 27 ++++++++++++++------------- scm_setup | 18 +++++++++--------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/scm_run.j b/scm_run.j index 6a8ba010..39df1d49 100755 --- a/scm_run.j +++ b/scm_run.j @@ -1,24 +1,25 @@ #!/bin/tcsh -f -#@BATCH_TIME -#@BATCH_TASKS -#@BATCH_JOBNAME -#@BATCH_GROUP +#{{ BATCH_TIME }} +#{{ BATCH_TASKS }} +#{{ BATCH_JOBNAME }} +#{{ BATCH_GROUP }} umask 022 limit stacksize unlimited setenv ARCH `uname` -setenv SITE @SITE -setenv GEOSDIR @INSTALLDIR -setenv GEOSBIN @INSTALLDIR/bin -setenv GEOSETC @INSTALLDIR/etc -setenv GEOSUTIL @INSTALLDIR +setenv SITE {{ SITE }} +setenv GEOSDIR {{ INSTALLDIR }} +setenv GEOSBIN {{ INSTALLDIR }}/bin +setenv GEOSETC {{ INSTALLDIR }}/etc +setenv GEOSUTIL {{ INSTALLDIR }} source $GEOSBIN/g5_modules -setenv @LD_LIBRARY_PATH_CMD ${LD_LIBRARY_PATH}:${GEOSDIR}/lib -# We only add BASEDIR to the @LD_LIBRARY_PATH_CMD if BASEDIR is defined (i.e., not running with Spack) +setenv {{ LD_LIBRARY_PATH_CMD }} ${LD_LIBRARY_PATH}:${GEOSDIR}/lib +# We only add BASEDIR to the {{ LD_LIBRARY_PATH_CMD }} if BASEDIR is defined (i.e., not running with Spack) if ( $?BASEDIR ) then - setenv @LD_LIBRARY_PATH_CMD ${@LD_LIBRARY_PATH_CMD}:${BASEDIR}/${ARCH}/lib + setenv {{ LD_LIBRARY_PATH_CMD }} ${{'{'}}{{LD_LIBRARY_PATH_CMD}}{{'}'}}:${BASEDIR}/${ARCH}/lib + setenv PATH ${PATH}:${BASEDIR}/${ARCH}/bin endif setenv RUN_CMD "$GEOSBIN/esma_mpirun -np " @@ -26,7 +27,7 @@ setenv RUN_CMD "$GEOSBIN/esma_mpirun -np " setenv GCMVER `cat $GEOSETC/.AGCM_VERSION` echo VERSION: $GCMVER -setenv EXPDIR @EXPDIR +setenv EXPDIR {{ EXPDIR }} cd $EXPDIR diff --git a/scm_setup b/scm_setup index ded22e5f..876940ce 100755 --- a/scm_setup +++ b/scm_setup @@ -513,15 +513,15 @@ else fi cat > $expdir/sedfile << EOF -s?@EXPDIR?$expdir?g -s?@SITE?$SITE?g -s?@INSTALLDIR?$INSTALLDIR?g -s?@BATCH_TASKS?$BATCH_TASKS?g -s?@BATCH_TIME?$BATCH_TIME?g -s?@BATCH_GROUP?$BATCH_GROUP?g -s?@BATCH_JOBNAME?$BATCH_JOBNAME?g -s?@PRELOAD_COMMAND?$PRELOAD_COMMAND?g -s?@LD_LIBRARY_PATH_CMD?$LD_LIBRARY_PATH_CMD?g +s?{{ EXPDIR }}?$expdir?g +s?{{ SITE }}?$SITE?g +s?{{ INSTALLDIR }}?$INSTALLDIR?g +s?{{ BATCH_TASKS }}?$BATCH_TASKS?g +s?{{ BATCH_TIME }}?$BATCH_TIME?g +s?{{ BATCH_GROUP }}?$BATCH_GROUP?g +s?{{ BATCH_JOBNAME }}?$BATCH_JOBNAME?g +s?{{ PRELOAD_COMMAND }}?$PRELOAD_COMMAND?g +s?{{ LD_LIBRARY_PATH_CMD }}?$LD_LIBRARY_PATH_CMD?g EOF $ISED -f $expdir/sedfile $expdir/scm_run.j From 789d0f206b92ef4101a0b0697fa5fb254a8bd54e Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Wed, 30 Jul 2025 15:17:28 -0400 Subject: [PATCH 32/37] Add shebang to gcm_setup.py --- gcmpy/scripts/gcm_setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index bdf758e4..f4257850 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + from ocean import ocean from atmosphere import atmosphere as atmos from land import land @@ -642,7 +644,7 @@ def copy_src_tarfile(self): shutil.rmtree(src_dir) src_dir.mkdir(parents=True) print(f"Copying build source code into {color.GREEN}{src_dir}{color.RESET}") - + if os.path.exists(tarfile_path): shutil.copy(tarfile_path, src_dir) else: @@ -910,7 +912,7 @@ def organize_exp_dir(self): try: #only if using MOM ocean shutil.move(f"{exp_dir}/plotocn.j", f"{exp_dir}/plot/plotocn.j") except FileNotFoundError: - pass + pass # post dir shutil.move(f"{exp_dir}/gcm_post.j", f"{exp_dir}/post/gcm_post.j") From 33edb2d98a85d1340ca7dcf0015ed941aba02c77 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Wed, 30 Jul 2025 15:25:56 -0400 Subject: [PATCH 33/37] Turn off exp description different from exp id for now --- gcmpy/scripts/process_questions.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index a340ccfc..4374ad26 100755 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -15,12 +15,16 @@ def select_type(answerdict, i): # If that changes it's probably best to delete this function. answerdict[i].q_answer = answerdict[i].q_answer.split(None, 1)[0] + # Commenting this out for now until we know if we want to make sure + # the experiment description is different from the experiment ID. + ''' @staticmethod def experiment_desc(answerdict, i): if i == "experiment_description" and answerdict[i].q_answer != None: while answerdict["experiment_description"].q_answer == answerdict["experiment_id"].q_answer: print(color.RED + "The experiment description must be different from the ID!") answerdict[i].load_question(answerdict) + ''' @staticmethod def io_server_defualt(answerdict, i): @@ -252,7 +256,7 @@ def process(): # input validation and other post processing goes here, # AFTER load_question() call - handle.experiment_desc(answerdict, i) + # handle.experiment_desc(answerdict, i) # handle.OM_hres_valid(answerdict, i) handle.heartbeat_valid(answerdict, i) handle.exp_dir_valid(answerdict, i) From a51fb18cc066b3d3631a5291569b9e1c3a15918c Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Tue, 16 Sep 2025 05:04:03 -0400 Subject: [PATCH 34/37] new dt changes, CLIM_IM/JM, ice_in regex subsitution --- gcmpy/scripts/atmosphere.py | 75 ++++++++++++++++++++---------- gcmpy/scripts/gcm_setup.py | 18 ++++++- gcmpy/scripts/process_questions.py | 6 +-- 3 files changed, 69 insertions(+), 30 deletions(-) diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py index 8b212dd1..3d21ec38 100755 --- a/gcmpy/scripts/atmosphere.py +++ b/gcmpy/scripts/atmosphere.py @@ -12,7 +12,6 @@ def __init__(self): self.dt_solar = None self.dt_irrad = None self.dt_ocean = answerdict['heartbeat'].q_answer - self.dt_long = None self.lm = int(answerdict['AM_vertical_res'].q_answer) self.im = int(answerdict['AM_horizontal_res'].q_answer[1:]) self.jm = self.im * 6 @@ -64,9 +63,10 @@ def print_vars(self): def hres(self, ocean_nx, ocean_ny): match answerdict["AM_horizontal_res"].q_answer: case "c12": + self.conv_dt = 3600 + self.chem_dt = 3600 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 3600 self.dt_ocean = 3600 if answerdict["OM_name"].q_answer == "MOM6": self.nx = 1 @@ -82,9 +82,10 @@ def hres(self, ocean_nx, ocean_ny): case "c24": + self.conv_dt = 1800 + self.chem_dt = 3600 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 3600 self.dt_ocean = 3600 self.nx = 4 self.ny = self.nx * 6 @@ -96,9 +97,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF0024x6C' case "c48": + self.conv_dt = 1200 + self.chem_dt = 3600 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 3600 self.dt_ocean = 3600 self.nx = 6 self.ny = self.nx * 6 @@ -112,9 +114,10 @@ def hres(self, ocean_nx, ocean_ny): self.hist_jm = 91 case "c90": + self.conv_dt = 900 + self.chem_dt = 1800 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 1800 self.dt_ocean = self.dt if answerdict['OM_name'].q_answer == 'MIT': self.nx = 10 @@ -135,9 +138,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF0090x6C' case "c180": + self.conv_dt = 600 + self.chem_dt = 1200 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 1200 self.dt_ocean = self.dt if answerdict['OM_name'].q_answer == 'MOM6': self.nx = 30 @@ -156,9 +160,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF0180x6C' case "c360": + self.conv_dt = 450 + self.chem_dt = 900 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 900 self.dt_ocean = 4600 self.nx = 30 self.ny = self.nx * 6 @@ -170,9 +175,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF0360x6C' case "c720": + self.conv_dt = 300 + self.chem_dt = 900 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 600 self.dt_ocean = 3600 self.nx = 40 self.ny = self.nx * 6 @@ -185,9 +191,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF0720x6C' case "1120": + self.conv_dt = 300 + self.chem_dt = 900 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 600 self.dt_ocean = 3600 self.nx = 60 self.ny = self.nx * 6 @@ -200,9 +207,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF1120x6C' case "c1440": + self.conv_dt = 225 + self.chem_dt = 900 self.dt_solar = 1800 self.dt_irrad = 1800 - self.dt_long = 450 self.dt_ocean = 1800 self.nx = 80 self.ny = self.nx * 6 @@ -215,9 +223,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF1440x6C' case "c2880": + self.conv_dt = 150 + self.chem_dt = 900 self.dt_solar = 1800 self.dt_irrad = 1800 - self.dt_long = 300 self.dt_ocean = 1800 self.nx = 80 self.ny = self.nx * 6 @@ -231,9 +240,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF2880x6C' case "c5760": + self.conv_dt = 75 + self.chem_dt = 900 self.dt_solar = 1800 self.dt_irrad = 1800 - self.dt_long = 300 self.dt_ocean = 1800 self.nx = 80 self.ny = self.nx * 6 @@ -247,9 +257,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF5760x6C' case "c270": + self.conv_dt = 600 + self.chem_dt = 1800 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 1200 self.dt_ocean = 3600 self.nx = 20 self.ny = self.nx * 6 * 2 @@ -264,9 +275,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF0270x6C-SG001' case "c540": + self.conv_dt = 300 + self.chem_dt = 900 self.dt_solar = 3600 self.dt_irrad = 3600 - self.dt_long = 600 self.dt_ocean = 3600 self.nx = 30 self.ny = self.nx * 6 * 2 @@ -281,9 +293,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF0540x6C-SG001' case "c1080": + self.conv_dt = 300 + self.chem_dt = 600 self.dt_solar = 1800 self.dt_irrad = 1800 - self.dt_long = 300 self.dt_ocean = 1800 self.nx = 40 self.ny = self.nx * 6 * 2 @@ -298,9 +311,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF1080x6C-SG001' case "c1536": + self.conv_dt = 300 + self.chem_dt = 900 self.dt_solar = 900 self.dt_irrad = 900 - self.dt_long = 300 self.dt_ocean = 900 self.nx = 60 self.ny = self.nx * 6 @@ -315,9 +329,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF1536x6C-SG002' case "c2160": + self.conv_dt = 300 + self.chem_dt = 300 self.dt_solar = 900 self.dt_irrad = 900 - self.dt_long = 300 self.dt_ocean = 900 self.nx = 80 self.ny = self.nx * 6 * 2 @@ -332,9 +347,10 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF2160x6C-SG001' case 'c4320': + self.conv_dt = 300 + self.chem_dt = 300 self.dt_solar = 900 self.dt_irrad = 900 - self.dt_long = 300 self.dt_ocean = 900 self.nx = 80 self.ny = self.nx * 6 * 2 @@ -351,13 +367,14 @@ def hres(self, ocean_nx, ocean_ny): def set_microphysics(self): - match self.microphysics: - case "BACM_1M": - self.BACM_1M = "" - case "GFDL_1M": - self.GFDL_1M = "" - case "MGB2_2M": - self.MGB2_2M = "" + if self.microphysics == "BACM_1M": + self.BACM_1M = "" + self.conv_dt = 450 + self.chem_dt = 3600 + elif self.microphysics == "GFDL_1M": + self.GFDL_1M = "" + elif self.microphysics == "MGB2_2M": + self.MGB2_2M = "" def set_turnoff_wsub(self): if self.microphysics == "MGB2_2M": @@ -384,9 +401,17 @@ def set_wsub_extdata(self): else: self.mp_turn_off_wsub_extdata = '#DELETE#' + # Set coarse resolution CLIM output + def set_CLIM(self): + self.CLIM_IM = 576 + self.CLIM_JM = 361 + if (self.CLIM_IM > self.im_hist): + self.CLIM_IM = im_hist + self.CLIM_JM = jm_hist def config(self, ocean_nx, ocean_ny): self.hres(ocean_nx, ocean_ny) self.set_microphysics() self.set_conus() self.set_wsub_extdata() + self.set_CLIM() diff --git a/gcmpy/scripts/gcm_setup.py b/gcmpy/scripts/gcm_setup.py index f4257850..f2e8c262 100755 --- a/gcmpy/scripts/gcm_setup.py +++ b/gcmpy/scripts/gcm_setup.py @@ -595,8 +595,8 @@ def config_gocartGridComp(self): file.write(file_content) + # Modify MOM input files to match HEARTBEAT def config_heartbeat(self): - # With MOM5 we need to change dt lines in input.nml to # use $OCEAN_DT instead. NOTE: This regex assumes integer followed by comma if self.ocean.model == 'MOM5': @@ -610,6 +610,17 @@ def config_heartbeat(self): with open(f"{answerdict['exp_dir'].q_answer}/input.nml", 'w') as file: file.write(file_content) + # We also need to change the dt in ice_in as well for CICE6 + if self.ocean.seaice_model == 'CICE6': + file_path = f"{answerdict['exp_dir'].q_answer}/icein" + with open(file_path, 'r') as file: + content = file.read() + + file_content = re.sub(r"^(\s*dt\s*=\s*)[0-9]+(\.[0-9]+)?", r"\1" + self.atmos.dt_ocean, content) + + with open(file_path, 'w') as file: + file.write(file_content) + # We also must change the MOM_override file to # have consistent DTs with the AGCM. So we use OCEAN_DT @@ -785,10 +796,11 @@ def template(self): 'TILEDATA': self.tile_data, 'TILEBIN': self.tile_bin, 'DT': self.atmos.dt, + 'CONV_DT': self.atmos.conv_dt, + 'CHEM_DT': self.atmos.chem_dt, 'SOLAR_DT': self.atmos.dt_solar, 'IRRAD_DT': self.atmos.dt_irrad, 'OCEAN_DT': self.atmos.dt_ocean, - 'LONG_DT': self.atmos.dt_long, 'NX': self.atmos.nx, 'NY': self.atmos.ny, 'USE_SHMEM': int(self.atmos.use_SHMEM), @@ -823,6 +835,8 @@ def template(self): 'INTERPOLATE_SST': self.interpolate_sst, 'HIST_IM': self.atmos.hist_im, 'HIST_JM': self.atmos.hist_jm, + 'CLIM_IM': self.atmos.CLIM_IM, + 'CLIM_JM': self.atmos.CLIM_JM, 'ISCCP_SATSIM': 1, 'MODIS_SATSIM': 0, 'RADAR_SATSIM': 0, diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index 4374ad26..e928c8cd 100755 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -104,9 +104,9 @@ def heartbeat_default(answerdict, i): heartbeat = "" match answerdict["AM_horizontal_res"].q_answer: case 'c12': - heartbeat = 1800 + heartbeat = 3600 case 'c24': - heartbeat = 1200 + heartbeat = 1800 case 'c48': heartbeat = 1200 case 'c90': @@ -124,7 +124,7 @@ def heartbeat_default(answerdict, i): case 'c5760' | 'c1536' | 'c2160': heartbeat = 75 case 'c4320': - heartbeat = 30 + heartbeat = 60 # Per W. Putman recommendation, set heartbeat to 450s anytime BACM_1M is selected From 9159095d84ae422fd97990d4065172f1795e668c Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Thu, 2 Oct 2025 12:19:34 -0400 Subject: [PATCH 35/37] Add c --- gcmpy/scripts/atmosphere.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py index 3d21ec38..d809801e 100755 --- a/gcmpy/scripts/atmosphere.py +++ b/gcmpy/scripts/atmosphere.py @@ -190,7 +190,7 @@ def hres(self, ocean_nx, ocean_ny): self.use_SHMEM = 1 self.res = 'CF0720x6C' - case "1120": + case "c1120": self.conv_dt = 300 self.chem_dt = 900 self.dt_solar = 3600 From eb888db88cb06c018f890eab16916515ec61a1fd Mon Sep 17 00:00:00 2001 From: Shayon Shakoorzadeh Date: Thu, 2 Oct 2025 18:19:17 -0400 Subject: [PATCH 36/37] updated resolutions (v12 match) --- gcmpy/scripts/atmosphere.py | 34 +++++++++++++++--------------- gcmpy/scripts/process_questions.py | 8 ++----- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/gcmpy/scripts/atmosphere.py b/gcmpy/scripts/atmosphere.py index d809801e..3683d7b6 100755 --- a/gcmpy/scripts/atmosphere.py +++ b/gcmpy/scripts/atmosphere.py @@ -176,7 +176,7 @@ def hres(self, ocean_nx, ocean_ny): case "c720": self.conv_dt = 300 - self.chem_dt = 900 + self.chem_dt = 600 self.dt_solar = 3600 self.dt_irrad = 3600 self.dt_ocean = 3600 @@ -192,7 +192,7 @@ def hres(self, ocean_nx, ocean_ny): case "c1120": self.conv_dt = 300 - self.chem_dt = 900 + self.chem_dt = 600 self.dt_solar = 3600 self.dt_irrad = 3600 self.dt_ocean = 3600 @@ -207,11 +207,11 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF1120x6C' case "c1440": - self.conv_dt = 225 - self.chem_dt = 900 - self.dt_solar = 1800 - self.dt_irrad = 1800 - self.dt_ocean = 1800 + self.conv_dt = 300 + self.chem_dt = 600 + self.dt_solar = 1200 + self.dt_irrad = 1200 + self.dt_ocean = 1200 self.nx = 80 self.ny = self.nx * 6 self.num_readers = 6 @@ -223,11 +223,11 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF1440x6C' case "c2880": - self.conv_dt = 150 - self.chem_dt = 900 - self.dt_solar = 1800 - self.dt_irrad = 1800 - self.dt_ocean = 1800 + self.conv_dt = 300 + self.chem_dt = 300 + self.dt_solar = 900 + self.dt_irrad = 900 + self.dt_ocean = 900 self.nx = 80 self.ny = self.nx * 6 self.num_readers = 6 @@ -240,11 +240,11 @@ def hres(self, ocean_nx, ocean_ny): self.res = 'CF2880x6C' case "c5760": - self.conv_dt = 75 - self.chem_dt = 900 - self.dt_solar = 1800 - self.dt_irrad = 1800 - self.dt_ocean = 1800 + self.conv_dt = 300 + self.chem_dt = 300 + self.dt_solar = 600 + self.dt_irrad = 600 + self.dt_ocean = 600 self.nx = 80 self.ny = self.nx * 6 self.num_readers = 6 diff --git a/gcmpy/scripts/process_questions.py b/gcmpy/scripts/process_questions.py index e928c8cd..b7b5557d 100755 --- a/gcmpy/scripts/process_questions.py +++ b/gcmpy/scripts/process_questions.py @@ -117,14 +117,10 @@ def heartbeat_default(answerdict, i): heartbeat = 450 case 'c720' | 'c1120' | 'c540': heartbeat = 300 - case 'c1440': - heartbeat = 225 - case 'c2880' | 'c1080': + case 'c1440' | 'c1080': heartbeat = 150 - case 'c5760' | 'c1536' | 'c2160': + case 'c2880' | 'c5760' | 'c1536' | 'c2160' | 'c4320': heartbeat = 75 - case 'c4320': - heartbeat = 60 # Per W. Putman recommendation, set heartbeat to 450s anytime BACM_1M is selected From 4dbdfad6ebaaadd0382631a21f8e4939a646b058 Mon Sep 17 00:00:00 2001 From: Matthew Thompson Date: Tue, 28 Oct 2025 13:21:24 -0400 Subject: [PATCH 37/37] Add comment about I_MPI_JOB_RESPECT_PROCESS_PLACEMENT --- gcmpy/yaml/mpi_config.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gcmpy/yaml/mpi_config.yaml b/gcmpy/yaml/mpi_config.yaml index f2aaed6a..ae3be822 100755 --- a/gcmpy/yaml/mpi_config.yaml +++ b/gcmpy/yaml/mpi_config.yaml @@ -70,3 +70,13 @@ NCCS: | # This has been found to help with congestion setenv FI_PSM3_CONN_TIMEOUT 120 + + # NOTE: If you are seeing oddities with Intel MPI + # and a -perhost/-ppn use, you might need to + # uncomment the below line + # + #setenv I_MPI_JOB_RESPECT_PROCESS_PLACEMENT disable + # + # This is usually needed when running interactively + # as SLURM/PBS in batch mode is usually fine with process placement +