151 lines
5.0 KiB
Python
151 lines
5.0 KiB
Python
"""
|
|
Check the results of a run with prescribed sowing dates and maturity requirements
|
|
"""
|
|
import sys
|
|
import argparse
|
|
import glob
|
|
import os
|
|
import numpy as np
|
|
|
|
# Import the CTSM Python utilities.
|
|
# sys.path.insert() is necessary for RXCROPMATURITY to work. The fact that it's calling this script
|
|
# in the RUN phase seems to require the python/ directory to be manually added to path.
|
|
_CTSM_PYTHON = os.path.join(
|
|
os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, os.pardir, "python"
|
|
)
|
|
sys.path.insert(1, _CTSM_PYTHON)
|
|
import ctsm.crop_calendars.cropcal_module as cc # pylint: disable=wrong-import-position
|
|
from ctsm.crop_calendars.check_rx_obeyed import ( # pylint: disable=wrong-import-position
|
|
check_rx_obeyed,
|
|
)
|
|
from ctsm.crop_calendars.check_constant_vars import ( # pylint: disable=wrong-import-position
|
|
check_constant_vars,
|
|
)
|
|
|
|
|
|
def main(argv):
|
|
"""
|
|
Main method: Check the results of a run with prescribed sowing dates and maturity requirements
|
|
"""
|
|
# Set arguments
|
|
parser = argparse.ArgumentParser(description="ADD DESCRIPTION HERE")
|
|
parser.add_argument(
|
|
"-d", "--directory", help="Directory with CLM output history files", required=True
|
|
)
|
|
parser.add_argument(
|
|
"--rx_sdates_file", "--rx-sdates-file", help="Prescribed sowing dates file", required=True
|
|
)
|
|
parser.add_argument(
|
|
"--rx_gdds_file",
|
|
"--rx-gdds-file",
|
|
help="Prescribed maturity requirements file",
|
|
required=True,
|
|
)
|
|
parser.add_argument(
|
|
"-y1",
|
|
"--first_usable_year",
|
|
"--first-usable-year",
|
|
type=int,
|
|
help="First usable year in the outputs",
|
|
required=True,
|
|
)
|
|
parser.add_argument(
|
|
"-yN",
|
|
"--last_usable_year",
|
|
"--last-usable-year",
|
|
type=int,
|
|
help="Last usable year in the outputs",
|
|
required=True,
|
|
)
|
|
args = parser.parse_args(argv)
|
|
|
|
# Note that _PERHARV will be stripped off upon import
|
|
my_vars = [
|
|
"GRAINC_TO_FOOD_PERHARV",
|
|
"GRAINC_TO_FOOD_ANN",
|
|
"SDATES",
|
|
"SDATES_PERHARV",
|
|
"SYEARS_PERHARV",
|
|
"HDATES",
|
|
"HYEARS",
|
|
"GDDHARV_PERHARV",
|
|
"GDDACCUM_PERHARV",
|
|
"HUI_PERHARV",
|
|
"SOWING_REASON_PERHARV",
|
|
"HARVEST_REASON_PERHARV",
|
|
]
|
|
|
|
annual_outfiles = glob.glob(os.path.join(args.directory, "*.clm2.h1.*.nc"))
|
|
|
|
# These should be constant in a Prescribed Calendars (rxboth) run, as long as the inputs were
|
|
# static.
|
|
case = {
|
|
"const_vars": ["SDATES", "GDDHARV"],
|
|
"rx_sdates_file": args.rx_sdates_file,
|
|
"rx_gdds_file": args.rx_gdds_file,
|
|
}
|
|
|
|
case["ds"] = cc.import_output(
|
|
annual_outfiles,
|
|
my_vars=my_vars,
|
|
year_1=args.first_usable_year,
|
|
year_n=args.last_usable_year,
|
|
)
|
|
check_constant_vars(case["ds"], case, ignore_nan=True, verbose=True, throw_error=True)
|
|
|
|
# Import GGCMI sowing and harvest dates, and check sims
|
|
casename = "Prescribed Calendars"
|
|
gdd_min = None
|
|
if "rx_sdates_file" in case:
|
|
if case["rx_sdates_file"]:
|
|
case["rx_sdates_ds"] = cc.import_rx_dates("sdate", case["rx_sdates_file"], case["ds"])
|
|
if case["rx_gdds_file"]:
|
|
case["rx_gdds_ds"] = cc.import_rx_dates("gdd", case["rx_gdds_file"], case["ds"])
|
|
|
|
# Equalize lons/lats
|
|
lonlat_tol = 1e-4
|
|
for ds_name in ["rx_sdates_ds", "rx_gdds_ds"]:
|
|
if ds_name in case:
|
|
for coord_name in ["lon", "lat"]:
|
|
max_diff_orig = np.max(
|
|
np.abs(case[ds_name][coord_name].values - case["ds"][coord_name].values)
|
|
)
|
|
if max_diff_orig > lonlat_tol:
|
|
raise RuntimeError(
|
|
f"{ds_name} {coord_name} values differ too much ({max_diff_orig} > "
|
|
+ f"{lonlat_tol})"
|
|
)
|
|
if max_diff_orig > 0:
|
|
case[ds_name] = case[ds_name].assign_coords(
|
|
{coord_name: case["ds"][coord_name].values}
|
|
)
|
|
max_diff = np.max(
|
|
np.abs(case[ds_name][coord_name].values - case["ds"][coord_name].values)
|
|
)
|
|
print(f"{ds_name} {coord_name} max_diff {max_diff_orig} → {max_diff}")
|
|
else:
|
|
print(f"{ds_name} {coord_name} max_diff {max_diff_orig}")
|
|
|
|
# Check
|
|
if case["rx_sdates_file"]:
|
|
check_rx_obeyed(
|
|
case["ds"].vegtype_str.values,
|
|
case["rx_sdates_ds"].isel(time=0),
|
|
case["ds"],
|
|
casename,
|
|
"SDATES",
|
|
)
|
|
if case["rx_gdds_file"]:
|
|
check_rx_obeyed(
|
|
case["ds"].vegtype_str.values,
|
|
case["rx_gdds_ds"].isel(time=0),
|
|
case["ds"],
|
|
casename,
|
|
"GDDHARV",
|
|
gdd_min=gdd_min,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main(sys.argv[1:])
|