From 8c435897cebfa62400091cc21ec68c02cf3da96f Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 10 Jan 2024 14:12:04 +0100 Subject: [PATCH 01/27] new passing of 10m wind explicitly to ww3 - done in a backwards compatible way --- datm/datm_datamode_core2_mod.F90 | 12 ++++++++++++ datm/datm_datamode_jra_mod.F90 | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/datm/datm_datamode_core2_mod.F90 b/datm/datm_datamode_core2_mod.F90 index 552b35dae..41d2caae8 100644 --- a/datm/datm_datamode_core2_mod.F90 +++ b/datm/datm_datamode_core2_mod.F90 @@ -40,6 +40,8 @@ module datm_datamode_core2_mod ! export state pointers real(r8), pointer :: Sa_u(:) => null() real(r8), pointer :: Sa_v(:) => null() + real(r8), pointer :: Sa_u10m(:) => null() + real(r8), pointer :: Sa_v10m(:) => null() real(r8), pointer :: Sa_z(:) => null() real(r8), pointer :: Sa_tbot(:) => null() real(r8), pointer :: Sa_ptem(:) => null() @@ -115,6 +117,8 @@ subroutine datm_datamode_core2_advertise(exportState, fldsexport, flds_scalar_na call dshr_fldList_add(fldsExport, 'Sa_z' ) call dshr_fldList_add(fldsExport, 'Sa_u' ) call dshr_fldList_add(fldsExport, 'Sa_v' ) + call dshr_fldList_add(fldsExport, 'Sa_u10m' ) + call dshr_fldList_add(fldsExport, 'Sa_v10m' ) call dshr_fldList_add(fldsExport, 'Sa_ptem' ) call dshr_fldList_add(fldsExport, 'Sa_dens' ) call dshr_fldList_add(fldsExport, 'Sa_pslv' ) @@ -219,6 +223,10 @@ subroutine datm_datamode_core2_init_pointers(exportState, sdat, datamode, factor if (ChkErr(rc,__LINE__,u_FILE_u)) return call dshr_state_getfldptr(exportState, 'Sa_v' , fldptr1=Sa_v , rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(exportState, 'Sa_u10m' , fldptr1=Sa_u10m , rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(exportState, 'Sa_v10m' , fldptr1=Sa_v10m , rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call dshr_state_getfldptr(exportState, 'Sa_tbot' , fldptr1=Sa_tbot , rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call dshr_state_getfldptr(exportState, 'Sa_pbot' , fldptr1=Sa_pbot , rc=rc) @@ -315,6 +323,10 @@ subroutine datm_datamode_core2_advance(datamode, target_ymd, target_tod, target_ Sa_u(n) = uprime*cos(winddFactor(n)*degtorad) - vprime*sin(winddFactor(n)*degtorad) Sa_v(n) = uprime*sin(winddFactor(n)*degtorad) + vprime*cos(winddFactor(n)*degtorad) + ! Set Sa_u10m and Sa_v10m to Sa_u and Sa_v + Sa_u10m(n) = Sa_u(n) + Sa_v10m(n) = Sa_v(n) + !--- density and pslv taken directly from input stream, set pbot --- Sa_pbot(n) = Sa_pslv(n) diff --git a/datm/datm_datamode_jra_mod.F90 b/datm/datm_datamode_jra_mod.F90 index d280bf860..9eb815150 100644 --- a/datm/datm_datamode_jra_mod.F90 +++ b/datm/datm_datamode_jra_mod.F90 @@ -25,6 +25,10 @@ module datm_datamode_jra_mod ! export state pointers real(r8), pointer :: Sa_z(:) => null() + real(r8), pointer :: Sa_u(:) => null() + real(r8), pointer :: Sa_v(:) => null() + real(r8), pointer :: Sa_u10m(:) => null() + real(r8), pointer :: Sa_v10m(:) => null() real(r8), pointer :: Sa_tbot(:) => null() real(r8), pointer :: Sa_ptem(:) => null() real(r8), pointer :: Sa_shum(:) => null() @@ -88,6 +92,8 @@ subroutine datm_datamode_jra_advertise(exportState, fldsexport, flds_scalar_name call dshr_fldList_add(fldsExport, 'Sa_z' ) call dshr_fldList_add(fldsExport, 'Sa_u' ) call dshr_fldList_add(fldsExport, 'Sa_v' ) + call dshr_fldList_add(fldsExport, 'Sa_u10m' ) + call dshr_fldList_add(fldsExport, 'Sa_v10m' ) call dshr_fldList_add(fldsExport, 'Sa_ptem' ) call dshr_fldList_add(fldsExport, 'Sa_dens' ) call dshr_fldList_add(fldsExport, 'Sa_pslv' ) @@ -174,6 +180,14 @@ subroutine datm_datamode_jra_init_pointers(exportState, sdat, rc) call shr_strdata_get_stream_pointer( sdat, 'Faxa_swdn' , strm_swdn , rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(exportState, 'Sa_u' , fldptr1=Sa_u , rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(exportState, 'Sa_v' , fldptr1=Sa_v , rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(exportState, 'Sa_u10m' , fldptr1=Sa_u10m , rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(exportState, 'Sa_v10m' , fldptr1=Sa_v10m , rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call dshr_state_getfldptr(exportState, 'Sa_z' , fldptr1=Sa_z , rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call dshr_state_getfldptr(exportState, 'Sa_tbot' , fldptr1=Sa_tbot , rc=rc) @@ -253,6 +267,10 @@ subroutine datm_datamode_jra_advance(exportstate, target_ymd, target_tod, model_ Sa_pbot(n) = Sa_pslv(n) Sa_ptem(n) = Sa_tbot(n) + ! Set Sa_u10m and Sa_v10m to Sa_u and Sa_v + Sa_u10m(n) = Sa_u(n) + Sa_v10m(n) = Sa_v(n) + ! density computation for JRA55 forcing Sa_dens(n) = Sa_pbot(n)/(rdair*Sa_tbot(n)*(1 + 0.608*Sa_shum(n))) From 56a3eb54870e7d5812336811b2537a016ed4d36a Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Mon, 18 Mar 2024 10:44:25 +0100 Subject: [PATCH 02/27] first draft implementation of multiple ice sheets in the dglc code - namelist still needs to be implemented --- datm/atm_comp_nuopc.F90 | 2 +- dice/ice_comp_nuopc.F90 | 2 +- dlnd/lnd_comp_nuopc.F90 | 4 ++-- docn/ocn_comp_nuopc.F90 | 2 +- drof/rof_comp_nuopc.F90 | 4 ++-- dshr/dshr_mod.F90 | 5 ++--- dwav/wav_comp_nuopc.F90 | 2 +- 7 files changed, 10 insertions(+), 11 deletions(-) diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 index dbd441085..233e4c2b5 100644 --- a/datm/atm_comp_nuopc.F90 +++ b/datm/atm_comp_nuopc.F90 @@ -264,7 +264,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Obtain flds_scalar values, mpi values, multi-instance values and ! set logunit and set shr logging to my log file - call dshr_init(gcomp, 'ATM', sdat, mpicom, my_task, inst_index, inst_suffix, & + call dshr_init(gcomp, 'ATM', mpicom, my_task, inst_index, inst_suffix, & flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, & logunit, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return diff --git a/dice/ice_comp_nuopc.F90 b/dice/ice_comp_nuopc.F90 index fd552bbcb..63539e812 100644 --- a/dice/ice_comp_nuopc.F90 +++ b/dice/ice_comp_nuopc.F90 @@ -195,7 +195,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Obtain flds_scalar values, mpi values, multi-instance values and ! set logunit and set shr logging to my log file - call dshr_init(gcomp, 'ICE', sdat, mpicom, my_task, inst_index, inst_suffix, & + call dshr_init(gcomp, 'ICE', mpicom, my_task, inst_index, inst_suffix, & flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, & logunit, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return diff --git a/dlnd/lnd_comp_nuopc.F90 b/dlnd/lnd_comp_nuopc.F90 index ff84bae05..56a360c83 100644 --- a/dlnd/lnd_comp_nuopc.F90 +++ b/dlnd/lnd_comp_nuopc.F90 @@ -25,7 +25,7 @@ module cdeps_dlnd_comp use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs use shr_sys_mod , only : shr_sys_abort use shr_cal_mod , only : shr_cal_ymd2date - use shr_log_mod , only : shr_log_setLogUnit + use shr_log_mod , only : shr_log_setLogUnit use dshr_methods_mod , only : dshr_state_getfldptr, dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_get_stream_domain use dshr_strdata_mod , only : shr_strdata_init_from_config @@ -187,7 +187,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Obtain flds_scalar values, mpi values, multi-instance values and ! set logunit and set shr logging to my log file - call dshr_init(gcomp, 'LND', sdat, mpicom, my_task, inst_index, inst_suffix, & + call dshr_init(gcomp, 'LND', mpicom, my_task, inst_index, inst_suffix, & flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, & logunit, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return diff --git a/docn/ocn_comp_nuopc.F90 b/docn/ocn_comp_nuopc.F90 index 462989995..4bdeb81f6 100644 --- a/docn/ocn_comp_nuopc.F90 +++ b/docn/ocn_comp_nuopc.F90 @@ -212,7 +212,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Obtain flds_scalar values, mpi values, multi-instance values and ! set logunit and set shr logging to my log file - call dshr_init(gcomp, 'OCN', sdat, mpicom, my_task, inst_index, inst_suffix, & + call dshr_init(gcomp, 'OCN', mpicom, my_task, inst_index, inst_suffix, & flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, logunit, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return diff --git a/drof/rof_comp_nuopc.F90 b/drof/rof_comp_nuopc.F90 index c3602cd97..959421a70 100644 --- a/drof/rof_comp_nuopc.F90 +++ b/drof/rof_comp_nuopc.F90 @@ -27,7 +27,7 @@ module cdeps_drof_comp use shr_const_mod , only : SHR_CONST_SPVAL use shr_sys_mod , only : shr_sys_abort use shr_cal_mod , only : shr_cal_ymd2date - use shr_log_mod , only : shr_log_setLogUnit + use shr_log_mod , only : shr_log_setLogUnit use dshr_methods_mod , only : dshr_state_getfldptr, dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_get_stream_domain use dshr_strdata_mod , only : shr_strdata_init_from_config @@ -183,7 +183,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Obtain flds_scalar values, mpi values, multi-instance values and ! set logunit and set shr logging to my log file - call dshr_init(gcomp, 'ROF', sdat, mpicom, my_task, inst_index, inst_suffix, & + call dshr_init(gcomp, 'ROF', mpicom, my_task, inst_index, inst_suffix, & flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, & logunit, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return diff --git a/dshr/dshr_mod.F90 b/dshr/dshr_mod.F90 index f253adc05..977b9d439 100644 --- a/dshr/dshr_mod.F90 +++ b/dshr/dshr_mod.F90 @@ -111,14 +111,13 @@ subroutine dshr_model_initphase(gcomp, importState, exportState, clock, rc) end subroutine dshr_model_initphase !=============================================================================== - subroutine dshr_init(gcomp, compname, sdat, mpicom, my_task, inst_index, inst_suffix, & + subroutine dshr_init(gcomp, compname, mpicom, my_task, inst_index, inst_suffix, & flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, logunit, rc) #ifdef CESMCOUPLED use nuopc_shr_methods, only : set_component_logging #endif ! input/output variables type(ESMF_GridComp) :: gcomp - type(shr_strdata_type), intent(in) :: sdat ! No longer used character(len=*) , intent(in) :: compname !e.g. ATM, OCN, ... integer , intent(inout) :: mpicom integer , intent(out) :: my_task @@ -246,7 +245,7 @@ subroutine dshr_mesh_init(gcomp, sdat, nullstr, logunit, compname, model_nxg, mo ! input/output variables type(ESMF_GridComp) , intent(inout) :: gcomp - type(shr_strdata_type) , intent(inout) :: sdat + type(shr_strdata_type) , intent(inout) :: sdat integer , intent(in) :: logunit character(len=*) , intent(in) :: compname !e.g. ATM, OCN, ... character(len=*) , intent(in) :: nullstr diff --git a/dwav/wav_comp_nuopc.F90 b/dwav/wav_comp_nuopc.F90 index e200e00b6..13728738a 100644 --- a/dwav/wav_comp_nuopc.F90 +++ b/dwav/wav_comp_nuopc.F90 @@ -181,7 +181,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Obtain flds_scalar values, mpi values, multi-instance values and ! set logunit and set shr logging to my log file - call dshr_init(gcomp, 'WAV', sdat, mpicom, my_task, inst_index, inst_suffix, & + call dshr_init(gcomp, 'WAV', mpicom, my_task, inst_index, inst_suffix, & flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, & logunit, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return From e1f092749b7ff45ee120298250cb1ffd1e415628 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 19 Mar 2024 11:13:50 +0100 Subject: [PATCH 03/27] additional changes for noevolve mode --- dglc/CMakeLists.txt | 34 + dglc/cime_config/buildlib | 54 ++ dglc/cime_config/buildnml | 198 ++++++ dglc/cime_config/config_archive.xml | 11 + dglc/cime_config/config_component.xml | 59 ++ dglc/cime_config/namelist_definition_dglc.xml | 109 ++++ dglc/cime_config/stream_definition_dglc.xml | 16 + dglc/cime_config/user_nl_dglc | 13 + dglc/cime_config/user_nl_dglc_streams | 33 + dglc/dglc_datamode_noevolve_mod.F90 | 279 ++++++++ dglc/glc_comp_nuopc.F90 | 617 ++++++++++++++++++ 11 files changed, 1423 insertions(+) create mode 100644 dglc/CMakeLists.txt create mode 100755 dglc/cime_config/buildlib create mode 100755 dglc/cime_config/buildnml create mode 100644 dglc/cime_config/config_archive.xml create mode 100644 dglc/cime_config/config_component.xml create mode 100644 dglc/cime_config/namelist_definition_dglc.xml create mode 100644 dglc/cime_config/stream_definition_dglc.xml create mode 100644 dglc/cime_config/user_nl_dglc create mode 100644 dglc/cime_config/user_nl_dglc_streams create mode 100644 dglc/dglc_datamode_noevolve_mod.F90 create mode 100644 dglc/glc_comp_nuopc.F90 diff --git a/dglc/CMakeLists.txt b/dglc/CMakeLists.txt new file mode 100644 index 000000000..2c62d04b0 --- /dev/null +++ b/dglc/CMakeLists.txt @@ -0,0 +1,34 @@ +project(dglc Fortran) +set(SRCFILES glc_comp_nuopc.F90 + dglc_datamode_noevolve_mod.F90) + +foreach(FILE ${SRCFILES}) + if(EXISTS "${CASEROOT}/SourceMods/src.dglc/${FILE}") + list(REMOVE_ITEM SRCFILES ${FILE}) + list(APPEND SRCFILES "${CASEROOT}/SourceMods/src.dglc/${FILE}") + message("Using ${FILE} from ${CASEROOT}/SourceMods/src.dglc") + endif() +endforeach() + +message("DGLC srcfiles are ${SRCFILES}") + +add_library(dglc ${SRCFILES}) + +add_dependencies(dglc dshr streams) +target_include_directories (dglc PRIVATE ${ESMF_F90COMPILEPATHS}) +target_include_directories (dglc PRIVATE ${CMAKE_SOURCE_DIR}) +target_include_directories (dglc PRIVATE ${PIO_Fortran_INCLUDE_DIR}) +if(NOT DISABLE_FoX) + target_include_directories (dglc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../fox/include) +endif() + +if(BLD_STANDALONE) + # ESMX requires mod files + foreach (SRC ${SRCFILES}) + string(REGEX REPLACE "[.]F90$" ".mod" MOD ${SRC}) + if (NOT DEFINED CIMEROOT AND MOD STREQUAL glc_comp_nuopc.mod) + set(MOD cdeps_dglc_comp.mod) + endif() + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${MOD}" DESTINATION include) + endforeach () +endif() diff --git a/dglc/cime_config/buildlib b/dglc/cime_config/buildlib new file mode 100755 index 000000000..281f0d4e9 --- /dev/null +++ b/dglc/cime_config/buildlib @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +""" +build cime component model library. This buildlib script is used by all CDEPS components. +""" + +import sys, os + +_CIMEROOT = os.environ.get("CIMEROOT") +if _CIMEROOT is None: + raise SystemExit("ERROR: must set CIMEROOT environment variable") +sys.path.append(os.path.join(_CIMEROOT, "CIME", "Tools")) + +_LIBDIR = os.path.join(_CIMEROOT, "CIME") +sys.path.append(_LIBDIR) + +from standard_script_setup import * +from CIME.buildlib import parse_input +from CIME.case import Case +from CIME.utils import run_cmd, symlink_force, expect + +# pragma pylint: disable=unused-argument,undefined-variable + +logger = logging.getLogger(__name__) + + +def buildlib(bldroot, libroot, case, compname=None): + if not compname: + expect( + bldroot.endswith("obj"), + "It appears that buildlib_comps is being called for the main CDEPS build\n" + "(the main CDEPS build should use buildlib, not buildlib_comps)", + ) + compname = os.path.basename(os.path.abspath(os.path.join(bldroot, os.pardir))) + + _, o, e = run_cmd("make d{}".format(compname), from_dir=bldroot, verbose=True) + libname = "lib{}.a".format(compname) + dlibname = "libd{}.a".format(compname) + dlibpath = os.path.join(bldroot, dlibname) + if os.path.exists(dlibpath): + symlink_force(os.path.join(bldroot, dlibname), os.path.join(libroot, libname)) + else: + expect(False, "ERROR in {} build {} {}".format(compname, o, e)) + logger.info(f"build successful for comp={compname}") + + +def _main_func(args): + caseroot, libroot, bldroot = parse_input(args) + with Case(caseroot) as case: + buildlib(bldroot, libroot, case) + + +if __name__ == "__main__": + _main_func(sys.argv) diff --git a/dglc/cime_config/buildnml b/dglc/cime_config/buildnml new file mode 100755 index 000000000..6994b7051 --- /dev/null +++ b/dglc/cime_config/buildnml @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 + +"""Namelist creator for CIME's data glc model. +""" + +# Typically ignore this. +# pylint: disable=invalid-name + +# Disable these because this is our standard setup +# pylint: disable=wildcard-import,unused-wildcard-import,wrong-import-position + +import os, sys + +_CDEPS_CONFIG = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir,os.pardir,"cime_config") +_CIMEROOT = os.environ.get("CIMEROOT") +if _CIMEROOT is None: + raise SystemExit("ERROR: must set CIMEROOT environment variable") +_LIBDIR = os.path.join(_CIMEROOT, "CIME", "Tools") +sys.path.append(_LIBDIR) +sys.path.append(_CDEPS_CONFIG) + +from standard_script_setup import * +from CIME.case import Case +from CIME.nmlgen import NamelistGenerator +from CIME.utils import expect, safe_copy +from CIME.XML.files import Files +from CIME.buildnml import create_namelist_infile, parse_input, copy_inputs_to_rundir +from stream_cdeps import StreamCDEPS + +logger = logging.getLogger(__name__) + +# pylint: disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements +#################################################################################### +def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path): +#################################################################################### + """Write out the namelist and stream xml files for this component. + + Most arguments are the same as those for `NamelistGenerator`. The + `inst_string` argument is used as a suffix to distinguish files for + different instances. The `confdir` argument is used to specify the directory + in which output files will be placed. + """ + #---------------------------------------------------- + # Write out dglc_in and dglc.streams.xml + #---------------------------------------------------- + caseroot = case.get_value("CASEROOT") + dglc_mode = case.get_value("DGLC_MODE") + glc_grid = case.get_value("GLC_GRID") + + # Check for incompatible options. + expect(glc_grid != "null", + "DGLC_GRID cannot be null") + + # Log some settings. + logger.debug("DGLC mode is {}".format(dglc_mode)) + + # Initialize namelist defaults + # Note: always use model mesh file to set mask for drof + config = {} + config['dglc_mode'] = dglc_mode + config['glc_grid'] = glc_grid + + # Do not allow single column mode for dglc + if case.get_value('PTS_LON'): + scol_lon = float(case.get_value('PTS_LON')) + else: + scol_lon = -999. + if case.get_value('PTS_LAT'): + scol_lat = float(case.get_value('PTS_LAT')) + else: + scol_lat = -999. + if (scol_lon > -999. and scol_lat > 999.): + expect(False, + "single column mode for DGLC is not currently allowed") + + # Initialize nmlgen + nmlgen.init_defaults(infile, config) + + # Generate dglc_in + namelist_file = os.path.join(confdir, "dglc_in") + nmlgen.write_output_file(namelist_file, data_list_path, groups=['dglc_nml']) + + # Determine streams + streamlist = nmlgen.get_streams() + if type(streamlist) == type(str()): + streamlist = [] + + # Generate dglc.streams.xml + print("dglc_mode is {}".format(dglc_mode)) + if 'NOEVOLVE' in dglc_mode: + generate_stream_file = False + else: + generate_stream_file = True + #endif + if generate_stream_file: + outfile = os.path.join(confdir, "dglc.streams"+inst_string+".xml" ) + schema_file = os.path.join(_CDEPS_CONFIG,"stream_definition_v2.0.xsd") + stream_file = os.path.join(_CDEPS_CONFIG,os.pardir, "dglc","cime_config","stream_definition_dglc.xml") + streams = StreamCDEPS(stream_file, schema_file) + streams.create_stream_xml(streamlist, case, outfile, data_list_path, + os.path.join(caseroot,'user_nl_dglc_streams'+inst_string)) + #endif + +############################################################################### +def buildnml(case, caseroot, compname): +############################################################################### + rundir = case.get_value("RUNDIR") + inst_name = compname.upper()[1:] + ninst = case.get_value("NINST_"+inst_name) + if ninst is None: + ninst = case.get_value("NINST") + confdir = os.path.join(caseroot,"Buildconf",compname + "conf") + if not os.path.isdir(confdir): + os.makedirs(confdir) + + #---------------------------------------------------- + # Construct the namelist generator + #---------------------------------------------------- + # determine directory for user modified namelist_definitions.xml + user_xml_dir = os.path.join(caseroot, "SourceMods", "src." + compname) + expect (os.path.isdir(user_xml_dir), + "user_xml_dir {} does not exist ".format(user_xml_dir)) + + # NOTE: User definition *replaces* existing definition. + files = Files(comp_interface="nuopc") + definition_file = [files.get_value("NAMELIST_DEFINITION_FILE", {"component":compname})] + + user_definition = os.path.join(user_xml_dir, "namelist_definition_"+compname+".xml") + if os.path.isfile(user_definition): + definition_file = [user_definition] + for file_ in definition_file: + expect(os.path.isfile(file_), "Namelist XML file {} not found!".format(file_)) + + # Create the namelist generator object - independent of instance + nmlgen = NamelistGenerator(case, definition_file, files=files) + + #---------------------------------------------------- + # Clear out old data. + #---------------------------------------------------- + + data_list_path = os.path.join(caseroot, "Buildconf", compname+".input_data_list") + if os.path.exists(data_list_path): + os.remove(data_list_path) + + #---------------------------------------------------- + # Loop over instances + #---------------------------------------------------- + for inst_counter in range(1, ninst+1): + # determine instance string + inst_string = "" + if ninst > 1: + inst_string = '_' + "{:04d}".format(inst_counter) + + # If multi-instance case does not have restart file, use + # single-case restart for each instance + rpointer = "rpointer." + compname + if (os.path.isfile(os.path.join(rundir,rpointer)) and + (not os.path.isfile(os.path.join(rundir,rpointer + inst_string)))): + safe_copy(os.path.join(rundir, rpointer), + os.path.join(rundir, rpointer + inst_string)) + + inst_string_label = inst_string + if not inst_string_label: + inst_string_label = "\"\"" + + # create namelist output infile using user_nl_file as input + user_nl_file = os.path.join(caseroot, "user_nl_" + compname + inst_string) + expect(os.path.isfile(user_nl_file), + "Missing required user_nl_file {} ".format(user_nl_file)) + infile = os.path.join(confdir, "namelist_infile") + create_namelist_infile(case, user_nl_file, infile) + namelist_infile = [infile] + + # create namelist and xml stream file(s) + _create_namelists(case, confdir, inst_string, namelist_infile, nmlgen, data_list_path) + + # copy namelist files and stream text files, to rundir + copy_inputs_to_rundir(caseroot, compname, confdir, rundir, inst_string) + +############################################################################### +def get_user_nl_list(case): +############################################################################### + """Returns a list of user_nl_dglc* files needed in this case + This function is called by CIME to stage the user_nl_dglc* files in the case + directory. + """ + user_nl_list = ["user_nl_dglc", "user_nl_dglc_streams"] + return user_nl_list + +############################################################################### +def _main_func(): + # Build the component namelist and required stream xml files + caseroot = parse_input(sys.argv) + with Case(caseroot) as case: + buildnml(case, caseroot, "dglc") + +if __name__ == "__main__": + _main_func() diff --git a/dglc/cime_config/config_archive.xml b/dglc/cime_config/config_archive.xml new file mode 100644 index 000000000..f61daec79 --- /dev/null +++ b/dglc/cime_config/config_archive.xml @@ -0,0 +1,11 @@ + + + r + rs1 + unset + + rpointer.glc$NINST_STRING + $CASE.dglc$NINST_STRING.r.$DATENAME.nc,$CASE.dglc$NINST_STRING.rs1.$DATENAME.bin + + + diff --git a/dglc/cime_config/config_component.xml b/dglc/cime_config/config_component.xml new file mode 100644 index 000000000..ae4a0549a --- /dev/null +++ b/dglc/cime_config/config_component.xml @@ -0,0 +1,59 @@ + + + + + + + + Data glc model (DGLC) + no evolve mode + + + + char + dglc + dglc + case_comp + env_case.xml + Name of land component + + + + char + NOEVOLVE + NOEVOLVE + + noevolve + + run_component_dglc + env_run.xml + + model mode. + TODO: fill in what noevolve mode does + + + + + logical + TRUE,FALSE + FALSE + run_component_dglc + env_run.xml + If set to true, than dglc restarts will not be read on a continuation run. + + + + + ========================================= + DGLC naming conventions + ========================================= + + + diff --git a/dglc/cime_config/namelist_definition_dglc.xml b/dglc/cime_config/namelist_definition_dglc.xml new file mode 100644 index 000000000..2fabb50a8 --- /dev/null +++ b/dglc/cime_config/namelist_definition_dglc.xml @@ -0,0 +1,109 @@ + + + + + + + + + + char(100) + streams + streams_file + List of streams used for each supported dglc_mode + + none + + + + + char + dglc + dglc_nml + noevolve + + Copies all fields directly from the input data streams Any required + fields not found on an input stream will be set to zero. + + + noevolve + + + + + char + streams + abs + dglc_nml + + $GLC_DOMAIN_MESH + + + file(s) specifying model mesh + for more than one ice sheets this will contain an array of mesh file names + + + + + integer(20) + streams + dglc_nml + + 704,416 + 704 + 416 + 76 + + + global size(s) of nx + for more than one ice sheets this will contain an array of nx values + + + + + integer(20) + streams + dglc_nml + + 576,704 + 576 + 704 + 141 + + + global size(s) of ny + for more than one ice sheets this will contain an array of ny values + + + + + char + dglc + dglc_nml + + main restart file name for dglc model + + + null + + + + + logical + dglc + dglc_nml + + If set to true, than dglc restarts will not be read on a continuation run. + This capability is used, for example, in CTSM spinup runs. + + + $DGLC_SKIP_RESTART_READ + + + + diff --git a/dglc/cime_config/stream_definition_dglc.xml b/dglc/cime_config/stream_definition_dglc.xml new file mode 100644 index 000000000..2811e8806 --- /dev/null +++ b/dglc/cime_config/stream_definition_dglc.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/dglc/cime_config/user_nl_dglc b/dglc/cime_config/user_nl_dglc new file mode 100644 index 000000000..2cbcf3997 --- /dev/null +++ b/dglc/cime_config/user_nl_dglc @@ -0,0 +1,13 @@ +!------------------------------------------------------------------------ +! Users should ONLY USE user_nl_dglc to change namelists variables +! Users should add all user specific namelist changes below in the form of +! namelist_var = new_namelist_value +! Note that any namelist variable from shr_strdata_nml and dglc_nml can +! be modified below using the above syntax +! User preview_namelists to view (not modify) the output namelist in the +! directory $CASEROOT/CaseDocs +! To modify the contents of a stream txt file, first use preview_namelists +! to obtain the contents of the stream txt files in CaseDocs, and then +! place a copy of the modified stream txt file in $CASEROOT with the string +! user_ prepended. +!------------------------------------------------------------------------ diff --git a/dglc/cime_config/user_nl_dglc_streams b/dglc/cime_config/user_nl_dglc_streams new file mode 100644 index 000000000..856ee8944 --- /dev/null +++ b/dglc/cime_config/user_nl_dglc_streams @@ -0,0 +1,33 @@ +!------------------------------------------------------------------------ +! This file is used to modify datm.streams.xml generated in $RUNDIR +! Entries should have the form +! :<= new stream_value> +! The following are accepted values for an assume streamname of foo +! foo:meshfile = character string +! foo:datafiles = comma separated string of full pathnames (e.g. file1,file2,file3...) +! foo:datavars = comma separated string of field pairs (e.g. foo foobar,foo2 foobar2...) +! foo:taxmode = one of [cycle, extend, limit] +! foo:tintalgo = one of [lower,upper,nearest,linear,coszen] +! foo:readmode = single (only suported mode right now) +! foo:mapalgo = one of [bilinear,redist,nn,consf,consd,none] +! foo:dtlimit = real (1.5 is default) +! foo:year_first = integer +! foo:year_last = integer +! foo:year_align = integer +! foo:vectors = one of [none,u:v] +! foo:lev_dimname: = one of [null,name of level dimenion name] +! foo:offset = integer +! As an example: +! foo:year_first = 1950 +! would change the stream year_first stream_entry to 1950 for the foo stream block +! NOTE: multi-line inputs are enabled by adding a \ at the end of the line +! As an emaple: +! foo:datafiles=foo1,foo2, \ +! foo3 +! Will yield the following new entry for datafiles in stream foo +! +! foo1 +! foo2 +! foo3 +! +!------------------------------------------------------------------------ diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 new file mode 100644 index 000000000..b1e77c6d2 --- /dev/null +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -0,0 +1,279 @@ +module dglc_datamode_noevolve_mod + + use ESMF , only : ESMF_State, ESMF_LOGMSG_INFO, ESMF_LogWrite, ESMF_SUCCESS + use NUOPC , only : NUOPC_Advertise + use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs + use shr_sys_mod , only : shr_sys_abort + use dshr_methods_mod , only : dshr_state_getfldptr, dshr_fldbun_getfldptr, chkerr + use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add + use dshr_mod , only : dshr_restart_read, dshr_restart_write + use dshr_strdata_mod , only : shr_strdata_type + + implicit none + private ! except + + public :: dglc_datamode_noevolve_advertise + public :: dglc_datamode_noevolve_init_pointers + public :: dglc_datamode_noevolve_advance + public :: dglc_datamode_noevolve_restart_read + public :: dglc_datamode_noevolve_restart_write + + integer :: num_icesheets + + ! export fields + type icesheet_ptr_t + real(r8), pointer :: ptr => null() ! pointer to array + endtype icesheet_ptr_t + type(icesheet_ptr_t), allocatable :: Sg_area(:) + type(icesheet_ptr_t), allocatable :: Sg_ice_covered(:) + type(icesheet_ptr_t), allocatable :: Sg_topo(:) + type(icesheet_ptr_t), allocatable :: Sg_icemask(:) + + character(len=*), parameter :: field_in_tsrf = 'Sl_tsrf' + character(len=*), parameter :: field_in_qice = 'Flgl_qice' + + character(len=*), parameter :: field_out_area = 'Sg_area' + character(len=*), parameter :: field_out_ice_covered = 'Sg_ice_covered' + character(len=*), parameter :: field_out_topo = 'Sg_topo' + character(len=*), parameter :: field_out_icemask = 'Sg_icemask' + character(len=*), parameter :: field_out_icemask_coupled_fluxes = 'Sg_icemask_coupled_fluxes' + + character(len=*), parameter :: field_out_hflx_to_lnd = 'Flgg_hflx' + character(len=*), parameter :: field_out_rofi_to_ice = 'Figg_rofi' + character(len=*), parameter :: field_out_rofi_to_ocn = 'Fogg_rofi' + character(len=*), parameter :: field_out_rofl_to_ocn = 'Fogg_rofl' + + character(*) , parameter :: nullstr = 'null' + character(*) , parameter :: rpfile = 'rpointer.glc' + character(*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================================== +contains +!=============================================================================== + + subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_name, rc) + + ! input/output variables + type(esmf_State) , intent(inout) :: NstateExp(num_icesheets_in) + type(fldlist_type) , pointer :: fldsexport + character(len=*) , intent(in) :: flds_scalar_name + integer , intent(out) :: rc + + ! local variables + integer :: nf,ns + character(len=CS) :: cnum + character(len=CL) :: cvalue + character(len=CL) :: logmsg + logical :: isPresent, isSet + type(fldlist_type), pointer :: fldList + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + !-------------------------------- + ! Create nested state for active ice sheets only + !-------------------------------- + + num_icesheets = size(NStateExp) + + do ns = 1,num_icesheets + write(cnum,'(i0)') ns + call NUOPC_AddNestedState(importState, CplSet="GLC"//trim(cnum), nestedState=NStateImp(ns), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call NUOPC_AddNestedState(exportState, CplSet="GLC"//trim(cnum), nestedState=NStateExp(ns), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + + ! Advertise export fields + call dshr_fldList_add(fldsExport, trim(flds_scalar_name)) + call dshr_fldList_add(fldsExport, field_out_ice_covered) + call dshr_fldList_add(fldsExport, field_out_topo) + call dshr_fldList_add(fldsExport, field_out_icemask) + call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) + + do ns = 1,num_icesheets + fldlist => fldsExport ! the head of the linked list + do while (associated(fldlist)) + call NUOPC_Advertise(NStateExp(ns), standardName=fldlist%stdname, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (ns == 1) then + call ESMF_LogWrite('(dglc_comp_advertise): Fr_glc'//trim(fldList%stdname), ESMF_LOGMSG_INFO) + end if + fldList => fldList%next + end do + enddo + + end subroutine dglc_datamode_noevolve_advertise + + !=============================================================================== + subroutine dglc_datamode_noevolve_init_pointers(NStateExport, rc) + + ! input/output variables + type(ESMF_State) , intent(inout) :: NStateExport(:) + integer , intent(out) :: rc + + ! local variables + character(len=*), parameter :: subname='(dglc_init_pointers): ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! So this is tricky since you need pointers to fields in the nested state + ! So this will have to be done below in a loop + + ! initialize pointers to export fields + allocate(Sg_area(num_icesheets)) + allocate(Sg_topo(num_icesheets)) + allocate(Sg_ice_covered(num_icesheets)) + allocate(Sg_icemask(num_icesheets)) + + do ns = 1,num_icesheets + call dshr_state_getfldptr(NStateExport, 'Sg_topo', fldptr1=Sg_topo(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end do + + end subroutine dglc_datamode_noevolve_init_pointers + + !=============================================================================== + subroutine dglc_datamode_noevolve_advance(sdat, mesh, fileName_data, thickness, topo, rc) + + ! Assume that the model mesh is the same as the input data mesh + + ! input/output variables + integer, intent(out) :: rc + + ! local variables + character(len=*), parameter :: subname='(dglc_datamode_noevolve_advance): ' + !------------------------------------------------------------------------------- + + ! input/output variables + type(shr_strdata_type) , intent(in) :: sdat + type(ESMF_Mesh) , intent(in) :: mesh ! mesh read in from fileName_mesh + character(*) , intent(in) :: fileName_data ! file name string + real(R8) , pointer :: thickness(:) ! ice thickness + real(R8) , pointer :: topo(:) ! topography + integer , intent(out) :: rc + + ! local variables + type(ESMF_DistGrid) :: distgrid + type(ESMF_FieldBundle) :: fldbun_src + type(ESMF_Field) :: field_src + integer :: lsize + integer, pointer :: gindex(:) ! domain decomposition of data + integer :: ndims ! number of dims + integer, allocatable :: dimid(:) + type(var_desc_t) :: varid + type(file_desc_t) :: pioid + type(io_desc_t) :: pio_iodesc + integer :: rcode + integer :: nxg, nyg + real(r8), pointer :: data(:) + integer :: srcTermProcessing_Value = 0 + character(*) ,parameter :: subName = '(datm_get_adjustment_factors) ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Create input + fldbun_src = ESMF_FieldBundleCreate(rc=rc) ! input field bundle + + ! "ice thickness" ; + field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='thk', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! "bed topography" ; + field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='topg', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! "area" + field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='area', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Get mesh info + call ESMF_MeshGet(mesh, elementdistGrid=distGrid, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(gindex(lsize)) + call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=gindex, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Create_pio_iodesc + rcode = pio_openfile(sdat%pio_subsystem, pioid, sdat%io_type, trim(filename_data), pio_nowrite) + call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) + rcode = pio_inq_varid(pioid, 'thk', varid) + rcode = pio_inq_varndims(pioid, varid, ndims) + allocate(dimid(ndims)) + rcode = pio_inq_varid(pioid, 'topg', varid) + rcode = pio_inq_vardimid(pioid, varid, dimid(1:ndims)) + rcode = pio_inq_dimlen(pioid, dimid(1), nxg) + rcode = pio_inq_dimlen(pioid, dimid(2), nyg) + call pio_initdecomp(sdat%pio_subsystem, pio_double, (/nxg,nyg/), gindex, pio_iodesc) + deallocate(gindex) + + ! Read in the data into the appropriate field bundle pointers + call dshr_fldbun_getFldPtr(fldbun_src, 'thk', data, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + rcode = pio_inq_varid(pioid, 'thk', varid) + call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) + + call dshr_fldbun_getFldPtr(fldbun_src, 'topg', data, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + rcode = pio_inq_varid(pioid, 'topg', varid) + call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) + + call pio_closefile(pioid) + call pio_freedecomp(sdat%pio_subsystem, pio_iodesc) + call ESMF_RouteHandleDestroy(route_handle, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + + + + + + end subroutine dglc_datamode_noevolve_advance + + !=============================================================================== + subroutine dglc_datamode_noevolve_restart_write(case_name, inst_suffix, ymd, tod, & + logunit, my_task, sdat) + + ! input/output variables + character(len=*) , intent(in) :: case_name + character(len=*) , intent(in) :: inst_suffix + integer , intent(in) :: ymd ! model date + integer , intent(in) :: tod ! model sec into model date + integer , intent(in) :: logunit + integer , intent(in) :: my_task + type(shr_strdata_type) , intent(inout) :: sdat + !------------------------------------------------------------------------------- + + call dshr_restart_write(rpfile, case_name, 'dglc', inst_suffix, ymd, tod, & + logunit, my_task, sdat) + + end subroutine dglc_datamode_noevolve_restart_write + + !=============================================================================== + subroutine dglc_datamode_noevolve_restart_read(rest_filem, inst_suffix, logunit, my_task, mpicom, sdat) + + ! input/output arguments + character(len=*) , intent(inout) :: rest_filem + character(len=*) , intent(in) :: inst_suffix + integer , intent(in) :: logunit + integer , intent(in) :: my_task + integer , intent(in) :: mpicom + type(shr_strdata_type) , intent(inout) :: sdat + !------------------------------------------------------------------------------- + + call dshr_restart_read(rest_filem, rpfile, inst_suffix, nullstr, logunit, my_task, mpicom, sdat) + + end subroutine dglc_datamode_noevolve_restart_read + +end module dglc_datamode_noevolve_mod diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 new file mode 100644 index 000000000..8b4257fe3 --- /dev/null +++ b/dglc/glc_comp_nuopc.F90 @@ -0,0 +1,617 @@ +#ifdef CESMCOUPLED +module glc_comp_nuopc +#else +module cdeps_dglc_comp +#endif + + !---------------------------------------------------------------------------- + ! This is the NUOPC cap for DGLC + !---------------------------------------------------------------------------- + use ESMF , only : ESMF_VM, ESMF_VMBroadcast, ESMF_GridCompGet + use ESMF , only : ESMF_Mesh, ESMF_GridComp, ESMF_State, ESMF_Clock, ESMF_Time + use ESMF , only : ESMF_SUCCESS, ESMF_LogWrite, ESMF_LOGMSG_INFO, ESMF_METHOD_INITIALIZE + use ESMF , only : ESMF_TraceRegionEnter, ESMF_TraceRegionExit, ESMF_ClockGet + use ESMF , only : ESMF_TimeGet, ESMF_TimeInterval, ESMF_Field, ESMF_MAXSTR + use ESMF , only : ESMF_Alarm, ESMF_MethodRemove, ESMF_MethodAdd + use ESMF , only : ESMF_GridCompSetEntryPoint, ESMF_ClockGetAlarm, ESMF_AlarmIsRinging + use ESMF , only : ESMF_StateGet, operator(+), ESMF_AlarmRingerOff, ESMF_LogWrite + use ESMF , only : ESMF_Field, ESMF_FieldGet, ESMF_VmLogMemInfo + use NUOPC , only : NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize + use NUOPC , only : NUOPC_Advertise, NUOPC_CompAttributeGet, NUOPC_CompAttributeSet + use NUOPC_Model , only : model_routine_SS => SetServices + use NUOPC_Model , only : model_label_Advance => label_Advance + use NUOPC_Model , only : model_label_SetRunClock => label_SetRunClock + use NUOPC_Model , only : model_label_Finalize => label_Finalize + use NUOPC_Model , only : NUOPC_ModelGet, SetVM + use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs + use shr_sys_mod , only : shr_sys_abort + use shr_cal_mod , only : shr_cal_ymd2date + use shr_log_mod , only : shr_log_setLogUnit + use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck + use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config + use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init + use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_check_restart_alarm + use dshr_dfield_mod , only : dfield_type, dshr_dfield_add, dshr_dfield_copy + use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_realize + + ! Datamode specialized modules + use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_advertise + use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_init_pointers + use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_advance + use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_restart_read + use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_restart_write + + implicit none + private ! except + + public :: SetServices + public :: SetVM + private :: InitializeAdvertise + private :: InitializeRealize + private :: ModelAdvance + private :: dglc_comp_run + private :: ModelFinalize + + !-------------------------------------------------------------------------- + ! Private module data + !-------------------------------------------------------------------------- + + ! module variables for multiple ice sheets + type(ESMF_State) , allocatable :: NStateImp(:) + type(ESMF_State) , allocatable :: NStateExp(:) + type(shr_strdata_type) , allocatable :: sdat(:) + type(ESMF_Mesh) , allocatable :: model_mesh(:) + + ! module variables common to all data models + character(CS) :: flds_scalar_name = '' + integer :: flds_scalar_num = 0 + integer :: flds_scalar_index_nx = 0 + integer :: flds_scalar_index_ny = 0 + integer :: mpicom ! mpi communicator + integer :: my_task ! my task in mpi communicator mpicom + logical :: mainproc ! true of my_task == main_task + character(len=16) :: inst_suffix = "" ! char string associated with instance (ie. "_0001" or "") + integer :: logunit ! logging unit number + logical :: restart_read ! start from restart + character(CL) :: case_name + character(*) , parameter :: nullstr = 'null' + + ! dglc_in namelist input + integer ,parameter :: max_icesheets = 10 + integer :: num_icesheets = 0 + character(CL) :: streamfilename = nullstr ! filename to obtain stream info from + character(CL) :: nlfilename = nullstr ! filename to obtain namelist info from + character(CL) :: datamode = nullstr ! flags physics options wrt input data + character(CS) :: icesheet_names(max_icesheets) + integer :: nx_global(max_ice_sheets) = -999 + integer :: ny_global(max_ice_sheets) = -999 + character(CL) :: model_meshfile(max_icesheets) = nullstr ! full pathname to model meshfile + character(CL) :: restfilm = nullstr ! model restart file namelist + logical :: skip_restart_read = .false. ! true => skip restart read in continuation run + logical :: export_all = .false. ! true => export all fields, do not check connected or not + + ! linked lists + type(fldList_type) , pointer :: fldsImport => null() + type(fldList_type) , pointer :: fldsExport => null() + + type dfields_icesheets_type + type(dfield_type), pointer :: dfields => null() + end type dfields_icesheets_type + type(dfields_icesheets_type), allocatable :: dfields_icesheets(:) + + ! constants + logical :: diagnose_data = .true. + integer , parameter :: main_task = 0 ! task number of main task +#ifdef CESMCOUPLED + character(*) , parameter :: module_name = "(glc_comp_nuopc)" +#else + character(*) , parameter :: module_name = "(cdeps_dglc_comp)" +#endif + character(*) , parameter :: modelname = 'dglc' + character(*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================================== +contains +!=============================================================================== + + subroutine SetServices(gcomp, rc) + type(ESMF_GridComp) :: gcomp + integer, intent(out) :: rc + + ! Local varaibles + character(len=*),parameter :: subname=trim(module_name)//':(SetServices) ' + !-------------------------------- + + rc = ESMF_SUCCESS + call ESMF_LogWrite(subname//' called', ESMF_LOGMSG_INFO) + + ! the NUOPC gcomp component will register the generic methods + call NUOPC_CompDerive(gcomp, model_routine_SS, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! switching to IPD versions + call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & + userRoutine=dshr_model_initphase, phase=0, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! set entry point for methods that require specific implementation + call NUOPC_CompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & + phaseLabelList=(/"IPDv01p1"/), userRoutine=InitializeAdvertise, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call NUOPC_CompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & + phaseLabelList=(/"IPDv01p3"/), userRoutine=InitializeRealize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! attach specializing method(s) + call NUOPC_CompSpecialize(gcomp, specLabel=model_label_Advance, specRoutine=ModelAdvance, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call ESMF_MethodRemove(gcomp, label=model_label_SetRunClock, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call NUOPC_CompSpecialize(gcomp, specLabel=model_label_SetRunClock, specRoutine=dshr_set_runclock, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call NUOPC_CompSpecialize(gcomp, specLabel=model_label_Finalize, specRoutine=ModelFinalize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call ESMF_LogWrite(subname//' done', ESMF_LOGMSG_INFO) + + end subroutine SetServices + + !=============================================================================== + subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) + + use shr_nl_mod, only: shr_nl_find_group_name + + ! input/output variables + type(ESMF_GridComp) :: gcomp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + ! local variables + integer :: inst_index ! number of current instance (ie. 1) + integer :: nu ! unit number + integer :: ierr ! error code + integer :: bcasttmp(1) + type(ESMF_VM) :: vm + integer :: ns, n + character(len=CS) :: cnum + character(len=*),parameter :: subname=trim(module_name)//':(InitializeAdvertise) ' + !------------------------------------------------------------------------------- + + !icesheet_names = "ais", "gris" + !num_icesheets = 2 + + namelist / dglc_nml / datamode, & + model_meshfile, ice_sheet_names, nx_global, ny_global, + restfilm, skip_restart_read + + rc = ESMF_SUCCESS + + call NUOPC_CompAttributeGet(gcomp, name='case_name', value=case_name, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine logical mainproc + mainproc = (my_task == main_task) + + ! Obtain flds_scalar values, mpi values, multi-instance values and + ! set logunit and set shr logging to my log file + call dshr_init(gcomp, 'GLC', mpicom, my_task, inst_index, inst_suffix, & + flds_scalar_name, flds_scalar_num, flds_scalar_index_nx, flds_scalar_index_ny, logunit, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Read dglc_nml from nlfilename + if (my_task == main_task) then + nlfilename = "dglc_in"//trim(inst_suffix) + open (newunit=nu,file=trim(nlfilename),status="old",action="read") + call shr_nl_find_group_name(nu, 'dglc_nml', status=ierr) + read (nu,nml=dglc_nml,iostat=ierr) + close(nu) + if (ierr > 0) then + write(logunit,'(a,i8)') 'ERROR: reading input namelist, '//trim(nlfilename)//' iostat=',ierr + call shr_sys_abort(subName//': namelist read error '//trim(nlfilename)) + end if + + ! write namelist input to standard out + write(logunit,'(a,a)')' case_name = ',trim(case_name) + write(logunit,'(a,a)')' datamode = ',trim(datamode) + do ns = 1,max_ice_sheets + if (model_meshfile(n) == nullstr) exit + num_icesheets = num_icesheets + 1 + write(logunit,'(a,i4 )')' ice_sheet index = ',ns + write(logunit,'(a,a )')' model_meshfile = ',trim(model_meshfile(ns)) + write(logunit,'(a,i10)')' nx_global = ',nx_global(ns) + write(logunit,'(a,i10)')' ny_global = ',ny_global(ns) + end do + write(logunit,'(a,a )')' restfilm = ',trim(restfilm) + write(logunit,'(a,l6)')' skip_restart_read = ',skip_restart_read + if (skip_restart_read) then + bcasttmp = 1 + else + bcasttmp = 0 + end if + endif + + ! Broadcast namelist input + call ESMF_GridCompGet(gcomp, vm=vm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, datamode, CL, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, restfilm, CL, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do ns = 1,num_icesheets + call ESMF_VMBroadcast(vm, model_meshfile(n), CL, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, nx_global(ns), 1, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, ny_global(ns), 1, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Validate datamode + if ( trim(datamode) == 'noevolve') ! read stream, no import data + else + call shr_sys_abort(' ERROR illegal dglc datamode = '//trim(datamode)) + endif + + ! Allocate module variables + allocate(NStateImp(num_icesheets)) + allocate(NStateExp(num_icesheets)) + allocate(sdat(num_icesheets)) + allocate(model_mesh(num_icesheets)) + allocate(dfields_icesheets(num_icesheets)) + + ! Create nested states + do ns = 1,num_icesheets + write(cnum,'(i0)') ns + call NUOPC_AddNestedState(importState, CplSet="GLC"//trim(cnum), nestedState=NStateImp(ns), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call NUOPC_AddNestedState(exportState, CplSet="GLC"//trim(cnum), nestedState=NStateExp(ns), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + + ! Advertise dglc fields + if (trim(datamode)=='noevolve') then + call dglc_datamode_noevolve_advertise(exportState, fldsExport, flds_scalar_name, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + end subroutine InitializeAdvertise + + !=============================================================================== + subroutine InitializeRealize(gcomp, clock, rc) + + ! input/output variables + type(ESMF_GridComp) :: gcomp + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + ! local variables + type(ESMF_Time) :: currTime + integer :: current_ymd ! model date + integer :: current_year ! model year + integer :: current_mon ! model month + integer :: current_day ! model day + integer :: current_tod ! model sec into model date + type(ESMF_Field) :: lfield + character(CL) ,pointer :: lfieldnamelist(:) => null() + integer :: fieldcount + real(r8), pointer :: fldptr(:) + integer :: n + integer :: imask + real(r8) :: rmask + character(CL) :: cvalue + character(len=*), parameter :: subname=trim(module_name)//':(InitializeRealize) ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + call ESMF_VMLogMemInfo("Entering "//trim(subname)) + + ! Initialize model mesh, restart flag, logunit, model_mask and model_frac + call ESMF_TraceRegionEnter('dglc_strdata_init') + + ! Determine stream filename + streamfilename = trim(modelname)//'.streams'//trim(inst_suffix) +#ifndef DISABLE_FoX + streamfilename = trim(streamfilename)//'.xml' +#endif + + ! generate local mpi comm + call ESMF_GridCompGet(gcomp, vm=vm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMGet(vm, localPet=my_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + mainproc = (my_task == main_task) + call shr_log_setLogUnit(logunit) + + ! Set restart flag + call NUOPC_CompAttributeGet(gcomp, name='read_restart', value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (isPresent .and. isSet) then + read(cvalue,*) read_restart + else + call shr_sys_abort(subname//' ERROR: read restart flag must be present') + end if + + ! Loop over ice sheets + do ns = 1,num_icesheets + write(cns,'(i0)') ns + + ! Initialize pio subsystem +#ifdef CESMCOUPLED + sdat(ns)%pio_subsystem => shr_pio_getiosys('GLC') + sdat(ns)%io_type = shr_pio_getiotype('GLC') + sdat(ns)%io_format = shr_pio_getioformat('GLC') +#else + call dshr_pio_init(gcomp, sdat(ns), logunit, rc) +#endif + + ! Check that model_meshfile exists + if (my_task == main_task) then + inquire(file=trim(model_meshfile(ns)), exist=exists) + if (.not.exists) then + write(logunit, *)' ERROR: model_meshfile '//trim(model_meshfile)//' does not exist' + call shr_sys_abort(trim(subname)//' ERROR: model_meshfile '//trim(model_meshfile)//' does not exist') + end if + endif + + ! Read in model mesh + model_mesh(ns) = ESMF_MeshCreate(trim(model_meshfile(ns)), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Initialize stream data type + call shr_strdata_init_from_config(sdat(ns), streamfilename, model_mesh(ns), clock, 'GLC', logunit, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TraceRegionExit('dglc_strdata_init') + + ! Realize the actively coupled fields, now that a mesh is established and + ! NUOPC_Realize "realizes" a previously advertised field in the importState and exportState + ! by replacing the advertised fields with the newly created fields of the same name. + + call dshr_fldlist_realize( NStateExp(ns), fldsExport, flds_scalar_name, flds_scalar_num, model_mesh(ns), & + subname//trim(modelname)//':Export', export_all, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call dshr_fldlist_realize( NStateImp(ns), fldsImport, flds_scalar_name, flds_scalar_num, model_mesh(ns), & + subname//trim(modelname)//':Import', .false., rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + end do ! loop over ice sheets + + ! Get the time to interpolate the stream data to + call ESMF_ClockGet(clock, currTime=currTime, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TimeGet(currTime, yy=current_year, mm=current_mon, dd=current_day, s=current_tod, rc=rc ) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call shr_cal_ymd2date(current_year, current_mon, current_day, current_ymd) + + ! loop over ice sheets + do ns = 1,num_icesheets + ! Run dglc + call dglc_comp_run(clock, current_ymd, current_tod, restart_write=.false., rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Add scalars to export state + call dshr_state_SetScalar(dble(nx_global(ns)),flds_scalar_index_nx, & + NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_SetScalar(dble(ny_global(ns)),flds_scalar_index_ny,& + NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + + call ESMF_VMLogMemInfo("Leaving "//trim(subname)) + + end subroutine InitializeRealize + + !=============================================================================== + subroutine ModelAdvance(gcomp, rc) + + ! input/output variables + type(ESMF_GridComp) :: gcomp + integer, intent(out) :: rc + + ! local variables + type(ESMF_Clock) :: clock + type(ESMF_TimeInterval) :: timeStep + type(ESMF_Time) :: currTime, nextTime + integer :: next_ymd ! model date + integer :: next_tod ! model sec into model date + integer :: yr ! year + integer :: mon ! month + integer :: day ! day in month + logical :: restart_write + character(len=*),parameter :: subname=trim(module_name)//':(ModelAdvance) ' + !------------------------------------------------------------------------------- + + + rc = ESMF_SUCCESS + call shr_log_setLogUnit(logunit) + + call memcheck(subname, 5, my_task == main_task) + + ! query the Component for its clock + call NUOPC_ModelGet(gcomp, modelClock=clock, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! For nuopc - the component clock is advanced at the end of the time interval + ! Need to advance nuopc one timestep ahead for shr_strdata time interpolation + call ESMF_ClockGet( clock, currTime=currTime, timeStep=timeStep, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + nextTime = currTime + timeStep + call ESMF_TimeGet( nextTime, yy=yr, mm=mon, dd=day, s=next_tod, rc=rc ) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call shr_cal_ymd2date(yr, mon, day, next_ymd) + + ! determine if will write restart + restart_write = dshr_check_restart_alarm(clock, rc=rc) + + ! run dglc + call dglc_comp_run(clock, next_ymd, next_tod, restart_write, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + end subroutine ModelAdvance + + !=============================================================================== + subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) + + ! -------------------------- + ! advance dglc + ! -------------------------- + + ! input/output variables: + type(ESMF_Clock) , intent(in) :: clock + integer , intent(in) :: target_ymd ! model date + integer , intent(in) :: target_tod ! model sec into model date + logical , intent(in) :: restart_write + integer , intent(out) :: rc + + ! local variables + character(len=CS) :: cnum + integer :: ns ! ice sheet index + logical :: first_time = .true. + character(*), parameter :: subName = "(dglc_comp_run) " + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call ESMF_TraceRegionEnter('DGLC_RUN') + + ! Loop over ice sheets + do ns = 1,size(NStateImp) + + !-------------------- + ! First time initialization + !-------------------- + + if (first_time) then + ! Initialize dfields for given ice sheet + call dglc_init_dfields(NStateImp(ns), NStateExp(ns), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Initialize datamode module ponters + select case (trim(datamode)) + case('noevolve') + call dglc_datamode_copyall_init_pointers(NStateExp(ns), rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end select + + ! Read restart if needed + ! if (restart_read .and. .not. skip_restart_read) then + ! select case (trim(datamode)) + ! case('noevolve') + ! call dglc_datamode_copyall_restart_read(restfilm, inst_suffix, logunit, my_task, mpicom, sdat(ns)) + ! end select + ! end if + + ! Reset first_time + first_time = .false. + end if + + !-------------------- + ! Update export (and possibly import data model states) + !-------------------- + + ! Advance data model streams - time and spatially interpolate to model time and grid + call ESMF_TraceRegionEnter('dglc_strdata_advance') + call shr_strdata_advance(sdat(ns), target_ymd, target_tod, logunit, 'dglc', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TraceRegionExit('dglc_strdata_advance') + + ! Copy all fields from streams to export state as default + ! This automatically will update the fields in the export state + call ESMF_TraceRegionEnter('dglc_dfield_copy') + call dshr_dfield_copy(dfields_icesheets(ns)%dfields, sdat(ns), rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TraceRegionExit('dglc_dfield_copy') + + ! Perform data mode specific calculations + select case (trim(datamode)) + case('noevolve') + call dglc_datamode_noevolve_advance(rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end select + + ! Write restarts if needed + if (restart_write) then + select case (trim(datamode)) + case('noevolve') + call dglc_datamode_noevolve_restart_write(case_name, inst_suffix, target_ymd, target_tod, & + logunit, my_task, sdat(ns)) + end select + end if + + ! Write diagnostics + if (diagnose_data) then + write(cnum,'(i0)') ns + call dshr_state_diagnose(NStateExp, flds_scalar_name, trim(subname)//':ES_'//trim(cnum), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + end do ! end of loop over ice sheets + + call ESMF_TraceRegionExit('DGLC_RUN') + + contains + + subroutine dglc_init_dfields(ns, rc) + ! ----------------------------- + ! Initialize dfields arrays + ! ----------------------------- + + ! input/output variables + integer , intent(in) :: ns ! ice sheet index + integer , intent(out) :: rc + + ! local variables + integer :: n + integer :: fieldcount + type(ESMF_Field) :: lfield + character(ESMF_MAXSTR) ,pointer :: lfieldnamelist(:) + character(*), parameter :: subName = "(dglc_init_dfields) " + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Initialize dfields data type (to map streams to export state fields) + ! Create dfields linked list - used for copying stream fields to export state fields + call ESMF_StateGet(NStateExp(ns), itemCount=fieldCount, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + allocate(lfieldnamelist(fieldCount)) + call ESMF_StateGet(NStateExp(ns), itemNameList=lfieldnamelist, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do n = 1, fieldCount + call ESMF_StateGet(NStateExp(ns), itemName=trim(lfieldNameList(n)), field=lfield, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (trim(lfieldnamelist(n)) /= flds_scalar_name) then + call dshr_dfield_add( dfields, sdat(ns), trim(lfieldnamelist(n)), trim(lfieldnamelist(n)), NStateExp(ns), & + logunit, mainproc, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + end do + end subroutine dglc_init_dfields + + end subroutine dglc_comp_run + + !=============================================================================== + subroutine ModelFinalize(gcomp, rc) + type(ESMF_GridComp) :: gcomp + integer, intent(out) :: rc + !------------------------------------------------------------------------------- + rc = ESMF_SUCCESS + if (my_task == main_task) then + write(logunit,*) + write(logunit,*) 'dglc : end of main integration loop' + write(logunit,*) + end if + end subroutine ModelFinalize + +#ifdef CESMCOUPLED +end module glc_comp_nuopc +#else +end module cdeps_dglc_comp +#endif From 96f8b7af94516b647a1bdda28988fefb2df68b5f Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Tue, 19 Mar 2024 19:34:35 +0100 Subject: [PATCH 04/27] more updates to fix compilation issues - not there yet --- CMakeLists.txt | 2 +- dglc/dglc_datamode_noevolve_mod.F90 | 483 +++++++++++++--------------- dglc/glc_comp_nuopc.F90 | 144 +++++---- 3 files changed, 293 insertions(+), 336 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28fb2a269..bc7cce6df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,7 @@ endif() target_include_directories(dshr PUBLIC $ $) -foreach(COMP datm dice dlnd docn drof dwav) +foreach(COMP datm dice dglc dlnd docn drof dwav) add_subdirectory("${COMP}") if(BLD_STANDALONE) target_include_directories(${COMP} PUBLIC $ diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index b1e77c6d2..3e06254fc 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -1,52 +1,57 @@ module dglc_datamode_noevolve_mod - use ESMF , only : ESMF_State, ESMF_LOGMSG_INFO, ESMF_LogWrite, ESMF_SUCCESS - use NUOPC , only : NUOPC_Advertise - use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs - use shr_sys_mod , only : shr_sys_abort - use dshr_methods_mod , only : dshr_state_getfldptr, dshr_fldbun_getfldptr, chkerr - use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add - use dshr_mod , only : dshr_restart_read, dshr_restart_write - use dshr_strdata_mod , only : shr_strdata_type - - implicit none - private ! except - - public :: dglc_datamode_noevolve_advertise - public :: dglc_datamode_noevolve_init_pointers - public :: dglc_datamode_noevolve_advance - public :: dglc_datamode_noevolve_restart_read - public :: dglc_datamode_noevolve_restart_write - - integer :: num_icesheets - - ! export fields - type icesheet_ptr_t - real(r8), pointer :: ptr => null() ! pointer to array - endtype icesheet_ptr_t - type(icesheet_ptr_t), allocatable :: Sg_area(:) - type(icesheet_ptr_t), allocatable :: Sg_ice_covered(:) - type(icesheet_ptr_t), allocatable :: Sg_topo(:) - type(icesheet_ptr_t), allocatable :: Sg_icemask(:) - - character(len=*), parameter :: field_in_tsrf = 'Sl_tsrf' - character(len=*), parameter :: field_in_qice = 'Flgl_qice' - - character(len=*), parameter :: field_out_area = 'Sg_area' - character(len=*), parameter :: field_out_ice_covered = 'Sg_ice_covered' - character(len=*), parameter :: field_out_topo = 'Sg_topo' - character(len=*), parameter :: field_out_icemask = 'Sg_icemask' - character(len=*), parameter :: field_out_icemask_coupled_fluxes = 'Sg_icemask_coupled_fluxes' - - character(len=*), parameter :: field_out_hflx_to_lnd = 'Flgg_hflx' - character(len=*), parameter :: field_out_rofi_to_ice = 'Figg_rofi' - character(len=*), parameter :: field_out_rofi_to_ocn = 'Fogg_rofi' - character(len=*), parameter :: field_out_rofl_to_ocn = 'Fogg_rofl' - - character(*) , parameter :: nullstr = 'null' - character(*) , parameter :: rpfile = 'rpointer.glc' - character(*) , parameter :: u_FILE_u = & - __FILE__ + use ESMF , only : ESMF_State, ESMF_LOGMSG_INFO, ESMF_LogWrite, ESMF_SUCCESS + use ESMF , only : ESMF_Mesh, ESMF_DistGrid, ESMF_FieldBundle, ESMF_Field + use ESMF , only : ESMF_FieldBundleCreate, ESMF_FieldCreate, ESMF_MeshLoc_Element + use ESMF , only : ESMF_FieldBundleAdd, ESMF_MeshGet, ESMF_DistGridGet, ESMF_Typekind_R8 + use NUOPC , only : NUOPC_Advertise, NUOPC_AddNestedState + use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs + use shr_sys_mod , only : shr_sys_abort + use dshr_methods_mod , only : dshr_state_getfldptr, dshr_fldbun_getfldptr, chkerr + use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add + use dshr_strdata_mod , only : shr_strdata_type + use pio , only : file_desc_t, io_desc_t, var_desc_t, PIO_BCAST_ERROR, PIO_NOWRITE + use pio , only : pio_openfile, pio_inq_varid, pio_inq_varndims, pio_inq_vardimid + use pio , only : pio_inq_dimlen, pio_initdecomp, pio_read_darray, pio_double + use pio , only : pio_closefile, pio_freedecomp, pio_subsystem_t + + implicit none + private ! except + + public :: dglc_datamode_noevolve_advertise + public :: dglc_datamode_noevolve_init_pointers + public :: dglc_datamode_noevolve_advance + + integer :: num_icesheets + + ! export fields + type icesheet_ptr_t + real(r8), pointer :: ptr(:) => null() ! pointer to array + endtype icesheet_ptr_t + type(icesheet_ptr_t), allocatable :: Sg_area(:) + type(icesheet_ptr_t), allocatable :: Sg_topo(:) + type(icesheet_ptr_t), allocatable :: Sg_ice_covered(:) + type(icesheet_ptr_t), allocatable :: Sg_icemask(:) + + character(len=*), parameter :: field_in_tsrf = 'Sl_tsrf' + character(len=*), parameter :: field_in_qice = 'Flgl_qice' + + character(len=*), parameter :: field_out_area = 'Sg_area' + character(len=*), parameter :: field_out_ice_covered = 'Sg_ice_covered' + character(len=*), parameter :: field_out_topo = 'Sg_topo' + character(len=*), parameter :: field_out_icemask = 'Sg_icemask' + character(len=*), parameter :: field_out_icemask_coupled_fluxes = 'Sg_icemask_coupled_fluxes' + + character(len=*), parameter :: field_out_hflx_to_lnd = 'Flgg_hflx' + character(len=*), parameter :: field_out_rofi_to_ice = 'Figg_rofi' + character(len=*), parameter :: field_out_rofi_to_ocn = 'Fogg_rofi' + character(len=*), parameter :: field_out_rofl_to_ocn = 'Fogg_rofl' + + character(*) , parameter :: nullstr = 'null' + character(*) , parameter :: rpfile = 'rpointer.glc' + + character(*) , parameter :: u_FILE_u = & + __FILE__ !=============================================================================== contains @@ -54,226 +59,168 @@ module dglc_datamode_noevolve_mod subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_name, rc) - ! input/output variables - type(esmf_State) , intent(inout) :: NstateExp(num_icesheets_in) - type(fldlist_type) , pointer :: fldsexport - character(len=*) , intent(in) :: flds_scalar_name - integer , intent(out) :: rc - - ! local variables - integer :: nf,ns - character(len=CS) :: cnum - character(len=CL) :: cvalue - character(len=CL) :: logmsg - logical :: isPresent, isSet - type(fldlist_type), pointer :: fldList - !------------------------------------------------------------------------------- - - rc = ESMF_SUCCESS - - !-------------------------------- - ! Create nested state for active ice sheets only - !-------------------------------- - - num_icesheets = size(NStateExp) - - do ns = 1,num_icesheets - write(cnum,'(i0)') ns - call NUOPC_AddNestedState(importState, CplSet="GLC"//trim(cnum), nestedState=NStateImp(ns), rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call NUOPC_AddNestedState(exportState, CplSet="GLC"//trim(cnum), nestedState=NStateExp(ns), rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end do - - ! Advertise export fields - call dshr_fldList_add(fldsExport, trim(flds_scalar_name)) - call dshr_fldList_add(fldsExport, field_out_ice_covered) - call dshr_fldList_add(fldsExport, field_out_topo) - call dshr_fldList_add(fldsExport, field_out_icemask) - call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) - - do ns = 1,num_icesheets - fldlist => fldsExport ! the head of the linked list - do while (associated(fldlist)) - call NUOPC_Advertise(NStateExp(ns), standardName=fldlist%stdname, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ns == 1) then - call ESMF_LogWrite('(dglc_comp_advertise): Fr_glc'//trim(fldList%stdname), ESMF_LOGMSG_INFO) - end if - fldList => fldList%next - end do - enddo - - end subroutine dglc_datamode_noevolve_advertise - - !=============================================================================== - subroutine dglc_datamode_noevolve_init_pointers(NStateExport, rc) - - ! input/output variables - type(ESMF_State) , intent(inout) :: NStateExport(:) - integer , intent(out) :: rc - - ! local variables - character(len=*), parameter :: subname='(dglc_init_pointers): ' - !------------------------------------------------------------------------------- - - rc = ESMF_SUCCESS - - ! So this is tricky since you need pointers to fields in the nested state - ! So this will have to be done below in a loop - - ! initialize pointers to export fields - allocate(Sg_area(num_icesheets)) - allocate(Sg_topo(num_icesheets)) - allocate(Sg_ice_covered(num_icesheets)) - allocate(Sg_icemask(num_icesheets)) - - do ns = 1,num_icesheets - call dshr_state_getfldptr(NStateExport, 'Sg_topo', fldptr1=Sg_topo(ns)%ptr, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end do - - end subroutine dglc_datamode_noevolve_init_pointers - - !=============================================================================== - subroutine dglc_datamode_noevolve_advance(sdat, mesh, fileName_data, thickness, topo, rc) - - ! Assume that the model mesh is the same as the input data mesh - - ! input/output variables - integer, intent(out) :: rc - - ! local variables - character(len=*), parameter :: subname='(dglc_datamode_noevolve_advance): ' - !------------------------------------------------------------------------------- - - ! input/output variables - type(shr_strdata_type) , intent(in) :: sdat - type(ESMF_Mesh) , intent(in) :: mesh ! mesh read in from fileName_mesh - character(*) , intent(in) :: fileName_data ! file name string - real(R8) , pointer :: thickness(:) ! ice thickness - real(R8) , pointer :: topo(:) ! topography - integer , intent(out) :: rc - - ! local variables - type(ESMF_DistGrid) :: distgrid - type(ESMF_FieldBundle) :: fldbun_src - type(ESMF_Field) :: field_src - integer :: lsize - integer, pointer :: gindex(:) ! domain decomposition of data - integer :: ndims ! number of dims - integer, allocatable :: dimid(:) - type(var_desc_t) :: varid - type(file_desc_t) :: pioid - type(io_desc_t) :: pio_iodesc - integer :: rcode - integer :: nxg, nyg - real(r8), pointer :: data(:) - integer :: srcTermProcessing_Value = 0 - character(*) ,parameter :: subName = '(datm_get_adjustment_factors) ' - !------------------------------------------------------------------------------- - - rc = ESMF_SUCCESS - - ! Create input - fldbun_src = ESMF_FieldBundleCreate(rc=rc) ! input field bundle - - ! "ice thickness" ; - field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='thk', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! "bed topography" ; - field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='topg', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! "area" - field_src = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, name='area', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_src, (/field_src/), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! Get mesh info - call ESMF_MeshGet(mesh, elementdistGrid=distGrid, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - allocate(gindex(lsize)) - call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=gindex, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - ! Create_pio_iodesc - rcode = pio_openfile(sdat%pio_subsystem, pioid, sdat%io_type, trim(filename_data), pio_nowrite) - call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) - rcode = pio_inq_varid(pioid, 'thk', varid) - rcode = pio_inq_varndims(pioid, varid, ndims) - allocate(dimid(ndims)) - rcode = pio_inq_varid(pioid, 'topg', varid) - rcode = pio_inq_vardimid(pioid, varid, dimid(1:ndims)) - rcode = pio_inq_dimlen(pioid, dimid(1), nxg) - rcode = pio_inq_dimlen(pioid, dimid(2), nyg) - call pio_initdecomp(sdat%pio_subsystem, pio_double, (/nxg,nyg/), gindex, pio_iodesc) - deallocate(gindex) - - ! Read in the data into the appropriate field bundle pointers - call dshr_fldbun_getFldPtr(fldbun_src, 'thk', data, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - rcode = pio_inq_varid(pioid, 'thk', varid) - call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) - - call dshr_fldbun_getFldPtr(fldbun_src, 'topg', data, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - rcode = pio_inq_varid(pioid, 'topg', varid) - call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) - - call pio_closefile(pioid) - call pio_freedecomp(sdat%pio_subsystem, pio_iodesc) - call ESMF_RouteHandleDestroy(route_handle, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - - - - - - end subroutine dglc_datamode_noevolve_advance - - !=============================================================================== - subroutine dglc_datamode_noevolve_restart_write(case_name, inst_suffix, ymd, tod, & - logunit, my_task, sdat) - - ! input/output variables - character(len=*) , intent(in) :: case_name - character(len=*) , intent(in) :: inst_suffix - integer , intent(in) :: ymd ! model date - integer , intent(in) :: tod ! model sec into model date - integer , intent(in) :: logunit - integer , intent(in) :: my_task - type(shr_strdata_type) , intent(inout) :: sdat - !------------------------------------------------------------------------------- - - call dshr_restart_write(rpfile, case_name, 'dglc', inst_suffix, ymd, tod, & - logunit, my_task, sdat) - - end subroutine dglc_datamode_noevolve_restart_write - - !=============================================================================== - subroutine dglc_datamode_noevolve_restart_read(rest_filem, inst_suffix, logunit, my_task, mpicom, sdat) - - ! input/output arguments - character(len=*) , intent(inout) :: rest_filem - character(len=*) , intent(in) :: inst_suffix - integer , intent(in) :: logunit - integer , intent(in) :: my_task - integer , intent(in) :: mpicom - type(shr_strdata_type) , intent(inout) :: sdat - !------------------------------------------------------------------------------- - - call dshr_restart_read(rest_filem, rpfile, inst_suffix, nullstr, logunit, my_task, mpicom, sdat) - - end subroutine dglc_datamode_noevolve_restart_read + ! input/output variables + type(ESMF_State) , intent(inout) :: NStateExp(:) + type(fldlist_type) , pointer :: fldsexport + character(len=*) , intent(in) :: flds_scalar_name + integer , intent(out) :: rc + + ! local variables + integer :: ns + logical :: isPresent, isSet + type(fldlist_type), pointer :: fldList + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + !-------------------------------- + ! Create nested state for active ice sheets only + !-------------------------------- + + ! Set module variable for number of ice sheets + num_icesheets = size(NStateExp) + + ! Advertise export fields + call dshr_fldList_add(fldsExport, trim(flds_scalar_name)) + call dshr_fldList_add(fldsExport, field_out_ice_covered) + call dshr_fldList_add(fldsExport, field_out_topo) + call dshr_fldList_add(fldsExport, field_out_icemask) + Call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) + + do ns = 1,num_icesheets + fldlist => fldsExport ! the head of the linked list + do while (associated(fldlist)) + call NUOPC_Advertise(NStateExp(ns), standardName=fldlist%stdname, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (ns == 1) then + call ESMF_LogWrite('(dglc_comp_advertise): Fr_glc'//trim(fldList%stdname), ESMF_LOGMSG_INFO) + end if + fldList => fldList%next + end do + enddo + + end subroutine dglc_datamode_noevolve_advertise + + !=============================================================================== + subroutine dglc_datamode_noevolve_init_pointers(NStateExp, rc) + + ! input/output variables + type(ESMF_State) , intent(inout) :: NStateExp(:) + integer , intent(out) :: rc + + ! local variables + integer :: ns + character(len=*), parameter :: subname='(dglc_init_pointers): ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! So this is tricky since you need pointers to fields in the nested state + ! So this will have to be done below in a loop + + ! initialize pointers to export fields + allocate(Sg_area(num_icesheets)) + allocate(Sg_topo(num_icesheets)) + allocate(Sg_ice_covered(num_icesheets)) + allocate(Sg_icemask(num_icesheets)) + + do ns = 1,num_icesheets + call dshr_state_getfldptr(NStateExp(ns), 'Sg_topo' , fldptr1=Sg_topo(ns)%ptr , rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(NStateExp(ns), 'Sg_ice_covered' , fldptr1=Sg_ice_covered(ns)%ptr , rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(NStateExp(ns), 'Sg_icemask' , fldptr1=Sg_icemask(ns)%ptr , rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end do + + end subroutine dglc_datamode_noevolve_init_pointers + + !=============================================================================== + subroutine dglc_datamode_noevolve_advance(ns, pio_subsystem, io_type, io_format, & + model_mesh, input_file, rc) + + ! Assume that the model mesh is the same as the input data mesh + + ! input/output variables + integer , intent(in) :: ns ! ice sheet index + type(iosystem_desc_t) , pointer :: pio_subsystem ! pio info + integer , intent(in) :: io_type ! pio info + integer , intent(in) :: io_format ! pio info + type(ESMF_Mesh) , intent(in) :: model_mesh ! mesh read in from fileName_mesh + character(len=*) , intent(in) :: input_file ! file name string + integer , intent(out) :: rc + + ! local variables + type(ESMF_FieldBundle) :: fldbun_noevolve + type(file_desc_t) :: pioid + type(io_desc_t) :: pio_iodesc + type(ESMF_DistGrid) :: distgrid + type(ESMF_Field) :: field_noevolve + integer :: lsize + integer, pointer :: gindex(:) ! domain decomposition of data + integer :: ndims ! number of dims + integer, allocatable :: dimid(:) + type(var_desc_t) :: varid + integer :: rcode + integer :: nxg, nyg + real(r8), pointer :: data(:) + character(len=*), parameter :: subname='(dglc_datamode_noevolve_advance): ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Create module level field bundle + fldbun_noevolve = ESMF_FieldBundleCreate(rc=rc) ! input field bundle + + ! "ice thickness" ; + field_noevolve = ESMF_FieldCreate(model_mesh, ESMF_TYPEKIND_R8, name='thk', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! "bed topography" ; + field_noevolve = ESMF_FieldCreate(model_mesh, ESMF_TYPEKIND_R8, name='topg', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Get mesh info + call ESMF_MeshGet(model_mesh, elementdistGrid=distGrid, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(gindex(lsize)) + call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=gindex, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Create pioid and pio_iodesc at the module level + call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) + rcode = pio_openfile(pio_subsystem, pioid, io_type, trim(input_file), pio_nowrite) + rcode = pio_inq_varid(pioid, 'thk', varid) + rcode = pio_inq_varndims(pioid, varid, ndims) + allocate(dimid(ndims)) + rcode = pio_inq_vardimid(pioid, varid, dimid(1:ndims)) + rcode = pio_inq_dimlen(pioid, dimid(1), nxg) + rcode = pio_inq_dimlen(pioid, dimid(2), nyg) + call pio_initdecomp(pio_subsystem, pio_double, (/nxg,nyg/), gindex, pio_iodesc) + deallocate(gindex) + + ! Read in the data into the appropriate field bundle pointers + call dshr_fldbun_getFldPtr(fldbun_noevolve, 'thk', data, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + rcode = pio_inq_varid(pioid, 'thk', varid) + call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) + Sg_ice_covered(ns)%ptr(:) = data(:) + + call dshr_fldbun_getFldPtr(fldbun_noevolve, 'topg', data, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + rcode = pio_inq_varid(pioid, 'topg', varid) + call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) + Sg_topo(ns)%ptr(:) = data(:) + + call pio_closefile(pioid) + call pio_freedecomp(pio_subsystem, pio_iodesc) + + end subroutine dglc_datamode_noevolve_advance end module dglc_datamode_noevolve_mod diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index 8b4257fe3..586404a35 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -7,7 +7,7 @@ module cdeps_dglc_comp !---------------------------------------------------------------------------- ! This is the NUOPC cap for DGLC !---------------------------------------------------------------------------- - use ESMF , only : ESMF_VM, ESMF_VMBroadcast, ESMF_GridCompGet + use ESMF , only : ESMF_VM, ESMF_VmGet, ESMF_VMBroadcast, ESMF_GridCompGet use ESMF , only : ESMF_Mesh, ESMF_GridComp, ESMF_State, ESMF_Clock, ESMF_Time use ESMF , only : ESMF_SUCCESS, ESMF_LogWrite, ESMF_LOGMSG_INFO, ESMF_METHOD_INITIALIZE use ESMF , only : ESMF_TraceRegionEnter, ESMF_TraceRegionExit, ESMF_ClockGet @@ -16,8 +16,10 @@ module cdeps_dglc_comp use ESMF , only : ESMF_GridCompSetEntryPoint, ESMF_ClockGetAlarm, ESMF_AlarmIsRinging use ESMF , only : ESMF_StateGet, operator(+), ESMF_AlarmRingerOff, ESMF_LogWrite use ESMF , only : ESMF_Field, ESMF_FieldGet, ESMF_VmLogMemInfo + use ESMF , only : ESMF_MeshCreate, ESMF_FILEFORMAT_ESMFMESH use NUOPC , only : NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize use NUOPC , only : NUOPC_Advertise, NUOPC_CompAttributeGet, NUOPC_CompAttributeSet + use NUOPC , only : NUOPC_AddNestedState use NUOPC_Model , only : model_routine_SS => SetServices use NUOPC_Model , only : model_label_Advance => label_Advance use NUOPC_Model , only : model_label_SetRunClock => label_SetRunClock @@ -27,6 +29,8 @@ module cdeps_dglc_comp use shr_sys_mod , only : shr_sys_abort use shr_cal_mod , only : shr_cal_ymd2date use shr_log_mod , only : shr_log_setLogUnit + use shr_string_mod , only : shr_string_listgetnum + use shr_pio_mod , only : shr_pio_getiosys, shr_pio_getiotype, shr_pio_getioformat use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init @@ -38,8 +42,6 @@ module cdeps_dglc_comp use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_advertise use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_init_pointers use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_advance - use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_restart_read - use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_restart_write implicit none private ! except @@ -57,10 +59,14 @@ module cdeps_dglc_comp !-------------------------------------------------------------------------- ! module variables for multiple ice sheets + type(shr_strdata_type) , allocatable :: sdat(:) type(ESMF_State) , allocatable :: NStateImp(:) type(ESMF_State) , allocatable :: NStateExp(:) - type(shr_strdata_type) , allocatable :: sdat(:) - type(ESMF_Mesh) , allocatable :: model_mesh(:) + type(ESMF_Mesh) , allocatable :: model_meshes(:) + character(CL) , allocatable :: model_meshfiles(:) + character(CS) , allocatable :: icesheet_names(:) + integer , allocatable :: nx_global(:) + integer , allocatable :: ny_global(:) ! module variables common to all data models character(CS) :: flds_scalar_name = '' @@ -69,7 +75,7 @@ module cdeps_dglc_comp integer :: flds_scalar_index_ny = 0 integer :: mpicom ! mpi communicator integer :: my_task ! my task in mpi communicator mpicom - logical :: mainproc ! true of my_task == main_task + logical :: mainproc ! true of my_task == main_task character(len=16) :: inst_suffix = "" ! char string associated with instance (ie. "_0001" or "") integer :: logunit ! logging unit number logical :: restart_read ! start from restart @@ -77,15 +83,11 @@ module cdeps_dglc_comp character(*) , parameter :: nullstr = 'null' ! dglc_in namelist input - integer ,parameter :: max_icesheets = 10 integer :: num_icesheets = 0 + character(ESMF_MAXSTR) :: model_meshfiles_list ! colon separated string containing model meshfiles character(CL) :: streamfilename = nullstr ! filename to obtain stream info from character(CL) :: nlfilename = nullstr ! filename to obtain namelist info from character(CL) :: datamode = nullstr ! flags physics options wrt input data - character(CS) :: icesheet_names(max_icesheets) - integer :: nx_global(max_ice_sheets) = -999 - integer :: ny_global(max_ice_sheets) = -999 - character(CL) :: model_meshfile(max_icesheets) = nullstr ! full pathname to model meshfile character(CL) :: restfilm = nullstr ! model restart file namelist logical :: skip_restart_read = .false. ! true => skip restart read in continuation run logical :: export_all = .false. ! true => export all fields, do not check connected or not @@ -171,11 +173,11 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) integer, intent(out) :: rc ! local variables + type(ESMF_VM) :: vm integer :: inst_index ! number of current instance (ie. 1) integer :: nu ! unit number integer :: ierr ! error code integer :: bcasttmp(1) - type(ESMF_VM) :: vm integer :: ns, n character(len=CS) :: cnum character(len=*),parameter :: subname=trim(module_name)//':(InitializeAdvertise) ' @@ -185,7 +187,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) !num_icesheets = 2 namelist / dglc_nml / datamode, & - model_meshfile, ice_sheet_names, nx_global, ny_global, + ice_sheet_names, model_meshfiles_list, nx_global, ny_global, & restfilm, skip_restart_read rc = ESMF_SUCCESS @@ -217,11 +219,13 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! write namelist input to standard out write(logunit,'(a,a)')' case_name = ',trim(case_name) write(logunit,'(a,a)')' datamode = ',trim(datamode) - do ns = 1,max_ice_sheets - if (model_meshfile(n) == nullstr) exit - num_icesheets = num_icesheets + 1 + + num_icesheets = shr_string_listGetNum(model_meshfiles_list) + do ns = 1,num_icesheets + ! determine mesh filename + call shr_string_listGetName(model_meshfiles_list, ns, model_meshfile(ns)) write(logunit,'(a,i4 )')' ice_sheet index = ',ns - write(logunit,'(a,a )')' model_meshfile = ',trim(model_meshfile(ns)) + write(logunit,'(a,a )')' model_meshfile = ',trim(model_meshfiles(ns)) write(logunit,'(a,i10)')' nx_global = ',nx_global(ns) write(logunit,'(a,i10)')' ny_global = ',ny_global(ns) end do @@ -242,7 +246,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call ESMF_VMBroadcast(vm, restfilm, CL, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return do ns = 1,num_icesheets - call ESMF_VMBroadcast(vm, model_meshfile(n), CL, main_task, rc=rc) + call ESMF_VMBroadcast(vm, model_meshfiles(ns), CL, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, nx_global(ns), 1, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -253,7 +257,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Validate datamode - if ( trim(datamode) == 'noevolve') ! read stream, no import data + if ( trim(datamode) == 'noevolve') then ! read stream, no import data + ! do nothing else call shr_sys_abort(' ERROR illegal dglc datamode = '//trim(datamode)) endif @@ -262,7 +267,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) allocate(NStateImp(num_icesheets)) allocate(NStateExp(num_icesheets)) allocate(sdat(num_icesheets)) - allocate(model_mesh(num_icesheets)) + allocate(model_meshes(num_icesheets)) allocate(dfields_icesheets(num_icesheets)) ! Create nested states @@ -276,7 +281,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Advertise dglc fields if (trim(datamode)=='noevolve') then - call dglc_datamode_noevolve_advertise(exportState, fldsExport, flds_scalar_name, rc) + call dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_name, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -291,20 +296,20 @@ subroutine InitializeRealize(gcomp, clock, rc) integer, intent(out) :: rc ! local variables - type(ESMF_Time) :: currTime - integer :: current_ymd ! model date - integer :: current_year ! model year - integer :: current_mon ! model month - integer :: current_day ! model day - integer :: current_tod ! model sec into model date - type(ESMF_Field) :: lfield - character(CL) ,pointer :: lfieldnamelist(:) => null() - integer :: fieldcount - real(r8), pointer :: fldptr(:) - integer :: n - integer :: imask - real(r8) :: rmask - character(CL) :: cvalue + type(ESMF_VM) :: vm + type(ESMF_Time) :: currTime + integer :: current_ymd ! model date + integer :: current_year ! model year + integer :: current_mon ! model month + integer :: current_day ! model day + integer :: current_tod ! model sec into model date + integer :: localpet + integer :: n, ns + character(CL) :: cvalue + character(CS) :: cns + logical :: ispresent, isset + logical :: read_restart + logical :: exists character(len=*), parameter :: subname=trim(module_name)//':(InitializeRealize) ' !------------------------------------------------------------------------------- @@ -339,6 +344,7 @@ subroutine InitializeRealize(gcomp, clock, rc) ! Loop over ice sheets do ns = 1,num_icesheets + write(cns,'(i0)') ns ! Initialize pio subsystem @@ -352,20 +358,23 @@ subroutine InitializeRealize(gcomp, clock, rc) ! Check that model_meshfile exists if (my_task == main_task) then - inquire(file=trim(model_meshfile(ns)), exist=exists) + inquire(file=trim(model_meshfiles(ns)), exist=exists) if (.not.exists) then - write(logunit, *)' ERROR: model_meshfile '//trim(model_meshfile)//' does not exist' - call shr_sys_abort(trim(subname)//' ERROR: model_meshfile '//trim(model_meshfile)//' does not exist') + write(logunit,'(a)')' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist' + call shr_sys_abort(trim(subname)//' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist') end if endif ! Read in model mesh - model_mesh(ns) = ESMF_MeshCreate(trim(model_meshfile(ns)), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + model_meshes(ns) = ESMF_MeshCreate(trim(model_meshfiles(ns)), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Initialize stream data type - call shr_strdata_init_from_config(sdat(ns), streamfilename, model_mesh(ns), clock, 'GLC', logunit, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (trim(datamode) /= 'noevolve') then + call shr_strdata_init_from_config(sdat(ns), streamfilename, model_meshes(ns), clock, 'GLC', logunit, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + call ESMF_TraceRegionExit('dglc_strdata_init') ! Realize the actively coupled fields, now that a mesh is established and @@ -482,7 +491,7 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) call ESMF_TraceRegionEnter('DGLC_RUN') ! Loop over ice sheets - do ns = 1,size(NStateImp) + do ns = 1,size(NStateExp) !-------------------- ! First time initialization @@ -490,8 +499,10 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) if (first_time) then ! Initialize dfields for given ice sheet - call dglc_init_dfields(NStateImp(ns), NStateExp(ns), rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (trim(datamode) /= 'noevolve') then + call dglc_init_dfields(ns, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if ! Initialize datamode module ponters select case (trim(datamode)) @@ -501,12 +512,11 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) end select ! Read restart if needed - ! if (restart_read .and. .not. skip_restart_read) then - ! select case (trim(datamode)) - ! case('noevolve') - ! call dglc_datamode_copyall_restart_read(restfilm, inst_suffix, logunit, my_task, mpicom, sdat(ns)) - ! end select - ! end if + if (trim(datamode) /= 'noevolve') then + if (restart_read .and. .not. skip_restart_read) then + ! placeholder for future datamodes + end if + end if ! Reset first_time first_time = .false. @@ -516,18 +526,20 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) ! Update export (and possibly import data model states) !-------------------- - ! Advance data model streams - time and spatially interpolate to model time and grid - call ESMF_TraceRegionEnter('dglc_strdata_advance') - call shr_strdata_advance(sdat(ns), target_ymd, target_tod, logunit, 'dglc', rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_TraceRegionExit('dglc_strdata_advance') + if (trim(datamode) /= 'noevolve') then + ! Advance data model streams - time and spatially interpolate to model time and grid + call ESMF_TraceRegionEnter('dglc_strdata_advance') + call shr_strdata_advance(sdat(ns), target_ymd, target_tod, logunit, 'dglc', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TraceRegionExit('dglc_strdata_advance') - ! Copy all fields from streams to export state as default - ! This automatically will update the fields in the export state - call ESMF_TraceRegionEnter('dglc_dfield_copy') - call dshr_dfield_copy(dfields_icesheets(ns)%dfields, sdat(ns), rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_TraceRegionExit('dglc_dfield_copy') + ! Copy all fields from streams to export state as default + ! This automatically will update the fields in the export state + call ESMF_TraceRegionEnter('dglc_dfield_copy') + call dshr_dfield_copy(dfields_icesheets(ns)%dfields, sdat(ns), rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TraceRegionExit('dglc_dfield_copy') + end if ! Perform data mode specific calculations select case (trim(datamode)) @@ -538,11 +550,9 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) ! Write restarts if needed if (restart_write) then - select case (trim(datamode)) - case('noevolve') - call dglc_datamode_noevolve_restart_write(case_name, inst_suffix, target_ymd, target_tod, & - logunit, my_task, sdat(ns)) - end select + if (trim(datamode) /= 'evolve') then + ! this is a place holder for future datamode + end if end if ! Write diagnostics @@ -572,7 +582,7 @@ subroutine dglc_init_dfields(ns, rc) integer :: fieldcount type(ESMF_Field) :: lfield character(ESMF_MAXSTR) ,pointer :: lfieldnamelist(:) - character(*), parameter :: subName = "(dglc_init_dfields) " + character(*), parameter :: subName = "(dglc_init_dfields) " !------------------------------------------------------------------------------- rc = ESMF_SUCCESS From 1f42d9c8c3e16a1699d1bc8d75792d9610673848 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 20 Mar 2024 12:26:41 +0100 Subject: [PATCH 05/27] more compilation fixes --- dglc/cime_config/buildlib | 54 -- dglc/cime_config/namelist_definition_dglc.xml | 18 +- dglc/dglc_datamode_noevolve_mod.F90 | 135 ++--- dglc/glc_comp_nuopc.F90 | 465 +++++++++--------- 4 files changed, 333 insertions(+), 339 deletions(-) delete mode 100755 dglc/cime_config/buildlib diff --git a/dglc/cime_config/buildlib b/dglc/cime_config/buildlib deleted file mode 100755 index 281f0d4e9..000000000 --- a/dglc/cime_config/buildlib +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 - -""" -build cime component model library. This buildlib script is used by all CDEPS components. -""" - -import sys, os - -_CIMEROOT = os.environ.get("CIMEROOT") -if _CIMEROOT is None: - raise SystemExit("ERROR: must set CIMEROOT environment variable") -sys.path.append(os.path.join(_CIMEROOT, "CIME", "Tools")) - -_LIBDIR = os.path.join(_CIMEROOT, "CIME") -sys.path.append(_LIBDIR) - -from standard_script_setup import * -from CIME.buildlib import parse_input -from CIME.case import Case -from CIME.utils import run_cmd, symlink_force, expect - -# pragma pylint: disable=unused-argument,undefined-variable - -logger = logging.getLogger(__name__) - - -def buildlib(bldroot, libroot, case, compname=None): - if not compname: - expect( - bldroot.endswith("obj"), - "It appears that buildlib_comps is being called for the main CDEPS build\n" - "(the main CDEPS build should use buildlib, not buildlib_comps)", - ) - compname = os.path.basename(os.path.abspath(os.path.join(bldroot, os.pardir))) - - _, o, e = run_cmd("make d{}".format(compname), from_dir=bldroot, verbose=True) - libname = "lib{}.a".format(compname) - dlibname = "libd{}.a".format(compname) - dlibpath = os.path.join(bldroot, dlibname) - if os.path.exists(dlibpath): - symlink_force(os.path.join(bldroot, dlibname), os.path.join(libroot, libname)) - else: - expect(False, "ERROR in {} build {} {}".format(compname, o, e)) - logger.info(f"build successful for comp={compname}") - - -def _main_func(args): - caseroot, libroot, bldroot = parse_input(args) - with Case(caseroot) as case: - buildlib(bldroot, libroot, case) - - -if __name__ == "__main__": - _main_func(sys.argv) diff --git a/dglc/cime_config/namelist_definition_dglc.xml b/dglc/cime_config/namelist_definition_dglc.xml index 2fabb50a8..0041e88af 100644 --- a/dglc/cime_config/namelist_definition_dglc.xml +++ b/dglc/cime_config/namelist_definition_dglc.xml @@ -35,6 +35,22 @@ + + char + streams + abs + dglc_nml + + $DIN_LOC_ROOT/glc/cism/Antarctica/ISMIP6_Antarctica_8km.init.c210908.nc:$DIN_LOC_ROOT/glc/cism/Greenland/greenland_4km_epsg3413_c171126.nc + $DIN_LOC_ROOT/glc/cism/Greenland/gland20.input_c150415.nc + $DIN_LOC_ROOT/glc/cism/Greenland/greenland_4km_epsg3413_c171126.nc + $DIN_LOC_ROOT/glc/cism/Antarctica/ISMIP6_Antarctica_8km.init.c210908.nc + + + colon deliminted string of inputdata files + + + char streams @@ -44,7 +60,7 @@ $GLC_DOMAIN_MESH - file(s) specifying model mesh + colon deliminted string of file(s) specifying model mesh for more than one ice sheets this will contain an array of mesh file names diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index 3e06254fc..03ba9d4b3 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -10,10 +10,10 @@ module dglc_datamode_noevolve_mod use dshr_methods_mod , only : dshr_state_getfldptr, dshr_fldbun_getfldptr, chkerr use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add use dshr_strdata_mod , only : shr_strdata_type - use pio , only : file_desc_t, io_desc_t, var_desc_t, PIO_BCAST_ERROR, PIO_NOWRITE + use pio , only : file_desc_t, io_desc_t, var_desc_t, iosystem_desc_t use pio , only : pio_openfile, pio_inq_varid, pio_inq_varndims, pio_inq_vardimid use pio , only : pio_inq_dimlen, pio_initdecomp, pio_read_darray, pio_double - use pio , only : pio_closefile, pio_freedecomp, pio_subsystem_t + use pio , only : pio_closefile, pio_freedecomp, PIO_BCAST_ERROR, PIO_NOWRITE implicit none private ! except @@ -136,26 +136,26 @@ subroutine dglc_datamode_noevolve_init_pointers(NStateExp, rc) end subroutine dglc_datamode_noevolve_init_pointers !=============================================================================== - subroutine dglc_datamode_noevolve_advance(ns, pio_subsystem, io_type, io_format, & - model_mesh, input_file, rc) + subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & + model_meshes, input_files, rc) ! Assume that the model mesh is the same as the input data mesh ! input/output variables - integer , intent(in) :: ns ! ice sheet index - type(iosystem_desc_t) , pointer :: pio_subsystem ! pio info - integer , intent(in) :: io_type ! pio info - integer , intent(in) :: io_format ! pio info - type(ESMF_Mesh) , intent(in) :: model_mesh ! mesh read in from fileName_mesh - character(len=*) , intent(in) :: input_file ! file name string + type(iosystem_desc_t) , pointer :: pio_subsystem ! pio info + integer , intent(in) :: io_type ! pio info + integer , intent(in) :: io_format ! pio info + type(ESMF_Mesh) , intent(in) :: model_meshes(:) ! ice sheets meshes + character(len=*) , intent(in) :: input_files(:) ! input file names integer , intent(out) :: rc ! local variables type(ESMF_FieldBundle) :: fldbun_noevolve - type(file_desc_t) :: pioid - type(io_desc_t) :: pio_iodesc type(ESMF_DistGrid) :: distgrid type(ESMF_Field) :: field_noevolve + type(file_desc_t) :: pioid + type(io_desc_t) :: pio_iodesc + integer :: ns ! ice sheet index integer :: lsize integer, pointer :: gindex(:) ! domain decomposition of data integer :: ndims ! number of dims @@ -169,57 +169,66 @@ subroutine dglc_datamode_noevolve_advance(ns, pio_subsystem, io_type, io_format, rc = ESMF_SUCCESS - ! Create module level field bundle - fldbun_noevolve = ESMF_FieldBundleCreate(rc=rc) ! input field bundle - - ! "ice thickness" ; - field_noevolve = ESMF_FieldCreate(model_mesh, ESMF_TYPEKIND_R8, name='thk', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! "bed topography" ; - field_noevolve = ESMF_FieldCreate(model_mesh, ESMF_TYPEKIND_R8, name='topg', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - - ! Get mesh info - call ESMF_MeshGet(model_mesh, elementdistGrid=distGrid, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - allocate(gindex(lsize)) - call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=gindex, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - ! Create pioid and pio_iodesc at the module level - call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) - rcode = pio_openfile(pio_subsystem, pioid, io_type, trim(input_file), pio_nowrite) - rcode = pio_inq_varid(pioid, 'thk', varid) - rcode = pio_inq_varndims(pioid, varid, ndims) - allocate(dimid(ndims)) - rcode = pio_inq_vardimid(pioid, varid, dimid(1:ndims)) - rcode = pio_inq_dimlen(pioid, dimid(1), nxg) - rcode = pio_inq_dimlen(pioid, dimid(2), nyg) - call pio_initdecomp(pio_subsystem, pio_double, (/nxg,nyg/), gindex, pio_iodesc) - deallocate(gindex) - - ! Read in the data into the appropriate field bundle pointers - call dshr_fldbun_getFldPtr(fldbun_noevolve, 'thk', data, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - rcode = pio_inq_varid(pioid, 'thk', varid) - call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) - Sg_ice_covered(ns)%ptr(:) = data(:) - - call dshr_fldbun_getFldPtr(fldbun_noevolve, 'topg', data, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - rcode = pio_inq_varid(pioid, 'topg', varid) - call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) - Sg_topo(ns)%ptr(:) = data(:) - - call pio_closefile(pioid) - call pio_freedecomp(pio_subsystem, pio_iodesc) + do ns = 1,num_icesheets + + ! Create module level field bundle + fldbun_noevolve = ESMF_FieldBundleCreate(rc=rc) ! input field bundle + + ! "ice thickness" ; + field_noevolve = ESMF_FieldCreate(model_meshes(ns), ESMF_TYPEKIND_R8, name='thk', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! "bed topography" ; + field_noevolve = ESMF_FieldCreate(model_meshes(ns), ESMF_TYPEKIND_R8, name='topg', meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Get mesh info + call ESMF_MeshGet(model_meshes(ns), elementdistGrid=distGrid, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(gindex(lsize)) + call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=gindex, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Create pioid and pio_iodesc at the module level + call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) + rcode = pio_openfile(pio_subsystem, pioid, io_type, trim(input_files(ns)), pio_nowrite) + rcode = pio_inq_varid(pioid, 'thk', varid) + rcode = pio_inq_varndims(pioid, varid, ndims) + allocate(dimid(ndims)) + rcode = pio_inq_vardimid(pioid, varid, dimid(1:ndims)) + rcode = pio_inq_dimlen(pioid, dimid(1), nxg) + rcode = pio_inq_dimlen(pioid, dimid(2), nyg) + call pio_initdecomp(pio_subsystem, pio_double, (/nxg,nyg/), gindex, pio_iodesc) + deallocate(gindex) + + ! Read in the data into the appropriate field bundle pointers + ! Note that Sg_ice_covered(ns)%ptr points into the data for + ! the Sg_ice_covered field in NStateExp(ns) + ! Note that Sg_topo(ns)%ptr points into the data for + ! the Sg_topon NStateExp(ns) + + call dshr_fldbun_getFldPtr(fldbun_noevolve, 'thk', data, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + rcode = pio_inq_varid(pioid, 'thk', varid) + call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) + Sg_ice_covered(ns)%ptr(:) = data(:) + + call dshr_fldbun_getFldPtr(fldbun_noevolve, 'topg', data, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + rcode = pio_inq_varid(pioid, 'topg', varid) + call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) + Sg_topo(ns)%ptr(:) = data(:) + + call pio_closefile(pioid) + call pio_freedecomp(pio_subsystem, pio_iodesc) + + end do ! end loop over ice sheets end subroutine dglc_datamode_noevolve_advance diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index 586404a35..428c77086 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -29,7 +29,7 @@ module cdeps_dglc_comp use shr_sys_mod , only : shr_sys_abort use shr_cal_mod , only : shr_cal_ymd2date use shr_log_mod , only : shr_log_setLogUnit - use shr_string_mod , only : shr_string_listgetnum + use shr_string_mod , only : shr_string_listGetNum, shr_string_listGetName use shr_pio_mod , only : shr_pio_getiosys, shr_pio_getiotype, shr_pio_getioformat use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config @@ -58,33 +58,38 @@ module cdeps_dglc_comp ! Private module data !-------------------------------------------------------------------------- + integer, parameter :: max_icesheets = 10 ! maximum number of ice sheets for namelist input + integer :: num_icesheets = 0 ! actual number of ice sheets + + ! namelist input + character(CS) :: icesheet_names(max_icesheets) + character(CL) :: model_meshfiles(max_icesheets) + character(CL) :: model_datafiles(max_icesheets) + integer :: nx_global(max_icesheets) + integer :: ny_global(max_icesheets) + ! module variables for multiple ice sheets type(shr_strdata_type) , allocatable :: sdat(:) type(ESMF_State) , allocatable :: NStateImp(:) type(ESMF_State) , allocatable :: NStateExp(:) type(ESMF_Mesh) , allocatable :: model_meshes(:) - character(CL) , allocatable :: model_meshfiles(:) - character(CS) , allocatable :: icesheet_names(:) - integer , allocatable :: nx_global(:) - integer , allocatable :: ny_global(:) ! module variables common to all data models - character(CS) :: flds_scalar_name = '' - integer :: flds_scalar_num = 0 - integer :: flds_scalar_index_nx = 0 - integer :: flds_scalar_index_ny = 0 - integer :: mpicom ! mpi communicator - integer :: my_task ! my task in mpi communicator mpicom - logical :: mainproc ! true of my_task == main_task - character(len=16) :: inst_suffix = "" ! char string associated with instance (ie. "_0001" or "") - integer :: logunit ! logging unit number - logical :: restart_read ! start from restart - character(CL) :: case_name - character(*) , parameter :: nullstr = 'null' + character(CS) :: flds_scalar_name = '' + integer :: flds_scalar_num = 0 + integer :: flds_scalar_index_nx = 0 + integer :: flds_scalar_index_ny = 0 + integer :: mpicom ! mpi communicator + integer :: my_task ! my task in mpi communicator mpicom + logical :: mainproc ! true of my_task == main_task + character(len=16) :: inst_suffix = "" ! char string associated with instance (ie. "_0001" or "") + integer :: logunit ! logging unit number + logical :: restart_read ! start from restart + character(CL) :: case_name + character(*) , parameter :: nullstr = 'null' ! dglc_in namelist input - integer :: num_icesheets = 0 - character(ESMF_MAXSTR) :: model_meshfiles_list ! colon separated string containing model meshfiles + character(CL) :: streamfilename = nullstr ! filename to obtain stream info from character(CL) :: nlfilename = nullstr ! filename to obtain namelist info from character(CL) :: datamode = nullstr ! flags physics options wrt input data @@ -180,14 +185,18 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) integer :: bcasttmp(1) integer :: ns, n character(len=CS) :: cnum + character(len=CL) :: icesheets_list + character(len=ESMF_MAXSTR) :: model_datafiles_list ! colon separated string containing input datafiles + character(len=ESMF_MAXSTR) :: model_meshfiles_list ! colon separated string containing model meshfiles character(len=*),parameter :: subname=trim(module_name)//':(InitializeAdvertise) ' !------------------------------------------------------------------------------- !icesheet_names = "ais", "gris" !num_icesheets = 2 + ! Note that the suffix '-list' refers to a colon delimited string of names namelist / dglc_nml / datamode, & - ice_sheet_names, model_meshfiles_list, nx_global, ny_global, & + icesheets_list, model_meshfiles_list, model_datafiles_list, nx_global, ny_global, & restfilm, skip_restart_read rc = ESMF_SUCCESS @@ -206,36 +215,44 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Read dglc_nml from nlfilename if (my_task == main_task) then - nlfilename = "dglc_in"//trim(inst_suffix) - open (newunit=nu,file=trim(nlfilename),status="old",action="read") - call shr_nl_find_group_name(nu, 'dglc_nml', status=ierr) - read (nu,nml=dglc_nml,iostat=ierr) - close(nu) - if (ierr > 0) then - write(logunit,'(a,i8)') 'ERROR: reading input namelist, '//trim(nlfilename)//' iostat=',ierr - call shr_sys_abort(subName//': namelist read error '//trim(nlfilename)) - end if - - ! write namelist input to standard out - write(logunit,'(a,a)')' case_name = ',trim(case_name) - write(logunit,'(a,a)')' datamode = ',trim(datamode) - - num_icesheets = shr_string_listGetNum(model_meshfiles_list) - do ns = 1,num_icesheets - ! determine mesh filename - call shr_string_listGetName(model_meshfiles_list, ns, model_meshfile(ns)) - write(logunit,'(a,i4 )')' ice_sheet index = ',ns - write(logunit,'(a,a )')' model_meshfile = ',trim(model_meshfiles(ns)) - write(logunit,'(a,i10)')' nx_global = ',nx_global(ns) - write(logunit,'(a,i10)')' ny_global = ',ny_global(ns) - end do - write(logunit,'(a,a )')' restfilm = ',trim(restfilm) - write(logunit,'(a,l6)')' skip_restart_read = ',skip_restart_read - if (skip_restart_read) then - bcasttmp = 1 - else - bcasttmp = 0 - end if + nlfilename = "dglc_in"//trim(inst_suffix) + open (newunit=nu,file=trim(nlfilename),status="old",action="read") + call shr_nl_find_group_name(nu, 'dglc_nml', status=ierr) + read (nu,nml=dglc_nml,iostat=ierr) + close(nu) + if (ierr > 0) then + write(logunit,'(a,i8)') 'ERROR: reading input namelist, '//trim(nlfilename)//' iostat=',ierr + call shr_sys_abort(subName//': namelist read error '//trim(nlfilename)) + end if + + ! Determine number of ice sheets + num_icesheets = shr_string_listGetNum(model_meshfiles_list) + + ! Determine array of model meshfile(s) and model input datafile(s) + do ns = 1,num_icesheets + ! determine mesh filename(s) + call shr_string_listGetName(model_meshfiles_list, ns, model_meshfiles(ns)) + ! determine input datafile name(s) + call shr_string_listGetName(model_datafiles_list, ns, model_datafiles(ns)) + end do + if (skip_restart_read) then + bcasttmp = 1 + else + bcasttmp = 0 + end if + + ! Write diagnostics + write(logunit,'(a,a)')' case_name = ',trim(case_name) + write(logunit,'(a,a)')' datamode = ',trim(datamode) + do ns = 1,num_icesheets + write(logunit,'(a,i4 )')' ice_sheet index = ',ns + write(logunit,'(a,a )')' model_meshfile = ',trim(model_meshfiles(ns)) + write(logunit,'(a,a )')' model_datafile = ',trim(model_datafiles(ns)) + write(logunit,'(a,i10)')' nx_global = ',nx_global(ns) + write(logunit,'(a,i10)')' ny_global = ',ny_global(ns) + end do + write(logunit,'(a,a )')' restfilm = ',trim(restfilm) + write(logunit,'(a,l6)')' skip_restart_read = ',skip_restart_read endif ! Broadcast namelist input @@ -246,52 +263,54 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) call ESMF_VMBroadcast(vm, restfilm, CL, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return do ns = 1,num_icesheets - call ESMF_VMBroadcast(vm, model_meshfiles(ns), CL, main_task, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_VMBroadcast(vm, nx_global(ns), 1, main_task, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_VMBroadcast(vm, ny_global(ns), 1, main_task, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, model_meshfiles(ns), CL, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + bcasttmp(1) = nx_global(ns) + call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + bcasttmp(1) = ny_global(ns) + call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return end do call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Validate datamode if ( trim(datamode) == 'noevolve') then ! read stream, no import data - ! do nothing + ! do nothing else - call shr_sys_abort(' ERROR illegal dglc datamode = '//trim(datamode)) + call shr_sys_abort(' ERROR illegal dglc datamode = '//trim(datamode)) endif ! Allocate module variables + allocate(sdat(num_icesheets)) allocate(NStateImp(num_icesheets)) allocate(NStateExp(num_icesheets)) - allocate(sdat(num_icesheets)) allocate(model_meshes(num_icesheets)) - allocate(dfields_icesheets(num_icesheets)) ! Create nested states do ns = 1,num_icesheets - write(cnum,'(i0)') ns - call NUOPC_AddNestedState(importState, CplSet="GLC"//trim(cnum), nestedState=NStateImp(ns), rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call NUOPC_AddNestedState(exportState, CplSet="GLC"//trim(cnum), nestedState=NStateExp(ns), rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + write(cnum,'(i0)') ns + call NUOPC_AddNestedState(importState, CplSet="GLC"//trim(cnum), nestedState=NStateImp(ns), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call NUOPC_AddNestedState(exportState, CplSet="GLC"//trim(cnum), nestedState=NStateExp(ns), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return end do ! Advertise dglc fields if (trim(datamode)=='noevolve') then - call dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_name, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_name, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return end if end subroutine InitializeAdvertise !=============================================================================== - subroutine InitializeRealize(gcomp, clock, rc) + subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) ! input/output variables type(ESMF_GridComp) :: gcomp + type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc @@ -337,60 +356,11 @@ subroutine InitializeRealize(gcomp, clock, rc) call NUOPC_CompAttributeGet(gcomp, name='read_restart', value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (isPresent .and. isSet) then - read(cvalue,*) read_restart + read(cvalue,*) read_restart else - call shr_sys_abort(subname//' ERROR: read restart flag must be present') + call shr_sys_abort(subname//' ERROR: read restart flag must be present') end if - ! Loop over ice sheets - do ns = 1,num_icesheets - - write(cns,'(i0)') ns - - ! Initialize pio subsystem -#ifdef CESMCOUPLED - sdat(ns)%pio_subsystem => shr_pio_getiosys('GLC') - sdat(ns)%io_type = shr_pio_getiotype('GLC') - sdat(ns)%io_format = shr_pio_getioformat('GLC') -#else - call dshr_pio_init(gcomp, sdat(ns), logunit, rc) -#endif - - ! Check that model_meshfile exists - if (my_task == main_task) then - inquire(file=trim(model_meshfiles(ns)), exist=exists) - if (.not.exists) then - write(logunit,'(a)')' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist' - call shr_sys_abort(trim(subname)//' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist') - end if - endif - - ! Read in model mesh - model_meshes(ns) = ESMF_MeshCreate(trim(model_meshfiles(ns)), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - ! Initialize stream data type - if (trim(datamode) /= 'noevolve') then - call shr_strdata_init_from_config(sdat(ns), streamfilename, model_meshes(ns), clock, 'GLC', logunit, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end if - - call ESMF_TraceRegionExit('dglc_strdata_init') - - ! Realize the actively coupled fields, now that a mesh is established and - ! NUOPC_Realize "realizes" a previously advertised field in the importState and exportState - ! by replacing the advertised fields with the newly created fields of the same name. - - call dshr_fldlist_realize( NStateExp(ns), fldsExport, flds_scalar_name, flds_scalar_num, model_mesh(ns), & - subname//trim(modelname)//':Export', export_all, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - call dshr_fldlist_realize( NStateImp(ns), fldsImport, flds_scalar_name, flds_scalar_num, model_mesh(ns), & - subname//trim(modelname)//':Import', .false., rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - end do ! loop over ice sheets - ! Get the time to interpolate the stream data to call ESMF_ClockGet(clock, currTime=currTime, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -398,24 +368,68 @@ subroutine InitializeRealize(gcomp, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call shr_cal_ymd2date(current_year, current_mon, current_day, current_ymd) - ! loop over ice sheets + ! Loop over ice sheets do ns = 1,num_icesheets - ! Run dglc - call dglc_comp_run(clock, current_ymd, current_tod, restart_write=.false., rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - ! Add scalars to export state - call dshr_state_SetScalar(dble(nx_global(ns)),flds_scalar_index_nx, & - NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call dshr_state_SetScalar(dble(ny_global(ns)),flds_scalar_index_ny,& - NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + write(cns,'(i0)') ns + + ! Initialize pio subsystem +#ifdef CESMCOUPLED + sdat(ns)%pio_subsystem => shr_pio_getiosys('GLC') + sdat(ns)%io_type = shr_pio_getiotype('GLC') + sdat(ns)%io_format = shr_pio_getioformat('GLC') +#else + call dshr_pio_init(gcomp, sdat(ns), logunit, rc) +#endif + + ! Check that model_meshfile exists + if (my_task == main_task) then + inquire(file=trim(model_meshfiles(ns)), exist=exists) + if (.not.exists) then + write(logunit,'(a)')' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist' + call shr_sys_abort(trim(subname)//' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist') + end if + endif + + ! Read in model mesh for given ice sheet + model_meshes(ns) = ESMF_MeshCreate(trim(model_meshfiles(ns)), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Initialize stream data type + if (trim(datamode) /= 'noevolve') then + call shr_strdata_init_from_config(sdat(ns), streamfilename, model_meshes(ns), clock, 'GLC', logunit, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + call ESMF_TraceRegionExit('dglc_strdata_init') + + ! Realize the actively coupled fields, now that a mesh is established and + ! NUOPC_Realize "realizes" a previously advertised field in the importState and exportState + ! by replacing the advertised fields with the newly created fields of the same name. + + call dshr_fldlist_realize( NStateExp(ns), fldsExport, flds_scalar_name, flds_scalar_num, model_meshes(ns), & + subname//trim(modelname)//':Export', export_all, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call dshr_fldlist_realize( NStateImp(ns), fldsImport, flds_scalar_name, flds_scalar_num, model_meshes(ns), & + subname//trim(modelname)//':Import', .false., rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Run dglc + call dglc_comp_run(clock, current_ymd, current_tod, restart_write=.false., rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Add scalars to export state + call dshr_state_SetScalar(dble(nx_global(ns)),flds_scalar_index_nx, & + NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_SetScalar(dble(ny_global(ns)),flds_scalar_index_ny,& + NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return end do call ESMF_VMLogMemInfo("Leaving "//trim(subname)) - end subroutine InitializeRealize + end subroutine InitializeRealize !=============================================================================== subroutine ModelAdvance(gcomp, rc) @@ -490,95 +504,100 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) call ESMF_TraceRegionEnter('DGLC_RUN') - ! Loop over ice sheets - do ns = 1,size(NStateExp) - - !-------------------- - ! First time initialization - !-------------------- - - if (first_time) then - ! Initialize dfields for given ice sheet - if (trim(datamode) /= 'noevolve') then - call dglc_init_dfields(ns, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end if - - ! Initialize datamode module ponters - select case (trim(datamode)) - case('noevolve') - call dglc_datamode_copyall_init_pointers(NStateExp(ns), rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end select - - ! Read restart if needed - if (trim(datamode) /= 'noevolve') then - if (restart_read .and. .not. skip_restart_read) then - ! placeholder for future datamodes - end if - end if + !-------------------- + ! First time initialization + !-------------------- + + if (first_time) then + ! Initialize dfields for all ice sheets + if (trim(datamode) /= 'noevolve') then + call dglc_init_dfields(rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + ! Initialize datamode module ponters + select case (trim(datamode)) + case('noevolve') + call dglc_datamode_copyall_init_pointers(NStateExp(ns), rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end select + + ! Read restart if needed + if (trim(datamode) /= 'noevolve') then + if (restart_read .and. .not. skip_restart_read) then + ! placeholder for future datamodes + end if + end if + + ! Reset first_time + first_time = .false. + end if - ! Reset first_time - first_time = .false. - end if - - !-------------------- - ! Update export (and possibly import data model states) - !-------------------- - - if (trim(datamode) /= 'noevolve') then - ! Advance data model streams - time and spatially interpolate to model time and grid - call ESMF_TraceRegionEnter('dglc_strdata_advance') - call shr_strdata_advance(sdat(ns), target_ymd, target_tod, logunit, 'dglc', rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_TraceRegionExit('dglc_strdata_advance') - - ! Copy all fields from streams to export state as default - ! This automatically will update the fields in the export state - call ESMF_TraceRegionEnter('dglc_dfield_copy') - call dshr_dfield_copy(dfields_icesheets(ns)%dfields, sdat(ns), rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_TraceRegionExit('dglc_dfield_copy') - end if - - ! Perform data mode specific calculations - select case (trim(datamode)) - case('noevolve') - call dglc_datamode_noevolve_advance(rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end select - - ! Write restarts if needed - if (restart_write) then - if (trim(datamode) /= 'evolve') then - ! this is a place holder for future datamode - end if - end if + !-------------------- + ! Update export (and possibly import data model states) + !-------------------- + + if (trim(datamode) /= 'noevolve') then + if (.not. allocated(dfields_icesheets)) then + allocate(dfields_icesheets(num_icesheets)) + end if + + ! Loop over ice sheets + do ns = 1,num_icesheets + ! Advance data model streams - time and spatially interpolate to model time and grid + ! Note that loop over ice sheets is done inside shr_strdata_advance + call ESMF_TraceRegionEnter('dglc_strdata_advance') + call shr_strdata_advance(sdat(ns), target_ymd, target_tod, logunit, 'dglc', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TraceRegionExit('dglc_strdata_advance') + + ! Copy all fields from streams to export state as default + ! This automatically will update the fields in the export state + call ESMF_TraceRegionEnter('dglc_dfield_copy') + call dshr_dfield_copy(dfields_icesheets(ns)%dfields, sdat(ns), rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TraceRegionExit('dglc_dfield_copy') + end do + end if - ! Write diagnostics - if (diagnose_data) then - write(cnum,'(i0)') ns - call dshr_state_diagnose(NStateExp, flds_scalar_name, trim(subname)//':ES_'//trim(cnum), rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end if + ! Perform data mode specific calculations + select case (trim(datamode)) + case('noevolve') + call dglc_datamode_noevolve_advance(sdat(1)%pio_subsystem, sdat(1)%io_type, sdat(1)%io_format, & + model_meshes, model_datafiles, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end select + + ! Write restarts if needed + if (restart_write) then + if (trim(datamode) /= 'evolve') then + ! this is a place holder for future datamode + end if + end if - end do ! end of loop over ice sheets + ! Write diagnostics + if (diagnose_data) then + do ns = 1,num_icesheets + write(cnum,'(i0)') ns + call dshr_state_diagnose(NStateExp(ns), flds_scalar_name, trim(subname)//':ES_'//trim(cnum), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end do + end if call ESMF_TraceRegionExit('DGLC_RUN') contains - subroutine dglc_init_dfields(ns, rc) + subroutine dglc_init_dfields(rc) ! ----------------------------- ! Initialize dfields arrays ! ----------------------------- ! input/output variables - integer , intent(in) :: ns ! ice sheet index - integer , intent(out) :: rc + integer, intent(out) :: rc ! local variables - integer :: n + integer :: nf, ns integer :: fieldcount type(ESMF_Field) :: lfield character(ESMF_MAXSTR) ,pointer :: lfieldnamelist(:) @@ -587,21 +606,25 @@ subroutine dglc_init_dfields(ns, rc) rc = ESMF_SUCCESS + ! Loop over ice sheets ! Initialize dfields data type (to map streams to export state fields) ! Create dfields linked list - used for copying stream fields to export state fields - call ESMF_StateGet(NStateExp(ns), itemCount=fieldCount, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - allocate(lfieldnamelist(fieldCount)) - call ESMF_StateGet(NStateExp(ns), itemNameList=lfieldnamelist, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - do n = 1, fieldCount - call ESMF_StateGet(NStateExp(ns), itemName=trim(lfieldNameList(n)), field=lfield, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - if (trim(lfieldnamelist(n)) /= flds_scalar_name) then - call dshr_dfield_add( dfields, sdat(ns), trim(lfieldnamelist(n)), trim(lfieldnamelist(n)), NStateExp(ns), & - logunit, mainproc, rc) + do ns = 1,num_icesheets + call ESMF_StateGet(NStateExp(ns), itemCount=fieldCount, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + allocate(lfieldnamelist(fieldCount)) + call ESMF_StateGet(NStateExp(ns), itemNameList=lfieldnamelist, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do nf = 1, fieldCount + call ESMF_StateGet(NStateExp(ns), itemName=trim(lfieldNameList(nf)), field=lfield, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (trim(lfieldnamelist(nf)) /= flds_scalar_name) then + call dshr_dfield_add( dfields_icesheets(ns)%dfields, sdat(ns), & + trim(lfieldnamelist(nf)), trim(lfieldnamelist(nf)), NStateExp(ns), logunit, mainproc, rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - end if + end if + end do + deallocate(lfieldnamelist) end do end subroutine dglc_init_dfields @@ -614,9 +637,9 @@ subroutine ModelFinalize(gcomp, rc) !------------------------------------------------------------------------------- rc = ESMF_SUCCESS if (my_task == main_task) then - write(logunit,*) - write(logunit,*) 'dglc : end of main integration loop' - write(logunit,*) + write(logunit,*) + write(logunit,*) 'dglc : end of main integration loop' + write(logunit,*) end if end subroutine ModelFinalize From d7e590d151b84c79a934547d936262a34846b370 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 20 Mar 2024 12:26:57 +0100 Subject: [PATCH 06/27] more compilation fixes --- cime_config/buildlib | 2 +- cime_config/buildlib_comps | 2 ++ dglc/dglc_datamode_noevolve_mod.F90 | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index a692a4e50..2da096a7a 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -184,7 +184,7 @@ def buildlib(bldroot, libroot, case): expect(False, nextline) # Link the CDEPS component directories to the location expected by cime - for comp in ("atm", "lnd", "ice", "ocn", "rof", "wav"): + for comp in ("atm", "glc", "lnd", "ice", "ocn", "rof", "wav"): compname = case.get_value("COMP_{}".format(comp.upper())) comppath = os.path.join(case.get_value("EXEROOT"), comp, "obj") if compname == "d" + comp: diff --git a/cime_config/buildlib_comps b/cime_config/buildlib_comps index 281f0d4e9..1366a4cfe 100755 --- a/cime_config/buildlib_comps +++ b/cime_config/buildlib_comps @@ -33,7 +33,9 @@ def buildlib(bldroot, libroot, case, compname=None): ) compname = os.path.basename(os.path.abspath(os.path.join(bldroot, os.pardir))) + print("DEBUG: here3") _, o, e = run_cmd("make d{}".format(compname), from_dir=bldroot, verbose=True) + print("DEBUG: here4") libname = "lib{}.a".format(compname) dlibname = "libd{}.a".format(compname) dlibpath = os.path.join(bldroot, dlibname) diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index 03ba9d4b3..b6cc8dcb6 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -14,6 +14,7 @@ module dglc_datamode_noevolve_mod use pio , only : pio_openfile, pio_inq_varid, pio_inq_varndims, pio_inq_vardimid use pio , only : pio_inq_dimlen, pio_initdecomp, pio_read_darray, pio_double use pio , only : pio_closefile, pio_freedecomp, PIO_BCAST_ERROR, PIO_NOWRITE + use pio , only : pio_seterrorhandling implicit none private ! except From f60351789350d2937821cec10e1976905f4e9e45 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 20 Mar 2024 15:16:14 +0100 Subject: [PATCH 07/27] fixes to for advertise and realize --- dglc/cime_config/buildlib | 1 + dglc/cime_config/namelist_definition_dglc.xml | 4 +- dglc/glc_comp_nuopc.F90 | 103 +++++++++--------- 3 files changed, 54 insertions(+), 54 deletions(-) create mode 120000 dglc/cime_config/buildlib diff --git a/dglc/cime_config/buildlib b/dglc/cime_config/buildlib new file mode 120000 index 000000000..0c5e984ac --- /dev/null +++ b/dglc/cime_config/buildlib @@ -0,0 +1 @@ +../../cime_config/buildlib_comps \ No newline at end of file diff --git a/dglc/cime_config/namelist_definition_dglc.xml b/dglc/cime_config/namelist_definition_dglc.xml index 0041e88af..b2ede04bc 100644 --- a/dglc/cime_config/namelist_definition_dglc.xml +++ b/dglc/cime_config/namelist_definition_dglc.xml @@ -35,7 +35,7 @@ - + char streams abs @@ -51,7 +51,7 @@ - + char streams abs diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index 428c77086..31f249f8c 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -39,9 +39,9 @@ module cdeps_dglc_comp use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_realize ! Datamode specialized modules - use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_advertise - use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_init_pointers - use dglc_datamode_noevolve_mod , only : dglc_datamode_noevolve_advance + use dglc_datamode_noevolve_mod, only : dglc_datamode_noevolve_advertise + use dglc_datamode_noevolve_mod, only : dglc_datamode_noevolve_init_pointers + use dglc_datamode_noevolve_mod, only : dglc_datamode_noevolve_advance implicit none private ! except @@ -58,15 +58,16 @@ module cdeps_dglc_comp ! Private module data !-------------------------------------------------------------------------- - integer, parameter :: max_icesheets = 10 ! maximum number of ice sheets for namelist input - integer :: num_icesheets = 0 ! actual number of ice sheets + character(*) , parameter :: nullstr = 'null' + integer , parameter :: max_icesheets = 10 ! maximum number of ice sheets for namelist input + integer :: num_icesheets ! actual number of ice sheets ! namelist input - character(CS) :: icesheet_names(max_icesheets) - character(CL) :: model_meshfiles(max_icesheets) - character(CL) :: model_datafiles(max_icesheets) - integer :: nx_global(max_icesheets) - integer :: ny_global(max_icesheets) + character(CS) :: icesheet_names(max_icesheets) = nullstr + character(CL) :: model_meshfiles(max_icesheets) = nullstr + character(CL) :: model_datafiles(max_icesheets) = nullstr + integer :: nx_global(max_icesheets) = 0 + integer :: ny_global(max_icesheets) = 0 ! module variables for multiple ice sheets type(shr_strdata_type) , allocatable :: sdat(:) @@ -75,27 +76,25 @@ module cdeps_dglc_comp type(ESMF_Mesh) , allocatable :: model_meshes(:) ! module variables common to all data models - character(CS) :: flds_scalar_name = '' - integer :: flds_scalar_num = 0 - integer :: flds_scalar_index_nx = 0 - integer :: flds_scalar_index_ny = 0 - integer :: mpicom ! mpi communicator - integer :: my_task ! my task in mpi communicator mpicom - logical :: mainproc ! true of my_task == main_task - character(len=16) :: inst_suffix = "" ! char string associated with instance (ie. "_0001" or "") - integer :: logunit ! logging unit number - logical :: restart_read ! start from restart - character(CL) :: case_name - character(*) , parameter :: nullstr = 'null' + character(CS) :: flds_scalar_name = '' + integer :: flds_scalar_num = 0 + integer :: flds_scalar_index_nx = 0 + integer :: flds_scalar_index_ny = 0 + integer :: mpicom ! mpi communicator + integer :: my_task ! my task in mpi communicator mpicom + logical :: mainproc ! true of my_task == main_task + character(len=16) :: inst_suffix = "" ! char string associated with instance (ie. "_0001" or "") + integer :: logunit ! logging unit number + logical :: restart_read ! start from restart + character(CL) :: case_name ! dglc_in namelist input - - character(CL) :: streamfilename = nullstr ! filename to obtain stream info from - character(CL) :: nlfilename = nullstr ! filename to obtain namelist info from - character(CL) :: datamode = nullstr ! flags physics options wrt input data - character(CL) :: restfilm = nullstr ! model restart file namelist - logical :: skip_restart_read = .false. ! true => skip restart read in continuation run - logical :: export_all = .false. ! true => export all fields, do not check connected or not + character(CL) :: streamfilename = nullstr ! filename to obtain stream info from + character(CL) :: nlfilename = nullstr ! filename to obtain namelist info from + character(CL) :: datamode = nullstr ! flags physics options wrt input data + character(CL) :: restfilm = nullstr ! model restart file namelist + logical :: skip_restart_read = .false. ! true => skip restart read in continuation run + logical :: export_all = .false. ! true => export all fields, do not check connected or not ! linked lists type(fldList_type) , pointer :: fldsImport => null() @@ -191,9 +190,6 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) character(len=*),parameter :: subname=trim(module_name)//':(InitializeAdvertise) ' !------------------------------------------------------------------------------- - !icesheet_names = "ais", "gris" - !num_icesheets = 2 - ! Note that the suffix '-list' refers to a colon delimited string of names namelist / dglc_nml / datamode, & icesheets_list, model_meshfiles_list, model_datafiles_list, nx_global, ny_global, & @@ -235,11 +231,6 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! determine input datafile name(s) call shr_string_listGetName(model_datafiles_list, ns, model_datafiles(ns)) end do - if (skip_restart_read) then - bcasttmp = 1 - else - bcasttmp = 0 - end if ! Write diagnostics write(logunit,'(a,a)')' case_name = ',trim(case_name) @@ -253,6 +244,9 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) end do write(logunit,'(a,a )')' restfilm = ',trim(restfilm) write(logunit,'(a,l6)')' skip_restart_read = ',skip_restart_read + + bcasttmp(1) = 0 + if(skip_restart_read) bcasttmp(1) = 1 endif ! Broadcast namelist input @@ -262,18 +256,23 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, restfilm, CL, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - do ns = 1,num_icesheets - call ESMF_VMBroadcast(vm, model_meshfiles(ns), CL, main_task, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - bcasttmp(1) = nx_global(ns) - call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - bcasttmp(1) = ny_global(ns) - call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end do + call ESMF_VMBroadcast(vm, model_meshfiles, CL*max_icesheets, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, nx_global, max_icesheets, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, ny_global, max_icesheets, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Set number of ice sheets for all mpi tasks + bcasttmp(1) = num_icesheets + call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + num_icesheets = bcasttmp(1) + + ! Determine if will skip restart read for all mpi tasks call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + skip_restart_read = (bcasttmp(1) == 1) ! Validate datamode if ( trim(datamode) == 'noevolve') then ! read stream, no import data @@ -333,9 +332,9 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) !------------------------------------------------------------------------------- rc = ESMF_SUCCESS - call ESMF_VMLogMemInfo("Entering "//trim(subname)) ! Initialize model mesh, restart flag, logunit, model_mask and model_frac + call ESMF_VMLogMemInfo("Entering "//trim(subname)) call ESMF_TraceRegionEnter('dglc_strdata_init') ! Determine stream filename @@ -400,8 +399,6 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if - call ESMF_TraceRegionExit('dglc_strdata_init') - ! Realize the actively coupled fields, now that a mesh is established and ! NUOPC_Realize "realizes" a previously advertised field in the importState and exportState ! by replacing the advertised fields with the newly created fields of the same name. @@ -425,8 +422,10 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) call dshr_state_SetScalar(dble(ny_global(ns)),flds_scalar_index_ny,& NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - end do + end do ! end loop over ice sheets + + call ESMF_TraceRegionExit('dglc_strdata_init') call ESMF_VMLogMemInfo("Leaving "//trim(subname)) end subroutine InitializeRealize @@ -518,7 +517,7 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) ! Initialize datamode module ponters select case (trim(datamode)) case('noevolve') - call dglc_datamode_copyall_init_pointers(NStateExp(ns), rc) + call dglc_datamode_noevolve_init_pointers(NStateExp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end select From ececaaa7bc7c927e58a291ebad63a57056991bb7 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 20 Mar 2024 16:25:27 +0100 Subject: [PATCH 08/27] finished advertise and realize phases --- dglc/dglc_datamode_noevolve_mod.F90 | 20 ++++++++++---------- dglc/glc_comp_nuopc.F90 | 2 +- dshr/dshr_fldlist_mod.F90 | 3 +++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index b6cc8dcb6..10a2cbb38 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -69,6 +69,7 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_n ! local variables integer :: ns logical :: isPresent, isSet + character(len=CS) :: cnum type(fldlist_type), pointer :: fldList !------------------------------------------------------------------------------- @@ -86,18 +87,17 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_n call dshr_fldList_add(fldsExport, field_out_ice_covered) call dshr_fldList_add(fldsExport, field_out_topo) call dshr_fldList_add(fldsExport, field_out_icemask) - Call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) + call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) do ns = 1,num_icesheets - fldlist => fldsExport ! the head of the linked list - do while (associated(fldlist)) - call NUOPC_Advertise(NStateExp(ns), standardName=fldlist%stdname, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ns == 1) then - call ESMF_LogWrite('(dglc_comp_advertise): Fr_glc'//trim(fldList%stdname), ESMF_LOGMSG_INFO) - end if - fldList => fldList%next - end do + write(cnum,'(i0)') ns + fldlist => fldsExport ! the head of the linked list + do while (associated(fldlist)) + call NUOPC_Advertise(NStateExp(ns), standardName=fldlist%stdname, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite('(dglc_comp_advertise): Fr_glc'//trim(cnum)//"_"//trim(fldList%stdname), ESMF_LOGMSG_INFO) + fldList => fldList%next + end do enddo end subroutine dglc_datamode_noevolve_advertise diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index 31f249f8c..fca0f92eb 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -19,7 +19,7 @@ module cdeps_dglc_comp use ESMF , only : ESMF_MeshCreate, ESMF_FILEFORMAT_ESMFMESH use NUOPC , only : NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize use NUOPC , only : NUOPC_Advertise, NUOPC_CompAttributeGet, NUOPC_CompAttributeSet - use NUOPC , only : NUOPC_AddNestedState + use NUOPC , only : NUOPC_AddNestedState, NUOPC_IsConnected use NUOPC_Model , only : model_routine_SS => SetServices use NUOPC_Model , only : model_label_Advance => label_Advance use NUOPC_Model , only : model_label_SetRunClock => label_SetRunClock diff --git a/dshr/dshr_fldlist_mod.F90 b/dshr/dshr_fldlist_mod.F90 index 398e1ce61..d35a6d073 100644 --- a/dshr/dshr_fldlist_mod.F90 +++ b/dshr/dshr_fldlist_mod.F90 @@ -77,8 +77,11 @@ subroutine dshr_fldlist_realize(state, fldLists, flds_scalar_name, flds_scalar_n fldList => fldLists ! note that fldlists is the head of the linked list do while (associated(fldList)) stdname = fldList%stdname + write(6,*)'DEBUG: stdname is ',trim(stdname) if (NUOPC_IsConnected(state, fieldName=stdname) .or. export_all) then + write(6,*)'DEBUG: field '//trim(stdname)//' is connected ' + ! Check field name since linked list might have empty string if (trim(stdname) == '') then fldList => fldList%next From aa6a9e934357a8f69f2b4ed2ef24e14d674150b3 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 20 Mar 2024 19:12:58 +0100 Subject: [PATCH 09/27] now in run phase --- cime_config/buildlib_comps | 2 - dglc/dglc_datamode_noevolve_mod.F90 | 4 +- dglc/glc_comp_nuopc.F90 | 103 ++++++++++++++-------------- dshr/dshr_fldlist_mod.F90 | 2 - streams/dshr_methods_mod.F90 | 5 +- 5 files changed, 60 insertions(+), 56 deletions(-) diff --git a/cime_config/buildlib_comps b/cime_config/buildlib_comps index 1366a4cfe..281f0d4e9 100755 --- a/cime_config/buildlib_comps +++ b/cime_config/buildlib_comps @@ -33,9 +33,7 @@ def buildlib(bldroot, libroot, case, compname=None): ) compname = os.path.basename(os.path.abspath(os.path.join(bldroot, os.pardir))) - print("DEBUG: here3") _, o, e = run_cmd("make d{}".format(compname), from_dir=bldroot, verbose=True) - print("DEBUG: here4") libname = "lib{}.a".format(compname) dlibname = "libd{}.a".format(compname) dlibpath = os.path.join(bldroot, dlibname) diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index 10a2cbb38..e3843536a 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -128,8 +128,10 @@ subroutine dglc_datamode_noevolve_init_pointers(NStateExp, rc) do ns = 1,num_icesheets call dshr_state_getfldptr(NStateExp(ns), 'Sg_topo' , fldptr1=Sg_topo(ns)%ptr , rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(NStateExp(ns), 'Sg_ice_covered' , fldptr1=Sg_ice_covered(ns)%ptr , rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(NStateExp(ns), 'Sg_icemask' , fldptr1=Sg_icemask(ns)%ptr , rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return end do @@ -197,8 +199,8 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Create pioid and pio_iodesc at the module level - call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) rcode = pio_openfile(pio_subsystem, pioid, io_type, trim(input_files(ns)), pio_nowrite) + call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) rcode = pio_inq_varid(pioid, 'thk', varid) rcode = pio_inq_varndims(pioid, varid, ndims) allocate(dimid(ndims)) diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index fca0f92eb..9bc423f28 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -355,9 +355,9 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) call NUOPC_CompAttributeGet(gcomp, name='read_restart', value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (isPresent .and. isSet) then - read(cvalue,*) read_restart + read(cvalue,*) read_restart else - call shr_sys_abort(subname//' ERROR: read restart flag must be present') + call shr_sys_abort(subname//' ERROR: read restart flag must be present') end if ! Get the time to interpolate the stream data to @@ -369,62 +369,65 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) ! Loop over ice sheets do ns = 1,num_icesheets - write(cns,'(i0)') ns - ! Initialize pio subsystem + write(cns,'(i0)') ns + + ! Initialize pio subsystem #ifdef CESMCOUPLED - sdat(ns)%pio_subsystem => shr_pio_getiosys('GLC') - sdat(ns)%io_type = shr_pio_getiotype('GLC') - sdat(ns)%io_format = shr_pio_getioformat('GLC') + sdat(ns)%pio_subsystem => shr_pio_getiosys('GLC') + sdat(ns)%io_type = shr_pio_getiotype('GLC') + sdat(ns)%io_format = shr_pio_getioformat('GLC') #else - call dshr_pio_init(gcomp, sdat(ns), logunit, rc) + call dshr_pio_init(gcomp, sdat(ns), logunit, rc) #endif - ! Check that model_meshfile exists - if (my_task == main_task) then - inquire(file=trim(model_meshfiles(ns)), exist=exists) - if (.not.exists) then - write(logunit,'(a)')' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist' - call shr_sys_abort(trim(subname)//' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist') - end if - endif - - ! Read in model mesh for given ice sheet - model_meshes(ns) = ESMF_MeshCreate(trim(model_meshfiles(ns)), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - ! Initialize stream data type - if (trim(datamode) /= 'noevolve') then - call shr_strdata_init_from_config(sdat(ns), streamfilename, model_meshes(ns), clock, 'GLC', logunit, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - end if - - ! Realize the actively coupled fields, now that a mesh is established and - ! NUOPC_Realize "realizes" a previously advertised field in the importState and exportState - ! by replacing the advertised fields with the newly created fields of the same name. - - call dshr_fldlist_realize( NStateExp(ns), fldsExport, flds_scalar_name, flds_scalar_num, model_meshes(ns), & - subname//trim(modelname)//':Export', export_all, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - call dshr_fldlist_realize( NStateImp(ns), fldsImport, flds_scalar_name, flds_scalar_num, model_meshes(ns), & - subname//trim(modelname)//':Import', .false., rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - ! Run dglc - call dglc_comp_run(clock, current_ymd, current_tod, restart_write=.false., rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - - ! Add scalars to export state - call dshr_state_SetScalar(dble(nx_global(ns)),flds_scalar_index_nx, & - NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call dshr_state_SetScalar(dble(ny_global(ns)),flds_scalar_index_ny,& - NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! Check that model_meshfile exists + if (my_task == main_task) then + inquire(file=trim(model_meshfiles(ns)), exist=exists) + if (.not.exists) then + write(logunit,'(a)')' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist' + call shr_sys_abort(trim(subname)//' ERROR: model_meshfile '//trim(model_meshfiles(ns))//' does not exist') + end if + endif + + ! Read in model mesh for given ice sheet + model_meshes(ns) = ESMF_MeshCreate(trim(model_meshfiles(ns)), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Initialize stream data type + if (trim(datamode) /= 'noevolve') then + call shr_strdata_init_from_config(sdat(ns), streamfilename, model_meshes(ns), clock, 'GLC', logunit, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + ! Realize the actively coupled fields, now that a mesh is established and + ! NUOPC_Realize "realizes" a previously advertised field in the importState and exportState + ! by replacing the advertised fields with the newly created fields of the same name. + + call ESMF_LogWrite(subname//' calling dshr_fldlist_realize export for ice sheet '//trim(cns), ESMF_LOGMSG_INFO) + call dshr_fldlist_realize( NStateExp(ns), fldsExport, flds_scalar_name, flds_scalar_num, model_meshes(ns), & + subname//trim(modelname)//':Export', export_all, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call ESMF_LogWrite(subname//' calling dshr_fldlist_realize importfor ice sheet '//trim(cns), ESMF_LOGMSG_INFO) + call dshr_fldlist_realize( NStateImp(ns), fldsImport, flds_scalar_name, flds_scalar_num, model_meshes(ns), & + subname//trim(modelname)//':Import', .false., rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Add scalars to export state + call dshr_state_SetScalar(dble(nx_global(ns)),flds_scalar_index_nx, & + NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call dshr_state_SetScalar(dble(ny_global(ns)),flds_scalar_index_ny,& + NStateExp(ns), flds_scalar_name, flds_scalar_num, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return end do ! end loop over ice sheets + ! Run dglc + call dglc_comp_run(clock, current_ymd, current_tod, restart_write=.false., rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_TraceRegionExit('dglc_strdata_init') call ESMF_VMLogMemInfo("Leaving "//trim(subname)) diff --git a/dshr/dshr_fldlist_mod.F90 b/dshr/dshr_fldlist_mod.F90 index d35a6d073..a06912fc1 100644 --- a/dshr/dshr_fldlist_mod.F90 +++ b/dshr/dshr_fldlist_mod.F90 @@ -77,10 +77,8 @@ subroutine dshr_fldlist_realize(state, fldLists, flds_scalar_name, flds_scalar_n fldList => fldLists ! note that fldlists is the head of the linked list do while (associated(fldList)) stdname = fldList%stdname - write(6,*)'DEBUG: stdname is ',trim(stdname) if (NUOPC_IsConnected(state, fieldName=stdname) .or. export_all) then - write(6,*)'DEBUG: field '//trim(stdname)//' is connected ' ! Check field name since linked list might have empty string if (trim(stdname) == '') then diff --git a/streams/dshr_methods_mod.F90 b/streams/dshr_methods_mod.F90 index b1972f7c8..8e721bed1 100644 --- a/streams/dshr_methods_mod.F90 +++ b/streams/dshr_methods_mod.F90 @@ -541,6 +541,7 @@ subroutine dshr_field_getfldptr(field, fldptr1, fldptr2, rank, abort, rc) integer :: ungriddedUBound(1) integer :: lrank logical :: labort + character(len=CS) :: name character(len=*), parameter :: subname='(field_getfldptr)' ! ---------------------------------------------- rc = ESMF_SUCCESS @@ -554,7 +555,9 @@ subroutine dshr_field_getfldptr(field, fldptr1, fldptr2, rank, abort, rc) if (chkerr(rc,__LINE__,u_FILE_u)) return if (status /= ESMF_FIELDSTATUS_COMPLETE) then if (labort) then - call ESMF_LogWrite(trim(subname)//": ERROR data not allocated ", ESMF_LOGMSG_ERROR, rc=rc) + call ESMF_FieldGet(field, name=name, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite(trim(subname)//": field "//trim(name)//" has no data not allocated ", ESMF_LOGMSG_ERROR, rc=rc) rc = ESMF_FAILURE return else From f09996397c0509fd92746c747c763986f3bb19c0 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 20 Mar 2024 20:58:09 +0100 Subject: [PATCH 10/27] dglc now runs and produces good values for topog --- dglc/dglc_datamode_noevolve_mod.F90 | 7 +++++++ dglc/glc_comp_nuopc.F90 | 2 ++ 2 files changed, 9 insertions(+) diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index e3843536a..b0153e442 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -167,6 +167,7 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & integer :: rcode integer :: nxg, nyg real(r8), pointer :: data(:) + logical :: exists character(len=*), parameter :: subname='(dglc_datamode_noevolve_advance): ' !------------------------------------------------------------------------------- @@ -199,6 +200,11 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Create pioid and pio_iodesc at the module level + inquire(file=trim(input_files(ns)), exist=exists) + if (.not.exists) then + write(6,'(a)')' ERROR: model input file '//trim(input_files(ns))//' does not exist' + call shr_sys_abort() + end if rcode = pio_openfile(pio_subsystem, pioid, io_type, trim(input_files(ns)), pio_nowrite) call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) rcode = pio_inq_varid(pioid, 'thk', varid) @@ -208,6 +214,7 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & rcode = pio_inq_dimlen(pioid, dimid(1), nxg) rcode = pio_inq_dimlen(pioid, dimid(2), nyg) call pio_initdecomp(pio_subsystem, pio_double, (/nxg,nyg/), gindex, pio_iodesc) + deallocate(dimid) deallocate(gindex) ! Read in the data into the appropriate field bundle pointers diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index 9bc423f28..37ed7747b 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -258,6 +258,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, model_meshfiles, CL*max_icesheets, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, model_datafiles, CL*max_icesheets, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, nx_global, max_icesheets, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, ny_global, max_icesheets, main_task, rc=rc) From f724a787063d5ea7c47732ee5a42ed1577e9d7ba Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Thu, 21 Mar 2024 13:43:51 +0100 Subject: [PATCH 11/27] implemented correct export fields for noevolve mode --- dglc/dglc_datamode_noevolve_mod.F90 | 112 +++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 19 deletions(-) diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index b0153e442..a64a75f0f 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -4,9 +4,10 @@ module dglc_datamode_noevolve_mod use ESMF , only : ESMF_Mesh, ESMF_DistGrid, ESMF_FieldBundle, ESMF_Field use ESMF , only : ESMF_FieldBundleCreate, ESMF_FieldCreate, ESMF_MeshLoc_Element use ESMF , only : ESMF_FieldBundleAdd, ESMF_MeshGet, ESMF_DistGridGet, ESMF_Typekind_R8 - use NUOPC , only : NUOPC_Advertise, NUOPC_AddNestedState + use NUOPC , only : NUOPC_Advertise use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs use shr_sys_mod , only : shr_sys_abort + use shr_const_mod , only : SHR_CONST_RHOICE, SHR_CONST_RHOSW use dshr_methods_mod , only : dshr_state_getfldptr, dshr_fldbun_getfldptr, chkerr use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add use dshr_strdata_mod , only : shr_strdata_type @@ -23,9 +24,10 @@ module dglc_datamode_noevolve_mod public :: dglc_datamode_noevolve_init_pointers public :: dglc_datamode_noevolve_advance - integer :: num_icesheets + integer :: num_icesheets + real(r8) :: thk0 = 1._r8 - ! export fields + ! Export fields type icesheet_ptr_t real(r8), pointer :: ptr(:) => null() ! pointer to array endtype icesheet_ptr_t @@ -34,23 +36,20 @@ module dglc_datamode_noevolve_mod type(icesheet_ptr_t), allocatable :: Sg_ice_covered(:) type(icesheet_ptr_t), allocatable :: Sg_icemask(:) + ! Field names character(len=*), parameter :: field_in_tsrf = 'Sl_tsrf' character(len=*), parameter :: field_in_qice = 'Flgl_qice' - character(len=*), parameter :: field_out_area = 'Sg_area' character(len=*), parameter :: field_out_ice_covered = 'Sg_ice_covered' character(len=*), parameter :: field_out_topo = 'Sg_topo' character(len=*), parameter :: field_out_icemask = 'Sg_icemask' character(len=*), parameter :: field_out_icemask_coupled_fluxes = 'Sg_icemask_coupled_fluxes' - character(len=*), parameter :: field_out_hflx_to_lnd = 'Flgg_hflx' character(len=*), parameter :: field_out_rofi_to_ice = 'Figg_rofi' character(len=*), parameter :: field_out_rofi_to_ocn = 'Fogg_rofi' character(len=*), parameter :: field_out_rofl_to_ocn = 'Fogg_rofl' - character(*) , parameter :: nullstr = 'null' character(*) , parameter :: rpfile = 'rpointer.glc' - character(*) , parameter :: u_FILE_u = & __FILE__ @@ -87,7 +86,7 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_n call dshr_fldList_add(fldsExport, field_out_ice_covered) call dshr_fldList_add(fldsExport, field_out_topo) call dshr_fldList_add(fldsExport, field_out_icemask) - call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) + !call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) do ns = 1,num_icesheets write(cnum,'(i0)') ns @@ -128,10 +127,8 @@ subroutine dglc_datamode_noevolve_init_pointers(NStateExp, rc) do ns = 1,num_icesheets call dshr_state_getfldptr(NStateExp(ns), 'Sg_topo' , fldptr1=Sg_topo(ns)%ptr , rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call dshr_state_getfldptr(NStateExp(ns), 'Sg_ice_covered' , fldptr1=Sg_ice_covered(ns)%ptr , rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call dshr_state_getfldptr(NStateExp(ns), 'Sg_icemask' , fldptr1=Sg_icemask(ns)%ptr , rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return end do @@ -159,6 +156,7 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & type(file_desc_t) :: pioid type(io_desc_t) :: pio_iodesc integer :: ns ! ice sheet index + integer :: ng ! grid cell index integer :: lsize integer, pointer :: gindex(:) ! domain decomposition of data integer :: ndims ! number of dims @@ -166,8 +164,14 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & type(var_desc_t) :: varid integer :: rcode integer :: nxg, nyg - real(r8), pointer :: data(:) + real(r8), pointer :: topog(:) + real(r8), pointer :: thck(:) logical :: exists + real(r8) :: rhoi ! density of ice ~ kg/m^3 + real(r8) :: rhoo ! density of sea water ~ kg/m^3 + real(r8) :: eus ! eustatic sea level + real(r8), allocatable :: lsrf(:) + real(r8), allocatable :: usrf(:) character(len=*), parameter :: subname='(dglc_datamode_noevolve_advance): ' !------------------------------------------------------------------------------- @@ -222,18 +226,58 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & ! the Sg_ice_covered field in NStateExp(ns) ! Note that Sg_topo(ns)%ptr points into the data for ! the Sg_topon NStateExp(ns) + ! Note that topog is bedrock topography - call dshr_fldbun_getFldPtr(fldbun_noevolve, 'thk', data, rc=rc) + call dshr_fldbun_getFldPtr(fldbun_noevolve, 'topg', topog, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - rcode = pio_inq_varid(pioid, 'thk', varid) - call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) - Sg_ice_covered(ns)%ptr(:) = data(:) + rcode = pio_inq_varid(pioid, 'topg', varid) + call pio_read_darray(pioid, varid, pio_iodesc, topog, rcode) - call dshr_fldbun_getFldPtr(fldbun_noevolve, 'topg', data, rc=rc) + call dshr_fldbun_getFldPtr(fldbun_noevolve, 'thk', thck, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - rcode = pio_inq_varid(pioid, 'topg', varid) - call pio_read_darray(pioid, varid, pio_iodesc, data, rcode) - Sg_topo(ns)%ptr(:) = data(:) + rcode = pio_inq_varid(pioid, 'thk', varid) + call pio_read_darray(pioid, varid, pio_iodesc, thck, rcode) + + allocate(lsrf(lsize)) + allocate(usrf(lsize)) + + rhoi = SHR_CONST_RHOICE ! 0.917e3 + rhoo = SHR_CONST_RHOSW ! 1.026e3 + eus = 0 + do ng = 1,lsize + if (topog(ng) - eus < (-rhoi/rhoo) * thck(ng)) then + lsrf(ng) = (-rhoi/rhoo) * thck(ng) + else + lsrf(ng) = topog(ng) + end if + usrf(ng) = max(0.d0, thck(ng) + lsrf(ng)) + end do + + !Sg_ice_covered(ns)%ptr(:) = thk(:) + do ng = 1,lsize + if (is_in_active_grid(usrf(ng))) then + Sg_icemask(ns)%ptr(ng) = 1.d0 + if (is_ice_covered(thck(ng))) then + Sg_ice_covered(ns)%ptr(ng) = 1.d0 + else + Sg_ice_covered(ns)%ptr(ng) = 0.d0 + end if + ! Note that we use the same method for computing topo whether this point is + ! ice-covered or ice-free. This is in contrast to the method for computing + ! ice-free topo in glint_upscaling_gcm. + Sg_topo(ns)%ptr(ng) = thk0 * usrf(ng) + else + ! Note that this logic implies that if (in theory) we had an ice-covered + ! point outside the "active grid", it will get classified as ice-free for + ! these purposes. This mimics the logic currently in glint_upscaling_gcm. + Sg_icemask(ns)%ptr(ng) = 0.d0 + Sg_ice_covered(ns)%ptr(ng) = 0.d0 + Sg_topo(ns)%ptr(ng) = 0.d0 + end if + end do + + deallocate(lsrf) + deallocate(usrf) call pio_closefile(pioid) call pio_freedecomp(pio_subsystem, pio_iodesc) @@ -242,4 +286,34 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & end subroutine dglc_datamode_noevolve_advance + !=============================================================================== + logical function is_in_active_grid(usrf) + ! Return true if the given point is inside the "active grid". The active grid includes + ! any point that can receive a positive surface mass balance, which includes any + ! point classified as land or ice sheet. + + real(r8), intent(in) :: usrf ! surface elevation (m) + + if (thk0 * usrf > 0.d0) then + ! points not at sea level are assumed to be land or ice sheet + is_in_active_grid = .true. + else + is_in_active_grid = .false. + end if + end function is_in_active_grid + + !=============================================================================== + logical function is_ice_covered(thck) + ! Return true if the given point is ice-covered + + real(r8), intent(in) :: thck ! ice thickness (m) + real(r8), parameter :: min_thck = 0.d0 + + if (thk0 * thck > min_thck) then + is_ice_covered = .true. + else + is_ice_covered = .false. + end if + end function is_ice_covered + end module dglc_datamode_noevolve_mod From d24fac4022a7861f78847327e10b252661424c58 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 22 Mar 2024 14:16:40 +0100 Subject: [PATCH 12/27] more fixes for having import data sent back --- dglc/dglc_datamode_noevolve_mod.F90 | 110 +++++++++++++++++++++------- dglc/glc_comp_nuopc.F90 | 4 +- 2 files changed, 86 insertions(+), 28 deletions(-) diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index a64a75f0f..1943cf1dd 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -4,7 +4,7 @@ module dglc_datamode_noevolve_mod use ESMF , only : ESMF_Mesh, ESMF_DistGrid, ESMF_FieldBundle, ESMF_Field use ESMF , only : ESMF_FieldBundleCreate, ESMF_FieldCreate, ESMF_MeshLoc_Element use ESMF , only : ESMF_FieldBundleAdd, ESMF_MeshGet, ESMF_DistGridGet, ESMF_Typekind_R8 - use NUOPC , only : NUOPC_Advertise + use NUOPC , only : NUOPC_Advertise, NUOPC_IsConnected use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs use shr_sys_mod , only : shr_sys_abort use shr_const_mod , only : SHR_CONST_RHOICE, SHR_CONST_RHOSW @@ -24,30 +24,36 @@ module dglc_datamode_noevolve_mod public :: dglc_datamode_noevolve_init_pointers public :: dglc_datamode_noevolve_advance + logical :: initialized_noevolve = .false. integer :: num_icesheets real(r8) :: thk0 = 1._r8 - ! Export fields + ! Data structure to enable multiple ice sheets type icesheet_ptr_t real(r8), pointer :: ptr(:) => null() ! pointer to array endtype icesheet_ptr_t + + ! Export fields type(icesheet_ptr_t), allocatable :: Sg_area(:) type(icesheet_ptr_t), allocatable :: Sg_topo(:) type(icesheet_ptr_t), allocatable :: Sg_ice_covered(:) type(icesheet_ptr_t), allocatable :: Sg_icemask(:) + type(icesheet_ptr_t), allocatable :: Sg_icemask_coupled_fluxes(:) - ! Field names - character(len=*), parameter :: field_in_tsrf = 'Sl_tsrf' - character(len=*), parameter :: field_in_qice = 'Flgl_qice' + ! Import fields + type(icesheet_ptr_t), allocatable :: Sl_tsrf(:) + type(icesheet_ptr_t), allocatable :: Flgl_qice(:) + + ! Export Field names character(len=*), parameter :: field_out_area = 'Sg_area' - character(len=*), parameter :: field_out_ice_covered = 'Sg_ice_covered' character(len=*), parameter :: field_out_topo = 'Sg_topo' + character(len=*), parameter :: field_out_ice_covered = 'Sg_ice_covered' character(len=*), parameter :: field_out_icemask = 'Sg_icemask' character(len=*), parameter :: field_out_icemask_coupled_fluxes = 'Sg_icemask_coupled_fluxes' - character(len=*), parameter :: field_out_hflx_to_lnd = 'Flgg_hflx' - character(len=*), parameter :: field_out_rofi_to_ice = 'Figg_rofi' - character(len=*), parameter :: field_out_rofi_to_ocn = 'Fogg_rofi' - character(len=*), parameter :: field_out_rofl_to_ocn = 'Fogg_rofl' + + ! Import Field names + character(len=*), parameter :: field_in_tsrf = 'Sl_tsrf' + character(len=*), parameter :: field_in_qice = 'Flgl_qice' character(*) , parameter :: rpfile = 'rpointer.glc' character(*) , parameter :: u_FILE_u = & @@ -57,18 +63,20 @@ module dglc_datamode_noevolve_mod contains !=============================================================================== - subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_name, rc) + subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fldsimport, flds_scalar_name, rc) ! input/output variables - type(ESMF_State) , intent(inout) :: NStateExp(:) - type(fldlist_type) , pointer :: fldsexport - character(len=*) , intent(in) :: flds_scalar_name - integer , intent(out) :: rc + type(ESMF_State) , intent(inout) :: NStateExp(:) + type(fldlist_type), pointer :: fldsexport + type(ESMF_State) , intent(inout) :: NStateImp(:) + type(fldlist_type), pointer :: fldsimport + character(len=*) , intent(in) :: flds_scalar_name + integer , intent(out) :: rc ! local variables - integer :: ns - logical :: isPresent, isSet - character(len=CS) :: cnum + integer :: ns + logical :: isPresent, isSet + character(len=CS) :: cnum type(fldlist_type), pointer :: fldList !------------------------------------------------------------------------------- @@ -83,10 +91,11 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_n ! Advertise export fields call dshr_fldList_add(fldsExport, trim(flds_scalar_name)) + call dshr_fldList_add(fldsExport, field_out_area) call dshr_fldList_add(fldsExport, field_out_ice_covered) call dshr_fldList_add(fldsExport, field_out_topo) call dshr_fldList_add(fldsExport, field_out_icemask) - !call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) + call dshr_fldList_add(fldsExport, field_out_icemask_coupled_fluxes) do ns = 1,num_icesheets write(cnum,'(i0)') ns @@ -99,13 +108,30 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_n end do enddo + ! Advertise import fields + call dshr_fldList_add(fldsImport, trim(flds_scalar_name)) + call dshr_fldList_add(fldsImport, field_in_tsrf) + call dshr_fldList_add(fldsImport, field_in_qice) + + do ns = 1,num_icesheets + write(cnum,'(i0)') ns + fldlist => fldsImport ! the head of the linked list + do while (associated(fldlist)) + call NUOPC_Advertise(NStateImp(ns), standardName=fldlist%stdname, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite('(dglc_comp_advertise): To_glc'//trim(cnum)//"_"//trim(fldList%stdname), ESMF_LOGMSG_INFO) + fldList => fldList%next + end do + enddo + end subroutine dglc_datamode_noevolve_advertise !=============================================================================== - subroutine dglc_datamode_noevolve_init_pointers(NStateExp, rc) + subroutine dglc_datamode_noevolve_init_pointers(NStateExp, NstateImp, rc) ! input/output variables type(ESMF_State) , intent(inout) :: NStateExp(:) + type(ESMF_State) , intent(inout) :: NStateImp(:) integer , intent(out) :: rc ! local variables @@ -123,14 +149,34 @@ subroutine dglc_datamode_noevolve_init_pointers(NStateExp, rc) allocate(Sg_topo(num_icesheets)) allocate(Sg_ice_covered(num_icesheets)) allocate(Sg_icemask(num_icesheets)) + allocate(Sg_icemask_coupled_fluxes(num_icesheets)) do ns = 1,num_icesheets - call dshr_state_getfldptr(NStateExp(ns), 'Sg_topo' , fldptr1=Sg_topo(ns)%ptr , rc=rc) + call dshr_state_getfldptr(NStateExp(ns), field_out_topo, fldptr1=Sg_topo(ns)%ptr, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call dshr_state_getfldptr(NStateExp(ns), 'Sg_ice_covered' , fldptr1=Sg_ice_covered(ns)%ptr , rc=rc) + call dshr_state_getfldptr(NStateExp(ns), field_out_ice_covered, fldptr1=Sg_ice_covered(ns)%ptr, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call dshr_state_getfldptr(NStateExp(ns), 'Sg_icemask' , fldptr1=Sg_icemask(ns)%ptr , rc=rc) + call dshr_state_getfldptr(NStateExp(ns), field_out_icemask, fldptr1=Sg_icemask(ns)%ptr, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return + call dshr_state_getfldptr(NStateExp(ns), field_out_icemask_coupled_fluxes, fldptr1=Sg_icemask_coupled_fluxes(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end do + + ! initialize pointers to import fields + allocate(Sl_tsrf(num_icesheets)) + allocate(Flgl_qice(num_icesheets)) + + do ns = 1,num_icesheets + ! NOTE: the field is connected ONLY if the MED->GLC entry is in the nuopc.runconfig file + ! This restriction occurs even if the field was advertised + if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_tsrf)) then + call dshr_state_getfldptr(NStateImp(ns), field_in_tsrf, fldptr1=Sl_tsrf(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_qice)) then + call dshr_state_getfldptr(NStateImp(ns), field_in_qice, fldptr1=Flgl_qice(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if end do end subroutine dglc_datamode_noevolve_init_pointers @@ -177,6 +223,17 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & rc = ESMF_SUCCESS + if (initialized_noevolve) then + RETURN + end if + + real(r8), allocatable :: glc_areas(:,:) + glc_areas(:,:) = get_dns(params%instances(instance_index)%model) * & + get_dew(params%instances(instance_index)%model) + call get_areas(ice_sheet, instance_index = ns, areas=glc_areas) + glc_areas(:,:) = glc_areas(:,:)/(radius*radius) ! convert from m^2 to radians^2 + + do ns = 1,num_icesheets ! Create module level field bundle @@ -251,12 +308,10 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & lsrf(ng) = topog(ng) end if usrf(ng) = max(0.d0, thck(ng) + lsrf(ng)) - end do - !Sg_ice_covered(ns)%ptr(:) = thk(:) - do ng = 1,lsize if (is_in_active_grid(usrf(ng))) then Sg_icemask(ns)%ptr(ng) = 1.d0 + Sg_icemask_coupled_fluxes(ns)%ptr(ng) = 1.d0 if (is_ice_covered(thck(ng))) then Sg_ice_covered(ns)%ptr(ng) = 1.d0 else @@ -271,6 +326,7 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & ! point outside the "active grid", it will get classified as ice-free for ! these purposes. This mimics the logic currently in glint_upscaling_gcm. Sg_icemask(ns)%ptr(ng) = 0.d0 + Sg_icemask_coupled_fluxes(ns)%ptr(ng) = 0.d0 Sg_ice_covered(ns)%ptr(ng) = 0.d0 Sg_topo(ns)%ptr(ng) = 0.d0 end if @@ -284,6 +340,8 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & end do ! end loop over ice sheets + initialized_noevolve = .true. + end subroutine dglc_datamode_noevolve_advance !=============================================================================== diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index 37ed7747b..c5d20fd7b 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -300,7 +300,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Advertise dglc fields if (trim(datamode)=='noevolve') then - call dglc_datamode_noevolve_advertise(NStateExp, fldsexport, flds_scalar_name, rc) + call dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fldsimport, flds_scalar_name, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -522,7 +522,7 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) ! Initialize datamode module ponters select case (trim(datamode)) case('noevolve') - call dglc_datamode_noevolve_init_pointers(NStateExp, rc) + call dglc_datamode_noevolve_init_pointers(NStateExp, NStateImp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end select From e5c7386eba53c3826717992f6a0ae23f06734226 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Sun, 24 Mar 2024 10:42:55 +0100 Subject: [PATCH 13/27] hard-wired greenland area as a prototype test --- dglc/dglc_datamode_noevolve_mod.F90 | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index 1943cf1dd..c9cb25d41 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -152,6 +152,8 @@ subroutine dglc_datamode_noevolve_init_pointers(NStateExp, NstateImp, rc) allocate(Sg_icemask_coupled_fluxes(num_icesheets)) do ns = 1,num_icesheets + call dshr_state_getfldptr(NStateExp(ns), field_out_area, fldptr1=Sg_area(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return call dshr_state_getfldptr(NStateExp(ns), field_out_topo, fldptr1=Sg_topo(ns)%ptr, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call dshr_state_getfldptr(NStateExp(ns), field_out_ice_covered, fldptr1=Sg_ice_covered(ns)%ptr, rc=rc) @@ -218,6 +220,8 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & real(r8) :: eus ! eustatic sea level real(r8), allocatable :: lsrf(:) real(r8), allocatable :: usrf(:) + ! TODO: make this a namelist variable + real(r8) :: glc_areas(num_icesheets) ! internal ice sheet area radians**2 character(len=*), parameter :: subname='(dglc_datamode_noevolve_advance): ' !------------------------------------------------------------------------------- @@ -227,15 +231,22 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & RETURN end if - real(r8), allocatable :: glc_areas(:,:) - glc_areas(:,:) = get_dns(params%instances(instance_index)%model) * & - get_dew(params%instances(instance_index)%model) - call get_areas(ice_sheet, instance_index = ns, areas=glc_areas) - glc_areas(:,:) = glc_areas(:,:)/(radius*radius) ! convert from m^2 to radians^2 + ! real(r8), allocatable :: glc_areas(:,:) + ! glc_areas(:,:) = get_dns(params%instances(instance_index)%model) * & + ! get_dew(params%instances(instance_index)%model) + ! call get_areas(ice_sheet, instance_index = ns, areas=glc_areas) + ! glc_areas(:,:) = glc_areas(:,:)/(radius*radius) ! convert from m^2 to radians^2 + ! glc_areas(:,:) = + glc_areas(1) = 3.94162024004361e-07 do ns = 1,num_icesheets + ! "area" ; + do ng = 1,lsize + Sg_area(ns)%ptr(ng) = glc_areas(ns) + end do + ! Create module level field bundle fldbun_noevolve = ESMF_FieldBundleCreate(rc=rc) ! input field bundle From 862df107ff060212b677ed66b5b3cfbf31aa4da0 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 27 Mar 2024 04:43:55 -0600 Subject: [PATCH 14/27] more changes to get dglc working with CLM --- dglc/cime_config/buildnml | 17 ++- dglc/cime_config/config_component.xml | 41 +++++++ dglc/cime_config/namelist_definition_dglc.xml | 30 +++++ dglc/dglc_datamode_noevolve_mod.F90 | 112 +++++++++--------- dglc/glc_comp_nuopc.F90 | 40 ++++--- 5 files changed, 157 insertions(+), 83 deletions(-) diff --git a/dglc/cime_config/buildnml b/dglc/cime_config/buildnml index 6994b7051..4dfef53b8 100755 --- a/dglc/cime_config/buildnml +++ b/dglc/cime_config/buildnml @@ -51,15 +51,6 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path expect(glc_grid != "null", "DGLC_GRID cannot be null") - # Log some settings. - logger.debug("DGLC mode is {}".format(dglc_mode)) - - # Initialize namelist defaults - # Note: always use model mesh file to set mask for drof - config = {} - config['dglc_mode'] = dglc_mode - config['glc_grid'] = glc_grid - # Do not allow single column mode for dglc if case.get_value('PTS_LON'): scol_lon = float(case.get_value('PTS_LON')) @@ -73,6 +64,14 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path expect(False, "single column mode for DGLC is not currently allowed") + # Log some settings. + logger.debug("DGLC mode is {}".format(dglc_mode)) + + # Initialize namelist defaults + config = {} + config['dglc_mode'] = dglc_mode + config['glc_grid'] = glc_grid + # Initialize nmlgen nmlgen.init_defaults(infile, config) diff --git a/dglc/cime_config/config_component.xml b/dglc/cime_config/config_component.xml index ae4a0549a..27cc4af61 100644 --- a/dglc/cime_config/config_component.xml +++ b/dglc/cime_config/config_component.xml @@ -40,6 +40,47 @@ + + logical + FALSE + run_component_dglc + env_run.xml + + If true, have the mediator calculate import values that are sent back to + GLC even in GLC is in NOEVOLVE mode + + + + + logical + FALSE + run_component_dglc + env_run.xml + + TRUE + + Whether to include the Greenland Ice Sheet in this DGLC simulation + This should generally be set at create_newcase time (via the compset). In principle it + can be changed later, but great care is needed to change a number of other variables + to be consistent (GLC_GRID, GLC_DOMAIN_MESH and possibly others). + + + + + logical + FALSE + run_component_dglc + env_run.xml + + TRUE + + Whether to include the Antarctica Ice Sheet in this DGLC simulation + This should generally be set at create_newcase time (via the compset). In principle it + can be changed later, but great care is needed to change a number of other variables + to be consistent (GLC_GRID, GLC_DOMAIN_MESH and possibly others). + + + logical TRUE,FALSE diff --git a/dglc/cime_config/namelist_definition_dglc.xml b/dglc/cime_config/namelist_definition_dglc.xml index b2ede04bc..20dd0bde1 100644 --- a/dglc/cime_config/namelist_definition_dglc.xml +++ b/dglc/cime_config/namelist_definition_dglc.xml @@ -65,6 +65,21 @@ + + real(20) + streams + dglc_nml + + 3.94162024004361e-07,1.57664809601744e-06 + 1. + 3.94162024004361e-07 + 1.57664809601744e-06 + + + colon deliminted string of inputdata files + + + integer(20) streams @@ -109,6 +124,21 @@ + + logical + dglc + dglc_nml + + If set to true, than dglc will advertise and realize import + fields even if it does not do anything with them. This + capability is used, for example, in generating coupler history + data for GLC spinup runs. + + + $DGLC_GET_IMPORT_DATA + + + logical dglc diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index c9cb25d41..7b6427497 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -27,6 +27,7 @@ module dglc_datamode_noevolve_mod logical :: initialized_noevolve = .false. integer :: num_icesheets real(r8) :: thk0 = 1._r8 + logical :: get_import_data ! Data structure to enable multiple ice sheets type icesheet_ptr_t @@ -63,12 +64,14 @@ module dglc_datamode_noevolve_mod contains !=============================================================================== - subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fldsimport, flds_scalar_name, rc) + subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fldsimport, & + get_import_data_in, flds_scalar_name, rc) ! input/output variables type(ESMF_State) , intent(inout) :: NStateExp(:) type(fldlist_type), pointer :: fldsexport type(ESMF_State) , intent(inout) :: NStateImp(:) + logical , intent(in) :: get_import_data_in type(fldlist_type), pointer :: fldsimport character(len=*) , intent(in) :: flds_scalar_name integer , intent(out) :: rc @@ -82,6 +85,9 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fl rc = ESMF_SUCCESS + ! Set module vraiable + get_import_data = get_import_data_in + !-------------------------------- ! Create nested state for active ice sheets only !-------------------------------- @@ -108,21 +114,23 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fl end do enddo - ! Advertise import fields - call dshr_fldList_add(fldsImport, trim(flds_scalar_name)) - call dshr_fldList_add(fldsImport, field_in_tsrf) - call dshr_fldList_add(fldsImport, field_in_qice) - - do ns = 1,num_icesheets - write(cnum,'(i0)') ns - fldlist => fldsImport ! the head of the linked list - do while (associated(fldlist)) - call NUOPC_Advertise(NStateImp(ns), standardName=fldlist%stdname, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_LogWrite('(dglc_comp_advertise): To_glc'//trim(cnum)//"_"//trim(fldList%stdname), ESMF_LOGMSG_INFO) - fldList => fldList%next - end do - enddo + ! Advertise import fields if appropriate + if (get_import_data) then + call dshr_fldList_add(fldsImport, trim(flds_scalar_name)) + call dshr_fldList_add(fldsImport, field_in_tsrf) + call dshr_fldList_add(fldsImport, field_in_qice) + + do ns = 1,num_icesheets + write(cnum,'(i0)') ns + fldlist => fldsImport ! the head of the linked list + do while (associated(fldlist)) + call NUOPC_Advertise(NStateImp(ns), standardName=fldlist%stdname, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite('(dglc_comp_advertise): To_glc'//trim(cnum)//"_"//trim(fldList%stdname), ESMF_LOGMSG_INFO) + fldList => fldList%next + end do + enddo + end if end subroutine dglc_datamode_noevolve_advertise @@ -164,28 +172,30 @@ subroutine dglc_datamode_noevolve_init_pointers(NStateExp, NstateImp, rc) if (chkerr(rc,__LINE__,u_FILE_u)) return end do - ! initialize pointers to import fields - allocate(Sl_tsrf(num_icesheets)) - allocate(Flgl_qice(num_icesheets)) - - do ns = 1,num_icesheets - ! NOTE: the field is connected ONLY if the MED->GLC entry is in the nuopc.runconfig file - ! This restriction occurs even if the field was advertised - if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_tsrf)) then - call dshr_state_getfldptr(NStateImp(ns), field_in_tsrf, fldptr1=Sl_tsrf(ns)%ptr, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_qice)) then - call dshr_state_getfldptr(NStateImp(ns), field_in_qice, fldptr1=Flgl_qice(ns)%ptr, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - end do + ! initialize pointers to import fields if appropriate + if (get_import_data) then + allocate(Sl_tsrf(num_icesheets)) + allocate(Flgl_qice(num_icesheets)) + + do ns = 1,num_icesheets + ! NOTE: the field is connected ONLY if the MED->GLC entry is in the nuopc.runconfig file + ! This restriction occurs even if the field was advertised + if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_tsrf)) then + call dshr_state_getfldptr(NStateImp(ns), field_in_tsrf, fldptr1=Sl_tsrf(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_qice)) then + call dshr_state_getfldptr(NStateImp(ns), field_in_qice, fldptr1=Flgl_qice(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + end do + end if end subroutine dglc_datamode_noevolve_init_pointers !=============================================================================== subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & - model_meshes, input_files, rc) + model_meshes, model_areas, input_files, rc) ! Assume that the model mesh is the same as the input data mesh @@ -194,6 +204,7 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & integer , intent(in) :: io_type ! pio info integer , intent(in) :: io_format ! pio info type(ESMF_Mesh) , intent(in) :: model_meshes(:) ! ice sheets meshes + real(r8) , intent(in) :: model_areas(:) ! internal model ice sheets areas (radians**2) character(len=*) , intent(in) :: input_files(:) ! input file names integer , intent(out) :: rc @@ -220,8 +231,6 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & real(r8) :: eus ! eustatic sea level real(r8), allocatable :: lsrf(:) real(r8), allocatable :: usrf(:) - ! TODO: make this a namelist variable - real(r8) :: glc_areas(num_icesheets) ! internal ice sheet area radians**2 character(len=*), parameter :: subname='(dglc_datamode_noevolve_advance): ' !------------------------------------------------------------------------------- @@ -231,20 +240,20 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & RETURN end if - ! real(r8), allocatable :: glc_areas(:,:) - ! glc_areas(:,:) = get_dns(params%instances(instance_index)%model) * & - ! get_dew(params%instances(instance_index)%model) - ! call get_areas(ice_sheet, instance_index = ns, areas=glc_areas) - ! glc_areas(:,:) = glc_areas(:,:)/(radius*radius) ! convert from m^2 to radians^2 - ! glc_areas(:,:) = - - glc_areas(1) = 3.94162024004361e-07 - do ns = 1,num_icesheets - ! "area" ; + ! Get mesh info + call ESMF_MeshGet(model_meshes(ns), elementdistGrid=distGrid, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(gindex(lsize)) + call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=gindex, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine "glc_area" ; do ng = 1,lsize - Sg_area(ns)%ptr(ng) = glc_areas(ns) + Sg_area(ns)%ptr(ng) = model_areas(ns) end do ! Create module level field bundle @@ -262,15 +271,6 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & call ESMF_FieldBundleAdd(fldbun_noevolve, (/field_noevolve/), rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - ! Get mesh info - call ESMF_MeshGet(model_meshes(ns), elementdistGrid=distGrid, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - allocate(gindex(lsize)) - call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=gindex, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - ! Create pioid and pio_iodesc at the module level inquire(file=trim(input_files(ns)), exist=exists) if (.not.exists) then @@ -322,7 +322,7 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & if (is_in_active_grid(usrf(ng))) then Sg_icemask(ns)%ptr(ng) = 1.d0 - Sg_icemask_coupled_fluxes(ns)%ptr(ng) = 1.d0 + Sg_icemask_coupled_fluxes(ns)%ptr(ng) = 0.d0 if (is_ice_covered(thck(ng))) then Sg_ice_covered(ns)%ptr(ng) = 1.d0 else diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index c5d20fd7b..6d160bdc3 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -61,6 +61,7 @@ module cdeps_dglc_comp character(*) , parameter :: nullstr = 'null' integer , parameter :: max_icesheets = 10 ! maximum number of ice sheets for namelist input integer :: num_icesheets ! actual number of ice sheets + logical :: get_import_data = .false. ! namelist input character(CS) :: icesheet_names(max_icesheets) = nullstr @@ -68,6 +69,7 @@ module cdeps_dglc_comp character(CL) :: model_datafiles(max_icesheets) = nullstr integer :: nx_global(max_icesheets) = 0 integer :: ny_global(max_icesheets) = 0 + real(r8) :: model_areas(max_icesheets) = 1.e36 ! module variables for multiple ice sheets type(shr_strdata_type) , allocatable :: sdat(:) @@ -181,7 +183,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) integer :: inst_index ! number of current instance (ie. 1) integer :: nu ! unit number integer :: ierr ! error code - integer :: bcasttmp(1) + integer :: bcasttmp(3) integer :: ns, n character(len=CS) :: cnum character(len=CL) :: icesheets_list @@ -192,8 +194,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Note that the suffix '-list' refers to a colon delimited string of names namelist / dglc_nml / datamode, & - icesheets_list, model_meshfiles_list, model_datafiles_list, nx_global, ny_global, & - restfilm, skip_restart_read + icesheets_list, model_meshfiles_list, model_datafiles_list, model_areas, nx_global, ny_global, & + get_import_data, restfilm, skip_restart_read rc = ESMF_SUCCESS @@ -236,17 +238,22 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) write(logunit,'(a,a)')' case_name = ',trim(case_name) write(logunit,'(a,a)')' datamode = ',trim(datamode) do ns = 1,num_icesheets - write(logunit,'(a,i4 )')' ice_sheet index = ',ns - write(logunit,'(a,a )')' model_meshfile = ',trim(model_meshfiles(ns)) - write(logunit,'(a,a )')' model_datafile = ',trim(model_datafiles(ns)) - write(logunit,'(a,i10)')' nx_global = ',nx_global(ns) - write(logunit,'(a,i10)')' ny_global = ',ny_global(ns) + write(logunit,'(a,i4 )') ' ice_sheet index = ',ns + write(logunit,'(a,a )') ' model_meshfile = ',trim(model_meshfiles(ns)) + write(logunit,'(a,a )') ' model_datafile = ',trim(model_datafiles(ns)) + write(logunit,'(a,i10)') ' nx_global = ',nx_global(ns) + write(logunit,'(a,i10)') ' ny_global = ',ny_global(ns) + write(logunit,'(a,d13.5)')' model_areas = ',model_areas(ns) end do write(logunit,'(a,a )')' restfilm = ',trim(restfilm) + write(logunit,'(a,l6)')' get_import_data = ',get_import_data write(logunit,'(a,l6)')' skip_restart_read = ',skip_restart_read bcasttmp(1) = 0 if(skip_restart_read) bcasttmp(1) = 1 + bcasttmp(2) = 0 + if(get_import_data) bcasttmp(2) = 1 + bcasttmp(3) = num_icesheets endif ! Broadcast namelist input @@ -264,17 +271,13 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, ny_global, max_icesheets, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - - ! Set number of ice sheets for all mpi tasks - bcasttmp(1) = num_icesheets - call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) + call ESMF_VMBroadcast(vm, model_areas, max_icesheets, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - num_icesheets = bcasttmp(1) - - ! Determine if will skip restart read for all mpi tasks - call ESMF_VMBroadcast(vm, bcasttmp, 1, main_task, rc=rc) + call ESMF_VMBroadcast(vm, bcasttmp, 3, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return skip_restart_read = (bcasttmp(1) == 1) + get_import_data = (bcasttmp(2) == 1) + num_icesheets = bcasttmp(3) ! Validate datamode if ( trim(datamode) == 'noevolve') then ! read stream, no import data @@ -300,7 +303,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Advertise dglc fields if (trim(datamode)=='noevolve') then - call dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fldsimport, flds_scalar_name, rc) + call dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fldsimport, & + get_import_data, flds_scalar_name, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -568,7 +572,7 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) select case (trim(datamode)) case('noevolve') call dglc_datamode_noevolve_advance(sdat(1)%pio_subsystem, sdat(1)%io_type, sdat(1)%io_format, & - model_meshes, model_datafiles, rc) + model_meshes, model_areas, model_datafiles, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end select From 63ed71f4067e73d9009c65d78a253e1dcb915b18 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Wed, 27 Mar 2024 06:30:01 -0600 Subject: [PATCH 15/27] first addition of documentation for dglc --- dglc/glc_comp_nuopc.F90 | 3 +- doc/source/dglc.rst | 113 ++++++++++++++++++++++++++++++++++++++++ doc/source/index.rst | 1 + 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 doc/source/dglc.rst diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index 6d160bdc3..26b3d15d0 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -186,7 +186,6 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) integer :: bcasttmp(3) integer :: ns, n character(len=CS) :: cnum - character(len=CL) :: icesheets_list character(len=ESMF_MAXSTR) :: model_datafiles_list ! colon separated string containing input datafiles character(len=ESMF_MAXSTR) :: model_meshfiles_list ! colon separated string containing model meshfiles character(len=*),parameter :: subname=trim(module_name)//':(InitializeAdvertise) ' @@ -194,7 +193,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Note that the suffix '-list' refers to a colon delimited string of names namelist / dglc_nml / datamode, & - icesheets_list, model_meshfiles_list, model_datafiles_list, model_areas, nx_global, ny_global, & + model_meshfiles_list, model_datafiles_list, model_areas, nx_global, ny_global, & get_import_data, restfilm, skip_restart_read rc = ESMF_SUCCESS diff --git a/doc/source/dglc.rst b/doc/source/dglc.rst new file mode 100644 index 000000000..56e35d191 --- /dev/null +++ b/doc/source/dglc.rst @@ -0,0 +1,113 @@ +.. _dglc: + +Data Ocean (DGLC) +================= + +DGLC is normally used as a substitute for CESM/CISM running in NOEVOLVE mode. +The various ways of running DGLC is referred to as its mode. + +NOEVOLVE mode is used in CESM as follows. +In typical runs, CISM is not evolving; CLM computes the surface mass +balance (SMB) and sends it to CISM, but CISM’s ice sheet geometry +remains fixed over the course of the run. In these runs, CISM serves +two roles in the system: + - Over the CISM domain (typically Greenland in + CESM2), CISM dictates glacier areas and topographic elevations, + overriding the values on CLM’s surface dataset. CISM also dictates the + elevation of non-glacier land units in its domain, and only in this + domain are atmospheric fields downscaled to non-glacier land + units. (So if you run with a stub glacier model - SGLC - then glacier + areas and elevations will be taken entirely from CLM’s surface + dataset, and no downscaling will be done over non-glacier land units.) + - CISM provides the grid onto which SMB is downscaled. (If you run with + SGLC then SMB will still be computed in CLM, but it won’t be + downscaled to a high-resolution ice sheet grid.) + +DGLC has the capability of supporting multiple ice sheets (as is the +case with CISM/CMEPS coupling). This is configured via the following +namelist settings: + + - ``model_meshfiles_list`` is a colon separated string containing model + meshfiles describing the different ice sheets. + + - ``model_datafiles_list`` is colon separated string containing + input datafiles that are used by CISM. Each datafile corresponds to a different + ice sheet mesh and should have the same order as those in the ``model_meshfiles_list``. + +.. _dglc-datamodes: + +-------------------- +Supported Data Modes +-------------------- + +DGLC has its own set of supported ``datamode`` values that appears in +the ``dglc_in`` namelist input. The datamode specifies what additional +operations need to be done by DGLC on *ALL* of the streams in the +``dglc.streams.xml`` file. Each datamode value is also associated with +a DGLC source file that carries out these operations and these are +listed in parentheses next to the mode name. Currently, the only +supported ``datamode`` is ``noevolve``. + +noevolve (``dglc_datamode_noevolve_mod.F90``) + - This mode is an analytic mode that has no associated stream files. + This mode uses ``dglc_in`` namelist variables as follows: + +.. _dglc-cime-vars: + +--------------------------------------- +Configuring DGLC using CIME-CCS +--------------------------------------- + +If CDEPS is coupled to the CIME-CCS then the CIME ``$CASEROOT`` xml +variable ``DGLC_MODE`` will be generated based on the compset +specification ``DGLC%{DGLC_MODE}``. ``DGLC_MODE`` will in term be +used in the ``namelist_definition_dglc.xml`` file to determine the +collection of streams that are associated with DGLC and also sets the +dglc namelist variable ``datamode`` in the file ``dglc_in``. + +The following list describes the valid values of ``DGLC_MODE`` +(defined in the ``config_component.xml`` file for DGLC), and how they +relate to the associated input streams and the ``datamode`` namelist +variable. + +DGLC%DOM + - SST data provided by a file + - dglc_mode: prescribed + - streams: prescribed + - datamode: sstdata + +DGLC%IAF + - SST data provided by a file + - dglc_mode: interannual + - streams: interannual + - datamode: iaf + +DGLC%SOM + - Slab Ocean Model is used to calculate sea surface temperature. + - dglc_mode: som + - streams: som + - datamode: som + +DGLC%SOMAQP + - Slab Ocean Model is used to calculate sea surface temperature. + - dglc_mode: som_aquap + - streams: N/A + - datamode: som_aquap + +DGLC%AQP[1-10] + - Lattitude varying analytical sea surface data + - dglc_mode: sst_aquap[1-10] + - streams: N/A + - datamode: sst_aquap[1-10] + +DGLC%AQPFILE + - SST data provided by a file + - dglc_mode: sst_aquap_file + - streams: aquapfile + - datamode: sst_aquapfile + +DGLC%AQPCONST + - Constant sea surface data from aquaplanet + - dglc_mode: sst_aquap_constant + - streams: N/A + - datamode: sst_aquap_constant diff --git a/doc/source/index.rst b/doc/source/index.rst index 3990258c3..f1a826f07 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -29,4 +29,5 @@ Table of contents dlnd.rst drof.rst dwav.rst + dglc.rst extending.rst From dbec7c93af394a339a4ae029e75ed924a58f577e Mon Sep 17 00:00:00 2001 From: mvertens Date: Wed, 27 Mar 2024 14:41:11 +0100 Subject: [PATCH 16/27] udpates for documentation for dglc --- dglc/cime_config/config_component.xml | 15 +-- doc/source/dglc.rst | 132 ++++++++++++++------------ 2 files changed, 79 insertions(+), 68 deletions(-) diff --git a/dglc/cime_config/config_component.xml b/dglc/cime_config/config_component.xml index 27cc4af61..d8ef6469f 100644 --- a/dglc/cime_config/config_component.xml +++ b/dglc/cime_config/config_component.xml @@ -27,16 +27,19 @@ char - NOEVOLVE - NOEVOLVE + noevolve + noevolve - noevolve + noevolve run_component_dglc env_run.xml - - model mode. - TODO: fill in what noevolve mode does + + NOEVOLVE mode is used in CESM as follows. + In typical runs, CISM is not evolving; CLM computes the surface mass + balance (SMB) and sends it to CISM, but CISM’s ice sheet geometry + remains fixed over the course of the run. In these runs, CISM serves + two roles in the system: diff --git a/doc/source/dglc.rst b/doc/source/dglc.rst index 56e35d191..9aa1ad6b9 100644 --- a/doc/source/dglc.rst +++ b/doc/source/dglc.rst @@ -1,6 +1,6 @@ .. _dglc: -Data Ocean (DGLC) +Data Land-Ice (DGLC) ================= DGLC is normally used as a substitute for CESM/CISM running in NOEVOLVE mode. @@ -11,34 +11,55 @@ In typical runs, CISM is not evolving; CLM computes the surface mass balance (SMB) and sends it to CISM, but CISM’s ice sheet geometry remains fixed over the course of the run. In these runs, CISM serves two roles in the system: - - Over the CISM domain (typically Greenland in - CESM2), CISM dictates glacier areas and topographic elevations, - overriding the values on CLM’s surface dataset. CISM also dictates the - elevation of non-glacier land units in its domain, and only in this - domain are atmospheric fields downscaled to non-glacier land - units. (So if you run with a stub glacier model - SGLC - then glacier - areas and elevations will be taken entirely from CLM’s surface - dataset, and no downscaling will be done over non-glacier land units.) - - CISM provides the grid onto which SMB is downscaled. (If you run with - SGLC then SMB will still be computed in CLM, but it won’t be - downscaled to a high-resolution ice sheet grid.) + + - Over the CISM domain (typically Greenland in + CESM2), CISM dictates glacier areas and topographic elevations, + overriding the values on CLM’s surface dataset. CISM also dictates the + elevation of non-glacier land units in its domain, and only in this + domain are atmospheric fields downscaled to non-glacier land + units. (So if you run with a stub glacier model - SGLC - then glacier + areas and elevations will be taken entirely from CLM’s surface + dataset, and no downscaling will be done over non-glacier land units.) + + - CISM provides the grid onto which SMB is downscaled. (If you run with + SGLC then SMB will still be computed in CLM, but it won’t be + downscaled to a high-resolution ice sheet grid.) + +-------------------- +Supported Data Modes +-------------------- DGLC has the capability of supporting multiple ice sheets (as is the case with CISM/CMEPS coupling). This is configured via the following -namelist settings: +``dglc_in`` namelist settings: - ``model_meshfiles_list`` is a colon separated string containing model meshfiles describing the different ice sheets. - ``model_datafiles_list`` is colon separated string containing - input datafiles that are used by CISM. Each datafile corresponds to a different - ice sheet mesh and should have the same order as those in the ``model_meshfiles_list``. - -.. _dglc-datamodes: - --------------------- -Supported Data Modes --------------------- + input datafiles that specify are used to obtain data for bedrock + topography and the ice thickness. + + - ``model_areas`` is an array that is the size of the number of ice + sheets and that specifies the gridcell areas that corresponds to + what internal gridcell areas the prognostic land-ice component + uses internally (in this case CISM). Specifying this at the + namelist level eliminates the need to duplicate the code that is + used in CISM to derive this quantity. + + - ``nx_global`` is an array that is the size of the number of ice + sheets and that specifies the global longitude dimension of the + each ice sheet. + + - ``ny_global`` is an array that is the size of the number of ice + sheets and that specifies the global latitude dimension of the + each ice sheet. + +.. note:: + Each element of ``model_data_filelist``, ``model_areas``, + ``nx_global`` and ``ny_global`` corresponds to a different ice + sheet mesh and should have the **same order** as those in the + ``model_meshfiles_list``. DGLC has its own set of supported ``datamode`` values that appears in the ``dglc_in`` namelist input. The datamode specifies what additional @@ -70,44 +91,31 @@ The following list describes the valid values of ``DGLC_MODE`` relate to the associated input streams and the ``datamode`` namelist variable. -DGLC%DOM - - SST data provided by a file - - dglc_mode: prescribed - - streams: prescribed - - datamode: sstdata - -DGLC%IAF - - SST data provided by a file - - dglc_mode: interannual - - streams: interannual - - datamode: iaf - -DGLC%SOM - - Slab Ocean Model is used to calculate sea surface temperature. - - dglc_mode: som - - streams: som - - datamode: som - -DGLC%SOMAQP - - Slab Ocean Model is used to calculate sea surface temperature. - - dglc_mode: som_aquap - - streams: N/A - - datamode: som_aquap - -DGLC%AQP[1-10] - - Lattitude varying analytical sea surface data - - dglc_mode: sst_aquap[1-10] - - streams: N/A - - datamode: sst_aquap[1-10] - -DGLC%AQPFILE - - SST data provided by a file - - dglc_mode: sst_aquap_file - - streams: aquapfile - - datamode: sst_aquapfile - -DGLC%AQPCONST - - Constant sea surface data from aquaplanet - - dglc_mode: sst_aquap_constant - - streams: N/A - - datamode: sst_aquap_constant +DGLC%NOEVOLVE + - fields sent to mediator are created analytically without stream + input + - dglc_mode: NOEVOLVE + - streams: none + - datamode: noevolve + +In addition, the following DGLC specific CIME-CCS xml variables will appear in ``$CASEROOT/env_run.xml``: + +DGLC_GET_IMPORT_DATA + - If true, have the mediator calculate import values that are sent back to + GLC even in GLC is in NOEVOLVE mode. The default value is FALSE. + +DGLC_USE_GREENLAND + - Whether to include the Greenland Ice Sheet in this DGLC simulation + This should generally be set at create_newcase time (via the compset). In principle it + can be changed later, but great care is needed to change a number of other variables + to be consistent (GLC_GRID, GLC_DOMAIN_MESH and possibly others). + +DGLC_USE_ANTARCTICA + - Whether to include the Antarctic Ice Sheet in this DGLC simulation + This should generally be set at create_newcase time (via the compset). In principle it + can be changed later, but great care is needed to change a number of other variables + to be consistent (GLC_GRID, GLC_DOMAIN_MESH and possibly others). + +DGLC_SKIP_RESTART_READ + - If set to true, than dglc restarts will not be read on a continuation run. + From 8f32440646ade064102e2362353ae91bb7a00eb2 Mon Sep 17 00:00:00 2001 From: mvertens Date: Wed, 27 Mar 2024 19:18:05 +0100 Subject: [PATCH 17/27] more additions for dglc --- doc/source/introduction.rst | 3 ++- doc/source/streams.rst | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/source/introduction.rst b/doc/source/introduction.rst index b34a67419..dcdf2ef1b 100644 --- a/doc/source/introduction.rst +++ b/doc/source/introduction.rst @@ -59,6 +59,7 @@ cime_config CIME Case Control System cmake Build (can be used with or without CIME) datm Data atmosphere component dice Data sea-ice component +dglc Data land-ice component dlnd Data land component docn Data ocean component drof Data river component @@ -132,7 +133,7 @@ CDEPS and CIME Control System (CCS) If the CDEPS data models are used in conjunction with the CIME Case Control System (CCS) then the following will also hold: Each data model has an xml variable in ``env_run.xml`` that specifies the data model mode. -These are: ``DATM_MODE``, ``DICE_MODE``, ``DLND_MODE``, ``DOCN_MODE``, ``DROF_MODE``, ``DWAV_MODE``. +These are: ``DATM_MODE``, ``DICE_MODE``, ``DGLC_MODE``, ``DLND_MODE``, ``DOCN_MODE``, ``DROF_MODE``, ``DWAV_MODE``. Each data model mode specifies the streams that are associated with that data model. More details of the data model design are covered in :ref:`design details`. diff --git a/doc/source/streams.rst b/doc/source/streams.rst index 3ce4d8023..0b6fa7235 100644 --- a/doc/source/streams.rst +++ b/doc/source/streams.rst @@ -365,7 +365,7 @@ Data Model Namelist Input ------------------------- Each data model has an associated input namelist file, ``d{model_name}_in``, -where ``model_name=[datm,dlnd,dice,docn,drof,dwav]``. +where ``model_name=[datm,dlnd,dglc,dice,docn,drof,dwav]``. The following namelist variables appear in each data model namelist: @@ -381,6 +381,8 @@ The following namelist variables appear in each data model namelist: :ref:`Data Land ` + :ref:`Data Land-Ice ` + :ref:`Data Ocean ` :ref:`Data Runoff ` From 368ea9568731e5210d601b01a207fb417fa08792 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Thu, 28 Mar 2024 08:00:14 -0600 Subject: [PATCH 18/27] update the testlist to work on derecho --- cime_config/testdefs/testlist_cdeps.xml | 68 ++++++++++++------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/cime_config/testdefs/testlist_cdeps.xml b/cime_config/testdefs/testlist_cdeps.xml index 03cbfb0c7..2147b04d3 100644 --- a/cime_config/testdefs/testlist_cdeps.xml +++ b/cime_config/testdefs/testlist_cdeps.xml @@ -1,97 +1,97 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -100,25 +100,25 @@ - + - + - + - + - + - + @@ -127,9 +127,9 @@ - + - + @@ -138,9 +138,9 @@ - + - + From a700dd1fba4993a2c1b88ec8de96c23e4c55228c Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Thu, 28 Mar 2024 13:17:08 -0600 Subject: [PATCH 19/27] added new derecho tests across the system including in dglc --- datm/cime_config/testdefs/testlist_datm.xml | 58 +++++++++------------ dglc/cime_config/buildnml | 11 ++-- dglc/cime_config/stream_definition_dglc.xml | 33 ++++++++++++ dglc/cime_config/testdefs/testlist_dglc.xml | 29 +++++++++++ dice/cime_config/testdefs/testlist_dice.xml | 8 +-- dlnd/cime_config/testdefs/testlist_dlnd.xml | 4 +- docn/cime_config/testdefs/testlist_docn.xml | 14 ++--- dwav/cime_config/testdefs/testlist_dwav.xml | 4 +- 8 files changed, 107 insertions(+), 54 deletions(-) create mode 100644 dglc/cime_config/testdefs/testlist_dglc.xml diff --git a/datm/cime_config/testdefs/testlist_datm.xml b/datm/cime_config/testdefs/testlist_datm.xml index ce9efb45a..0669f0518 100644 --- a/datm/cime_config/testdefs/testlist_datm.xml +++ b/datm/cime_config/testdefs/testlist_datm.xml @@ -3,108 +3,100 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + diff --git a/dglc/cime_config/buildnml b/dglc/cime_config/buildnml index 4dfef53b8..78dc9446f 100755 --- a/dglc/cime_config/buildnml +++ b/dglc/cime_config/buildnml @@ -79,19 +79,18 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path namelist_file = os.path.join(confdir, "dglc_in") nmlgen.write_output_file(namelist_file, data_list_path, groups=['dglc_nml']) - # Determine streams - streamlist = nmlgen.get_streams() - if type(streamlist) == type(str()): - streamlist = [] - # Generate dglc.streams.xml print("dglc_mode is {}".format(dglc_mode)) - if 'NOEVOLVE' in dglc_mode: + if 'noevolve' in dglc_mode: generate_stream_file = False else: generate_stream_file = True #endif if generate_stream_file: + # Determine streams + streamlist = nmlgen.get_streams() + if type(streamlist) == type(str()): + streamlist = [] outfile = os.path.join(confdir, "dglc.streams"+inst_string+".xml" ) schema_file = os.path.join(_CDEPS_CONFIG,"stream_definition_v2.0.xsd") stream_file = os.path.join(_CDEPS_CONFIG,os.pardir, "dglc","cime_config","stream_definition_dglc.xml") diff --git a/dglc/cime_config/stream_definition_dglc.xml b/dglc/cime_config/stream_definition_dglc.xml index 2811e8806..80ba75c5b 100644 --- a/dglc/cime_config/stream_definition_dglc.xml +++ b/dglc/cime_config/stream_definition_dglc.xml @@ -13,4 +13,37 @@ + + + + + unset + + + unset + + + unset unset + + null + + bilinear + + null + 0 + 0 + 0 + 0 + + lower + + + cycle + + + 1.5 + + single + + diff --git a/dglc/cime_config/testdefs/testlist_dglc.xml b/dglc/cime_config/testdefs/testlist_dglc.xml new file mode 100644 index 000000000..6557dec24 --- /dev/null +++ b/dglc/cime_config/testdefs/testlist_dglc.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dice/cime_config/testdefs/testlist_dice.xml b/dice/cime_config/testdefs/testlist_dice.xml index eac359d4e..7ef974fd4 100644 --- a/dice/cime_config/testdefs/testlist_dice.xml +++ b/dice/cime_config/testdefs/testlist_dice.xml @@ -1,17 +1,17 @@ - + - + - + - + diff --git a/dlnd/cime_config/testdefs/testlist_dlnd.xml b/dlnd/cime_config/testdefs/testlist_dlnd.xml index de52bac4a..a18c070de 100644 --- a/dlnd/cime_config/testdefs/testlist_dlnd.xml +++ b/dlnd/cime_config/testdefs/testlist_dlnd.xml @@ -1,9 +1,9 @@ - + - + diff --git a/docn/cime_config/testdefs/testlist_docn.xml b/docn/cime_config/testdefs/testlist_docn.xml index 5dea00d48..1fb29d5ba 100644 --- a/docn/cime_config/testdefs/testlist_docn.xml +++ b/docn/cime_config/testdefs/testlist_docn.xml @@ -1,29 +1,29 @@ - + - + - + - + - + - + - + diff --git a/dwav/cime_config/testdefs/testlist_dwav.xml b/dwav/cime_config/testdefs/testlist_dwav.xml index 0fed61eb2..65dd63d9e 100644 --- a/dwav/cime_config/testdefs/testlist_dwav.xml +++ b/dwav/cime_config/testdefs/testlist_dwav.xml @@ -1,9 +1,9 @@ - + - + From 0fdefdfb9323d6f318781e66e39d17146c457188 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Thu, 28 Mar 2024 13:18:00 -0600 Subject: [PATCH 20/27] removed cdeps/cime_config/testdefs - tests are already defined in cdeps/dxxx/cime_config/testdefs --- cime_config/testdefs/testlist_cdeps.xml | 150 ------------------------ 1 file changed, 150 deletions(-) delete mode 100644 cime_config/testdefs/testlist_cdeps.xml diff --git a/cime_config/testdefs/testlist_cdeps.xml b/cime_config/testdefs/testlist_cdeps.xml deleted file mode 100644 index 2147b04d3..000000000 --- a/cime_config/testdefs/testlist_cdeps.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From c6522b22c6c7f9c15cce730b0c36ae7f01318b2a Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 29 Mar 2024 07:36:11 -0600 Subject: [PATCH 21/27] fixed regression testing failures and also added aux_cdeps_noresm test category --- datm/cime_config/testdefs/testlist_datm.xml | 15 ++++++++++++++- dglc/cime_config/buildnml | 1 + dglc/cime_config/testdefs/testlist_dglc.xml | 3 +++ dice/cime_config/testdefs/testlist_dice.xml | 2 ++ dlnd/cime_config/testdefs/testlist_dlnd.xml | 1 + docn/cime_config/testdefs/testlist_docn.xml | 3 +++ drof/cime_config/testdefs/testlist_drof.xml | 1 + dwav/cime_config/testdefs/testlist_dwav.xml | 1 + 8 files changed, 26 insertions(+), 1 deletion(-) diff --git a/datm/cime_config/testdefs/testlist_datm.xml b/datm/cime_config/testdefs/testlist_datm.xml index 0669f0518..a20e56305 100644 --- a/datm/cime_config/testdefs/testlist_datm.xml +++ b/datm/cime_config/testdefs/testlist_datm.xml @@ -1,14 +1,16 @@ - + + + @@ -17,6 +19,7 @@ + @@ -25,6 +28,7 @@ + @@ -33,6 +37,7 @@ + @@ -41,6 +46,7 @@ + @@ -49,6 +55,7 @@ + @@ -57,6 +64,7 @@ + @@ -65,6 +73,7 @@ + @@ -73,6 +82,7 @@ + @@ -81,6 +91,7 @@ + @@ -89,6 +100,7 @@ + @@ -97,6 +109,7 @@ + diff --git a/dglc/cime_config/buildnml b/dglc/cime_config/buildnml index 78dc9446f..a18295e6e 100755 --- a/dglc/cime_config/buildnml +++ b/dglc/cime_config/buildnml @@ -81,6 +81,7 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path # Generate dglc.streams.xml print("dglc_mode is {}".format(dglc_mode)) + if 'noevolve' in dglc_mode: generate_stream_file = False else: diff --git a/dglc/cime_config/testdefs/testlist_dglc.xml b/dglc/cime_config/testdefs/testlist_dglc.xml index 6557dec24..194773fa7 100644 --- a/dglc/cime_config/testdefs/testlist_dglc.xml +++ b/dglc/cime_config/testdefs/testlist_dglc.xml @@ -4,6 +4,7 @@ + @@ -12,6 +13,7 @@ + @@ -20,6 +22,7 @@ + diff --git a/dice/cime_config/testdefs/testlist_dice.xml b/dice/cime_config/testdefs/testlist_dice.xml index 7ef974fd4..909980ce6 100644 --- a/dice/cime_config/testdefs/testlist_dice.xml +++ b/dice/cime_config/testdefs/testlist_dice.xml @@ -4,6 +4,7 @@ + @@ -12,6 +13,7 @@ + diff --git a/dlnd/cime_config/testdefs/testlist_dlnd.xml b/dlnd/cime_config/testdefs/testlist_dlnd.xml index a18c070de..59026878c 100644 --- a/dlnd/cime_config/testdefs/testlist_dlnd.xml +++ b/dlnd/cime_config/testdefs/testlist_dlnd.xml @@ -4,6 +4,7 @@ + diff --git a/docn/cime_config/testdefs/testlist_docn.xml b/docn/cime_config/testdefs/testlist_docn.xml index 1fb29d5ba..5c279cabf 100644 --- a/docn/cime_config/testdefs/testlist_docn.xml +++ b/docn/cime_config/testdefs/testlist_docn.xml @@ -4,6 +4,7 @@ + @@ -12,6 +13,7 @@ + @@ -20,6 +22,7 @@ + diff --git a/drof/cime_config/testdefs/testlist_drof.xml b/drof/cime_config/testdefs/testlist_drof.xml index 0515f0fc6..38b5fb142 100644 --- a/drof/cime_config/testdefs/testlist_drof.xml +++ b/drof/cime_config/testdefs/testlist_drof.xml @@ -4,6 +4,7 @@ + diff --git a/dwav/cime_config/testdefs/testlist_dwav.xml b/dwav/cime_config/testdefs/testlist_dwav.xml index 65dd63d9e..1864398ad 100644 --- a/dwav/cime_config/testdefs/testlist_dwav.xml +++ b/dwav/cime_config/testdefs/testlist_dwav.xml @@ -4,6 +4,7 @@ + From 4ee74e87db78ca00b9660b32561ec28a399bdb88 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 29 Mar 2024 09:36:55 -0600 Subject: [PATCH 22/27] removed unused variable declaration --- dglc/dglc_datamode_noevolve_mod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index 7b6427497..8e681b34e 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -78,7 +78,6 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fl ! local variables integer :: ns - logical :: isPresent, isSet character(len=CS) :: cnum type(fldlist_type), pointer :: fldList !------------------------------------------------------------------------------- From 24613eb03c8b3a19edea71344b9143aa1da7b088 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Fri, 29 Mar 2024 10:31:36 -0600 Subject: [PATCH 23/27] need CESMCOUPLED cpp here --- dglc/glc_comp_nuopc.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index 26b3d15d0..b78bb3537 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -30,7 +30,9 @@ module cdeps_dglc_comp use shr_cal_mod , only : shr_cal_ymd2date use shr_log_mod , only : shr_log_setLogUnit use shr_string_mod , only : shr_string_listGetNum, shr_string_listGetName +#ifdef CESMCOUPLED use shr_pio_mod , only : shr_pio_getiosys, shr_pio_getiotype, shr_pio_getioformat +#endif use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init From f7d6739925bbb25e136b253ff742209457b1ff05 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Fri, 29 Mar 2024 10:47:22 -0600 Subject: [PATCH 24/27] clean up --- dglc/glc_comp_nuopc.F90 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index b78bb3537..ad521bf9b 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -66,7 +66,6 @@ module cdeps_dglc_comp logical :: get_import_data = .false. ! namelist input - character(CS) :: icesheet_names(max_icesheets) = nullstr character(CL) :: model_meshfiles(max_icesheets) = nullstr character(CL) :: model_datafiles(max_icesheets) = nullstr integer :: nx_global(max_icesheets) = 0 @@ -186,7 +185,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) integer :: nu ! unit number integer :: ierr ! error code integer :: bcasttmp(3) - integer :: ns, n + integer :: ns character(len=CS) :: cnum character(len=ESMF_MAXSTR) :: model_datafiles_list ! colon separated string containing input datafiles character(len=ESMF_MAXSTR) :: model_meshfiles_list ! colon separated string containing model meshfiles @@ -328,8 +327,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) integer :: current_mon ! model month integer :: current_day ! model day integer :: current_tod ! model sec into model date - integer :: localpet - integer :: n, ns + integer :: ns character(CL) :: cvalue character(CS) :: cns logical :: ispresent, isset From a5f6ecb88ba20d26e2e21f5f10cf92f6f9a3d74d Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Fri, 29 Mar 2024 11:36:47 -0600 Subject: [PATCH 25/27] fixed indentation --- datm/atm_comp_nuopc.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 index 233e4c2b5..7a2a41c7b 100644 --- a/datm/atm_comp_nuopc.F90 +++ b/datm/atm_comp_nuopc.F90 @@ -29,7 +29,7 @@ module cdeps_datm_comp use shr_const_mod , only : shr_const_cday use shr_sys_mod , only : shr_sys_abort use shr_cal_mod , only : shr_cal_ymd2date - use shr_log_mod , only : shr_log_setLogUnit + use shr_log_mod , only : shr_log_setLogUnit use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_init_from_config, shr_strdata_advance use dshr_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_setOrbs From e88f40c03cf5a3b9d531baba08de5b99d33f82f3 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Sat, 30 Mar 2024 10:06:55 -0600 Subject: [PATCH 26/27] updates for dglc features required --- dglc/cime_config/buildnml | 4 +- dglc/cime_config/config_component.xml | 13 +-- dglc/cime_config/namelist_definition_dglc.xml | 37 +++---- dglc/dglc_datamode_noevolve_mod.F90 | 96 +++++++++---------- dglc/glc_comp_nuopc.F90 | 37 ++++--- 5 files changed, 75 insertions(+), 112 deletions(-) diff --git a/dglc/cime_config/buildnml b/dglc/cime_config/buildnml index a18295e6e..b68516429 100755 --- a/dglc/cime_config/buildnml +++ b/dglc/cime_config/buildnml @@ -60,7 +60,7 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path scol_lat = float(case.get_value('PTS_LAT')) else: scol_lat = -999. - if (scol_lon > -999. and scol_lat > 999.): + if (scol_lon > -999. or scol_lat > -999.): expect(False, "single column mode for DGLC is not currently allowed") @@ -80,7 +80,7 @@ def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path nmlgen.write_output_file(namelist_file, data_list_path, groups=['dglc_nml']) # Generate dglc.streams.xml - print("dglc_mode is {}".format(dglc_mode)) + logger.debug("dglc_mode is {}".format(dglc_mode)) if 'noevolve' in dglc_mode: generate_stream_file = False diff --git a/dglc/cime_config/config_component.xml b/dglc/cime_config/config_component.xml index d8ef6469f..15271a5b8 100644 --- a/dglc/cime_config/config_component.xml +++ b/dglc/cime_config/config_component.xml @@ -34,7 +34,7 @@ run_component_dglc env_run.xml - + NOEVOLVE mode is used in CESM as follows. In typical runs, CISM is not evolving; CLM computes the surface mass balance (SMB) and sends it to CISM, but CISM’s ice sheet geometry @@ -43,17 +43,6 @@ - - logical - FALSE - run_component_dglc - env_run.xml - - If true, have the mediator calculate import values that are sent back to - GLC even in GLC is in NOEVOLVE mode - - - logical FALSE diff --git a/dglc/cime_config/namelist_definition_dglc.xml b/dglc/cime_config/namelist_definition_dglc.xml index 20dd0bde1..8bc4e0c0e 100644 --- a/dglc/cime_config/namelist_definition_dglc.xml +++ b/dglc/cime_config/namelist_definition_dglc.xml @@ -42,7 +42,6 @@ dglc_nml $DIN_LOC_ROOT/glc/cism/Antarctica/ISMIP6_Antarctica_8km.init.c210908.nc:$DIN_LOC_ROOT/glc/cism/Greenland/greenland_4km_epsg3413_c171126.nc - $DIN_LOC_ROOT/glc/cism/Greenland/gland20.input_c150415.nc $DIN_LOC_ROOT/glc/cism/Greenland/greenland_4km_epsg3413_c171126.nc $DIN_LOC_ROOT/glc/cism/Antarctica/ISMIP6_Antarctica_8km.init.c210908.nc @@ -65,18 +64,19 @@ - + real(20) streams dglc_nml - 3.94162024004361e-07,1.57664809601744e-06 - 1. - 3.94162024004361e-07 - 1.57664809601744e-06 + 8000,4000 + 4000 + 8000 - colon deliminted string of inputdata files + model internal grid size(s) in m which is used to compute the internal model + model area in radians**2 using the formula (model_internal_gridsize/shr_const_rearth)**2 - + for more than one ice sheet this will contain an array of model_internal_gridsize values. @@ -91,8 +91,8 @@ 76 - global size(s) of nx - for more than one ice sheets this will contain an array of nx values + global size(s) of nx where for more than one ice sheet this + will contain an array of nx values @@ -107,8 +107,8 @@ 141 - global size(s) of ny - for more than one ice sheets this will contain an array of ny values + global size(s) of ny where for more than one ice sheet this + will contain an array of ny values @@ -124,21 +124,6 @@ - - logical - dglc - dglc_nml - - If set to true, than dglc will advertise and realize import - fields even if it does not do anything with them. This - capability is used, for example, in generating coupler history - data for GLC spinup runs. - - - $DGLC_GET_IMPORT_DATA - - - logical dglc diff --git a/dglc/dglc_datamode_noevolve_mod.F90 b/dglc/dglc_datamode_noevolve_mod.F90 index 8e681b34e..9a5431e62 100644 --- a/dglc/dglc_datamode_noevolve_mod.F90 +++ b/dglc/dglc_datamode_noevolve_mod.F90 @@ -7,7 +7,7 @@ module dglc_datamode_noevolve_mod use NUOPC , only : NUOPC_Advertise, NUOPC_IsConnected use shr_kind_mod , only : r8=>shr_kind_r8, i8=>shr_kind_i8, cl=>shr_kind_cl, cs=>shr_kind_cs use shr_sys_mod , only : shr_sys_abort - use shr_const_mod , only : SHR_CONST_RHOICE, SHR_CONST_RHOSW + use shr_const_mod , only : SHR_CONST_RHOICE, SHR_CONST_RHOSW, SHR_CONST_REARTH use dshr_methods_mod , only : dshr_state_getfldptr, dshr_fldbun_getfldptr, chkerr use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add use dshr_strdata_mod , only : shr_strdata_type @@ -27,7 +27,6 @@ module dglc_datamode_noevolve_mod logical :: initialized_noevolve = .false. integer :: num_icesheets real(r8) :: thk0 = 1._r8 - logical :: get_import_data ! Data structure to enable multiple ice sheets type icesheet_ptr_t @@ -65,13 +64,12 @@ module dglc_datamode_noevolve_mod !=============================================================================== subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fldsimport, & - get_import_data_in, flds_scalar_name, rc) + flds_scalar_name, rc) ! input/output variables type(ESMF_State) , intent(inout) :: NStateExp(:) type(fldlist_type), pointer :: fldsexport type(ESMF_State) , intent(inout) :: NStateImp(:) - logical , intent(in) :: get_import_data_in type(fldlist_type), pointer :: fldsimport character(len=*) , intent(in) :: flds_scalar_name integer , intent(out) :: rc @@ -84,9 +82,6 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fl rc = ESMF_SUCCESS - ! Set module vraiable - get_import_data = get_import_data_in - !-------------------------------- ! Create nested state for active ice sheets only !-------------------------------- @@ -114,22 +109,20 @@ subroutine dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fl enddo ! Advertise import fields if appropriate - if (get_import_data) then - call dshr_fldList_add(fldsImport, trim(flds_scalar_name)) - call dshr_fldList_add(fldsImport, field_in_tsrf) - call dshr_fldList_add(fldsImport, field_in_qice) - - do ns = 1,num_icesheets - write(cnum,'(i0)') ns - fldlist => fldsImport ! the head of the linked list - do while (associated(fldlist)) - call NUOPC_Advertise(NStateImp(ns), standardName=fldlist%stdname, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_LogWrite('(dglc_comp_advertise): To_glc'//trim(cnum)//"_"//trim(fldList%stdname), ESMF_LOGMSG_INFO) - fldList => fldList%next - end do - enddo - end if + call dshr_fldList_add(fldsImport, trim(flds_scalar_name)) + call dshr_fldList_add(fldsImport, field_in_tsrf) + call dshr_fldList_add(fldsImport, field_in_qice) + + do ns = 1,num_icesheets + write(cnum,'(i0)') ns + fldlist => fldsImport ! the head of the linked list + do while (associated(fldlist)) + call NUOPC_Advertise(NStateImp(ns), standardName=fldlist%stdname, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite('(dglc_comp_advertise): To_glc'//trim(cnum)//"_"//trim(fldList%stdname), ESMF_LOGMSG_INFO) + fldList => fldList%next + end do + enddo end subroutine dglc_datamode_noevolve_advertise @@ -172,39 +165,37 @@ subroutine dglc_datamode_noevolve_init_pointers(NStateExp, NstateImp, rc) end do ! initialize pointers to import fields if appropriate - if (get_import_data) then - allocate(Sl_tsrf(num_icesheets)) - allocate(Flgl_qice(num_icesheets)) - - do ns = 1,num_icesheets - ! NOTE: the field is connected ONLY if the MED->GLC entry is in the nuopc.runconfig file - ! This restriction occurs even if the field was advertised - if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_tsrf)) then - call dshr_state_getfldptr(NStateImp(ns), field_in_tsrf, fldptr1=Sl_tsrf(ns)%ptr, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_qice)) then - call dshr_state_getfldptr(NStateImp(ns), field_in_qice, fldptr1=Flgl_qice(ns)%ptr, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - end if - end do - end if + allocate(Sl_tsrf(num_icesheets)) + allocate(Flgl_qice(num_icesheets)) + + do ns = 1,num_icesheets + ! NOTE: the field is connected ONLY if the MED->GLC entry is in the nuopc.runconfig file + ! This restriction occurs even if the field was advertised + if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_tsrf)) then + call dshr_state_getfldptr(NStateImp(ns), field_in_tsrf, fldptr1=Sl_tsrf(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + if (NUOPC_IsConnected(NStateImp(ns), fieldName=field_in_qice)) then + call dshr_state_getfldptr(NStateImp(ns), field_in_qice, fldptr1=Flgl_qice(ns)%ptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + end if + end do end subroutine dglc_datamode_noevolve_init_pointers !=============================================================================== subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & - model_meshes, model_areas, input_files, rc) + model_meshes, model_internal_gridsize, model_datafiles, rc) ! Assume that the model mesh is the same as the input data mesh ! input/output variables - type(iosystem_desc_t) , pointer :: pio_subsystem ! pio info - integer , intent(in) :: io_type ! pio info - integer , intent(in) :: io_format ! pio info - type(ESMF_Mesh) , intent(in) :: model_meshes(:) ! ice sheets meshes - real(r8) , intent(in) :: model_areas(:) ! internal model ice sheets areas (radians**2) - character(len=*) , intent(in) :: input_files(:) ! input file names + type(iosystem_desc_t) , pointer :: pio_subsystem ! pio info + integer , intent(in) :: io_type ! pio info + integer , intent(in) :: io_format ! pio info + type(ESMF_Mesh) , intent(in) :: model_meshes(:) ! ice sheets meshes + real(r8) , intent(in) :: model_internal_gridsize(:) ! internal model gridsizes (m) + character(len=*) , intent(in) :: model_datafiles(:) ! input file names integer , intent(out) :: rc ! local variables @@ -251,8 +242,11 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Determine "glc_area" ; + ! Sg_areas is in radians + ! SHR_CONST_REARTH is the radius of earth in m + ! model_internal_gridsize is the internal model gridsize in m do ng = 1,lsize - Sg_area(ns)%ptr(ng) = model_areas(ns) + Sg_area(ns)%ptr(ng) = (model_internal_gridsize(ns)/SHR_CONST_REARTH)**2 end do ! Create module level field bundle @@ -271,12 +265,12 @@ subroutine dglc_datamode_noevolve_advance(pio_subsystem, io_type, io_format, & if (chkerr(rc,__LINE__,u_FILE_u)) return ! Create pioid and pio_iodesc at the module level - inquire(file=trim(input_files(ns)), exist=exists) + inquire(file=trim(model_datafiles(ns)), exist=exists) if (.not.exists) then - write(6,'(a)')' ERROR: model input file '//trim(input_files(ns))//' does not exist' + write(6,'(a)')' ERROR: model input file '//trim(model_datafiles(ns))//' does not exist' call shr_sys_abort() end if - rcode = pio_openfile(pio_subsystem, pioid, io_type, trim(input_files(ns)), pio_nowrite) + rcode = pio_openfile(pio_subsystem, pioid, io_type, trim(model_datafiles(ns)), pio_nowrite) call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) rcode = pio_inq_varid(pioid, 'thk', varid) rcode = pio_inq_varndims(pioid, varid, ndims) diff --git a/dglc/glc_comp_nuopc.F90 b/dglc/glc_comp_nuopc.F90 index ad521bf9b..233794fd3 100644 --- a/dglc/glc_comp_nuopc.F90 +++ b/dglc/glc_comp_nuopc.F90 @@ -63,14 +63,13 @@ module cdeps_dglc_comp character(*) , parameter :: nullstr = 'null' integer , parameter :: max_icesheets = 10 ! maximum number of ice sheets for namelist input integer :: num_icesheets ! actual number of ice sheets - logical :: get_import_data = .false. ! namelist input character(CL) :: model_meshfiles(max_icesheets) = nullstr character(CL) :: model_datafiles(max_icesheets) = nullstr integer :: nx_global(max_icesheets) = 0 integer :: ny_global(max_icesheets) = 0 - real(r8) :: model_areas(max_icesheets) = 1.e36 + real(r8) :: model_internal_gridsize(max_icesheets) = 1.e36 ! module variables for multiple ice sheets type(shr_strdata_type) , allocatable :: sdat(:) @@ -184,7 +183,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) integer :: inst_index ! number of current instance (ie. 1) integer :: nu ! unit number integer :: ierr ! error code - integer :: bcasttmp(3) + integer :: bcasttmp(2) integer :: ns character(len=CS) :: cnum character(len=ESMF_MAXSTR) :: model_datafiles_list ! colon separated string containing input datafiles @@ -194,8 +193,8 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Note that the suffix '-list' refers to a colon delimited string of names namelist / dglc_nml / datamode, & - model_meshfiles_list, model_datafiles_list, model_areas, nx_global, ny_global, & - get_import_data, restfilm, skip_restart_read + model_meshfiles_list, model_datafiles_list, model_internal_gridsize, nx_global, ny_global, & + restfilm, skip_restart_read rc = ESMF_SUCCESS @@ -238,22 +237,19 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) write(logunit,'(a,a)')' case_name = ',trim(case_name) write(logunit,'(a,a)')' datamode = ',trim(datamode) do ns = 1,num_icesheets - write(logunit,'(a,i4 )') ' ice_sheet index = ',ns - write(logunit,'(a,a )') ' model_meshfile = ',trim(model_meshfiles(ns)) - write(logunit,'(a,a )') ' model_datafile = ',trim(model_datafiles(ns)) - write(logunit,'(a,i10)') ' nx_global = ',nx_global(ns) - write(logunit,'(a,i10)') ' ny_global = ',ny_global(ns) - write(logunit,'(a,d13.5)')' model_areas = ',model_areas(ns) + write(logunit,'(a,i4 )') ' ice_sheet index = ',ns + write(logunit,'(a,a )') ' model_meshfile = ',trim(model_meshfiles(ns)) + write(logunit,'(a,a )') ' model_datafile = ',trim(model_datafiles(ns)) + write(logunit,'(a,d13.5)')' model_internal_gridsize = ',model_internal_gridsize(ns) + write(logunit,'(a,i10)') ' nx_global = ',nx_global(ns) + write(logunit,'(a,i10)') ' ny_global = ',ny_global(ns) end do write(logunit,'(a,a )')' restfilm = ',trim(restfilm) - write(logunit,'(a,l6)')' get_import_data = ',get_import_data write(logunit,'(a,l6)')' skip_restart_read = ',skip_restart_read bcasttmp(1) = 0 if(skip_restart_read) bcasttmp(1) = 1 - bcasttmp(2) = 0 - if(get_import_data) bcasttmp(2) = 1 - bcasttmp(3) = num_icesheets + bcasttmp(2) = num_icesheets endif ! Broadcast namelist input @@ -267,17 +263,16 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, model_datafiles, CL*max_icesheets, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBroadcast(vm, model_internal_gridsize, max_icesheets, main_task, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, nx_global, max_icesheets, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, ny_global, max_icesheets, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_VMBroadcast(vm, model_areas, max_icesheets, main_task, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_VMBroadcast(vm, bcasttmp, 3, main_task, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return skip_restart_read = (bcasttmp(1) == 1) - get_import_data = (bcasttmp(2) == 1) - num_icesheets = bcasttmp(3) + num_icesheets = bcasttmp(2) ! Validate datamode if ( trim(datamode) == 'noevolve') then ! read stream, no import data @@ -304,7 +299,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Advertise dglc fields if (trim(datamode)=='noevolve') then call dglc_datamode_noevolve_advertise(NStateExp, fldsexport, NStateImp, fldsimport, & - get_import_data, flds_scalar_name, rc) + flds_scalar_name, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if @@ -571,7 +566,7 @@ subroutine dglc_comp_run(clock, target_ymd, target_tod, restart_write, rc) select case (trim(datamode)) case('noevolve') call dglc_datamode_noevolve_advance(sdat(1)%pio_subsystem, sdat(1)%io_type, sdat(1)%io_format, & - model_meshes, model_areas, model_datafiles, rc) + model_meshes, model_internal_gridsize, model_datafiles, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end select From 68918090ddb39e7b0cc13f6c600e26649d7a4fe5 Mon Sep 17 00:00:00 2001 From: Mariana Vertenstein Date: Sat, 30 Mar 2024 10:17:45 -0600 Subject: [PATCH 27/27] updated documentation --- doc/source/dglc.rst | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/doc/source/dglc.rst b/doc/source/dglc.rst index 9aa1ad6b9..51175681e 100644 --- a/doc/source/dglc.rst +++ b/doc/source/dglc.rst @@ -38,14 +38,15 @@ case with CISM/CMEPS coupling). This is configured via the following - ``model_datafiles_list`` is colon separated string containing input datafiles that specify are used to obtain data for bedrock - topography and the ice thickness. + topography and the ice thickness. - - ``model_areas`` is an array that is the size of the number of ice - sheets and that specifies the gridcell areas that corresponds to + - ``model_internal_gridsize`` is an array that is the size of the number of ice + sheets and that specifies the internal gridcell size that corresponds what internal gridcell areas the prognostic land-ice component - uses internally (in this case CISM). Specifying this at the - namelist level eliminates the need to duplicate the code that is - used in CISM to derive this quantity. + uses internally (in this case CISM). From this value the internal grid areas in + radians squared are given by (model_internal_gridsize/radius_earth)**2. + Both model_internal_gridsize and radius_earth have units of meters. + - ``nx_global`` is an array that is the size of the number of ice sheets and that specifies the global longitude dimension of the @@ -53,7 +54,7 @@ case with CISM/CMEPS coupling). This is configured via the following - ``ny_global`` is an array that is the size of the number of ice sheets and that specifies the global latitude dimension of the - each ice sheet. + each ice sheet. .. note:: Each element of ``model_data_filelist``, ``model_areas``, @@ -100,10 +101,6 @@ DGLC%NOEVOLVE In addition, the following DGLC specific CIME-CCS xml variables will appear in ``$CASEROOT/env_run.xml``: -DGLC_GET_IMPORT_DATA - - If true, have the mediator calculate import values that are sent back to - GLC even in GLC is in NOEVOLVE mode. The default value is FALSE. - DGLC_USE_GREENLAND - Whether to include the Greenland Ice Sheet in this DGLC simulation This should generally be set at create_newcase time (via the compset). In principle it @@ -118,4 +115,3 @@ DGLC_USE_ANTARCTICA DGLC_SKIP_RESTART_READ - If set to true, than dglc restarts will not be read on a continuation run. -