diff --git a/.github/workflows/bumpversion.yml b/.github/workflows/bumpversion.yml deleted file mode 100644 index b17d491f0..000000000 --- a/.github/workflows/bumpversion.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Bump version -on: - push: - branches: - - main -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Bump version and push tag - id: tag_version - uses: mathieudutour/github-tag-action@v5.5 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - create_annotated_tag: true - default_bump: patch - dry_run: false - tag_prefix: cmeps diff --git a/.github/workflows/extbuild.yml b/.github/workflows/extbuild.yml index 86ed1a533..c5569014f 100644 --- a/.github/workflows/extbuild.yml +++ b/.github/workflows/extbuild.yml @@ -5,9 +5,9 @@ name: extbuild # events but only for the main branch on: push: - branches: [ main ] + branches: [ noresm ] pull_request: - branches: [ main ] + branches: [ noresm ] # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -23,8 +23,8 @@ jobs: ESMF_VERSION: v8.8.0 PNETCDF_VERSION: checkpoint.1.14.0 NETCDF_FORTRAN_VERSION: v4.6.1 - PIO_VERSION: pio2_6_4 - CDEPS_VERSION: cdeps1.0.64 + PIO_VERSION: pio2_6_5 + CDEPS_VERSION: cdeps1.0.80 steps: - uses: actions/checkout@v4 # Build the ESMF library, if the cache contains a previous build @@ -75,7 +75,7 @@ jobs: with: path: /homme/runner/work/CMEPS/CMEPS/build-cdeps key: ${{ runner.os }}-${{ env.CDEPS_VERSION }}.cdeps1 - + - name: checkout CDEPS uses: actions/checkout@v4 with: @@ -85,7 +85,7 @@ jobs: - name: get genf90 run: | cd cdeps-src - git submodule update --init + git submodule update --init - name: Build CDEPS if: steps.cache-cdeps.outputs.cache-hit != 'true' uses: ESCOMP/CDEPS/.github/actions/buildcdeps@cdeps1.0.26 @@ -95,7 +95,7 @@ jobs: src_root: ${GITHUB_WORKSPACE}/cdeps-src cmake_flags: " -Wno-dev -DDISABLE_FoX=ON -DCMAKE_BUILD_TYPE=DEBUG -DWERROR=ON -DCMAKE_Fortran_FLAGS=\"-DCPRGNU -g -Wall \ -ffree-form -ffree-line-length-none -fallow-argument-mismatch \"" - + - name: Build CMEPS run: | export PIO=$HOME/pio diff --git a/.github/workflows/srt.yml b/.github/workflows/srt.yml index 2983dea6f..ebc3c8b29 100644 --- a/.github/workflows/srt.yml +++ b/.github/workflows/srt.yml @@ -6,9 +6,9 @@ name: scripts regression tests # events but only for the main branch on: push: - branches: [ main ] + branches: [ noresm ] pull_request: - branches: [ main ] + branches: [ noresm ] # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -25,10 +25,10 @@ jobs: FC: mpifort CXX: mpicxx CPPFLAGS: "-I/usr/include -I/usr/local/include " - LDFLAGS: "-L/usr/lib/x86_64-linux-gnu -lnetcdf -lnetcdff -lpnetcdf" + LDFLAGS: "-L/usr/lib/x86_64-linux-gnu -lnetcdf -lnetcdff -lpnetcdf" # Versions of all dependencies can be updated here - ESMF_VERSION: v8.6.1 - PARALLELIO_VERSION: pio2_6_3 + ESMF_VERSION: v8.9.0 + PARALLELIO_VERSION: pio2_6_6 CIME_MODEL: cesm CIME_DRIVER: nuopc GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -40,9 +40,9 @@ jobs: id: load-env run: | set -x - sudo apt-get update + sudo apt-get update sudo apt-get install libxml2-utils - sudo apt-get install netcdf-bin + sudo apt-get install netcdf-bin sudo apt-get install libnetcdf-dev sudo apt-get install libnetcdff-dev sudo apt-get install pnetcdf-bin @@ -63,30 +63,30 @@ jobs: - run: echo "PyYAML" > requirements.txt - name: Install PyYAML run: pip install -r requirements.txt - # use the latest cesm main - - name: cesm checkout + # use the latest noresm main + - name: noresm checkout uses: actions/checkout@v4 with: - repository: ESCOMP/CESM - path: cesm + repository: NorESMhub/NorESM + path: noresm # this cmeps commit - name: cmeps checkout uses: actions/checkout@v4 with: - path: cesm/components/cmeps - - # Checkout cesm datamodels and support + path: noresm/components/cmeps + + # Checkout noresm datamodels and support # cpl7 is needed - i think that's a bug - name: checkout externals run: | git config --global user.name "${GITHUB_ACTOR}" git config --global user.email "${GITHUB_ACTOR_ID}+${GITHUB_ACTOR}@users.noreply.github.com" - pushd cesm + pushd noresm ./bin/git-fleximod update cime ccs_config cdeps share mct parallelio cd ccs_config - git checkout main + git checkout noresm cd ../cime - git checkout master + git checkout noresm git status if [[ ! -e "${PWD}/.gitmodules.bak" ]] then @@ -96,11 +96,11 @@ jobs: fi git submodule update --init cd ../components/cdeps - git checkout main + git checkout noresm git submodule update --init cd ../../share - git checkout main - + git checkout noresm + - name: Cache ESMF id: cache-esmf uses: actions/cache@v4 @@ -119,17 +119,17 @@ jobs: id: cache-inputdata uses: actions/cache@v4 with: - path: $HOME/cesm/inputdata + path: $HOME/noresm/inputdata key: inputdata - name: Build ParallelIO if: steps.cache-PARALLELIO.outputs.cache-hit != 'true' - uses: NCAR/ParallelIO/.github/actions/parallelio_cmake@05173a6556ea8d80eb34e3881a5014ea8f4b7543 + uses: NCAR/ParallelIO/.github/actions/parallelio_cmake@b38e34eeb9b75ce81ac94daf7c5245931de00b9d with: parallelio_version: ${{ env.ParallelIO_VERSION }} enable_fortran: True install_prefix: ${GITHUB_WORKSPACE}/pio - + - name: Install ESMF uses: esmf-org/install-esmf-action@v1 env: @@ -150,10 +150,10 @@ jobs: - name: PREP for scripts regression test run: | - mkdir -p $HOME/cesm/scratch - mkdir -p $HOME/cesm/inputdata - pushd $GITHUB_WORKSPACE/cesm/cime/CIME/tests - export SRCROOT=$GITHUB_WORKSPACE/cesm/ + mkdir -p $HOME/noresm/scratch + mkdir -p $HOME/noresm/inputdata + pushd $GITHUB_WORKSPACE/noresm/cime/CIME/tests + export SRCROOT=$GITHUB_WORKSPACE/noresm/ export CIME_TEST_PLATFORM=ubuntu-latest export PIO_INCDIR=$GITHUB_WORKSPACE/pio/include export PIO_LIBDIR=$GITHUB_WORKSPACE/pio/lib @@ -162,7 +162,7 @@ jobs: export NETCDF_PATH=/usr export PNETCDF_PATH=/usr export LD_LIBRARY_PATH=/usr/lib/libx86_64-linux-gnu/:$LD_LIBRARY_PATH - cat <> $GITHUB_WORKSPACE/cesm/ccs_config/machines/cmake_macros/ubuntu-latest.cmake + cat <> $GITHUB_WORKSPACE/noresm/ccs_config/machines/cmake_macros/ubuntu-latest.cmake set(NetCDF_Fortran_INCLUDE_DIR /usr/include) set(NetCDF_Fortran_LIBRARY /usr/lib/x86_64-gnu-Linux/libnetcdff.so) EOF @@ -170,11 +170,26 @@ jobs: popd - name: scripts regression tests run: | - pushd $GITHUB_WORKSPACE/cesm/cime/CIME/tests - ./scripts_regression_tests.py --no-fortran-run --compiler gnu --mpilib openmpi --machine ubuntu-latest + pushd $GITHUB_WORKSPACE/noresm/cime/CIME/tests + ./scripts_regression_tests.py --no-fortran-run --compiler gnu --mpilib openmpi --machine ubuntu-latest --no-teardown popd + + # How to download artifacts: + # https://docs.github.com/en/actions/managing-workflow-runs/downloading-workflow-artifacts + +# - name: Upload test logs +# if: ${{ failure() }} +# steps: +# - name: Tar test logs +# run: tar zcf scratch-${{ matrix.python-version }}.tar.gz /home/runner/noresm/scratch +# - name: save artifact +# uses: actions/upload-artifact@v4 +# with: +# name: test-logs-${{ matrix.python-version }} +# path: scratch-${{ matrix.python-version }}.tar.gz +# retention-days: 4 # the following can be used by developers to login to the github server in case of errors # see https://github.com/marketplace/actions/debugging-with-tmate for further details -# - name: Setup tmate session -# if: ${{ failure() }} -# uses: mxschmitt/action-tmate@v3 + - name: Setup tmate session + if: ${{ failure() }} + uses: mxschmitt/action-tmate@v3 diff --git a/cesm/driver/esm.F90 b/cesm/driver/esm.F90 index b2400a3ef..9a7bbf783 100644 --- a/cesm/driver/esm.F90 +++ b/cesm/driver/esm.F90 @@ -9,7 +9,7 @@ module ESM use shr_mem_mod , only : shr_mem_init use shr_log_mod , only : shr_log_setLogunit, shr_log_error use esm_utils_mod, only : logunit, maintask, dbug_flag, chkerr - use esmf , only : ESMF_FAILURE + use esmf , only : ESMF_FAILURE, ESMF_VMBARRIER implicit none private @@ -1557,6 +1557,9 @@ subroutine esm_finalize(driver, rc) call ESMF_VMGet(vm, mpiCommunicator=mpicomm, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMBarrier(vm, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call NUOPC_CompAttributeGet(driver, name="timing_dir",value=timing_dir, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return diff --git a/cesm/flux_atmocn/flux_atmocn_driver_mod.F90 b/cesm/flux_atmocn/flux_atmocn_driver_mod.F90 index 86ea6b2b9..82a2b97d8 100644 --- a/cesm/flux_atmocn/flux_atmocn_driver_mod.F90 +++ b/cesm/flux_atmocn/flux_atmocn_driver_mod.F90 @@ -54,7 +54,7 @@ subroutine flux_atmOcn_driver(logunit, nMax, & real(R8),intent(out) :: lwup (nMax) ! heat flux: lw upward (W/m^2) real(R8),intent(out) :: evap (nMax) ! water flux: evap ((kg/s)/m^2) real(R8),intent(out) :: taux (nMax) ! surface stress, zonal (N) - real(R8),intent(out) :: tauy (nMax) ! surface stress, maridional (N) + real(R8),intent(out) :: tauy (nMax) ! surface stress, meridional (N) real(R8),intent(out) :: tref (nMax) ! diag: 2m ref height T (K) real(R8),intent(out) :: qref (nMax) ! diag: 2m ref humidity (kg/kg) real(R8),intent(out) :: duu10n(nMax) ! diag: 10m wind speed squared (m/s)^2 diff --git a/cesm/nuopc_cap_share/shr_megan_mod.F90 b/cesm/nuopc_cap_share/shr_megan_mod.F90 index 57a218dd7..d26b85814 100644 --- a/cesm/nuopc_cap_share/shr_megan_mod.F90 +++ b/cesm/nuopc_cap_share/shr_megan_mod.F90 @@ -43,13 +43,13 @@ module shr_megan_mod integer :: index real(r8), pointer :: emis_factors(:) ! function of plant-function-type (PFT) integer :: class_number ! MEGAN class number - real(r8) :: coeff ! emissions component coeffecient real(r8) :: molec_weight ! molecular weight of the MEGAN compound (g/mole) type(shr_megan_megcomp_t), pointer :: next_megcomp ! points to next member in the linked list endtype shr_megan_megcomp_t type shr_megan_comp_ptr - type(shr_megan_megcomp_t), pointer :: ptr + type(shr_megan_megcomp_t), pointer :: ptr + real(r8) :: coeff ! emissions component coeffecient endtype shr_megan_comp_ptr ! chemical compound in CAM mechanism that has MEGAN emissions @@ -227,7 +227,8 @@ subroutine shr_megan_init( specifier) if (localPet==0) write(logunit,*) ' species : ', item%name do j = 1,item%n_terms if (localPet==0) write(logunit,'(f12.4,a,a)') item%coeffs(j),' * ', item%vars(j) - shr_megan_mechcomps(i)%megan_comps(j)%ptr => add_megan_comp( item%vars(j), item%coeffs(j) ) + shr_megan_mechcomps(i)%megan_comps(j)%ptr => add_megan_comp( item%vars(j) ) + shr_megan_mechcomps(i)%megan_comps(j)%coeff = item%coeffs(j) enddo shr_megan_mechcomps_n = shr_megan_mechcomps_n+1 @@ -243,10 +244,9 @@ end subroutine shr_megan_init !------------------------------------------------------------------------- - function add_megan_comp( name, coeff ) result(megan_comp) + function add_megan_comp( name ) result(megan_comp) character(len=16), intent(in) :: name - real(r8), intent(in) :: coeff type(shr_megan_megcomp_t), pointer :: megan_comp megan_comp => get_megan_comp_by_name(shr_megan_linkedlist, name) @@ -264,7 +264,7 @@ function add_megan_comp( name, coeff ) result(megan_comp) megan_comp%index = shr_megan_megcomps_n+1 megan_comp%name = trim(name) - megan_comp%coeff = coeff + nullify(megan_comp%next_megcomp) call add_megan_comp_to_list(megan_comp) diff --git a/cime_config/buildnml b/cime_config/buildnml index 41e7c1b6a..d1071d5c1 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -7,7 +7,7 @@ _CIMEROOT = os.environ.get("CIMEROOT") if _CIMEROOT is None: raise SystemExit("ERROR: must set CIMEROOT environment variable") -sys.path.append(os.path.join(_CIMEROOT, "scripts", "Tools")) +sys.path.append(os.path.join(_CIMEROOT, "CIME", "Tools")) import shutil, glob, itertools from standard_script_setup import * @@ -52,7 +52,6 @@ def _create_drv_namelists(case, infile, confdir, nmlgen, files): ) config["timer_level"] = "pos" if case.get_value("TIMER_LEVEL") >= 1 else "neg" config["continue_run"] = ".true." if case.get_value("CONTINUE_RUN") else ".false." - config["flux_epbal"] = "ocn" if case.get_value("CPL_EPBAL") == "ocn" else "off" config["mask_grid"] = case.get_value("MASK_GRID") for val in ("HIST", "REST", "STOP"): config[val.lower()+"_option"] = case.get_value(val+"_OPTION") @@ -143,7 +142,8 @@ def _create_drv_namelists(case, infile, confdir, nmlgen, files): elif case.get_value("RUN_TYPE") == "branch": config["run_type"] = "branch" - config['wav_ice_coupling'] = 'ww3' in config['COMP_WAV'] and config['COMP_ICE'] == 'cice' + if config['COMP_WAV'] == 'ww3' and config['COMP_ICE'] == 'cice': + config["wav_ice_coupling"] = "on" if config["COMP_OCN"] == "blom": if "ecosys" in case.get_value("BLOM_TRACER_MODULES"): @@ -682,6 +682,26 @@ def compare_drv_flds_in(first, second, infile1, infile2): % (infile1, infile2), ) +def cmeps_lib_list(case): + # provide a list of support libs that must be built for this case + # should be ordered with dependent libraries listed after those depended on + # the library names should match the keys in variable BUILD_LIB_FILE from config_files.xml + ufs_driver = os.environ.get("UFS_DRIVER") + if ufs_driver: + logger.info("UFS_DRIVER is set to {}".format(ufs_driver)) + + libs = case.get_values("CASE_SUPPORT_LIBRARIES") + + mpilib = case.get_value("MPILIB") + if mpilib == "mpi-serial" and "mpi-serial" not in libs: + libs.insert(0, mpilib) + + ocn_model = case.get_value("COMP_OCN") + # These will be handled by MOM and CAM, included here for backward compatibility. + atm_dycore = case.get_value("CAM_DYCORE") + if (ocn_model == "mom" or (atm_dycore and atm_dycore == "fv3")) and "FMS" not in libs: + libs.append("FMS") + return libs ############################################################################### def buildnml(case, caseroot, component): @@ -689,6 +709,10 @@ def buildnml(case, caseroot, component): if component != "drv": raise AttributeError + libs = cmeps_lib_list(case) + with Case(case.get_value("CASEROOT"), read_only=False) as case_tmp: + case_tmp.set_value("CASE_SUPPORT_LIBRARIES", ",".join(libs)) + esmfmkfile = os.getenv("ESMFMKFILE") expect( esmfmkfile and os.path.isfile(esmfmkfile), @@ -779,7 +803,7 @@ def buildnml(case, caseroot, component): def _main_func(): caseroot = parse_input(sys.argv) - with Case(caseroot) as case: + with Case(caseroot, read_only=False) as case: buildnml(case, caseroot, "drv") diff --git a/cime_config/config_archive.xml b/cime_config/config_archive.xml index ff8bbf533..44088fba2 100644 --- a/cime_config/config_archive.xml +++ b/cime_config/config_archive.xml @@ -1,17 +1,18 @@ r - hi?\d*.*\.nc$ + h[ix]?\d*\..*\.nc(\.gz)?$ unset - rpointer.cpl$NINST_STRING + rpointer.cpl$NINST_STRING.$DATENAME $CASE.cpl$NINST_STRING.r.$DATENAME.nc cpl_0001.log.5548574.chadmin1.180228-124723.gz casename.cpl.r.1976-01-01-00000.nc - rpointer.drv_0001 - rpointer.drv + rpointer.cpl_0001.1976-01-01-00000 + rpointer.cpl_0001.1976-01-01-43200 + rpointer.cpl.1976-01-01-00000 casenamenot.cpl.r.1976-01-01-00000.nc diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index ae6981fc4..6e933b041 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -489,17 +489,6 @@ - - logical - TRUE,FALSE - FALSE - run_begin_stop_restart - env_run.xml - - A setting of TRUE implies a continuation run for mediator only - - - integer 0 @@ -817,6 +806,8 @@ char none,a100 + none,a10,a2 + none,v100,a100,h100,mi300a none build_def env_build.xml @@ -881,6 +872,25 @@ CLM. This is currently only supported for certain machines. + + logical + TRUE,FALSE + FALSE + build_def + env_build.xml + TRUE implies linking to the FTorch library to allow calls between + fortran and a PyTorch model that has been saved to TorchScript. + + + + + char + + build_def + env_build.xml + location of libtorch and supporting libraries, may be supplied by ftorch interface if not present + + logical TRUE,FALSE @@ -896,21 +906,6 @@ machines. - - logical - TRUE,FALSE - FALSE - build_component_clm - env_build.xml - TRUE implies CLM is built with support for the PETSc - library. The Variably Saturated Flow Model (VSFM) solver in CLM - uses the PETSc library. In order to use the VSFM solver, CLM - must be built with PETSc support and linking to PETSc must occur - when building the ACME executable. This occurs if this variable - is set to TRUE. Note that is only available on a limited set of - machines/compilers. - - logical TRUE,FALSE @@ -1461,7 +1456,7 @@ env_run.xml wav2ocn state mapping file - + char 1.0e-02 @@ -1746,6 +1741,7 @@ env_mach_pes.xml ROOTPE (mpi task in MPI_COMM_WORLD) for each component + logical TRUE @@ -1850,7 +1846,7 @@ env_mach_pes.xml Number of GPUs per node used for simulation - + integer 0 @@ -1858,7 +1854,7 @@ env_mach_pes.xml Maximum number of GPUs allowed per node - + integer $MAX_MPITASKS_PER_NODE @@ -2311,7 +2307,7 @@ FALSE run_coupling env_run.xml - determine if per ice thickness category fields are passed from ice to ocean - DO NOT EDIT (set by POP build-namelist) + determine if per ice thickness category fields are passed from ice to ocean - DO NOT EDIT (set by MOM6) @@ -2500,9 +2496,21 @@ Remote git repository used for this case - - - + + char + + + gptl,pio,csm_share,FTorch,CDEPS + + build_def + env_build.xml + Support libraries required + + + + + + logical diff --git a/cime_config/config_component_cesm.xml b/cime_config/config_component_cesm.xml index 751964602..0472a0b5e 100644 --- a/cime_config/config_component_cesm.xml +++ b/cime_config/config_component_cesm.xml @@ -107,7 +107,6 @@ CO2A none - CO2A CO2A CO2A CO2A @@ -220,6 +219,7 @@ integer 48 + 2 144 288 288 @@ -231,8 +231,6 @@ 48 24 24 - - 72 @@ -248,8 +246,6 @@ - 24 - 48 48 48 @@ -269,6 +265,8 @@ 384 192 384 + 192 + 384 48 48 48 @@ -277,6 +275,23 @@ 72 144 288 + 48 + 48 + 48 + 96 + 192 + 360 + 720 + 1440 + + 2 + 2 + 2 + 4 + 8 + 15 + 30 + 60 @@ -389,16 +404,18 @@ 8 $ATM_NCPL + $ATM_NCPL + $OCN_NCPL $ATM_NCPL $ATM_NCPL $ATM_NCPL 1 - 8 8 8 $ATM_NCPL 1 $ATM_NCPL + $ATM_NCPL run_coupling env_run.xml @@ -418,57 +435,23 @@ - logical TRUE,FALSE FALSE - TRUE - TRUE - FALSE - TRUE - TRUE - TRUE - FALSE + TRUE + TRUE run_component_cpl env_run.xml - Only used for compsets with DATM and [POP or MOM] (currently C, G and J): - If true, compute albedos to work with daily avg SW down - If false (default), albedos are computed with the assumption that downward + If FALSE (default), albedos are computed with the assumption that downward solar radiation from the atm component has a diurnal cycle and zenith-angle - dependence. This is normally the case when using an active atm component - If true, albedos are computed with the assumption that downward + dependence. + If TRUE, albedos are computed with the assumption that downward solar radiation from the atm component is a daily average quantity and - does not have a zenith-angle dependence. This is often the case when - using a data atm component. Only used for compsets with DATM and POP (currently C, G and J). - NOTE: This should really depend on the datm forcing and not the compset per se. - So, for example, whether it is set in a J compset should depend on - what datm forcing is used. - - - - - char - off,ocn - off - - ocn - off - - run_component_cpl - env_run.xml - - Only used for compsets with DATM and POP (currently C, G and J): - If ocn, ocn provides EP balance factor for precipitation. - Provides EP balance factor for precip for POP. A factor computed by - POP is applied to precipitation so that precipitation balances - evaporation and ocn global salinity does not drift. This is intended - for use when coupling POP to a DATM. Only used for C, G and J compsets. - Default is off + does not have a zenith-angle dependence. @@ -536,12 +519,10 @@ TRUE,FALSE FALSE - TRUE TRUE TRUE TRUE TRUE - TRUE TRUE run_budgets @@ -561,8 +542,8 @@ env_run.xml Mechanism for setting the CO2 value in ppmv for - CLM if CLM_CO2_TYPE is constant or for - POP if OCN_CO2_TYPE is constant. + CLM if CLM_CO2_TYPE is constant or + MOM6 if OCN_CO2_TYPE is constant. diff --git a/cime_config/namelist_definition_drv.xml b/cime_config/namelist_definition_drv.xml index 1fdb7e63f..015169a92 100644 --- a/cime_config/namelist_definition_drv.xml +++ b/cime_config/namelist_definition_drv.xml @@ -431,7 +431,7 @@ if true, mediator is present in run - + char expdef ALLCOMP_attributes @@ -439,7 +439,7 @@ Model version - unknown + $MODEL_VERSION @@ -934,7 +934,7 @@ 1 : Taylor et al. (1996) - 0 + 1 @@ -2963,6 +2963,7 @@ .false. .false. .false. + .false. @@ -3926,8 +3927,7 @@ .false. - - + .true. diff --git a/cime_config/testdefs/testlist_drv.xml b/cime_config/testdefs/testlist_drv.xml index fd1ad7ac6..b57b7ba12 100644 --- a/cime_config/testdefs/testlist_drv.xml +++ b/cime_config/testdefs/testlist_drv.xml @@ -46,7 +46,7 @@ - + @@ -55,7 +55,7 @@ - + @@ -292,7 +292,7 @@ - + diff --git a/cime_config/testdefs/testmods_dirs/drv/interim_restart/shell_commands b/cime_config/testdefs/testmods_dirs/drv/interim_restart/shell_commands new file mode 100644 index 000000000..90c2d7364 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/drv/interim_restart/shell_commands @@ -0,0 +1,2 @@ +# use this with the ERR test to test the interim restart capability +./xmlchange REST_N=2 \ No newline at end of file diff --git a/mediator/esmFldsExchange_cesm_mod.F90 b/mediator/esmFldsExchange_cesm_mod.F90 index b524defa7..408834d2e 100644 --- a/mediator/esmFldsExchange_cesm_mod.F90 +++ b/mediator/esmFldsExchange_cesm_mod.F90 @@ -118,6 +118,7 @@ subroutine esmFldsExchange_cesm(gcomp, phase, rc) use med_internalstate_mod , only : mapbilnr, mapconsf, mapconsd, mappatch, mappatch_uv3d, mapbilnr_nstod use med_internalstate_mod , only : mapfcopy, mapnstod, mapnstod_consd, mapnstod_consf use med_internalstate_mod , only : map_rof2ocn_ice, map_rof2ocn_liq + use med_internalstate_mod, only : ocn_name, ice_name use esmFlds , only : addfld_ocnalb => med_fldList_addfld_ocnalb use esmFlds , only : addfld_aoflux => med_fldList_addfld_aoflux use esmFlds , only : addmap_aoflux => med_fldList_addmap_aoflux @@ -143,6 +144,8 @@ subroutine esmFldsExchange_cesm(gcomp, phase, rc) character(len=CS) :: mrgfld_source logical :: wav_coupling_to_cice logical :: ocn2glc_coupling + logical :: forr_rofl_glc_merged_to_ocn + logical :: forr_rofi_glc_merged_to_ocn character(len=*) , parameter :: subname=' (esmFldsExchange_cesm) ' !-------------------------------------- @@ -1363,6 +1366,18 @@ subroutine esmFldsExchange_cesm(gcomp, phase, rc) call addmrg_to(compatm, 'Si_vice', mrg_from=compice, mrg_fld='Si_vice', mrg_type='copy') end if end if + if (ice_name == 'mpassi') then + if (phase == 'advertise') then + call addfld_from(compice, 'Si_ithick') + call addfld_to(compatm, 'Si_ithick') + else + if ( fldchk(is_local%wrap%FBexp(compatm) , 'Si_ithick', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compice,compice), 'Si_ithick', rc=rc)) then + call addmap_from(compice, 'Si_ithick', compatm, mapconsf, 'ifrac', ice2atm_map) + call addmrg_to(compatm, 'Si_ithick', mrg_from=compice, mrg_fld='Si_ithick', mrg_type='copy') + end if + end if + end if if (phase == 'advertise') then call addfld_from(compice, 'Si_vsno') call addfld_to(compatm, 'Si_vsno') @@ -1638,6 +1653,22 @@ subroutine esmFldsExchange_cesm(gcomp, phase, rc) call addmrg_to(compocn, 'Si_ifrac', mrg_from=compice, mrg_fld='Si_ifrac', mrg_type='copy') end if + ! --------------------------------------------------------------------- + ! to ocn: seaice basal pressure + ! --------------------------------------------------------------------- + if (ice_name == 'mpassi' .or. ocn_name == 'mpaso') then + if (phase == 'advertise') then + call addfld_from(compice, 'Si_bpress') + call addfld_to(compocn, 'Si_bpress') + else + if ( fldchk(is_local%wrap%FBImp(compice, compice), 'Si_bpress', rc=rc) .and. & + fldchk(is_local%wrap%FBExp(compocn) , 'Si_bpress', rc=rc)) then + call addmap_from(compice, 'Si_bpress', compocn, mapfcopy, 'unset', 'unset') + call addmrg_to(compocn, 'Si_bpress', mrg_from=compice, mrg_fld='Si_bpress', mrg_type='copy') + end if + end if + end if + ! --------------------------------------------------------------------- ! to ocn: downward longwave heat flux from atm ! to ocn: downward direct near-infrared incident solar radiation from atm @@ -2255,12 +2286,21 @@ subroutine esmFldsExchange_cesm(gcomp, phase, rc) end if ! Liquid runoff from land and glc - merging + forr_rofl_glc_merged_to_ocn = .false. + if ( fldchk(is_local%wrap%FBExp(compocn), 'Forr_rofl_glc', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(comprof, comprof), 'Forr_rofl_glc', rc=rc)) then + ! If the ocean is prepared to handle Forr_rofl_glc as a separate field, then keep + ! it as a separate field rather than merging it to Foxx_rofl + call addmrg_to(compocn, 'Forr_rofl_glc', mrg_from=comprof, mrg_fld='Forr_rofl_glc', mrg_type='copy') + forr_rofl_glc_merged_to_ocn = .true. + end if if ( fldchk(is_local%wrap%FBExp(compocn), 'Foxx_rofl' , rc=rc)) then mrgfld_source = 'Forr_rofl' if (fldchk(is_local%wrap%FBImp(comprof, comprof), 'Flrr_flood', rc=rc)) then mrgfld_source = trim(mrgfld_source) //':Flrr_flood' end if - if (fldchk(is_local%wrap%FBImp(comprof, comprof), 'Forr_rofl_glc', rc=rc)) then + if (fldchk(is_local%wrap%FBImp(comprof, comprof), 'Forr_rofl_glc', rc=rc) .and. & + .not. forr_rofl_glc_merged_to_ocn) then mrgfld_source = trim(mrgfld_source) //':Forr_rofl_glc' end if call addmrg_to(compocn, 'Foxx_rofl', mrg_from=comprof, mrg_fld=trim(mrgfld_source), mrg_type='sum') @@ -2288,9 +2328,18 @@ subroutine esmFldsExchange_cesm(gcomp, phase, rc) end if ! Frozen runoff from land and glc - merging + forr_rofi_glc_merged_to_ocn = .false. + if ( fldchk(is_local%wrap%FBExp(compocn), 'Forr_rofi_glc', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(comprof, comprof), 'Forr_rofi_glc', rc=rc)) then + ! If the ocean is prepared to handle Forr_rofi_glc as a separate field, then keep + ! it as a separate field rather than merging it to Foxx_rofi + call addmrg_to(compocn, 'Forr_rofi_glc', mrg_from=comprof, mrg_fld='Forr_rofi_glc', mrg_type='copy') + forr_rofi_glc_merged_to_ocn = .true. + end if if ( fldchk(is_local%wrap%FBExp(compocn), 'Foxx_rofi' , rc=rc)) then mrgfld_source = 'Forr_rofi' - if (fldchk(is_local%wrap%FBImp(comprof, comprof), 'Forr_rofi_glc', rc=rc)) then + if (fldchk(is_local%wrap%FBImp(comprof, comprof), 'Forr_rofi_glc', rc=rc) .and. & + .not. forr_rofi_glc_merged_to_ocn) then mrgfld_source = trim(mrgfld_source) //':Forr_rofi_glc' end if call addmrg_to(compocn, 'Foxx_rofi', mrg_from=comprof, mrg_fld=trim(mrgfld_source), mrg_type='sum') @@ -2334,6 +2383,229 @@ subroutine esmFldsExchange_cesm(gcomp, phase, rc) call addmrg_to(compocn, 'Sw_lamult', mrg_from=compwav, mrg_fld='Sw_lamult', mrg_type='copy') end if end if + if (ocn_name == 'mpaso') then + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_Hs') + call addfld_to(compocn, 'Sw_Hs') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_Hs', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_Hs', rc=rc)) then + call addmap_from(compwav, 'Sw_Hs', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_Hs', mrg_from=compwav, mrg_fld='Sw_hs', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_Fp') + call addfld_to(compocn, 'Sw_Fp') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_Fp', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_Fp', rc=rc)) then + call addmap_from(compwav, 'Sw_Fp', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_Fp', mrg_from=compwav, mrg_fld='Sw_Fp', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_ustokes_wavenumber_1') + call addfld_to(compocn, 'Sw_ustokes_wavenumber_1') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_ustokes_wavenumber_1', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_ustokes_wavenumber_1', rc=rc)) then + call addmap_from(compwav, 'Sw_ustokes_wavenumber_1', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_ustokes_wavenumber_1', mrg_from=compwav, mrg_fld='Sw_ustokes_wavenumber_1', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_vstokes_wavenumber_1') + call addfld_to(compocn, 'Sw_vstokes_wavenumber_1') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_vstokes_wavenumber_1', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_vstokes_wavenumber_1', rc=rc)) then + call addmap_from(compwav, 'Sw_vstokes_wavenumber_1', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_vstokes_wavenumber_1', mrg_from=compwav, mrg_fld='Sw_lamult', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_ustokes_wavenumber_2') + call addfld_to(compocn, 'Sw_ustokes_wavenumber_2') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_ustokes_wavenumber_2', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_ustokes_wavenumber_2', rc=rc)) then + call addmap_from(compwav, 'Sw_ustokes_wavenumber_2', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_ustokes_wavenumber_2', mrg_from=compwav, mrg_fld='Sw_ustokes_wavenumber_2', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_vstokes_wavenumber_2') + call addfld_to(compocn, 'Sw_vstokes_wavenumber_2') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_vstokes_wavenumber_2', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_vstokes_wavenumber_2', rc=rc)) then + call addmap_from(compwav, 'Sw_vstokes_wavenumber_2', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_vstokes_wavenumber_2', mrg_from=compwav, mrg_fld='Sw_lamult', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_ustokes_wavenumber_3') + call addfld_to(compocn, 'Sw_ustokes_wavenumber_3') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_ustokes_wavenumber_3', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_ustokes_wavenumber_3', rc=rc)) then + call addmap_from(compwav, 'Sw_ustokes_wavenumber_3', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_ustokes_wavenumber_3', mrg_from=compwav, mrg_fld='Sw_ustokes_wavenumber_3', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_vstokes_wavenumber_3') + call addfld_to(compocn, 'Sw_vstokes_wavenumber_3') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_vstokes_wavenumber_3', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_vstokes_wavenumber_3', rc=rc)) then + call addmap_from(compwav, 'Sw_vstokes_wavenumber_3', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_vstokes_wavenumber_3', mrg_from=compwav, mrg_fld='Sw_lamult', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_ustokes_wavenumber_4') + call addfld_to(compocn, 'Sw_ustokes_wavenumber_4') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_ustokes_wavenumber_4', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_ustokes_wavenumber_4', rc=rc)) then + call addmap_from(compwav, 'Sw_ustokes_wavenumber_4', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_ustokes_wavenumber_4', mrg_from=compwav, mrg_fld='Sw_ustokes_wavenumber_4', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_vstokes_wavenumber_4') + call addfld_to(compocn, 'Sw_vstokes_wavenumber_4') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_vstokes_wavenumber_4', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_vstokes_wavenumber_4', rc=rc)) then + call addmap_from(compwav, 'Sw_vstokes_wavenumber_4', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_vstokes_wavenumber_4', mrg_from=compwav, mrg_fld='Sw_lamult', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_ustokes_wavenumber_5') + call addfld_to(compocn, 'Sw_ustokes_wavenumber_5') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_ustokes_wavenumber_5', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_ustokes_wavenumber_5', rc=rc)) then + call addmap_from(compwav, 'Sw_ustokes_wavenumber_5', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_ustokes_wavenumber_5', mrg_from=compwav, mrg_fld='Sw_ustokes_wavenumber_5', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_vstokes_wavenumber_5') + call addfld_to(compocn, 'Sw_vstokes_wavenumber_5') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_vstokes_wavenumber_5', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_vstokes_wavenumber_5', rc=rc)) then + call addmap_from(compwav, 'Sw_vstokes_wavenumber_5', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_vstokes_wavenumber_5', mrg_from=compwav, mrg_fld='Sw_lamult', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_ustokes_wavenumber_6') + call addfld_to(compocn, 'Sw_ustokes_wavenumber_6') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_ustokes_wavenumber_6', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_ustokes_wavenumber_6', rc=rc)) then + call addmap_from(compwav, 'Sw_ustokes_wavenumber_6', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_ustokes_wavenumber_6', mrg_from=compwav, mrg_fld='Sw_ustokes_wavenumber_6', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_vstokes_wavenumber_6') + call addfld_to(compocn, 'Sw_vstokes_wavenumber_6') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_vstokes_wavenumber_6', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_vstokes_wavenumber_6', rc=rc)) then + call addmap_from(compwav, 'Sw_vstokes_wavenumber_6', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_vstokes_wavenumber_6', mrg_from=compwav, mrg_fld='Sw_lamult', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_ustokes_wavenumber_6') + call addfld_to(compocn, 'Sw_ustokes_wavenumber_6') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_ustokes_wavenumber_6', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_ustokes_wavenumber_6', rc=rc)) then + call addmap_from(compwav, 'Sw_ustokes_wavenumber_6', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_ustokes_wavenumber_6', mrg_from=compwav, mrg_fld='Sw_ustokes_wavenumber_6', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_vstokes_wavenumber_6') + call addfld_to(compocn, 'Sw_vstokes_wavenumber_6') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_vstokes_wavenumber_6', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_vstokes_wavenumber_6', rc=rc)) then + call addmap_from(compwav, 'Sw_vstokes_wavenumber_6', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_vstokes_wavenumber_6', mrg_from=compwav, mrg_fld='Sw_lamult', mrg_type='copy') + end if + end if + !----------------------------- + ! to ocn: + !----------------------------- + if (phase == 'advertise') then + call addfld_from(compwav, 'Sw_Dp') + call addfld_to(compocn, 'Sw_Dp') + else + if ( fldchk(is_local%wrap%FBExp(compocn) , 'Sw_Dp', rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav, compwav), 'Sw_Dp', rc=rc)) then + call addmap_from(compwav, 'Sw_Dp', compocn, mapbilnr_nstod, 'one', wav2ocn_map) + call addmrg_to(compocn, 'Sw_Dp', mrg_from=compwav, mrg_fld='Sw_Dp', mrg_type='copy') + end if + end if + end if !----------------------------- ! to ocn: Stokes drift u component from wave !----------------------------- @@ -2766,6 +3038,21 @@ subroutine esmFldsExchange_cesm(gcomp, phase, rc) end if end if ! --------------------------------------------------------------------- + ! to ice: frazil from ocn + ! --------------------------------------------------------------------- + if (ocn_name == 'mpaso' .or. ice_name == 'mpassi') then + if (phase == 'advertise') then + call addfld_from(compocn, 'Fioo_frazil') + call addfld_to(compice, 'Fioo_frazil') + else + if ( fldchk(is_local%wrap%FBImp(compocn, compocn), 'Fioo_frazil', rc=rc) .and. & + fldchk(is_local%wrap%FBExp(compice) , 'Fioo_frazil', rc=rc)) then + call addmap_from(compocn, 'Fioo_frazil', compice, mapfcopy, 'unset', 'unset') + call addmrg_to(compice, 'Fioo_frazil', mrg_from=compocn, mrg_fld='Fioo_frazil', mrg_type='copy') + end if + end if + end if + ! --------------------------------------------------------------------- ! to ice: wave elevation spectrum (field with ungridded dimensions) ! --------------------------------------------------------------------- if (wav_coupling_to_cice) then diff --git a/mediator/esmFldsExchange_hafs_mod.F90 b/mediator/esmFldsExchange_hafs_mod.F90 index b545b9b1c..0515c8707 100644 --- a/mediator/esmFldsExchange_hafs_mod.F90 +++ b/mediator/esmFldsExchange_hafs_mod.F90 @@ -280,6 +280,18 @@ subroutine esmFldsExchange_hafs_advt(gcomp, phase, rc) end if end if + ! to ocn: partitioned stokes drift from wav + if (hafs_attr%wav_present .and. hafs_attr%ocn_present) then + allocate(S_flds(2)) + S_flds = (/'Sw_pstokes_x', 'Sw_pstokes_y'/) + do n = 1,size(S_flds) + fldname = trim(S_flds(n)) + call addfld_from(compwav , fldname) + call addfld_to(compocn , fldname) + end do + deallocate(S_flds) + end if + !===================================================================== ! FIELDS TO WAVE (compwav) !===================================================================== @@ -298,6 +310,22 @@ subroutine esmFldsExchange_hafs_advt(gcomp, phase, rc) deallocate(S_flds) end if + ! --------------------------------------------------------------------- + ! to wav: states from ocn + ! - zonal sea water velocity from ocn + ! - meridional sea water velocity from ocn + ! --------------------------------------------------------------------- + if (hafs_attr%ocn_present .and. hafs_attr%wav_present) then + allocate(S_flds(2)) + S_flds = (/'So_u', 'So_v'/) + do n = 1,size(S_flds) + fldname = trim(S_flds(n)) + call addfld_from(compocn , fldname) + call addfld_to(compwav , fldname) + end do + deallocate(S_flds) + end if + call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO) end subroutine esmFldsExchange_hafs_advt @@ -569,6 +597,22 @@ subroutine esmFldsExchange_hafs_init(gcomp, phase, rc) end if end if + ! --------------------------------------------------------------------- + ! to ocn: partitioned stokes drift from wav + ! --------------------------------------------------------------------- + allocate(S_flds(2)) + S_flds = (/'Sw_pstokes_x', 'Sw_pstokes_y'/) + do n = 1,size(S_flds) + fldname = trim(S_flds(n)) + if ( fldchk(is_local%wrap%FBexp(compocn) , fldname, rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compwav,compwav), fldname, rc=rc)) then + call addmap_from(compwav, fldname, compocn, mapfillv_bilnr, & + hafs_attr%mapnorm, 'unset') + call addmrg_to(compocn, fldname, mrg_from=compwav, mrg_fld=fldname, mrg_type='copy') + end if + end do + deallocate(S_flds) + !===================================================================== ! FIELDS TO WAVE (compwav) !===================================================================== @@ -581,7 +625,7 @@ subroutine esmFldsExchange_hafs_init(gcomp, phase, rc) S_flds = (/'Sa_u10m', 'Sa_v10m'/) do n = 1,size(S_flds) fldname = trim(S_flds(n)) - if (fldchk(is_local%wrap%FBexp(compwav),trim(fldname),rc=rc) .and. & + if (fldchk(is_local%wrap%FBexp(compwav), trim(fldname),rc=rc) .and. & fldchk(is_local%wrap%FBImp(compatm,compatm), trim(fldname),rc=rc) & ) then call addmap_from(compatm, trim(fldname), compwav, & @@ -593,6 +637,24 @@ subroutine esmFldsExchange_hafs_init(gcomp, phase, rc) deallocate(S_flds) end if + ! --------------------------------------------------------------------- + ! to wav: states from ocn + ! - zonal sea water velocity from ocn + ! - meridional sea water velocity from ocn + ! --------------------------------------------------------------------- + allocate(S_flds(2)) + S_flds = (/'So_u', 'So_v'/) + do n = 1,size(S_flds) + fldname = trim(S_flds(n)) + if ( fldchk(is_local%wrap%FBexp(compwav) , fldname, rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compocn,compocn), fldname, rc=rc)) then + call addmap_from(compocn, fldname, compwav, mapfillv_bilnr, & + hafs_attr%mapnorm, 'unset') + call addmrg_to(compwav, fldname, mrg_from=compocn, mrg_fld=fldname, mrg_type='copy') + end if + end do + deallocate(S_flds) + call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO) end subroutine esmFldsExchange_hafs_init diff --git a/mediator/esmFldsExchange_ufs_mod.F90 b/mediator/esmFldsExchange_ufs_mod.F90 index 57c266b59..dd342cf07 100644 --- a/mediator/esmFldsExchange_ufs_mod.F90 +++ b/mediator/esmFldsExchange_ufs_mod.F90 @@ -11,12 +11,15 @@ module esmFldsExchange_ufs_mod public :: esmFldsExchange_ufs + integer :: atm2lnd_maptype + integer :: lnd2atm_maptype + character(*), parameter :: u_FILE_u = & __FILE__ -!================================================================================ + !================================================================================ contains -!================================================================================ + !================================================================================ subroutine esmFldsExchange_ufs(gcomp, phase, rc) @@ -27,10 +30,10 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) use med_methods_mod , only : fldchk => med_methods_FB_FldChk use med_internalstate_mod , only : InternalState use med_internalstate_mod , only : compmed, compatm, compocn, compice, complnd, compwav, ncomps - use med_internalstate_mod , only : mapbilnr, mapconsf, mapconsd, mappatch + use med_internalstate_mod , only : mapbilnr, mapconsf, mapconsd, mappatch, mappatch_uv3d use med_internalstate_mod , only : mapfcopy, mapnstod, mapnstod_consd, mapnstod_consf - use med_internalstate_mod , only : mapconsf_aofrac, mapbilnr_nstod - use med_internalstate_mod , only : coupling_mode, mapnames + use med_internalstate_mod , only : mapconsf_aofrac, mapbilnr_nstod, mapconsf_uv3d + use med_internalstate_mod , only : coupling_mode, mapnames, samegrid_atmlnd use esmFlds , only : med_fldList_type use esmFlds , only : addfld_to => med_fldList_addfld_to use esmFlds , only : addmrg_to => med_fldList_addmrg_to @@ -50,11 +53,16 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) type(InternalState) :: is_local integer :: n, maptype logical :: med_aoflux_to_ocn + logical :: mapuv_with_cart3d + logical :: isPresent, isSet character(len=CX) :: msgString character(len=CL) :: cvalue character(len=CS) :: fldname character(len=CS), allocatable :: flds(:), oflds(:), aflds(:), iflds(:) character(len=*) , parameter :: subname='(esmFldsExchange_ufs)' + + ! component name + character(len=CS) :: lnd_name = '' !-------------------------------------- rc = ESMF_SUCCESS @@ -69,19 +77,46 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) ! Set maptype according to coupling_mode if (trim(coupling_mode) == 'ufs.nfrac' .or. trim(coupling_mode) == 'ufs.nfrac.aoflux') then - maptype = mapnstod_consf + maptype = mapnstod_consf else - maptype = mapconsf + maptype = mapconsf end if write(msgString,'(A,i6,A)') trim(subname)//': maptype is ',maptype,', '//mapnames(maptype) call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO) + ! determine which land model is present + if (is_local%wrap%comp_present(complnd)) then + call NUOPC_CompAttributeGet(gcomp, name="LND_model", value=cvalue, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + lnd_name = trim(cvalue) + end if + + ! uv cart3d mapping, default is true + mapuv_with_cart3d = .true. + call NUOPC_CompAttributeGet(gcomp, name='mapuv_with_cart3d', value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (isPresent .and. isSet) then + if (trim(cvalue) == 'false') then + mapuv_with_cart3d = .false. + end if + end if + if (trim(coupling_mode) == 'ufs.nfrac.aoflux' .or. trim(coupling_mode) == 'ufs.frac.aoflux') then med_aoflux_to_ocn = .true. else med_aoflux_to_ocn = .false. end if + ! determine if atm and lnd have the same mesh + if (phase == 'advertise') then + atm2lnd_maptype = maptype + lnd2atm_maptype = maptype + if (samegrid_atmlnd) then + atm2lnd_maptype = mapfcopy + lnd2atm_maptype = mapfcopy + end if + end if + !===================================================================== ! scalar information !===================================================================== @@ -124,7 +159,7 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) call addfld_from(compatm , fldname) else if ( fldchk(is_local%wrap%FBImp(compatm,compatm), fldname, rc=rc)) then - call addmap_from(compatm, fldname, compocn, maptype, 'one', 'unset') + call addmap_from(compatm, fldname, compocn, mapbilnr, 'one', 'unset') end if end if end do @@ -248,7 +283,7 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) do n = 1,size(flds) if ( fldchk(is_local%wrap%FBexp(compatm) , 'Fall_'//trim(flds(n)), rc=rc) .and. & fldchk(is_local%wrap%FBImp(complnd,complnd), 'Fall_'//trim(flds(n)), rc=rc)) then - call addmap_from(complnd, 'Fall_'//trim(flds(n)), compatm, maptype, 'lfrac', 'unset') + call addmap_from(complnd, 'Fall_'//trim(flds(n)), compatm, lnd2atm_maptype, 'lfrac', 'unset') call addmrg_to(compatm, 'Fall_'//trim(flds(n)), mrg_from=complnd, mrg_fld='Fall_'//trim(flds(n)), mrg_type='copy') end if end do @@ -269,7 +304,7 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) do n = 1,size(flds) if ( fldchk(is_local%wrap%FBexp(compatm) , 'Sl_'//trim(flds(n)), rc=rc) .and. & fldchk(is_local%wrap%FBImp(complnd,complnd), 'Sl_'//trim(flds(n)), rc=rc)) then - call addmap_from(complnd, 'Sl_'//trim(flds(n)), compatm, maptype, 'lfrac', 'unset') + call addmap_from(complnd, 'Sl_'//trim(flds(n)), compatm, lnd2atm_maptype, 'lfrac', 'unset') call addmrg_to(compatm, 'Sl_'//trim(flds(n)), mrg_from=complnd, mrg_fld='Sl_'//trim(flds(n)), mrg_type='copy') end if end do @@ -433,7 +468,11 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) fldchk(is_local%wrap%FBImp(compice,compice), 'Fioi_'//fldname, rc=rc) .and. & fldchk(is_local%wrap%FBImp(compatm,compatm), 'Faxa_'//fldname, rc=rc)) then call addmap_from(compice, 'Fioi_'//fldname, compocn, mapfcopy, 'unset', 'unset') - call addmap_from(compatm, 'Faxa_'//fldname, compocn, mapconsf_aofrac, 'aofrac', 'unset') + if (mapuv_with_cart3d) then + call addmap_from(compatm, 'Faxa_'//fldname, compocn, mapconsf_uv3d, 'aofrac', 'unset') + else + call addmap_from(compatm, 'Faxa_'//fldname, compocn, mapconsf_aofrac, 'aofrac', 'unset') + end if call addmrg_to(compocn, 'Foxx_'//fldname, & mrg_from=compice, mrg_fld='Fioi_'//fldname, mrg_type='merge', mrg_fracname='ifrac') call addmrg_to(compocn, 'Foxx_'//fldname, & @@ -441,7 +480,7 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) end if end if end if - end do + end do deallocate(flds) ! to ocn: net long wave via auto merge @@ -605,8 +644,8 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) ! - zonal wind at the lowest model level from atm ! - meridional wind at the lowest model level from atm ! - specific humidity at the lowest model level from atm - allocate(flds(6)) - flds = (/'Sa_u ', 'Sa_v ', 'Sa_z ', 'Sa_tbot', 'Sa_pbot', 'Sa_shum'/) + allocate(flds(4)) + flds = (/'Sa_z ', 'Sa_tbot', 'Sa_pbot', 'Sa_shum'/) do n = 1,size(flds) fldname = trim(flds(n)) if (phase == 'advertise') then @@ -617,13 +656,37 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) else if ( fldchk(is_local%wrap%FBexp(compice) , fldname, rc=rc) .and. & fldchk(is_local%wrap%FBImp(compatm,compatm), fldname, rc=rc)) then - call addmap_from(compatm, fldname, compice, maptype, 'one', 'unset') + call addmap_from(compatm, fldname, compice, mapbilnr, 'one', 'unset') call addmrg_to(compice, fldname, mrg_from=compatm, mrg_fld=fldname, mrg_type='copy') end if end if end do deallocate(flds) + allocate(flds(2)) + flds = (/'Sa_u', 'Sa_v'/) + do n = 1,size(flds) + fldname = trim(flds(n)) + if (phase == 'advertise') then + if (is_local%wrap%comp_present(compatm) .and. is_local%wrap%comp_present(compice)) then + call addfld_from(compatm , fldname) + call addfld_to(compice , fldname) + endif + else + if ( fldchk(is_local%wrap%FBexp(compice) , fldname, rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compatm,compatm), fldname, rc=rc)) then + if (mapuv_with_cart3d) then + call addmap_from(compatm, fldname, compice, mappatch_uv3d, 'one', 'unset') + else + call addmap_from(compatm, fldname, compice, mappatch, 'one', 'unset') + end if + call addmrg_to(compice, fldname, mrg_from=compatm, mrg_fld=fldname, mrg_type='copy') + end if + end if + end do + deallocate(flds) + + ! to ice: states and fluxes from ocn ! - sea surface temperature from ocn ! - sea surface salinity from ocn @@ -684,58 +747,58 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) else if ( fldchk(is_local%wrap%FBexp(compwav) , fldname, rc=rc) .and. & fldchk(is_local%wrap%FBImp(compatm,compatm), fldname, rc=rc)) then - call addmap_from(compatm, fldname, compwav, mapbilnr_nstod, 'one', 'unset') + call addmap_from(compatm, fldname, compwav, mapbilnr, 'one', 'unset') call addmrg_to(compwav, fldname, mrg_from=compatm, mrg_fld=fldname, mrg_type='copy') end if end if - end do - deallocate(flds) - - ! to wav: states from ice - ! - sea ice fraction - ! - sea ice thickness - ! - sea ice floe diameter - allocate(flds(3)) - flds = (/'Si_ifrac ', 'Si_floediam', 'Si_thick '/) - do n = 1,size(flds) - fldname = trim(flds(n)) - if (phase == 'advertise') then - if (is_local%wrap%comp_present(compice) .and. is_local%wrap%comp_present(compwav)) then - call addfld_from(compice , fldname) - call addfld_to(compwav , fldname) - end if - else - if ( fldchk(is_local%wrap%FBexp(compwav) , fldname, rc=rc) .and. & - fldchk(is_local%wrap%FBImp(compice,compice), fldname, rc=rc)) then - call addmap_from(compice, fldname, compwav, mapbilnr_nstod , 'one', 'unset') - call addmrg_to(compwav, fldname, mrg_from=compice, mrg_fld=fldname, mrg_type='copy') - end if - end if - end do - deallocate(flds) - - ! to wav: states from ocn - ! - zonal sea water velocity from ocn - ! - meridional sea water velocity from ocn - ! - surface temperature from ocn - allocate(flds(3)) - flds = (/'So_u', 'So_v', 'So_t'/) - do n = 1,size(flds) - fldname = trim(flds(n)) - if (phase == 'advertise') then - if (is_local%wrap%comp_present(compocn) .and. is_local%wrap%comp_present(compwav)) then - call addfld_from(compocn , fldname) - call addfld_to(compwav , fldname) - end if - else - if ( fldchk(is_local%wrap%FBexp(compwav) , fldname, rc=rc) .and. & - fldchk(is_local%wrap%FBImp(compocn,compocn), fldname, rc=rc)) then - call addmap_from(compocn, fldname, compwav, mapbilnr_nstod , 'one', 'unset') - call addmrg_to(compwav, fldname, mrg_from=compocn, mrg_fld=fldname, mrg_type='copy') - end if - end if - end do - deallocate(flds) + end do + deallocate(flds) + + ! to wav: states from ice + ! - sea ice fraction + ! - sea ice thickness + ! - sea ice floe diameter + allocate(flds(3)) + flds = (/'Si_ifrac ', 'Si_floediam', 'Si_thick '/) + do n = 1,size(flds) + fldname = trim(flds(n)) + if (phase == 'advertise') then + if (is_local%wrap%comp_present(compice) .and. is_local%wrap%comp_present(compwav)) then + call addfld_from(compice , fldname) + call addfld_to(compwav , fldname) + end if + else + if ( fldchk(is_local%wrap%FBexp(compwav) , fldname, rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compice,compice), fldname, rc=rc)) then + call addmap_from(compice, fldname, compwav, mapbilnr_nstod , 'one', 'unset') + call addmrg_to(compwav, fldname, mrg_from=compice, mrg_fld=fldname, mrg_type='copy') + end if + end if + end do + deallocate(flds) + + ! to wav: states from ocn + ! - zonal sea water velocity from ocn + ! - meridional sea water velocity from ocn + ! - surface temperature from ocn + allocate(flds(3)) + flds = (/'So_u', 'So_v', 'So_t'/) + do n = 1,size(flds) + fldname = trim(flds(n)) + if (phase == 'advertise') then + if (is_local%wrap%comp_present(compocn) .and. is_local%wrap%comp_present(compwav)) then + call addfld_from(compocn , fldname) + call addfld_to(compwav , fldname) + end if + else + if ( fldchk(is_local%wrap%FBexp(compwav) , fldname, rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compocn,compocn), fldname, rc=rc)) then + call addmap_from(compocn, fldname, compwav, mapbilnr_nstod , 'one', 'unset') + call addmrg_to(compwav, fldname, mrg_from=compocn, mrg_fld=fldname, mrg_type='copy') + end if + end if + end do + deallocate(flds) !===================================================================== ! FIELDS TO LAND (complnd) @@ -766,13 +829,35 @@ subroutine esmFldsExchange_ufs(gcomp, phase, rc) else if ( fldchk(is_local%wrap%FBexp(complnd) , fldname, rc=rc) .and. & fldchk(is_local%wrap%FBImp(compatm,compatm), fldname, rc=rc)) then - call addmap_from(compatm, fldname, complnd, maptype, 'one', 'unset') + call addmap_from(compatm, fldname, complnd, atm2lnd_maptype, 'one', 'unset') call addmrg_to(complnd, fldname, mrg_from=compatm, mrg_fld=fldname, mrg_type='copy') end if end if end do deallocate(flds) + + if (lnd_name == 'lm4') then + allocate(flds(4)) + flds = (/'Faxa_swndr', 'Faxa_swndf', 'Faxa_swvdr', 'Faxa_swvdf' /) + do n = 1,size(flds) + fldname = trim(flds(n)) + if (phase == 'advertise') then + if (is_local%wrap%comp_present(compatm) .and. is_local%wrap%comp_present(complnd)) then + call addfld_from(compatm , fldname) + call addfld_to(complnd , fldname) + end if + else + if ( fldchk(is_local%wrap%FBexp(complnd) , fldname, rc=rc) .and. & + fldchk(is_local%wrap%FBImp(compatm,compatm), fldname, rc=rc)) then + call addmap_from(compatm, fldname, complnd, maptype, 'one', 'unset') + call addmrg_to(complnd, fldname, mrg_from=compatm, mrg_fld=fldname, mrg_type='copy') + end if + end if + end do + deallocate(flds) + end if ! lm4 + end subroutine esmFldsExchange_ufs end module esmFldsExchange_ufs_mod diff --git a/mediator/fd_cesm.yaml b/mediator/fd_cesm.yaml index 231200982..6a0e2be80 100644 --- a/mediator/fd_cesm.yaml +++ b/mediator/fd_cesm.yaml @@ -764,6 +764,10 @@ canonical_units: m description: ice import to med - surface_snow_water_equivalent # + - standard_name: Si_ithick + canonical_units: m + description: sea-ice export - ice thickness + # - standard_name: Si_vsno alias: mean_snow_volume canonical_units: m @@ -777,6 +781,11 @@ canonical_units: m description: ice import to med - ice floe diameter # + - standard_name: Si_bpress + alias: basal_pressure + canonical_units: Pa + description: sea-ice export - ice basal pressure + # #----------------------------------- # section: ocn import to med #----------------------------------- @@ -786,6 +795,11 @@ canonical_units: W m-2 description: ocn import to med # + - standard_name: Fioo_frazil + alias: frazil_mass_flux + canonical_units: kg m-2 s-1 + description: ocean export + # - standard_name: Faoo_fco2_ocn canonical_units: moles m-2 s-1 description: ocn import to med - surface flux of CO2 (downward positive) @@ -1121,6 +1135,66 @@ canonical_units: 1 description: ocean import - Langmuir multiplier # + - standard_name: Sw_Hs + canonical_units: m + description: ocean import - Significant wave height + # + - standard_name: Sw_Fp + canonical_units: 1 + description: ocean import - Peak wave frequency + # + - standard_name: Sw_Dp + canonical_units: 1 + description: ocean import - Peak wave direction + # + - standard_name: Sw_ustokes_wavenumber_1 + canonical_units: m/s + description: ocean import - partitioned Stokes drift zonal wavenumber 1 + # + - standard_name: Sw_vstokes_wavenumber_1 + canonical_units: m/s + description: ocean import - partitioned Stokes drift meridional wavenumber 1 + # + - standard_name: Sw_ustokes_wavenumber_2 + canonical_units: m/s + description: ocean import - partitioned Stokes drift zonal wavenumber 2 + # + - standard_name: Sw_vstokes_wavenumber_2 + canonical_units: m/s + description: ocean import - partitioned Stokes drift meridional wavenumber 2 + # + - standard_name: Sw_ustokes_wavenumber_3 + canonical_units: m/s + description: ocean import - partitioned Stokes drift zonal wavenumber 3 + # + - standard_name: Sw_vstokes_wavenumber_3 + canonical_units: m/s + description: ocean import - partitioned Stokes drift meridional wavenumber 3 + # + - standard_name: Sw_ustokes_wavenumber_4 + canonical_units: m/s + description: ocean import - partitioned Stokes drift zonal wavenumber 4 + # + - standard_name: Sw_vstokes_wavenumber_4 + canonical_units: m/s + description: ocean import - partitioned Stokes drift meridional wavenumber 4 + # + - standard_name: Sw_ustokes_wavenumber_5 + canonical_units: m/s + description: ocean import - partitioned Stokes drift zonal wavenumber 5 + # + - standard_name: Sw_vstokes_wavenumber_5 + canonical_units: m/s + description: ocean import - partitioned Stokes drift meridional wavenumber 5 + # + - standard_name: Sw_ustokes_wavenumber_6 + canonical_units: m/s + description: ocean import - partitioned Stokes drift zonal wavenumber 6 + # + - standard_name: Sw_vstokes_wavenumber_6 + canonical_units: m/s + description: ocean import - partitioned Stokes drift meridional wavenumber 6 + # - standard_name: Sw_ustokes canonical_units: m/s description: ocean import - Stokes drift u component diff --git a/mediator/med_diag_mod.F90 b/mediator/med_diag_mod.F90 index e07898624..85edea7c0 100644 --- a/mediator/med_diag_mod.F90 +++ b/mediator/med_diag_mod.F90 @@ -1751,7 +1751,7 @@ subroutine med_diag_print_atm(data, ip, date, tod) integer , intent(in) :: tod ! local variables - integer :: ic,nf,is ! data array indicies + integer :: ic,nf ! data array indicies integer :: ica,icl integer :: icn,ics,ico character(len=40) :: str ! string @@ -1873,7 +1873,7 @@ subroutine med_diag_print_lnd_ice_ocn(data, ip, date, tod) integer , intent(in) :: tod ! local variables - integer :: ic,nf,is ! data array indicies + integer :: ic,nf ! data array indicies integer :: icar,icas integer :: icxs,icxr character(len=40) :: str ! string @@ -1980,7 +1980,7 @@ subroutine med_diag_print_summary(data, ip, date, tod) integer , intent(in) :: tod ! local variables - integer :: nf,is ! data array indicies + integer :: nf ! data array index real(r8) :: atm_area, lnd_area, ocn_area real(r8) :: ice_area_nh, ice_area_sh real(r8) :: sum_area diff --git a/mediator/med_internalstate_mod.F90 b/mediator/med_internalstate_mod.F90 index d2171b068..01ce1a42f 100644 --- a/mediator/med_internalstate_mod.F90 +++ b/mediator/med_internalstate_mod.F90 @@ -77,7 +77,8 @@ module med_internalstate_mod integer , public, parameter :: mapfillv_bilnr = 15 ! fill value followed by bilinear integer , public, parameter :: mapbilnr_nstod = 16 ! bilinear with nstod extrapolation integer , public, parameter :: mapconsf_aofrac = 17 ! conservative with aofrac normalization (ufs only) - integer , public, parameter :: nmappers = 17 + integer , public, parameter :: mapconsf_uv3d = 18 ! conservative with uv3d mapping + integer , public, parameter :: nmappers = 18 character(len=*) , public, parameter :: mapnames(nmappers) = & (/'bilnr ',& 'consf ',& @@ -95,7 +96,8 @@ module med_internalstate_mod 'glc2ocn_liq ',& 'fillv_bilnr ',& 'bilnr_nstod ',& - 'consf_aofrac'/) + 'consf_aofrac',& + 'consf_uv3d '/) type, public :: packed_data_type integer, allocatable :: fldindex(:) ! size of number of packed fields @@ -263,6 +265,23 @@ subroutine med_internalstate_init(gcomp, rc) samegrid_atmlnd = .true. end if + ! flexibility to overwrite samegrid_atmlnd option + call NUOPC_CompAttributeGet(gcomp, name='samegrid_atmlnd', value=cvalue, & + isPresent=isPresent, isSet=isSet, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + if (isPresent .and. isSet) then + if (trim(cvalue) == '.true.' .or. trim(cvalue) == 'true') then + samegrid_atmlnd = .true. + else + samegrid_atmlnd = .false. + end if + end if + + if (maintask) then + write(logunit,'(a,l2)') trim(subname)//' atm and lnd is on same grid = ', samegrid_atmlnd + end if + ! See med_fraction_mod for the following definitions if (samegrid_atmlnd) then map_fracname_lnd2atm = 'lfrin' ! in fraclist_a @@ -671,17 +690,16 @@ subroutine med_internalstate_defaultmasks(gcomp, rc) if (is_local%wrap%comp_present(compice)) defaultMasks(compice,:) = 0 if (is_local%wrap%comp_present(compwav)) defaultMasks(compwav,:) = 0 if ( coupling_mode(1:3) == 'ufs') then - if (is_local%wrap%comp_present(compatm)) defaultMasks(compatm,:) = 1 + if (is_local%wrap%comp_present(compatm)) defaultMasks(compatm,2) = 1 endif - if ( trim(coupling_mode) == 'hafs') then + if ( trim(coupling_mode) == 'hafs') then ! not hafs.mom6 if (is_local%wrap%comp_present(compatm)) defaultMasks(compatm,1) = 1 endif - if ( trim(coupling_mode) /= 'cesm') then - if (is_local%wrap%comp_present(compatm) .and. trim(atm_name(1:4)) == 'datm') then + if ( coupling_mode /= 'cesm') then + if (is_local%wrap%comp_present(compatm) .and. atm_name(1:4) == 'datm') then defaultMasks(compatm,1) = 0 end if end if - end subroutine med_internalstate_defaultmasks end module med_internalstate_mod diff --git a/mediator/med_map_mod.F90 b/mediator/med_map_mod.F90 index 5caeb8ca6..daacdd4af 100644 --- a/mediator/med_map_mod.F90 +++ b/mediator/med_map_mod.F90 @@ -10,7 +10,7 @@ module med_map_mod use med_utils_mod , only : chkerr => med_utils_ChkErr use perf_mod , only : t_startf, t_stopf use shr_log_mod , only : shr_log_error - + implicit none private @@ -299,7 +299,7 @@ end subroutine med_map_RouteHandles_initfrom_esmflds subroutine med_map_routehandles_initfrom_fieldbundle(n1, n2, FBsrc, FBdst, mapindex, RouteHandle, rc) use ESMF , only : ESMF_LogWrite, ESMF_LOGMSG_INFO, ESMF_SUCCESS, ESMF_LogFlush - use ESMF , only : ESMf_Field, ESMF_FieldBundle, ESMF_RouteHandle + use ESMF , only : ESMF_Field, ESMF_FieldBundle, ESMF_RouteHandle use med_methods_mod , only : med_methods_FB_getFieldN !--------------------------------------------- @@ -361,7 +361,7 @@ subroutine med_map_routehandles_initfrom_field(n1, n2, fldsrc, flddst, mapindex, use med_internalstate_mod , only : mapbilnr, mapconsf, mapconsd, mappatch, mappatch_uv3d, mapbilnr_uv3d, mapfcopy use med_internalstate_mod , only : mapunset, mapnames, nmappers use med_internalstate_mod , only : mapnstod, mapnstod_consd, mapnstod_consf, mapnstod_consd - use med_internalstate_mod , only : mapfillv_bilnr, mapbilnr_nstod, mapconsf_aofrac + use med_internalstate_mod , only : mapfillv_bilnr, mapbilnr_nstod, mapconsf_aofrac, mapconsf_uv3d use med_internalstate_mod , only : compocn, compwav, complnd, compname, compatm use med_internalstate_mod , only : coupling_mode use med_internalstate_mod , only : defaultMasks @@ -467,34 +467,46 @@ subroutine med_map_routehandles_initfrom_field(n1, n2, fldsrc, flddst, mapindex, ignoreUnmatchedIndices=.true., & srcTermProcessing=srcTermProcessing_Value, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - else if (mapindex == mapbilnr .or. mapindex == mapbilnr_uv3d) then - if (.not. ESMF_RouteHandleIsCreated(routehandles(mapbilnr))) then + else if (mapindex == mapbilnr ) then if (maintask) then write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) end if call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapbilnr), & - srcMaskValues=(/srcMaskValue/), & - dstMaskValues=(/dstMaskValue/), & - regridmethod=ESMF_REGRIDMETHOD_BILINEAR, & - polemethod=polemethod, & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_BILINEAR, & + polemethod=polemethod, & srcTermProcessing=srcTermProcessing_Value, & - ignoreDegenerate=.true., & - dstStatusField=lfield, & + ignoreDegenerate=.true., & + dstStatusField=lfield, & unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return + else if (mapindex == mapbilnr_uv3d ) then + if (maintask) then + write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) end if + call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapbilnr_uv3d), & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_BILINEAR, & + polemethod=polemethod, & + srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., & + dstStatusField=lfield, & + unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return else if (mapindex == mapfillv_bilnr) then if (maintask) then write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) end if call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapfillv_bilnr), & - srcMaskValues=(/srcMaskValue/), & - dstMaskValues=(/dstMaskValue/), & - regridmethod=ESMF_REGRIDMETHOD_BILINEAR, & - polemethod=polemethod, & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_BILINEAR, & + polemethod=polemethod, & srcTermProcessing=srcTermProcessing_Value, & - ignoreDegenerate=.true., & - dstStatusField=lfield, & + ignoreDegenerate=.true., & + dstStatusField=lfield, & unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return else if (mapindex == mapbilnr_nstod) then @@ -502,14 +514,14 @@ subroutine med_map_routehandles_initfrom_field(n1, n2, fldsrc, flddst, mapindex, write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) end if call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapbilnr_nstod), & - srcMaskValues=(/srcMaskValue/), & - dstMaskValues=(/dstMaskValue/), & - regridmethod=ESMF_REGRIDMETHOD_BILINEAR, & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_BILINEAR, & extrapMethod=ESMF_EXTRAPMETHOD_NEAREST_STOD, & - polemethod=polemethod, & - srcTermProcessing=srcTermProcessing_Value, & - ignoreDegenerate=.true., & - dstStatusField=lfield, & + polemethod=polemethod, & + srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., & + dstStatusField=lfield, & unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return else if (mapindex == mapconsf .or. mapindex == mapnstod_consf) then @@ -517,71 +529,85 @@ subroutine med_map_routehandles_initfrom_field(n1, n2, fldsrc, flddst, mapindex, write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) end if call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapconsf), & - srcMaskValues=(/srcMaskValue/), & - dstMaskValues=(/dstMaskValue/), & - regridmethod=ESMF_REGRIDMETHOD_CONSERVE, & - normType=ESMF_NORMTYPE_FRACAREA, & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, & + normType=ESMF_NORMTYPE_FRACAREA, & srcTermProcessing=srcTermProcessing_Value, & - ignoreDegenerate=.true., & - dstStatusField=lfield, & - unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & - rc=rc) + ignoreDegenerate=.true., & + dstStatusField=lfield, & + unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return else if (mapindex == mapconsf_aofrac) then - if (.not. ESMF_RouteHandleIsCreated(routehandles(mapconsf))) then - if (maintask) then - write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) - end if - call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapconsf_aofrac), & - srcMaskValues=(/srcMaskValue/), & - dstMaskValues=(/dstMaskValue/), & - regridmethod=ESMF_REGRIDMETHOD_CONSERVE, & - normType=ESMF_NORMTYPE_FRACAREA, & - srcTermProcessing=srcTermProcessing_Value, & - ignoreDegenerate=.true., & - dstStatusField=lfield, & - unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & - rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return - else - ! Copy existing consf RH - if (maintask) then - write(logunit,'(A)') trim(subname)//' copying RH(mapconsf) to '//trim(mapname)//' for '//trim(string) - end if - routehandles(mapconsf_aofrac) = ESMF_RouteHandleCreate(routehandles(mapconsf), rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return + if (maintask) then + write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) + end if + call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapconsf_aofrac), & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, & + normType=ESMF_NORMTYPE_FRACAREA, & + srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., & + dstStatusField=lfield, & + unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + else if (mapindex == mapconsf_uv3d) then + if (maintask) then + write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) end if + call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapconsf_uv3d), & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, & + normType=ESMF_NORMTYPE_FRACAREA, & + srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., & + dstStatusField=lfield, & + unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return else if (mapindex == mapconsd .or. mapindex == mapnstod_consd) then if (maintask) then write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) end if call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mapconsd), & - srcMaskValues=(/srcMaskValue/), & - dstMaskValues=(/dstMaskValue/), & - regridmethod=ESMF_REGRIDMETHOD_CONSERVE, & - normType=ESMF_NORMTYPE_DSTAREA, & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, & + normType=ESMF_NORMTYPE_DSTAREA, & srcTermProcessing=srcTermProcessing_Value, & - ignoreDegenerate=.true., & - dstStatusField=lfield, & - unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & - rc=rc) + ignoreDegenerate=.true., & + dstStatusField=lfield, & + unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - else if (mapindex == mappatch .or. mapindex == mappatch_uv3d) then - if (.not. ESMF_RouteHandleIsCreated(routehandles(mappatch))) then - if (maintask) then - write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) - end if - call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mappatch), & - srcMaskValues=(/srcMaskValue/), & - dstMaskValues=(/dstMaskValue/), & - regridmethod=ESMF_REGRIDMETHOD_PATCH, & - polemethod=polemethod, & - srcTermProcessing=srcTermProcessing_Value, & - ignoreDegenerate=.true., & - dstStatusField=lfield, & - unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) - if (chkerr(rc,__LINE__,u_FILE_u)) return + else if (mapindex == mappatch ) then + if (maintask) then + write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) + end if + call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mappatch), & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_PATCH, & + polemethod=polemethod, & + srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., & + dstStatusField=lfield, & + unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + else if (mapindex == mappatch_uv3d ) then + if (maintask) then + write(logunit,'(A)') trim(subname)//' creating RH '//trim(mapname)//' for '//trim(string) end if + call ESMF_FieldRegridStore(fldsrc, flddst, routehandle=routehandles(mappatch_uv3d), & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + regridmethod=ESMF_REGRIDMETHOD_PATCH, & + polemethod=polemethod, & + srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., & + dstStatusField=lfield, & + unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return else call shr_log_error(trim(subname)//' mapindex '//trim(mapname)//' not supported for '//trim(string), & line=__LINE__, file=u_FILE_u, rc=rc) @@ -922,7 +948,7 @@ subroutine med_map_field_packed(FBSrc, FBDst, FBFracSrc, FBDat, use_data, field_ use ESMF , only : ESMF_KIND_R8 use ESMF , only : ESMF_Region_Flag, ESMF_REGION_SELECT, ESMF_REGION_TOTAL use med_internalstate_mod , only : nmappers, mapfcopy - use med_internalstate_mod , only : mappatch_uv3d, mappatch, mapbilnr_uv3d, mapbilnr + use med_internalstate_mod , only : mappatch_uv3d, mappatch, mapbilnr_uv3d, mapconsf_uv3d, mapbilnr use med_internalstate_mod , only : packed_data_type use med_methods_mod , only : Field_diagnose => med_methods_Field_diagnose @@ -1005,13 +1031,19 @@ subroutine med_map_field_packed(FBSrc, FBDst, FBFracSrc, FBDat, use_data, field_ if (mapindex == mappatch_uv3d) then ! For mappatch_uv3d do not use packed field bundles - call med_map_uv_cart3d(FBsrc, FBdst, routehandles, mappatch, rc=rc) + call med_map_uv_cart3d(FBsrc, FBdst, routehandles, mappatch_uv3d, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return else if (mapindex == mapbilnr_uv3d) then ! For mapbilnr_uv3d do not use packed field bundles - call med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapbilnr, rc=rc) + call med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapbilnr_uv3d, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + else if (mapindex == mapconsf_uv3d) then + + ! For mapconsf_uv3d do not use packed field bundles + call med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapconsf_uv3d, map_stress=.true., rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return else @@ -1283,6 +1315,7 @@ subroutine med_map_field_normalized(field_src, field_dst, routehandles, maptype, character(len=*), parameter :: subname=' (med_map_mod:med_map_field_normalized) ' !----------------------------------------------------------- + call t_startf('MED:'//subname) rc = ESMF_SUCCESS ! get a pointer (data_fracsrc) to the normalization array @@ -1359,6 +1392,8 @@ subroutine med_map_field_normalized(field_src, field_dst, routehandles, maptype, end if end do end if + + call t_stopf('MED:'//subname) end subroutine med_map_field_normalized !================================================================================ @@ -1454,12 +1489,14 @@ subroutine med_map_field(field_src, field_dst, routehandles, maptype, fldname, z end subroutine med_map_field !================================================================================ - subroutine med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapindex, rc) - - use ESMF , only : ESMF_Mesh, ESMF_MeshGet, ESMF_MESHLOC_ELEMENT, ESMF_TYPEKIND_R8 - use ESMF , only : ESMF_Field, ESMF_FieldCreate, ESMF_FieldGet - use ESMF , only : ESMF_FieldBundle, ESMF_FieldBundleGet - use ESMF , only : ESMF_RouteHandle + subroutine med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapindex, map_stress, rc) + + use ESMF , only : operator(==) + use ESMF , only : ESMF_Mesh, ESMF_MeshGet, ESMF_MESHLOC_ELEMENT, ESMF_TYPEKIND_R8 + use ESMF , only : ESMF_Field, ESMF_FieldCreate, ESMF_FieldGet + use ESMF , only : ESMF_FieldBundle, ESMF_FieldBundleGet + use ESMF , only : ESMF_RouteHandle + use ESMF , only : ESMF_CoordSys_Flag, ESMF_COORDSYS_SPH_DEG, ESMF_COORDSYS_SPH_RAD use med_constants_mod , only : shr_const_pi ! input/output variables @@ -1467,48 +1504,69 @@ subroutine med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapindex, rc) type(ESMF_FieldBundle) , intent(inout) :: FBdst type(ESMF_RouteHandle) , intent(inout) :: routehandles(:) integer , intent(in) :: mapindex + logical, optional , intent(in) :: map_stress integer , intent(out) :: rc ! local variables - type(ESMF_Field) :: usrc - type(ESMF_Field) :: vsrc - type(ESMF_Field) :: udst - type(ESMF_Field) :: vdst - integer :: n - real(r8) :: lon,lat - real(r8) :: coslon,coslat - real(r8) :: sinlon,sinlat - real(r8) :: ux,uy,uz - type(ESMF_Mesh) :: lmesh_src - type(ESMF_Mesh) :: lmesh_dst - real(r8), pointer :: data_u_src(:) - real(r8), pointer :: data_u_dst(:) - real(r8), pointer :: data_v_src(:) - real(r8), pointer :: data_v_dst(:) - real(r8), pointer :: data2d_src(:,:) - real(r8), pointer :: data2d_dst(:,:) - real(r8), pointer :: ownedElemCoords_src(:) - real(r8), pointer :: ownedElemCoords_dst(:) - integer :: numOwnedElements - integer :: spatialDim - real(r8), parameter :: deg2rad = shr_const_pi/180.0_R8 ! deg to rads - logical :: first_time = .true. + type(ESMF_Field) :: usrc + type(ESMF_Field) :: vsrc + type(ESMF_Field) :: udst + type(ESMF_Field) :: vdst + type(ESMF_CoordSys_Flag) :: coordsys_src + type(ESMF_CoordSys_Flag) :: coordsys_dst + integer :: n + real(r8) :: lon,lat + real(r8) :: coslon,coslat + real(r8) :: sinlon,sinlat + real(r8) :: ux,uy,uz + type(ESMF_Mesh) :: lmesh_src + type(ESMF_Mesh) :: lmesh_dst + real(r8), pointer :: data_u_src(:) + real(r8), pointer :: data_u_dst(:) + real(r8), pointer :: data_v_src(:) + real(r8), pointer :: data_v_dst(:) + real(r8), pointer :: data2d_src(:,:) + real(r8), pointer :: data2d_dst(:,:) + real(r8), pointer :: ownedElemCoords_src(:) + real(r8), pointer :: ownedElemCoords_dst(:) + integer :: numOwnedElements + integer :: spatialDim + real(r8), parameter :: deg2rad = shr_const_pi/180.0_R8 ! deg to rads + logical :: first_time = .true. + logical :: lmap_stress + character(len=CS) :: uname, vname character(len=*), parameter :: subname=' (med_map_mod:med_map_uv_cart3d) ' !------------------------------------------------------------------------------- + call t_startf('MED:'//subname) rc = ESMF_SUCCESS + lmap_stress = .false. + if (present(map_stress)) then + lmap_stress = map_stress + end if + + if (lmap_stress) then + ! Get fields for atm zonal and merid stresses + uname = 'Faxa_taux' + vname = 'Faxa_tauy' + else + ! Get fields for atm u,v velocities + uname = 'Sa_u' + vname = 'Sa_v' + end if + ! Get fields for atm u,v velocities - call ESMF_FieldBundleGet(FBSrc, fieldName='Sa_u', field=usrc, rc=rc) + call ESMF_FieldBundleGet(FBSrc, fieldName=trim(uname), field=usrc, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleGet(FBDst, fieldName='Sa_u', field=udst, rc=rc) + call ESMF_FieldBundleGet(FBDst, fieldName=trim(uname), field=udst, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleGet(FBSrc, fieldName='Sa_v', field=vsrc, rc=rc) + call ESMF_FieldBundleGet(FBSrc, fieldName=trim(vname), field=vsrc, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_FieldBundleGet(FBDst, fieldName='Sa_v', field=vdst, rc=rc) + call ESMF_FieldBundleGet(FBDst, fieldName=trim(vname), field=vdst, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - ! GET pointer to input u and v data source field data + ! Get pointer to input u and v data source field data call ESMF_FieldGet(usrc, farrayPtr=data_u_src, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return call ESMF_FieldGet(vsrc, farrayPtr=data_v_src, rc=rc) @@ -1524,19 +1582,19 @@ subroutine med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapindex, rc) ! Get source mesh and coordinates call ESMF_FieldGet(usrc, mesh=lmesh_src, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_MeshGet(lmesh_src, spatialDim=spatialDim, numOwnedElements=numOwnedElements, rc=rc) + call ESMF_MeshGet(lmesh_src, spatialDim=spatialDim, numOwnedElements=numOwnedElements, coordSys=coordsys_src, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return allocate(ownedElemCoords_src(spatialDim*numOwnedElements)) - call ESMF_MeshGet(lmesh_src, ownedElemCoords=ownedElemCoords_src) + call ESMF_MeshGet(lmesh_src, ownedElemCoords=ownedElemCoords_src, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return ! Get destination mesh and coordinates call ESMF_FieldGet(udst, mesh=lmesh_dst, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - call ESMF_MeshGet(lmesh_dst, spatialDim=spatialDim, numOwnedElements=numOwnedElements, rc=rc) + call ESMF_MeshGet(lmesh_dst, spatialDim=spatialDim, numOwnedElements=numOwnedElements, coordSys=coordsys_dst, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return allocate(ownedElemCoords_dst(spatialDim*numOwnedElements)) - call ESMF_MeshGet(lmesh_dst, ownedElemCoords=ownedElemCoords_dst) + call ESMF_MeshGet(lmesh_dst, ownedElemCoords=ownedElemCoords_dst, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return if (first_time) then @@ -1561,12 +1619,17 @@ subroutine med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapindex, rc) ! Rotate Source data to cart3d do n = 1,size(data_u_src) - lon = ownedElemCoords_src(2*n-1) - lat = ownedElemCoords_src(2*n) - sinlon = sin(lon*deg2rad) - coslon = cos(lon*deg2rad) - sinlat = sin(lat*deg2rad) - coslat = cos(lat*deg2rad) + if (coordsys_src == ESMF_COORDSYS_SPH_DEG) then + lon = deg2rad*ownedElemCoords_src(2*n-1) + lat = deg2rad*ownedElemCoords_src(2*n) + else + lon = ownedElemCoords_src(2*n-1) + lat = ownedElemCoords_src(2*n) + end if + sinlon = sin(lon) + coslon = cos(lon) + sinlat = sin(lat) + coslat = cos(lat) data2d_src(1,n) = -coslon*sinlat*data_v_src(n) - sinlon*data_u_src(n) ! x data2d_src(2,n) = -sinlon*sinlat*data_v_src(n) + coslon*data_u_src(n) ! y data2d_src(3,n) = coslat*data_v_src(n) ! z @@ -1579,12 +1642,17 @@ subroutine med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapindex, rc) ! Rotate destination data back from cart3d to original do n = 1,size(data_u_dst) - lon = ownedElemCoords_dst(2*n-1) - lat = ownedElemCoords_dst(2*n) - sinlon = sin(lon*deg2rad) - coslon = cos(lon*deg2rad) - sinlat = sin(lat*deg2rad) - coslat = cos(lat*deg2rad) + if (coordsys_dst == ESMF_COORDSYS_SPH_DEG) then + lon = deg2rad*ownedElemCoords_dst(2*n-1) + lat = deg2rad*ownedElemCoords_dst(2*n) + else + lon = ownedElemCoords_dst(2*n-1) + lat = ownedElemCoords_dst(2*n) + end if + sinlon = sin(lon) + coslon = cos(lon) + sinlat = sin(lat) + coslat = cos(lat) ux = data2d_dst(1,n) uy = data2d_dst(2,n) uz = data2d_dst(3,n) @@ -1596,6 +1664,7 @@ subroutine med_map_uv_cart3d(FBsrc, FBdst, routehandles, mapindex, rc) deallocate(ownedElemCoords_src) deallocate(ownedElemCoords_dst) + call t_stopf('MED:'//subname) end subroutine med_map_uv_cart3d end module med_map_mod diff --git a/mediator/med_phases_ocnalb_mod.F90 b/mediator/med_phases_ocnalb_mod.F90 index 8590a2c7f..25c691ca1 100644 --- a/mediator/med_phases_ocnalb_mod.F90 +++ b/mediator/med_phases_ocnalb_mod.F90 @@ -105,7 +105,6 @@ subroutine med_phases_ocnalb_init(gcomp, ocnalb, rc) logical :: use_min_ocnalb logical :: isPresent, isSet integer :: fieldCount - character(CL) :: msg type(ESMF_Field), pointer :: fieldlist(:) character(*), parameter :: subname = '(med_phases_ocnalb_init) ' !----------------------------------------------------------------------- @@ -545,7 +544,7 @@ subroutine med_phases_ocnalb_orbital_init(gcomp, logunit, maintask, rc) use ESMF , only : ESMF_GridComp, ESMF_GridCompGet use ESMF , only : ESMF_LogWrite, ESMF_LogFoundError, ESMF_LogSetError - use ESMF , only : ESMf_SUCCESS, ESMF_FAILURE, ESMF_LOGMSG_INFO, ESMF_RC_NOT_VALID + use ESMF , only : ESMF_SUCCESS, ESMF_FAILURE, ESMF_LOGMSG_INFO, ESMF_RC_NOT_VALID use NUOPC , only : NUOPC_CompAttributeGet ! input/output variables diff --git a/mediator/med_phases_prep_atm_mod.F90 b/mediator/med_phases_prep_atm_mod.F90 index 0f031831a..b9665f5a8 100644 --- a/mediator/med_phases_prep_atm_mod.F90 +++ b/mediator/med_phases_prep_atm_mod.F90 @@ -288,7 +288,6 @@ subroutine med_phases_prep_atm_enthalpy_correction (gcomp, hcorr, rc) type(InternalState) :: is_local integer :: n real(r8) :: local_htot_corr(1) - real(r8) :: local_hrof_corr(1) type(ESMF_VM) :: vm !--------------------------------------- diff --git a/mediator/med_phases_restart_mod.F90 b/mediator/med_phases_restart_mod.F90 index 130c9c4a6..4dc72c43a 100644 --- a/mediator/med_phases_restart_mod.F90 +++ b/mediator/med_phases_restart_mod.F90 @@ -14,7 +14,12 @@ module med_phases_restart_mod use med_phases_prep_glc_mod , only : FBocnAccum2glc_o, ocnAccum2glc_cnt use med_phases_prep_rof_mod , only : FBlndAccum2rof_l, lndAccum2rof_cnt use pio , only : file_desc_t +#ifndef CESMCOUPLED + use shr_is_restart_fh_mod , only : init_is_restart_fh, is_restart_fh, is_restart_fh_type + use shr_is_restart_fh_mod , only : log_restart_fh +#endif use shr_log_mod , only : shr_log_error + implicit none private @@ -24,6 +29,9 @@ module med_phases_restart_mod private :: med_phases_restart_alarm_init logical :: write_restart_at_endofrun = .false. +#ifndef CESMCOUPLED + type(is_restart_fh_type) :: restartfh_info ! For flexible restarts in UFS +#endif logical :: whead(2) = (/.true. , .false./) logical :: wdata(2) = (/.false., .true. /) character(*), parameter :: u_FILE_u = & @@ -117,6 +125,10 @@ subroutine med_phases_restart_alarm_init(gcomp, rc) write(logunit,*) end if +#ifndef CESMCOUPLED + call init_is_restart_fh(mcurrtime, timestep_length,maintask, restartfh_info) +#endif + end subroutine med_phases_restart_alarm_init !=============================================================================== @@ -180,6 +192,9 @@ subroutine med_phases_restart_write(gcomp, rc) real(R8) :: tbnds(2) ! CF1.0 time bounds logical :: isPresent logical :: first_time = .true. +#ifndef CESMCOUPLED + logical :: write_restartfh +#endif character(len=*), parameter :: subname='(med_phases_restart_write)' !--------------------------------------- @@ -238,6 +253,11 @@ subroutine med_phases_restart_write(gcomp, rc) endif endif +#ifndef CESMCOUPLED + call is_restart_fh(clock, restartfh_info, write_restartfh) + if (write_restartfh) alarmIsOn = .true. +#endif + if (alarmIsOn) then call ESMF_ClockGet(clock, currtime=currtime, starttime=starttime, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -247,13 +267,21 @@ subroutine med_phases_restart_write(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call ESMF_TimeGet(currtime, yy=yr, mm=mon, dd=day, s=sec, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - write(currtimestr,'(i4.4,a,i2.2,a,i2.2,a,i5.5)') yr,'-',mon,'-',day,'-',sec + if(yr .le. 9999) then + write(currtimestr,'(i4.4,a,i2.2,a,i2.2,a,i5.5)') yr,'-',mon,'-',day,'-',sec + else + write(currtimestr,'(i6.6,a,i2.2,a,i2.2,a,i5.5)') yr,'-',mon,'-',day,'-',sec + endif if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": currtime = "//trim(currtimestr), ESMF_LOGMSG_INFO) endif call ESMF_TimeGet(nexttime, yy=yr, mm=mon, dd=day, s=sec, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - write(nexttimestr,'(i4.4,a,i2.2,a,i2.2,a,i5.5)') yr,'-',mon,'-',day,'-',sec + if(yr .le. 9999) then + write(nexttimestr,'(i4.4,a,i2.2,a,i2.2,a,i5.5)') yr,'-',mon,'-',day,'-',sec + else + write(nexttimestr,'(i6.6,a,i2.2,a,i2.2,a,i5.5)') yr,'-',mon,'-',day,'-',sec + endif if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": nexttime = "//trim(nexttimestr), ESMF_LOGMSG_INFO) endif @@ -429,7 +457,7 @@ subroutine med_phases_restart_write(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if - ! Write ocn albedo field bundle (CESM only) + ! Write ocn albedo field bundle (CESM/NorESM only) if (ESMF_FieldBundleIsCreated(is_local%wrap%FBMed_ocnalb_o,rc=rc)) then nx = is_local%wrap%nx(compocn) ny = is_local%wrap%ny(compocn) @@ -463,6 +491,12 @@ subroutine med_phases_restart_write(gcomp, rc) ! Close file call med_io_close(io_file, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return +#ifndef CESMCOUPLED + if (maintask) then + call log_restart_fh(nextTime, startTime, 'cmeps', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + endif +#endif endif !--------------------------------------- diff --git a/ufs/ccpp/data/MED_typedefs.F90 b/ufs/ccpp/data/MED_typedefs.F90 index 786ce4711..649ee9b69 100644 --- a/ufs/ccpp/data/MED_typedefs.F90 +++ b/ufs/ccpp/data/MED_typedefs.F90 @@ -183,6 +183,7 @@ module MED_typedefs logical :: restart !< flag whether this is a coldstart (.false.) or a warmstart/restart (.true.) logical :: cplice !< default no cplice collection (used together with cplflx) logical :: cplflx !< flag controlling cplflx collection (default off) + logical :: cpl_fire !< flag controlling fire behavior collection (default off) integer :: kdt !< current forecast iteration real(kind=kind_phys) :: min_lakeice !< minimum lake ice value real(kind=kind_phys) :: min_seaice !< minimum sea ice value @@ -262,7 +263,9 @@ module MED_typedefs real(kind=kind_phys), pointer :: ffhh(:) => null() !< Monin-Obukhov similarity function for heat real(kind=kind_phys), pointer :: ffmm(:) => null() !< Monin-Obukhov similarity function for momentum real(kind=kind_phys), pointer :: evap(:) => null() !< kinematic surface upward latent heat flux (kg kg-1 m s-1) + real(kind=kind_phys), pointer :: evap_fire(:) => null() !< kinematic surface upward latent heat flux of fire (kg kg-1 m s-1) real(kind=kind_phys), pointer :: hflx(:) => null() !< kinematic surface upward sensible heat flux (K m/s) + real(kind=kind_phys), pointer :: hflx_fire(:) => null() !< kinematic surface upward sensible heat flux of fire (K m/s) real(kind=kind_phys), pointer :: tiice(:,:) => null() !< sea ice internal temperature real(kind=kind_phys), pointer :: t2m(:) => null() !< temperature at 2 m real(kind=kind_phys), pointer :: q2m(:) => null() !< specific humidity at 2 m @@ -655,6 +658,7 @@ subroutine control_initialize(model) model%restart = .false. model%cplice = .false. model%cplflx = .false. + model%cpl_fire = .false. model%kdt = 0 ! nint(Model%fhour*con_hr/Model%dtp) model%min_lakeice = 0.15d0 model%min_seaice = 1.0d-11 @@ -767,8 +771,12 @@ subroutine sfcprop_create(sfcprop, im, model) sfcprop%ffmm = clear_val allocate(sfcprop%evap(im)) sfcprop%evap = clear_val + allocate(sfcprop%evap_fire(im)) + sfcprop%evap_fire = clear_val allocate(sfcprop%hflx(im)) sfcprop%hflx = clear_val + allocate(sfcprop%hflx_fire(im)) + sfcprop%hflx_fire = clear_val allocate(sfcprop%tiice(im,model%kice)) sfcprop%tiice = clear_val allocate(sfcprop%t2m(im)) diff --git a/ufs/ccpp/data/MED_typedefs.meta b/ufs/ccpp/data/MED_typedefs.meta index c14616a6a..046e4bfa6 100644 --- a/ufs/ccpp/data/MED_typedefs.meta +++ b/ufs/ccpp/data/MED_typedefs.meta @@ -917,6 +917,12 @@ units = 1 dimensions = () type = integer +[cpl_fire] + standard_name = do_fire_coupling + long_name = flag controlling fire_behavior collection (default off) + units = flag + dimensions = () + type = logical [kdt] standard_name = index_of_timestep long_name = current forecast iteration @@ -1267,6 +1273,13 @@ dimensions = (horizontal_loop_extent) type = real kind = kind_phys +[evap_fire] + standard_name = surface_upward_specific_humidity_flux_of_fire + long_name = kinematic surface upward latent heat flux of fire + units = kg kg-1 m s-1 + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys [hflx] standard_name = surface_upward_temperature_flux long_name = kinematic surface upward sensible heat flux @@ -1274,6 +1287,13 @@ dimensions = (horizontal_loop_extent) type = real kind = kind_phys +[hflx_fire] + standard_name = kinematic_surface_upward_sensible_heat_flux_of_fire + long_name = kinematic surface upward sensible heat flux of fire + units = K m s-1 + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys [tiice] standard_name = temperature_in_ice_layer long_name = sea ice internal temperature