From 8b02ffe1c9de2d2d4186ebe17911fb71860b8e92 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 12 Mar 2024 16:58:32 -0600 Subject: [PATCH 1/2] Run MED -> GLC in CISM NOEVOLVE mode Previously we hadn't been doing the mapping from MED -> GLC when CISM was running in NOEVOLVE mode. This was a problem because this downscaled SMB is one of the main benefits of running CISM in NOEVOLVE mode. Resolves ESCOMP/CMEPS#426. See that issue for details. One other change here is that I skip GLC -> MED in NOEVOLVE mode. I *think* that's a safe thing to do, but I'm not 100% sure of it. --- cime_config/runseq/driver_config.py | 2 +- cime_config/runseq/runseq_TG.py | 2 +- cime_config/runseq/runseq_general.py | 35 ++++++++++++++-------------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/cime_config/runseq/driver_config.py b/cime_config/runseq/driver_config.py index 9694c7503..68b862547 100644 --- a/cime_config/runseq/driver_config.py +++ b/cime_config/runseq/driver_config.py @@ -58,7 +58,7 @@ def __compute_glc(self, case, coupling_times): med_to_glc = False elif (comp_glc == 'cism'): if not case.get_value("CISM_EVOLVE"): - med_to_glc = False + run_glc = False # If CISM is not evolving only get data back from cism at the initial time # However will still need to call the exchange at the end if the stop_option diff --git a/cime_config/runseq/runseq_TG.py b/cime_config/runseq/runseq_TG.py index dea8aede5..c0bb4ab92 100644 --- a/cime_config/runseq/runseq_TG.py +++ b/cime_config/runseq/runseq_TG.py @@ -34,7 +34,7 @@ def gen_runseq(case, coupling_times): runseq.add_action ("MED med_phases_post_lnd" , run_lnd) runseq.add_action ("MED med_phases_prep_glc" , med_to_glc) runseq.add_action ("MED -> GLC :remapMethod=redist" , med_to_glc) - runseq.add_action ("GLC" , run_glc and med_to_glc) + runseq.add_action ("GLC" , run_glc) runseq.add_action ("GLC -> MED :remapMethod=redist" , run_glc) runseq.add_action ("MED med_phases_history_write" , True) diff --git a/cime_config/runseq/runseq_general.py b/cime_config/runseq/runseq_general.py index ddbfca598..2b77ebeb4 100644 --- a/cime_config/runseq/runseq_general.py +++ b/cime_config/runseq/runseq_general.py @@ -35,19 +35,6 @@ def gen_runseq(case, coupling_times): run_rof, med_to_rof, rof_cpl_time = driver_config['rof'] run_wav, med_to_wav, wav_cpl_time = driver_config['wav'] - comp_glc = case.get_value("COMP_GLC") - run_glc = False - post_glc = False - if (comp_glc == 'cism'): - run_glc = True - if case.get_value("CISM_EVOLVE"): - post_glc = True - else: - post_glc = False - elif (comp_glc == 'xglc'): - run_glc = True - post_glc = True - # Note: assume that atm_cpl_dt, lnd_cpl_dt, ice_cpl_dt and wav_cpl_dt are the same if lnd_cpl_time != atm_cpl_time: @@ -59,18 +46,32 @@ def gen_runseq(case, coupling_times): if rof_cpl_time < ocn_cpl_time: expect(False, "assume that rof_cpl_time is always greater than or equal to ocn_cpl_time") + if run_glc: + # It wouldn't make sense to run GLC unless we also do MED -> GLC to transfer fields to GLC, + # and some of the below logic controlling what appears in the run sequence depends on this + # (i.e., depends on the fact that, if run_glc is True, then med_to_glc is also True). + expect(med_to_glc, "if run_glc is True, then med_to_glc must also be True") + rof_outer_loop = run_rof and rof_cpl_time > atm_cpl_time ocn_outer_loop = run_ocn and ocn_cpl_time > atm_cpl_time + # Note that we do some aspects of the GLC outer loop even if run_glc is False + # (as long as med_to_glc is True). + # + # Note that, in contrast to the other outer_loop variables, this doesn't check glc_cpl_time. + # This is for consistency with the logic that was in place before adding this variable; + # this seems to implicitly assume that glc_cpl_time > atm_cpl_time. + glc_outer_loop = med_to_glc + inner_loop = ((atm_cpl_time < ocn_cpl_time) or (atm_cpl_time < rof_cpl_time) or - (run_glc and atm_cpl_time < glc_cpl_time) or + (glc_outer_loop and atm_cpl_time < glc_cpl_time) or atm_cpl_time == ocn_cpl_time) with RunSeq(os.path.join(caseroot, "CaseDocs", "nuopc.runseq")) as runseq: #------------------ - runseq.enter_time_loop(glc_cpl_time, newtime=run_glc, active=med_to_glc) + runseq.enter_time_loop(glc_cpl_time, newtime=glc_outer_loop) #------------------ #------------------ @@ -199,8 +200,8 @@ def gen_runseq(case, coupling_times): runseq.add_action("MED med_phases_prep_glc" , med_to_glc) runseq.add_action("MED -> GLC :remapMethod=redist" , med_to_glc) - runseq.add_action("GLC" , run_glc and med_to_glc) + runseq.add_action("GLC" , run_glc) runseq.add_action("GLC -> MED :remapMethod=redist" , run_glc) - runseq.add_action("MED med_phases_post_glc" , run_glc and post_glc) + runseq.add_action("MED med_phases_post_glc" , run_glc) shutil.copy(os.path.join(caseroot, "CaseDocs", "nuopc.runseq"), rundir) From ac458c37b3202f5a8e7b7e9e23aa1d8020b1b720 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 20 Mar 2024 09:51:04 -0600 Subject: [PATCH 2/2] Do GLC -> MED based on med_to_glc rather than run_glc When this was based on run_glc, NOEVOLVE cases were failing like this: 20240319 135112.648 ERROR PET0000 ESMF_ArrayGet.F90:1949 ESMF_ArrayGetFPtr Object being used before creation - Bad Object 20240319 135112.649 ERROR PET0000 ESMF_FieldGet.F90:2634 ESMF_FieldGetDataPtr Object being used before creation - Internal subroutine call returned Error 20240319 135112.649 ERROR PET0000 nuopc_shr_methods.F90:304 Object being used before creation - Passing error in return code 20240319 135112.649 ERROR PET0000 glc_import_export.F90:475 Object being used before creation - Passing error in return code 20240319 135112.649 ERROR PET0000 glc_comp_nuopc.F90:481 Object being used before creation - Passing error in return code 20240319 135112.649 ERROR PET0000 ESM0001:src/addon/NUOPC/src/NUOPC_Driver.F90:2901 Object being used before creation - Phase 'IPDv01p3' Initialize for modelComp 3: GLC did not return ESMF_SUCCESS 20240319 135112.649 ERROR PET0000 ESM0001:src/addon/NUOPC/src/NUOPC_Driver.F90:1985 Object being used before creation - Passing error in return code 20240319 135112.649 ERROR PET0000 ensemble:src/addon/NUOPC/src/NUOPC_Driver.F90:2901 Object being used before creation - Phase 'IPDv02p3' Initialize for modelComp 1: ESM0001 did not return ESMF_SUCCESS 20240319 135112.649 ERROR PET0000 ensemble:src/addon/NUOPC/src/NUOPC_Driver.F90:1990 Object being used before creation - Passing error in return code 20240319 135112.649 ERROR PET0000 ensemble:src/addon/NUOPC/src/NUOPC_Driver.F90:489 Object being used before creation - Passing error in return code 20240319 135112.649 ERROR PET0000 esmApp.F90:134 Object being used before creation - Passing error in return code 20240319 135112.649 INFO PET0000 Finalizing ESMF This fails in the InitializeRealize call to export_fields, and specifically in this: ! Set scalars in export state call State_SetScalar(dble(get_nx_tot(instance_index=ns)), flds_scalar_index_nx, & NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) So it seems like we need to have GLC -> MED in the run sequence for initialization to work correctly. --- cime_config/runseq/runseq_TG.py | 4 +++- cime_config/runseq/runseq_general.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cime_config/runseq/runseq_TG.py b/cime_config/runseq/runseq_TG.py index c0bb4ab92..acf56a87b 100644 --- a/cime_config/runseq/runseq_TG.py +++ b/cime_config/runseq/runseq_TG.py @@ -35,7 +35,9 @@ def gen_runseq(case, coupling_times): runseq.add_action ("MED med_phases_prep_glc" , med_to_glc) runseq.add_action ("MED -> GLC :remapMethod=redist" , med_to_glc) runseq.add_action ("GLC" , run_glc) - runseq.add_action ("GLC -> MED :remapMethod=redist" , run_glc) + # Need to do GLC -> MED even if not running GLC; otherwise, we get a + # failure in InitializeRealize ("Object being used before creation") + runseq.add_action ("GLC -> MED :remapMethod=redist" , med_to_glc) runseq.add_action ("MED med_phases_history_write" , True) runseq.leave_time_loop(True) diff --git a/cime_config/runseq/runseq_general.py b/cime_config/runseq/runseq_general.py index 2b77ebeb4..dfb0ea3ad 100644 --- a/cime_config/runseq/runseq_general.py +++ b/cime_config/runseq/runseq_general.py @@ -201,7 +201,9 @@ def gen_runseq(case, coupling_times): runseq.add_action("MED med_phases_prep_glc" , med_to_glc) runseq.add_action("MED -> GLC :remapMethod=redist" , med_to_glc) runseq.add_action("GLC" , run_glc) - runseq.add_action("GLC -> MED :remapMethod=redist" , run_glc) + # Need to do GLC -> MED even if not running GLC; otherwise, we get a + # failure in InitializeRealize ("Object being used before creation") + runseq.add_action("GLC -> MED :remapMethod=redist" , med_to_glc) runseq.add_action("MED med_phases_post_glc" , run_glc) shutil.copy(os.path.join(caseroot, "CaseDocs", "nuopc.runseq"), rundir)