Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Refactoring of neon_site into tower_site, and neon_site #2344

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ unit_test_build
/tools/site_and_regional/????.ad/
/tools/site_and_regional/????.postad/
/tools/site_and_regional/????.transient/
/tools/site_and_regional/archive/

# build output
*.o
Expand Down
4 changes: 2 additions & 2 deletions cime_config/buildnml
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ def buildnml(case, caseroot, compname):
or clm_usrdat_name is "NEON.PRISM"
):
logger.warning(
"WARNING: Do you have approriprate initial conditions for this simulation?"
+ " Check that the finidat file used in the lnd_in namelist is apprporiately spunup for your case"
"WARNING: Do you have appropriate initial conditions for this simulation?"
+ " Check that the finidat file used in the lnd_in namelist is appropriately spunup for your case"
)

if comp_atm != "datm":
Expand Down
168 changes: 17 additions & 151 deletions python/ctsm/site_and_regional/neon_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
_CTSM_PYTHON = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "python"))
sys.path.insert(1, _CTSM_PYTHON)

# -- import local classes for this script
# pylint: disable=wrong-import-position
from ctsm.site_and_regional.tower_site import TowerSite

# pylint: disable=wrong-import-position, import-error, unused-import, wrong-import-order
from ctsm import add_cime_to_path
from ctsm.path_utils import path_to_ctsm_root
Expand All @@ -27,126 +31,30 @@


# pylint: disable=too-many-instance-attributes
class NeonSite:
class NeonSite(TowerSite):
"""
A class for encapsulating neon sites.
"""

def __init__(self, name, start_year, end_year, start_month, end_month, finidat):
self.name = name
self.start_year = int(start_year)
self.end_year = int(end_year)
self.start_month = int(start_month)
self.end_month = int(end_month)
self.cesmroot = path_to_ctsm_root()
self.finidat = finidat
super().__init__(name, start_year, end_year, start_month, end_month, finidat)
# self.name = name
# self.start_year = int(start_year)
# self.end_year = int(end_year)
# self.start_month = int(start_month)
# self.end_month = int(end_month)
# self.cesmroot = path_to_ctsm_root()
# self.finidat = finidat

def build_base_case(
self, cesmroot, output_root, res, compset, overwrite=False, setup_only=False
):
"""
Function for building a base_case to clone.
To spend less time on building ctsm for the neon cases,
all the other cases are cloned from this case

Args:
self:
The NeonSite object
base_root (str):
root of the base_case CIME
res (str):
base_case resolution or gridname
compset (str):
base case compset
overwrite (bool) :
Flag to overwrite the case if exists
"""
print("---- building a base case -------")
# pylint: disable=attribute-defined-outside-init
self.base_case_root = output_root
# pylint: enable=attribute-defined-outside-init
user_mods_dirs = [os.path.join(cesmroot, "cime_config", "usermods_dirs", "NEON", self.name)]
if not output_root:
output_root = os.getcwd()
case_path = os.path.join(output_root, self.name)

logger.info("base_case_name : %s", self.name)
logger.info("user_mods_dir : %s", user_mods_dirs[0])

if overwrite and os.path.isdir(case_path):
print("Removing the existing case at: {}".format(case_path))
shutil.rmtree(case_path)

with Case(case_path, read_only=False) as case:
if not os.path.isdir(case_path):
print("---- creating a base case -------")

case.create(
case_path,
cesmroot,
compset,
res,
run_unsupported=True,
answer="r",
output_root=output_root,
user_mods_dirs=user_mods_dirs,
driver="nuopc",
)

print("---- base case created ------")

# --change any config for base_case:
# case.set_value("RUN_TYPE","startup")
print("---- base case setup ------")
case.case_setup()
else:
# For existing case check that the compset name is correct
existingcompname = case.get_value("COMPSET")
match = re.search("^HIST", existingcompname, flags=re.IGNORECASE)
if re.search("^HIST", compset, flags=re.IGNORECASE) is None:
expect(
match is None,
"""Existing base case is a historical type and should not be
--rerun with the --overwrite option""",
)
else:
expect(
match is not None,
"""Existing base case should be a historical type and is not
--rerun with the --overwrite option""",
)
# reset the case
case.case_setup(reset=True)
case_path = case.get_value("CASEROOT")
case_path = super().build_base_case(cesmroot, output_root, res, compset)

if setup_only:
return case_path

print("---- base case build ------")
print("--- This may take a while and you may see WARNING messages ---")
# always walk through the build process to make sure it's up to date.
initial_time = time.time()
build.case_build(case_path, case=case)
end_time = time.time()
total = end_time - initial_time
print("Time required to building the base case: {} s.".format(total))
# update case_path to be the full path to the base case
return case_path

# pylint: disable=no-self-use
def get_batch_query(self, case):
"""
Function for querying the batch queue query command for a case, depending on the
user's batch system.

Args:
case:
case object
"""

if case.get_value("BATCH_SYSTEM") == "none":
return "none"
return case.get_value("batch_query")
return super().get_batch_query(case)

# pylint: disable=too-many-statements
def run_case(
Expand Down Expand Up @@ -321,50 +229,8 @@ def run_case(
print(f"Use {batch_query} to check its run status")

def set_ref_case(self, case):
"""
Set an existing case as the reference case, eg for use with spinup.
"""
rundir = case.get_value("RUNDIR")
case_root = case.get_value("CASEROOT")
if case_root.endswith(".postad"):
ref_case_root = case_root.replace(".postad", ".ad")
root = ".ad"
else:
ref_case_root = case_root.replace(".transient", ".postad")
root = ".postad"
if not os.path.isdir(ref_case_root):
logger.warning(
"ERROR: spinup must be completed first, could not find directory %s", ref_case_root
)
return False

with Case(ref_case_root) as refcase:
refrundir = refcase.get_value("RUNDIR")
case.set_value("RUN_REFDIR", refrundir)
case.set_value("RUN_REFCASE", os.path.basename(ref_case_root))
refdate = None
for reffile in glob.iglob(refrundir + "/{}{}.clm2.r.*.nc".format(self.name, root)):
m_searched = re.search(r"(\d\d\d\d-\d\d-\d\d)-\d\d\d\d\d.nc", reffile)
if m_searched:
refdate = m_searched.group(1)
symlink_force(reffile, os.path.join(rundir, os.path.basename(reffile)))
logger.info("Found refdate of %s", refdate)
if not refdate:
logger.warning("Could not find refcase for %s", case_root)
return False

for rpfile in glob.iglob(refrundir + "/rpointer*"):
safe_copy(rpfile, rundir)
if not os.path.isdir(os.path.join(rundir, "inputdata")) and os.path.isdir(
os.path.join(refrundir, "inputdata")
):
symlink_force(os.path.join(refrundir, "inputdata"), os.path.join(rundir, "inputdata"))

case.set_value("RUN_REFDATE", refdate)
if case_root.endswith(".postad"):
case.set_value("RUN_STARTDATE", refdate)
# NOTE: if start options are set, RUN_STARTDATE should be modified here
return True
super().set_ref_case(case)
return True ### Check if super returns false, if this will still return True?

def modify_user_nl(self, case_root, run_type, rundir):
"""
Expand Down
Loading
Loading