From d9968bd6b96259ba095c65be5bd8e3ff433d8708 Mon Sep 17 00:00:00 2001 From: Paul Leopardi Date: Mon, 20 Oct 2025 14:46:52 +1100 Subject: [PATCH 1/5] Extend historical solar forcing from 1700 to 2300 --- .../atmosphere/cmip7_ancil_constants.py | 1 + .../solar/cmip7_HI_solar_generate.py | 53 ++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/CMIP7/esm1p6/atmosphere/cmip7_ancil_constants.py b/CMIP7/esm1p6/atmosphere/cmip7_ancil_constants.py index 8f97d48..f7c9f98 100644 --- a/CMIP7/esm1p6/atmosphere/cmip7_ancil_constants.py +++ b/CMIP7/esm1p6/atmosphere/cmip7_ancil_constants.py @@ -1,4 +1,5 @@ from datetime import datetime ANCIL_TODAY = datetime.now().strftime("%Y.%m.%d") +REAL_MISSING_DATA_INDICATOR = -32768 * 32768.0 UM_VERSION = "7.3" diff --git a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py index 3fa5313..fc62bea 100644 --- a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py +++ b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py @@ -1,7 +1,9 @@ from argparse import ArgumentParser import iris +import numpy as np from cmip7_ancil_argparse import common_parser +from cmip7_constants import REAL_MISSING_DATA_INDICATOR from cmip7_HI import ( CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR, @@ -9,6 +11,9 @@ ) from solar.cmip7_solar import cmip7_solar_dirpath, load_cmip7_solar_cube +SOLAR_ARRAY_BEG_YEAR = 1700 +SOLAR_ARRAY_END_YEAR = 2300 + def parse_args(): parser = ArgumentParser( @@ -25,19 +30,53 @@ def parse_args(): return parser.parse_args() +def cmip7_hi_solar_year_mean(cube): + """ + Calculate mean TSI values for each year and save them into an array. + """ + NBR_YEARS = SOLAR_ARRAY_END_YEAR - SOLAR_ARRAY_BEG_YEAR + 1 + solar_array = np.zeros(NBR_YEARS) + tsi_sum = 0.0 + # Calculate and save the mean annual TSI + # for each CMI7 historical year. + for year in range(CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR + 1): + year_cons = iris.Constraint(time=lambda cell: cell.point.year == year) + year_cube = cube.extract(year_cons) + year_mean = year_cube.collapsed("time", iris.analysis.MEAN).data + solar_array[year - SOLAR_ARRAY_BEG_YEAR] = year_mean + tsi_sum += year_mean + # Calculate the mean TSI over the CMIP7 historical years. + NBR_CMIP7_HI_YEARS = CMIP7_HI_END_YEAR - CMIP7_HI_BEG_YEAR + tsi_mean = tsi_sum / NBR_CMIP7_HI_YEARS + + # For the years from SOLAR_ARRAY_BEG_YEAR to CMIP7_HI_BEG_YEAR - 1, + # set the saved TSI value to the mean TSI. + for year in range(SOLAR_ARRAY_BEG_YEAR, CMIP7_HI_BEG_YEAR): + solar_array[year - SOLAR_ARRAY_BEG_YEAR] = tsi_mean + + # For the years from CMIP7_HI_END_YEAR + 1 to SOLAR_ARRAY_END_YEAR, + # set the saved TSI value to the real missing data indicator + for year in range(CMIP7_HI_END_YEAR + 1, SOLAR_ARRAY_END_YEAR + 1): + solar_array[year - SOLAR_ARRAY_BEG_YEAR] = REAL_MISSING_DATA_INDICATOR + return solar_array + + def cmip7_hi_solar_save(args, cube): + """ + Save the TSI values for each year into a text file. + """ + solar_array = cmip7_hi_solar_year_mean(cube) save_dirpath = esm_hi_forcing_save_dirpath(args) # Ensure that the save directory exists. save_dirpath.mkdir(mode=0o755, parents=True, exist_ok=True) save_filepath = save_dirpath / args.save_filename with open(save_filepath, "w") as save_file: - for year in range(CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR + 1): - year_cons = iris.Constraint( - time=lambda cell: cell.point.year == year - ) - year_cube = cube.extract(year_cons) - year_mean = year_cube.collapsed("time", iris.analysis.MEAN).data - print(year, f"{year_mean:.3f}", file=save_file) + for year in range(SOLAR_ARRAY_BEG_YEAR, SOLAR_ARRAY_END_YEAR + 1): + year_mean = solar_array[year - SOLAR_ARRAY_BEG_YEAR] + if year_mean == REAL_MISSING_DATA_INDICATOR: + print(year, f"{year_mean:.1f}", file=save_file) + else: + print(year, f"{year_mean:.3f}", file=save_file) if __name__ == "__main__": From bc1267889cd8e27a2993bf312d0044051d63a858 Mon Sep 17 00:00:00 2001 From: Paul Leopardi Date: Mon, 20 Oct 2025 14:54:18 +1100 Subject: [PATCH 2/5] Fix an import statement --- CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py index fc62bea..0282f83 100644 --- a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py +++ b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py @@ -3,7 +3,7 @@ import iris import numpy as np from cmip7_ancil_argparse import common_parser -from cmip7_constants import REAL_MISSING_DATA_INDICATOR +from cmip7_ancil_constants import REAL_MISSING_DATA_INDICATOR from cmip7_HI import ( CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR, From e62dcf497d6106ce4c0a3593807dc59667513089 Mon Sep 17 00:00:00 2001 From: Paul Leopardi Date: Mon, 20 Oct 2025 15:06:29 +1100 Subject: [PATCH 3/5] Calculate tsi_mean correctly --- CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py index 0282f83..4d6f5c8 100644 --- a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py +++ b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py @@ -46,7 +46,7 @@ def cmip7_hi_solar_year_mean(cube): solar_array[year - SOLAR_ARRAY_BEG_YEAR] = year_mean tsi_sum += year_mean # Calculate the mean TSI over the CMIP7 historical years. - NBR_CMIP7_HI_YEARS = CMIP7_HI_END_YEAR - CMIP7_HI_BEG_YEAR + NBR_CMIP7_HI_YEARS = CMIP7_HI_END_YEAR - CMIP7_HI_BEG_YEAR + 1 tsi_mean = tsi_sum / NBR_CMIP7_HI_YEARS # For the years from SOLAR_ARRAY_BEG_YEAR to CMIP7_HI_BEG_YEAR - 1, From 081a655cc07486251d3e31250e602d32314320d0 Mon Sep 17 00:00:00 2001 From: Paul Leopardi Date: Mon, 24 Nov 2025 17:05:15 +1100 Subject: [PATCH 4/5] Use pre-industrial TSI for years before historical period --- .../atmosphere/solar/cmip7_HI_solar_generate.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py index 4d6f5c8..1ac64dd 100644 --- a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py +++ b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py @@ -9,6 +9,7 @@ CMIP7_HI_END_YEAR, esm_hi_forcing_save_dirpath, ) +from cmip7_PI import CMIP7_PI_YEAR from solar.cmip7_solar import cmip7_solar_dirpath, load_cmip7_solar_cube SOLAR_ARRAY_BEG_YEAR = 1700 @@ -36,23 +37,21 @@ def cmip7_hi_solar_year_mean(cube): """ NBR_YEARS = SOLAR_ARRAY_END_YEAR - SOLAR_ARRAY_BEG_YEAR + 1 solar_array = np.zeros(NBR_YEARS) - tsi_sum = 0.0 - # Calculate and save the mean annual TSI - # for each CMI7 historical year. + # Calculate and save the mean annual TSI for each CMIP7 historical year. + assert CMIP7_PI_YEAR in range(CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR + 1) for year in range(CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR + 1): year_cons = iris.Constraint(time=lambda cell: cell.point.year == year) year_cube = cube.extract(year_cons) year_mean = year_cube.collapsed("time", iris.analysis.MEAN).data solar_array[year - SOLAR_ARRAY_BEG_YEAR] = year_mean - tsi_sum += year_mean - # Calculate the mean TSI over the CMIP7 historical years. - NBR_CMIP7_HI_YEARS = CMIP7_HI_END_YEAR - CMIP7_HI_BEG_YEAR + 1 - tsi_mean = tsi_sum / NBR_CMIP7_HI_YEARS + # Save the year mean for the pre-industrial year. + if year == CMIP7_PI_YEAR: + pi_year_mean = year_mean # For the years from SOLAR_ARRAY_BEG_YEAR to CMIP7_HI_BEG_YEAR - 1, - # set the saved TSI value to the mean TSI. + # set the saved TSI value to the pre-industrial year mean TSI. for year in range(SOLAR_ARRAY_BEG_YEAR, CMIP7_HI_BEG_YEAR): - solar_array[year - SOLAR_ARRAY_BEG_YEAR] = tsi_mean + solar_array[year - SOLAR_ARRAY_BEG_YEAR] = pi_year_mean # For the years from CMIP7_HI_END_YEAR + 1 to SOLAR_ARRAY_END_YEAR, # set the saved TSI value to the real missing data indicator From 1011a2c875568d7ee5a4abe35819b85fa6b5fb98 Mon Sep 17 00:00:00 2001 From: Paul Leopardi Date: Mon, 24 Nov 2025 18:33:45 +1100 Subject: [PATCH 5/5] Use a variable for the historical year range --- CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py index 1ac64dd..a926d89 100644 --- a/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py +++ b/CMIP7/esm1p6/atmosphere/solar/cmip7_HI_solar_generate.py @@ -38,8 +38,9 @@ def cmip7_hi_solar_year_mean(cube): NBR_YEARS = SOLAR_ARRAY_END_YEAR - SOLAR_ARRAY_BEG_YEAR + 1 solar_array = np.zeros(NBR_YEARS) # Calculate and save the mean annual TSI for each CMIP7 historical year. - assert CMIP7_PI_YEAR in range(CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR + 1) - for year in range(CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR + 1): + historical_year_range = range(CMIP7_HI_BEG_YEAR, CMIP7_HI_END_YEAR + 1) + assert CMIP7_PI_YEAR in historical_year_range + for year in historical_year_range: year_cons = iris.Constraint(time=lambda cell: cell.point.year == year) year_cube = cube.extract(year_cons) year_mean = year_cube.collapsed("time", iris.analysis.MEAN).data