Skip to content

Commit 224369f

Browse files
committed
Revert "Merge branch 'bartgol/eamxx/rad-cosp-freq-adjustments' (PR #7337)"
This reverts commit 8f970cf, reversing changes made to da8c3bd.
1 parent f32ae4f commit 224369f

File tree

11 files changed

+186
-81
lines changed

11 files changed

+186
-81
lines changed

components/eamxx/cime_config/eamxx_buildnml.py

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
# SCREAM imports
1717
from eamxx_buildnml_impl import get_valid_selectors, get_child, refine_type, \
18-
resolve_all_inheritances, gen_atm_proc_group, check_all_values
18+
resolve_all_inheritances, gen_atm_proc_group, check_all_values, find_node
1919
from atm_manip import apply_atm_procs_list_changes_from_buffer, apply_non_atm_procs_list_changes_from_buffer
2020

2121
from utils import ensure_yaml # pylint: disable=no-name-in-module
@@ -29,6 +29,7 @@
2929
# Cime imports
3030
from standard_script_setup import * # pylint: disable=wildcard-import
3131
from CIME.utils import expect, safe_copy, SharedArea
32+
from CIME.test_status import TestStatus, RUN_PHASE
3233

3334
logger = logging.getLogger(__name__) # pylint: disable=undefined-variable
3435

@@ -104,6 +105,121 @@ def do_cime_vars(entry, case, refine=False, extra=None):
104105

105106
return entry
106107

108+
###############################################################################
109+
def perform_consistency_checks(case, xml):
110+
###############################################################################
111+
"""
112+
There may be separate parts of the xml that must satisfy some consistency
113+
Here, we run any such check, so we can catch errors before submit time
114+
115+
>>> from eamxx_buildnml_impl import MockCase
116+
>>> xml_str = '''
117+
... <params>
118+
... <rrtmgp>
119+
... <rad_frequency type="integer">3</rad_frequency>
120+
... </rrtmgp>
121+
... </params>
122+
... '''
123+
>>> import xml.etree.ElementTree as ET
124+
>>> xml = ET.fromstring(xml_str)
125+
>>> case = MockCase({'ATM_NCPL':'24', 'REST_N':24, 'REST_OPTION':'nsteps'})
126+
>>> perform_consistency_checks(case,xml)
127+
>>> case = MockCase({'ATM_NCPL':'24', 'REST_N':2, 'REST_OPTION':'nsteps'})
128+
>>> perform_consistency_checks(case,xml)
129+
Traceback (most recent call last):
130+
CIME.utils.CIMEError: ERROR: rrtmgp::rad_frequency (3 steps) incompatible with restart frequency (2 steps).
131+
Please, ensure restart happens on a step when rad is ON
132+
>>> case = MockCase({'ATM_NCPL':'24', 'REST_N':10800, 'REST_OPTION':'nseconds'})
133+
>>> perform_consistency_checks(case,xml)
134+
>>> case = MockCase({'ATM_NCPL':'24', 'REST_N':7200, 'REST_OPTION':'nseconds'})
135+
>>> perform_consistency_checks(case,xml)
136+
Traceback (most recent call last):
137+
CIME.utils.CIMEError: ERROR: rrtmgp::rad_frequency incompatible with restart frequency.
138+
Please, ensure restart happens on a step when rad is ON
139+
rest_tstep: 7200
140+
rad_testep: 10800.0
141+
>>> case = MockCase({'ATM_NCPL':'24', 'REST_N':180, 'REST_OPTION':'nminutes'})
142+
>>> perform_consistency_checks(case,xml)
143+
>>> case = MockCase({'ATM_NCPL':'24', 'REST_N':120, 'REST_OPTION':'nminutes'})
144+
>>> perform_consistency_checks(case,xml)
145+
Traceback (most recent call last):
146+
CIME.utils.CIMEError: ERROR: rrtmgp::rad_frequency incompatible with restart frequency.
147+
Please, ensure restart happens on a step when rad is ON
148+
rest_tstep: 7200
149+
rad_testep: 10800.0
150+
>>> case = MockCase({'ATM_NCPL':'24', 'REST_N':6, 'REST_OPTION':'nhours'})
151+
>>> perform_consistency_checks(case,xml)
152+
>>> case = MockCase({'ATM_NCPL':'24', 'REST_N':8, 'REST_OPTION':'nhours'})
153+
>>> perform_consistency_checks(case,xml)
154+
Traceback (most recent call last):
155+
CIME.utils.CIMEError: ERROR: rrtmgp::rad_frequency incompatible with restart frequency.
156+
Please, ensure restart happens on a step when rad is ON
157+
rest_tstep: 28800
158+
rad_testep: 10800.0
159+
>>> case = MockCase({'ATM_NCPL':'12', 'REST_N':2, 'REST_OPTION':'ndays'})
160+
>>> perform_consistency_checks(case,xml)
161+
>>> case = MockCase({'ATM_NCPL':'10', 'REST_N':2, 'REST_OPTION':'ndays'})
162+
>>> perform_consistency_checks(case,xml)
163+
Traceback (most recent call last):
164+
CIME.utils.CIMEError: ERROR: rrtmgp::rad_frequency incompatible with restart frequency.
165+
Please, ensure restart happens on a step when rad is ON
166+
For daily (or less frequent) restart, rad_frequency must divide ATM_NCPL
167+
"""
168+
169+
# RRTMGP can be supercycled. Restarts cannot fall in the middle
170+
# of a rad superstep
171+
rrtmgp = find_node(xml,"rrtmgp")
172+
rest_opt = case.get_value("REST_OPTION")
173+
is_test = case.get_value("TEST")
174+
caseraw = case.get_value("CASE")
175+
caseroot = case.get_value("CASEROOT")
176+
casebaseid = case.get_value("CASEBASEID")
177+
if rrtmgp is not None and rest_opt is not None and rest_opt not in ["never","none"]:
178+
rest_n = int(case.get_value("REST_N"))
179+
rad_freq = int(find_node(rrtmgp,"rad_frequency").text)
180+
atm_ncpl = int(case.get_value("ATM_NCPL"))
181+
atm_tstep = 86400 / atm_ncpl
182+
rad_tstep = atm_tstep * rad_freq
183+
184+
# Some tests (ERS) make late (run-phase) changes, so we cannot validate restart
185+
# settings until RUN phase
186+
is_test_not_yet_run = False
187+
if is_test:
188+
test_name = casebaseid if casebaseid is not None else caseraw
189+
ts = TestStatus(test_dir=caseroot, test_name=test_name)
190+
phase = ts.get_latest_phase()
191+
if phase != RUN_PHASE:
192+
is_test_not_yet_run = True
193+
194+
if rad_freq==1 or is_test_not_yet_run:
195+
pass
196+
elif rest_opt in ["nsteps", "nstep"]:
197+
expect (rest_n % rad_freq == 0,
198+
f"rrtmgp::rad_frequency ({rad_freq} steps) incompatible with "
199+
f"restart frequency ({rest_n} steps).\n"
200+
" Please, ensure restart happens on a step when rad is ON")
201+
elif rest_opt in ["nseconds", "nsecond", "nminutes", "nminute", "nhours", "nhour"]:
202+
if rest_opt in ["nseconds", "nsecond"]:
203+
factor = 1
204+
elif rest_opt in ["nminutes", "nminute"]:
205+
factor = 60
206+
else:
207+
factor = 3600
208+
209+
rest_tstep = factor*rest_n
210+
expect (rest_tstep % rad_tstep == 0,
211+
"rrtmgp::rad_frequency incompatible with restart frequency.\n"
212+
" Please, ensure restart happens on a step when rad is ON\n"
213+
f" rest_tstep: {rest_tstep}\n"
214+
f" rad_testep: {rad_tstep}")
215+
216+
else:
217+
# for "very infrequent" restarts, we request rad_freq to divide atm_ncpl
218+
expect (atm_ncpl % rad_freq ==0,
219+
"rrtmgp::rad_frequency incompatible with restart frequency.\n"
220+
" Please, ensure restart happens on a step when rad is ON\n"
221+
" For daily (or less frequent) restart, rad_frequency must divide ATM_NCPL")
222+
107223
###############################################################################
108224
def ordered_dump(data, item, Dumper=yaml.SafeDumper, **kwds):
109225
###############################################################################
@@ -627,6 +743,8 @@ def _create_raw_xml_file_impl(case, xml, filepath=None):
627743

628744
raise e
629745

746+
perform_consistency_checks (case, xml)
747+
630748
return xml
631749

632750
###############################################################################

components/eamxx/cime_config/namelist_defaults_eamxx.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,6 @@ be lost if SCREAM_HACK_XML is not enabled.
561561
true
562562
</do_subcol_sampling>
563563
<pool_size_multiplier type="real">1.0</pool_size_multiplier>
564-
<force_run_after_restart type="logical" doc="Force rad to run on first step after restart, regardless of rad frequency">false</force_run_after_restart>
565-
566564
</rrtmgp>
567565

568566
<mac_aero_mic inherit="atm_proc_group">

components/eamxx/src/control/atmosphere_driver.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,11 +1620,9 @@ void AtmosphereDriver::run (const int dt) {
16201620
EKAT_REQUIRE_MSG (dt>0, "Error! Input time step must be positive.\n");
16211621

16221622
// Print current timestamp information
1623-
auto end_of_step = m_current_ts + dt;
16241623
m_atm_logger->log(ekat::logger::LogLevel::info,
1625-
"Atmosphere step = " + std::to_string(end_of_step.get_num_steps()) + "\n" +
1626-
" model beg-of-step timestamp: " + m_current_ts.get_date_string() + " " + m_current_ts.get_time_string() + "\n"
1627-
" model end-of-step timestamp: " + end_of_step.get_date_string() + " " + end_of_step.get_time_string() + "\n");
1624+
"Atmosphere step = " + std::to_string(m_current_ts.get_num_steps()) + "\n" +
1625+
" model start-of-step time = " + m_current_ts.get_date_string() + " " + m_current_ts.get_time_string() + "\n");
16281626

16291627
// Reset accum fields to 0
16301628
// Note: at the 1st timestep this is redundant, since we did it at init,

components/eamxx/src/physics/cosp/eamxx_cosp.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ class Cosp : public AtmosphereProcess
3232
// Set the grid
3333
void set_grids (const std::shared_ptr<const GridsManager> grids_manager);
3434

35-
inline bool cosp_do(const int cosp_freq, const int nstep) {
35+
inline bool cosp_do(const int icosp, const int nstep) {
3636
// If icosp == 0, then never do cosp;
37-
// Otherwise, do cosp if the timestep is divisible by cosp_freq
38-
if (cosp_freq == 0) {
37+
// Otherwise, we always call cosp at the first step,
38+
// and afterwards we do cosp if the timestep is divisible
39+
// by icosp
40+
if (icosp == 0) {
3941
return false;
4042
} else {
41-
return nstep % cosp_freq == 0;
43+
return ( (nstep == 0) || (nstep % icosp == 0) );
4244
}
4345
}
4446

components/eamxx/src/physics/rrtmgp/eamxx_rrtmgp_process_interface.cpp

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ RRTMGPRadiation (const ekat::Comm& comm, const ekat::ParameterList& params)
7979
}
8080

8181
m_ngas = m_gas_names.size();
82-
83-
// Determine rad timestep, specified as number of atm steps
84-
m_rad_freq_in_steps = m_params.get<Int>("rad_frequency", 1);
8582
}
8683

8784
void RRTMGPRadiation::set_grids(const std::shared_ptr<const GridsManager> grids_manager) {
@@ -201,6 +198,7 @@ void RRTMGPRadiation::set_grids(const std::shared_ptr<const GridsManager> grids_
201198
add_field<Computed>("LW_clrsky_flux_dn", scalar3d_int, W/m2, grid_name);
202199
add_field<Computed>("LW_clnsky_flux_up", scalar3d_int, W/m2, grid_name);
203200
add_field<Computed>("LW_clnsky_flux_dn", scalar3d_int, W/m2, grid_name);
201+
add_field<Computed>("rad_heating_pdel", scalar3d_mid, Pa*K/s, grid_name);
204202
// Cloud properties added as computed fields for diagnostic purposes
205203
add_field<Computed>("cldlow" , scalar2d, nondim, grid_name);
206204
add_field<Computed>("cldmed" , scalar2d, nondim, grid_name);
@@ -221,11 +219,6 @@ void RRTMGPRadiation::set_grids(const std::shared_ptr<const GridsManager> grids_
221219
add_field<Computed>("eff_radius_qc_at_cldtop", scalar2d, micron, grid_name);
222220
add_field<Computed>("eff_radius_qi_at_cldtop", scalar2d, micron, grid_name);
223221

224-
// This field is needed for restart
225-
Field rad_heating_pdel (FieldIdentifier("rad_heating_pdel", scalar3d_mid, Pa*K/s, grid_name));
226-
rad_heating_pdel.allocate_view();
227-
add_internal_field(rad_heating_pdel);
228-
229222
// Translation of variables from EAM
230223
// --------------------------------------------------------------
231224
// EAM name | EAMXX name | Description
@@ -237,19 +230,12 @@ void RRTMGPRadiation::set_grids(const std::shared_ptr<const GridsManager> grids_
237230
// netsw sfc_flux_sw_net net (down - up) SW flux at surface
238231
// flwds sfc_flux_lw_dn downwelling LW flux at surface
239232
// --------------------------------------------------------------
240-
241-
// We need to ensure that these fields are added to the RESTART group,
242-
// since the cpl will need them at every step, and rrtmgp may not run
243-
// the 1st step after restart (depending on rad freq).
244-
// NOTE: technically, we know rad freq, so we *could* avoid adding them
245-
// to the rest file if rad_freq=1. But a) that is not common at high
246-
// res anyways, and b) that could prevent changing rad_freq upon restart
247-
add_field<Computed>("sfc_flux_dir_nir", scalar2d, W/m2, grid_name, "RESTART");
248-
add_field<Computed>("sfc_flux_dir_vis", scalar2d, W/m2, grid_name, "RESTART");
249-
add_field<Computed>("sfc_flux_dif_nir", scalar2d, W/m2, grid_name, "RESTART");
250-
add_field<Computed>("sfc_flux_dif_vis", scalar2d, W/m2, grid_name, "RESTART");
251-
add_field<Computed>("sfc_flux_sw_net" , scalar2d, W/m2, grid_name, "RESTART");
252-
add_field<Computed>("sfc_flux_lw_dn" , scalar2d, W/m2, grid_name, "RESTART");
233+
add_field<Computed>("sfc_flux_dir_nir", scalar2d, W/m2, grid_name);
234+
add_field<Computed>("sfc_flux_dir_vis", scalar2d, W/m2, grid_name);
235+
add_field<Computed>("sfc_flux_dif_nir", scalar2d, W/m2, grid_name);
236+
add_field<Computed>("sfc_flux_dif_vis", scalar2d, W/m2, grid_name);
237+
add_field<Computed>("sfc_flux_sw_net" , scalar2d, W/m2, grid_name);
238+
add_field<Computed>("sfc_flux_lw_dn" , scalar2d, W/m2, grid_name);
253239

254240
// Boundary flux fields for energy and mass conservation checks
255241
if (has_column_conservation_check()) {
@@ -466,9 +452,12 @@ void RRTMGPRadiation::init_buffers(const ATMBufferManager &buffer_manager)
466452
EKAT_REQUIRE_MSG(used_mem==requested_buffer_size_in_bytes(), "Error! Used memory != requested memory for RRTMGPRadiation.");
467453
} // RRTMGPRadiation::init_buffers
468454

469-
void RRTMGPRadiation::initialize_impl(const RunType run_type) {
455+
void RRTMGPRadiation::initialize_impl(const RunType /* run_type */) {
470456
using PC = scream::physics::Constants<Real>;
471457

458+
// Determine rad timestep, specified as number of atm steps
459+
m_rad_freq_in_steps = m_params.get<Int>("rad_frequency", 1);
460+
472461
// Determine orbital year. If orbital_year is negative, use current year
473462
// from timestamp for orbital year; if positive, use provided orbital year
474463
// for duration of simulation.
@@ -542,13 +531,6 @@ void RRTMGPRadiation::initialize_impl(const RunType run_type) {
542531
auto co_vmr = get_field_out("co_volume_mix_ratio").get_view<Real**>();
543532
Kokkos::deep_copy(co_vmr, m_params.get<double>("covmr", 1.0e-7));
544533
}
545-
546-
// Ensure rad_heating_pdel is recognized as initialized by the driver
547-
auto& rad_heating = get_internal_field("rad_heating_pdel");
548-
rad_heating.get_header().get_tracking().update_time_stamp(start_of_step_ts());
549-
550-
m_force_run_on_next_step = run_type==RunType::Initial or
551-
m_params.get("force_run_after_restart",false);
552534
}
553535

554536
// =========================================================================================
@@ -614,7 +596,7 @@ void RRTMGPRadiation::run_impl (const double dt) {
614596
auto d_lw_clrsky_flux_dn = get_field_out("LW_clrsky_flux_dn").get_view<Real**>();
615597
auto d_lw_clnsky_flux_up = get_field_out("LW_clnsky_flux_up").get_view<Real**>();
616598
auto d_lw_clnsky_flux_dn = get_field_out("LW_clnsky_flux_dn").get_view<Real**>();
617-
auto d_rad_heating_pdel = get_internal_field("rad_heating_pdel").get_view<Real**>();
599+
auto d_rad_heating_pdel = get_field_out("rad_heating_pdel").get_view<Real**>();
618600
auto d_sfc_flux_dir_vis = get_field_out("sfc_flux_dir_vis").get_view<Real*>();
619601
auto d_sfc_flux_dir_nir = get_field_out("sfc_flux_dir_nir").get_view<Real*>();
620602
auto d_sfc_flux_dif_vis = get_field_out("sfc_flux_dif_vis").get_view<Real*>();
@@ -655,8 +637,8 @@ void RRTMGPRadiation::run_impl (const double dt) {
655637
const auto do_aerosol_rad = m_do_aerosol_rad;
656638

657639
// Are we going to update fluxes and heating this step?
658-
auto ts = end_of_step_ts();
659-
auto update_rad = m_force_run_on_next_step or scream::rrtmgp::radiation_do(m_rad_freq_in_steps, ts.get_num_steps());
640+
auto ts = start_of_step_ts();
641+
auto update_rad = scream::rrtmgp::radiation_do(m_rad_freq_in_steps, ts.get_num_steps());
660642

661643
if (update_rad) {
662644
// On each chunk, we internally "reset" the GasConcs object to subview the concs 3d array
@@ -1231,7 +1213,6 @@ void RRTMGPRadiation::run_impl (const double dt) {
12311213
});
12321214
}
12331215

1234-
m_force_run_on_next_step = false;
12351216
}
12361217
// =========================================================================================
12371218

components/eamxx/src/physics/rrtmgp/eamxx_rrtmgp_process_interface.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,6 @@ class RRTMGPRadiation : public AtmosphereProcess {
238238

239239
// Struct which contains local variables
240240
Buffer m_buffer;
241-
242-
bool m_force_run_on_next_step = false;
243241
}; // class RRTMGPRadiation
244242

245243
} // namespace scream

components/eamxx/src/physics/rrtmgp/rrtmgp_utils.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ void compute_heating_rate (
3737
));
3838
}
3939

40-
inline bool radiation_do(const int rad_freq, const int nstep) {
41-
// If rad_freq == 0, then never do radiation;
40+
inline bool radiation_do(const int irad, const int nstep) {
41+
// If irad == 0, then never do radiation;
4242
// Otherwise, we always call radiation at the first step,
4343
// and afterwards we do radiation if the timestep is divisible
44-
// by rad_freq
45-
if (rad_freq == 0) {
44+
// by irad
45+
if (irad == 0) {
4646
return false;
4747
} else {
48-
return nstep % rad_freq == 0;
48+
return ( (nstep == 0) || (nstep % irad == 0) );
4949
}
5050
}
5151

components/eamxx/src/physics/rrtmgp/tests/rrtmgp_unit_tests.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -411,14 +411,25 @@ TEST_CASE("rrtmgp_test_compute_broadband_surface_flux_k") {
411411
}
412412

413413
TEST_CASE("rrtmgp_test_radiation_do_k") {
414-
// Rad runs whenever step is a multiple of freq
415-
// NOTE: the rrtmgp process class handles logic for running on 1st step
416-
for (int istep : {1,2,3,4,5,6}) {
417-
for (int rad_freq : {1,2,3}) {
418-
bool divides = istep%rad_freq == 0;
419-
REQUIRE( scream::rrtmgp::radiation_do(rad_freq,istep)== divides );
420-
}
421-
}
414+
// If we specify rad every step, radiation_do should always be true
415+
REQUIRE(scream::rrtmgp::radiation_do(1, 0) == true);
416+
REQUIRE(scream::rrtmgp::radiation_do(1, 1) == true);
417+
REQUIRE(scream::rrtmgp::radiation_do(1, 2) == true);
418+
419+
// Test cases where we want rad called every other step
420+
REQUIRE(scream::rrtmgp::radiation_do(2, 0) == true);
421+
REQUIRE(scream::rrtmgp::radiation_do(2, 1) == false);
422+
REQUIRE(scream::rrtmgp::radiation_do(2, 2) == true);
423+
REQUIRE(scream::rrtmgp::radiation_do(2, 3) == false);
424+
425+
// Test cases where we want rad every third step
426+
REQUIRE(scream::rrtmgp::radiation_do(3, 0) == true);
427+
REQUIRE(scream::rrtmgp::radiation_do(3, 1) == false);
428+
REQUIRE(scream::rrtmgp::radiation_do(3, 2) == false);
429+
REQUIRE(scream::rrtmgp::radiation_do(3, 3) == true);
430+
REQUIRE(scream::rrtmgp::radiation_do(3, 4) == false);
431+
REQUIRE(scream::rrtmgp::radiation_do(3, 5) == false);
432+
REQUIRE(scream::rrtmgp::radiation_do(3, 6) == true);
422433
}
423434

424435
TEST_CASE("rrtmgp_test_check_range_k") {

components/eamxx/src/share/atm_process/atmosphere_process.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ void AtmosphereProcess::run (const double dt) {
150150
// Print hash of INPUTS before run
151151
print_global_state_hash(name() + "-pre-sc-" + std::to_string(m_subcycle_iter),
152152
m_start_of_step_ts,
153-
true, false, true);
153+
true, false, false);
154154

155155
// Run derived class implementation
156156
run_impl(dt_sub);
@@ -159,7 +159,7 @@ void AtmosphereProcess::run (const double dt) {
159159
// Print hash of OUTPUTS/INTERNALS after run
160160
print_global_state_hash(name() + "-pst-sc-" + std::to_string(m_subcycle_iter),
161161
m_end_of_step_ts,
162-
false, true, true);
162+
true, true, true);
163163

164164
if (has_column_conservation_check()) {
165165
// Run the column local mass and energy conservation checks

0 commit comments

Comments
 (0)