Skip to content
1 change: 1 addition & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ cdf40d265cc82775607a1bf25f5f527bacc97405
742cfa606039ab89602fde5fef46458516f56fd4
4ad46f46de7dde753b4653c15f05326f55116b73
75db098206b064b8b7b2a0604d3f0bf8fdb950cc
84609494b54ea9732f64add43b2f1dd035632b4c
15 changes: 15 additions & 0 deletions python/ctsm/longitude.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ def __ge__(self, other):
self._check_lons_same_type(other)
return self._lon >= other._lon

def __str__(self):
"""
We don't allow implicit string conversion because the user should always specify the
Longitude type they want
"""
raise NotImplementedError("Use Longitude.get_str() instead of implicit string conversion")

def get(self, lon_type_out):
"""
Get the longitude value, converting longitude type if needed
Expand All @@ -189,6 +196,14 @@ def get(self, lon_type_out):
return _convert_lon_type_180_to_360(self._lon)
raise RuntimeError(f"Add handling for lon_type_out {lon_type_out}")

def get_str(self, lon_type_out):
"""
Get the longitude value as a string, converting longitude type if needed
"""
lon_out = self.get(lon_type_out)
# Use float() because the standard in CTSM filenames is to put .0 after whole-number values
return str(float(lon_out))

def lon_type(self):
"""
Getter method for self._lon_type
Expand Down
24 changes: 19 additions & 5 deletions python/ctsm/site_and_regional/regional_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,20 @@ def _subset_lon_lat(self, x_dim, y_dim, f_in):
f_out = f_in.isel({y_dim: yind, x_dim: xind})
return f_out

def _get_lon_strings(self):
"""
Get the string versions of the region's longitudes
"""
if isinstance(self.lon1, Longitude):
lon1_str = self.lon1.get_str(self.lon1.lon_type())
else:
lon1_str = str(self.lon1)
if isinstance(self.lon2, Longitude):
lon2_str = self.lon2.get_str(self.lon2.lon_type())
else:
lon2_str = str(self.lon2)
return lon1_str, lon2_str

def create_tag(self):
"""
Create a tag for a region which is either the region name
Expand All @@ -169,20 +183,20 @@ def create_tag(self):
if self.reg_name:
self.tag = self.reg_name
else:
self.tag = "{}-{}_{}-{}".format(
str(self.lon1), str(self.lon2), str(self.lat1), str(self.lat2)
)
lon1_str, lon2_str = self._get_lon_strings()
self.tag = "{}-{}_{}-{}".format(lon1_str, lon2_str, str(self.lat1), str(self.lat2))

def check_region_bounds(self):
"""
Check for the regional bounds
"""
# If you're calling this, lat/lon bounds need to have been provided
if any(x is None for x in [self.lon1, self.lon2, self.lat1, self.lat2]):
lon1_str, lon2_str = self._get_lon_strings()
raise argparse.ArgumentTypeError(
"Latitude and longitude bounds must be provided and not None.\n"
+ f" lon1: {self.lon1}\n"
+ f" lon2: {self.lon2}\n"
+ f" lon1: {lon1_str}\n"
+ f" lon2: {lon2_str}\n"
+ f" lat1: {self.lat1}\n"
+ f" lat2: {self.lat2}"
)
Expand Down
31 changes: 21 additions & 10 deletions python/ctsm/site_and_regional/single_point_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,12 @@ def convert_plon_to_filetype_if_needed(self, lon_da):
plon_orig = plon_in.get(plon_type)
plon_out = plon_in.get(f_lon_type)
if plon_orig != plon_out:
print(
f"Converted plon from type {plon_type} (value {plon_orig}) "
f"to type {f_lon_type} (value {plon_out})"
logger.info(
"Converted plon from type %s (value %f) to type %s (value %f)",
plon_type,
plon_orig,
f_lon_type,
plon_out,
)
return plon_out

Expand All @@ -173,7 +176,7 @@ def create_tag(self):
if self.site_name:
self.tag = self.site_name
else:
self.tag = "{}_{}".format(str(self.plon), str(self.plat))
self.tag = "{}_{}".format(self.plon.get_str(self.plon.lon_type()), str(self.plat))

def check_dom_pft(self):
"""
Expand Down Expand Up @@ -333,7 +336,11 @@ def create_domain_at_point(self, indir, file):
Create domain file for this SinglePointCase class.
"""
logger.info("----------------------------------------------------------------------")
logger.info("Creating domain file at %s, %s.", str(self.plon), str(self.plat))
logger.info(
"Creating domain file at %s, %s.",
self.plon.get_str(self.plon.lon_type()),
str(self.plat),
)

# specify files
fdomain_in = os.path.join(indir, file)
Expand Down Expand Up @@ -367,7 +374,7 @@ def create_landuse_at_point(self, indir, file, user_mods_dir):
logger.info("----------------------------------------------------------------------")
logger.info(
"Creating land use file at %s, %s.",
str(self.plon),
self.plon.get_str(self.plon.lon_type()),
str(self.plat),
)

Expand Down Expand Up @@ -502,7 +509,7 @@ def create_surfdata_at_point(self, indir, file, user_mods_dir, specify_fsurf_out
logger.info("----------------------------------------------------------------------")
logger.info(
"Creating surface dataset file at %s, %s",
str(self.plon),
self.plon.get_str(self.plon.lon_type()),
str(self.plat),
)

Expand Down Expand Up @@ -577,7 +584,7 @@ def create_datmdomain_at_point(self, datm_tuple: DatmFiles):
logger.info("----------------------------------------------------------------------")
logger.info(
"Creating DATM domain file at %s, %s",
str(self.plon),
self.plon.get_str(self.plon.lon_type()),
str(self.plat),
)

Expand Down Expand Up @@ -646,7 +653,9 @@ def write_shell_commands(self, file, datm_syr, datm_eyr):
with open(file, "w") as nl_file:
self.write_to_file("# Change below line if you move the subset data directory", nl_file)
self.write_to_file("./xmlchange {}={}".format(USRDAT_DIR, self.out_dir), nl_file)
self.write_to_file("./xmlchange PTS_LON={}".format(str(self.plon)), nl_file)
self.write_to_file(
"./xmlchange PTS_LON={}".format(self.plon.get_str(self.plon.lon_type())), nl_file
)
self.write_to_file("./xmlchange PTS_LAT={}".format(str(self.plat)), nl_file)
self.write_to_file("./xmlchange MPILIB=mpi-serial", nl_file)
if self.create_datm:
Expand All @@ -672,7 +681,9 @@ def create_datm_at_point(self, datm_tuple: DatmFiles, datm_syr, datm_eyr, datm_s
Create all of a DATM dataset at a point.
"""
logger.info("----------------------------------------------------------------------")
logger.info("Creating DATM files at %s, %s", str(self.plon), str(self.plat))
logger.info(
"Creating DATM files at %s, %s", self.plon.get_str(self.plon.lon_type()), str(self.plat)
)

# -- create data files
infile = []
Expand Down
2 changes: 1 addition & 1 deletion python/ctsm/subset_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ def subset_region(args, file_dict: dict):
print("\nFor running this regional case with the created user_mods : ")
print(
"./create_newcase --case case --res CLM_USRDAT --compset I2000Clm60BgcCrop",
"--run-unsupported --user-mods-dirs ",
"--run-unsupported --user-mods-dir ",
args.user_mods_dir,
"\n\n",
)
Expand Down
Loading
Loading