├── .github ├── pull_request_template.md └── workflows │ ├── bumpversion.yml │ ├── extbuild.yml │ └── srt.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── cesm ├── driver │ ├── ensemble_driver.F90 │ ├── esm.F90 │ ├── esmApp.F90 │ ├── esm_time_mod.F90 │ ├── t_driver_timers_mod.F90 │ └── util.F90 ├── flux_atmocn │ └── shr_flux_mod.F90 └── nuopc_cap_share │ ├── driver_pio_mod.F90 │ ├── esm_utils_mod.F90 │ ├── glc_elevclass_mod.F90 │ ├── shr_carma_mod.F90 │ ├── shr_drydep_mod.F90 │ ├── shr_dust_emis_mod.F90 │ ├── shr_expr_parser_mod.F90 │ ├── shr_fire_emis_mod.F90 │ ├── shr_lightning_coupling_mod.F90 │ ├── shr_megan_mod.F90 │ ├── shr_ndep_mod.F90 │ └── shr_ozone_coupling_mod.F90 ├── cime_config ├── ExpectedTestFails.xml ├── buildexe ├── buildnml ├── config_archive.xml ├── config_component.xml ├── config_component_cesm.xml ├── config_compsets.xml ├── config_pes.xml ├── namelist_definition_drv.xml ├── namelist_definition_drv_flds.xml ├── runseq │ ├── driver_config.py │ ├── gen_runseq.py │ ├── runseq_D.py │ ├── runseq_TG.py │ └── runseq_general.py ├── testdefs │ ├── testlist_drv.xml │ └── testmods_dirs │ │ └── drv │ │ ├── 5steps │ │ └── shell_commands │ │ ├── aoflux_ogrid │ │ └── user_nl_cpl │ │ ├── asyncio1node │ │ └── shell_commands │ │ ├── asyncio1pernode │ │ └── shell_commands │ │ ├── default │ │ └── shell_commands │ │ ├── glcnec10 │ │ ├── include_user_mods │ │ └── shell_commands │ │ ├── som │ │ └── shell_commands │ │ └── y100k │ │ ├── README │ │ └── shell_commands └── user_nl_cpl ├── cmake ├── FindESMF.cmake ├── FindPIO.cmake ├── LibCheck.cmake └── LibFind.cmake ├── doc ├── .gitignore ├── Makefile └── source │ ├── CMEPS-grid1.png │ ├── CMEPS-grid2.png │ ├── CMEPS-grid3.png │ ├── _static │ └── pop_ver.js │ ├── _templates │ ├── footer.html │ └── layout.html │ ├── addendum │ ├── fieldnames.rst │ ├── index.rst │ ├── req_attributes.rst │ └── req_attributes_cesm.rst │ ├── conf.py │ ├── esmflds.rst │ ├── fractions.rst │ ├── generic.rst │ ├── index.rst │ ├── introduction.rst │ └── prep.rst ├── mediator ├── CMakeLists.txt ├── ESMFConvenienceMacros.h ├── ESMFVersionDefine.h ├── Makefile ├── esmFlds.F90 ├── esmFldsExchange_cesm_mod.F90 ├── esmFldsExchange_hafs_mod.F90 ├── esmFldsExchange_ufs_mod.F90 ├── fd_cesm.yaml ├── med.F90 ├── med_constants_mod.F90 ├── med_diag_mod.F90 ├── med_fraction_mod.F90 ├── med_internalstate_mod.F90 ├── med_io_mod.F90 ├── med_kind_mod.F90 ├── med_map_mod.F90 ├── med_merge_mod.F90 ├── med_methods_mod.F90 ├── med_phases_aofluxes_mod.F90 ├── med_phases_cdeps_mod.F90 ├── med_phases_history_mod.F90 ├── med_phases_ocnalb_mod.F90 ├── med_phases_post_atm_mod.F90 ├── med_phases_post_glc_mod.F90 ├── med_phases_post_ice_mod.F90 ├── med_phases_post_lnd_mod.F90 ├── med_phases_post_ocn_mod.F90 ├── med_phases_post_rof_mod.F90 ├── med_phases_post_wav_mod.F90 ├── med_phases_prep_atm_mod.F90 ├── med_phases_prep_glc_mod.F90 ├── med_phases_prep_ice_mod.F90 ├── med_phases_prep_lnd_mod.F90 ├── med_phases_prep_ocn_mod.F90 ├── med_phases_prep_rof_mod.F90 ├── med_phases_prep_wav_mod.F90 ├── med_phases_profile_mod.F90 ├── med_phases_restart_mod.F90 └── med_utils_mod.F90 ├── tcipylint └── ufs ├── CMakeLists.txt ├── ccpp ├── config │ └── ccpp_prebuild_config.py ├── data │ ├── MED_data.F90 │ ├── MED_data.meta │ ├── MED_typedefs.F90 │ └── MED_typedefs.meta ├── driver │ └── med_ccpp_driver.F90 └── suites │ └── suite_FV3_sfc_ocean.xml ├── flux_atmocn_ccpp_mod.F90 ├── flux_atmocn_mod.F90 ├── glc_elevclass_mod.F90 ├── perf_mod.F90 ├── ufs_const_mod.F90 ├── ufs_io_mod.F90 └── ufs_kind_mod.F90 /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Description of changes 2 | 3 | ### Specific notes 4 | 5 | Contributors other than yourself, if any: 6 | 7 | CMEPS Issues Fixed (include github issue #): 8 | 9 | Are changes expected to change answers? (specify if bfb, different at roundoff, more substantial) 10 | 11 | Any User Interface Changes (namelist or namelist defaults changes)? 12 | 13 | ### Testing performed 14 | Please describe the tests along with the target model and machine(s) 15 | If possible, please also added hashes that were used in the testing 16 | 17 | -------------------------------------------------------------------------------- /.github/workflows/bumpversion.yml: -------------------------------------------------------------------------------- 1 | name: Bump version 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Bump version and push tag 12 | id: tag_version 13 | uses: mathieudutour/github-tag-action@v6.2 14 | with: 15 | github_token: ${{ secrets.GITHUB_TOKEN }} 16 | create_annotated_tag: true 17 | default_bump: patch 18 | dry_run: false 19 | tag_prefix: cmeps 20 | -------------------------------------------------------------------------------- /.github/workflows/extbuild.yml: -------------------------------------------------------------------------------- 1 | # This is a workflow to compile the cmeps source without cime 2 | name: extbuild 3 | 4 | # Controls when the action will run. Triggers the workflow on push or pull request 5 | # events but only for the main branch 6 | on: 7 | push: 8 | branches: [ main ] 9 | pull_request: 10 | branches: [ main ] 11 | 12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 13 | jobs: 14 | build-cmeps: 15 | runs-on: ubuntu-latest 16 | env: 17 | CC: mpicc 18 | FC: mpifort 19 | CXX: mpicxx 20 | CPPFLAGS: "-I/usr/include -I/usr/local/include" 21 | 22 | # Versions of all dependencies can be updated here 23 | ESMF_VERSION: v8.8.0 24 | PNETCDF_VERSION: checkpoint.1.14.0 25 | NETCDF_FORTRAN_VERSION: v4.6.1 26 | PIO_VERSION: pio2_6_5 27 | CDEPS_VERSION: cdeps1.0.72 28 | steps: 29 | - uses: actions/checkout@v4 30 | # Build the ESMF library, if the cache contains a previous build 31 | # it will be used instead 32 | - id: load-env 33 | run: | 34 | sudo apt-get update 35 | sudo apt-get update 36 | sudo apt-get install gfortran 37 | sudo apt-get install wget 38 | sudo apt-get install openmpi-bin libopenmpi-dev 39 | sudo apt-get install netcdf-bin libnetcdf-dev libnetcdff-dev 40 | sudo apt-get install pnetcdf-bin libpnetcdf-dev 41 | sudo apt-get install autotools-dev autoconf 42 | - id: cache-esmf 43 | uses: actions/cache@v4 44 | with: 45 | path: ~/ESMF 46 | key: ${{ runner.os }}-${{ env.ESMF_VERSION }}-ESMF 47 | - name: Cache ParallelIO 48 | id: cache-ParallelIO 49 | uses: actions/cache@v4 50 | with: 51 | path: ~/pio 52 | key: ${{ runner.os }}-${{ env.PIO_VERSION }}.pio 53 | - name: Build ParallelIO 54 | if: steps.cache-ParallelIO.outputs.cache-hit != 'true' 55 | uses: NCAR/ParallelIO/.github/actions/parallelio_cmake@pio2_6_0 56 | with: 57 | parallelio_version: ${{ env.ParallelIO_VERSION }} 58 | enable_fortran: True 59 | install_prefix: $HOME/pio 60 | - name: Build ESMF 61 | if: steps.cache-esmf.outputs.cache-hit != 'true' 62 | uses: ESCOMP/CDEPS/.github/actions/buildesmf@cdeps1.0.15 63 | with: 64 | esmf_version: ${{ env.ESMF_VERSION }} 65 | esmf_bopt: g 66 | esmf_comm: openmpi 67 | install_prefix: $HOME/ESMF 68 | netcdf_c_path: /usr 69 | netcdf_fortran_path: /usr 70 | pnetcdf_path: /usr 71 | parallelio_path: $HOME/pio 72 | - name: Cache CDEPS 73 | id: cache-cdeps 74 | uses: actions/cache@v4 75 | with: 76 | path: /homme/runner/work/CMEPS/CMEPS/build-cdeps 77 | key: ${{ runner.os }}-${{ env.CDEPS_VERSION }}.cdeps1 78 | 79 | - name: checkout CDEPS 80 | uses: actions/checkout@v4 81 | with: 82 | repository: ESCOMP/CDEPS 83 | path: cdeps-src 84 | ref: ${{ env.CDEPS_VERSION }} 85 | - name: get genf90 86 | run: | 87 | cd cdeps-src 88 | git submodule update --init 89 | - name: Build CDEPS 90 | if: steps.cache-cdeps.outputs.cache-hit != 'true' 91 | uses: ESCOMP/CDEPS/.github/actions/buildcdeps@cdeps1.0.26 92 | with: 93 | esmfmkfile: $HOME/ESMF/lib/libg/Linux.gfortran.64.openmpi.default/esmf.mk 94 | pio_path: $HOME/pio 95 | src_root: ${GITHUB_WORKSPACE}/cdeps-src 96 | cmake_flags: " -Wno-dev -DDISABLE_FoX=ON -DCMAKE_BUILD_TYPE=DEBUG -DWERROR=ON -DCMAKE_Fortran_FLAGS=\"-DCPRGNU -g -Wall \ 97 | -ffree-form -ffree-line-length-none -fallow-argument-mismatch \"" 98 | 99 | - name: Build CMEPS 100 | run: | 101 | export PIO=$HOME/pio 102 | export ESMFMKFILE=$HOME/ESMF/lib/libg/Linux.gfortran.64.openmpi.default/esmf.mk 103 | mkdir build-cmeps 104 | pushd build-cmeps 105 | cmake -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_Fortran_FLAGS="-g -Wall -Werror -ffree-form -ffree-line-length-none -Wno-unused-dummy-argument -I /home/runner/work/CMEPS/CMEPS/build-cdeps/share" ../ 106 | make VERBOSE=1 107 | popd 108 | 109 | # - name: Setup tmate session 110 | # if: ${{ failure() }} 111 | # uses: mxschmitt/action-tmate@v3 112 | -------------------------------------------------------------------------------- /.github/workflows/srt.yml: -------------------------------------------------------------------------------- 1 | # CIME scripts regression tests 2 | 3 | name: scripts regression tests 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the main branch 7 | on: 8 | push: 9 | branches: [ main ] 10 | pull_request: 11 | branches: [ main ] 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "build" 16 | build: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | python-version: [ 3.8, 3.11, 3.x ] 23 | env: 24 | CC: mpicc 25 | FC: mpifort 26 | CXX: mpicxx 27 | CPPFLAGS: "-I/usr/include -I/usr/local/include " 28 | LDFLAGS: "-L/usr/lib/x86_64-linux-gnu -lnetcdf -lnetcdff -lpnetcdf" 29 | # Versions of all dependencies can be updated here 30 | ESMF_VERSION: v8.8.0 31 | PARALLELIO_VERSION: pio2_6_5 32 | CIME_MODEL: cesm 33 | CIME_DRIVER: nuopc 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | # Steps represent a sequence of tasks that will be executed as part of the job 36 | steps: 37 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 38 | 39 | - name: Setup Ubuntu Environment 40 | id: load-env 41 | run: | 42 | set -x 43 | sudo apt-get update 44 | sudo apt-get install libxml2-utils 45 | sudo apt-get install netcdf-bin 46 | sudo apt-get install libnetcdf-dev 47 | sudo apt-get install libnetcdff-dev 48 | sudo apt-get install pnetcdf-bin 49 | sudo apt-get install libpnetcdf-dev 50 | sudo apt-get install doxygen 51 | sudo apt-get install graphviz 52 | sudo apt-get install wget 53 | sudo apt-get install gfortran 54 | sudo apt-get install libjpeg-dev 55 | sudo apt-get install libz-dev 56 | sudo apt-get install openmpi-bin 57 | sudo apt-get install libopenmpi-dev 58 | 59 | - name: Set up Python ${{ matrix.python-version }} 60 | uses: actions/setup-python@v4 61 | with: 62 | python-version: ${{ matrix.python-version }} 63 | - run: echo "PyYAML" > requirements.txt 64 | - name: Install PyYAML 65 | run: pip install -r requirements.txt 66 | # use the latest cesm main 67 | - name: cesm checkout 68 | uses: actions/checkout@v4 69 | with: 70 | repository: ESCOMP/CESM 71 | path: cesm 72 | # this cmeps commit 73 | - name: cmeps checkout 74 | uses: actions/checkout@v4 75 | with: 76 | path: cesm/components/cmeps 77 | 78 | # Checkout cesm datamodels and support 79 | # cpl7 is needed - i think that's a bug 80 | - name: checkout externals 81 | run: | 82 | git config --global user.name "${GITHUB_ACTOR}" 83 | git config --global user.email "${GITHUB_ACTOR_ID}+${GITHUB_ACTOR}@users.noreply.github.com" 84 | pushd cesm 85 | ./bin/git-fleximod update cime ccs_config cdeps share mct parallelio 86 | cd ccs_config 87 | git checkout main 88 | cd ../cime 89 | git checkout master 90 | git status 91 | if [[ ! -e "${PWD}/.gitmodules.bak" ]] 92 | then 93 | echo "Converting git@github.com to https://github.com urls in ${PWD}/.gitmodules" 94 | 95 | sed -i".bak" "s/git@github.com:/https:\/\/github.com\//g" "${PWD}/.gitmodules" 96 | fi 97 | git submodule update --init 98 | cd ../components/cdeps 99 | git checkout main 100 | git submodule update --init 101 | cd ../../share 102 | git checkout main 103 | 104 | - name: Cache ESMF 105 | id: cache-esmf 106 | uses: actions/cache@v4 107 | with: 108 | path: ~/ESMF 109 | key: ${{ runner.os }}-${{ env.ESMF_VERSION }} 110 | 111 | - name: Cache ParallelIO 112 | id: cache-ParallelIO 113 | uses: actions/cache@v4 114 | with: 115 | path: ${GITHUB_WORKSPACE}/pio 116 | key: ${{ runner.os }}-${{ env.PARALLELIO_VERSION }}.parallelio 117 | 118 | - name: Cache inputdata 119 | id: cache-inputdata 120 | uses: actions/cache@v4 121 | with: 122 | path: $HOME/cesm/inputdata 123 | key: inputdata 124 | 125 | - name: Build ParallelIO 126 | if: steps.cache-PARALLELIO.outputs.cache-hit != 'true' 127 | uses: NCAR/ParallelIO/.github/actions/parallelio_cmake@b38e34eeb9b75ce81ac94daf7c5245931de00b9d 128 | with: 129 | parallelio_version: ${{ env.ParallelIO_VERSION }} 130 | enable_fortran: True 131 | install_prefix: ${GITHUB_WORKSPACE}/pio 132 | 133 | - name: Install ESMF 134 | uses: esmf-org/install-esmf-action@v1 135 | env: 136 | ESMF_COMPILER: gfortran 137 | ESMF_BOPT: g 138 | ESMF_COMM: openmpi 139 | ESMF_NETCDF: nc-config 140 | ESMF_PNETCDF: pnetcdf-config 141 | ESMF_INSTALL_PREFIX: ${GITHUB_WORKSPACE}/ESMF 142 | ESMF_PIO: external 143 | ESMF_PIO_INCLUDE: ${GITHUB_WORKSPACE}/pio/include 144 | ESMF_PIO_LIBPATH: ${GITHUB_WORKSPACE}/pio/lib 145 | with: 146 | version: ${{ env.ESMF_VERSION }} 147 | esmpy: false 148 | cache: true 149 | 150 | 151 | - name: PREP for scripts regression test 152 | run: | 153 | mkdir -p $HOME/cesm/scratch 154 | mkdir -p $HOME/cesm/inputdata 155 | pushd $GITHUB_WORKSPACE/cesm/cime/CIME/tests 156 | export SRCROOT=$GITHUB_WORKSPACE/cesm/ 157 | export CIME_TEST_PLATFORM=ubuntu-latest 158 | export PIO_INCDIR=$GITHUB_WORKSPACE/pio/include 159 | export PIO_LIBDIR=$GITHUB_WORKSPACE/pio/lib 160 | export PIO_VERSION_MAJOR=2 161 | export PIO_TYPENAME_VALID_VALUES="netcdf,pnetcdf" 162 | export NETCDF_PATH=/usr 163 | export PNETCDF_PATH=/usr 164 | export LD_LIBRARY_PATH=/usr/lib/libx86_64-linux-gnu/:$LD_LIBRARY_PATH 165 | cat <> $GITHUB_WORKSPACE/cesm/ccs_config/machines/cmake_macros/ubuntu-latest.cmake 166 | set(NetCDF_Fortran_INCLUDE_DIR /usr/include) 167 | set(NetCDF_Fortran_LIBRARY /usr/lib/x86_64-gnu-Linux/libnetcdff.so) 168 | EOF 169 | printenv >> $GITHUB_ENV 170 | popd 171 | - name: scripts regression tests 172 | run: | 173 | pushd $GITHUB_WORKSPACE/cesm/cime/CIME/tests 174 | ./scripts_regression_tests.py --no-fortran-run --compiler gnu --mpilib openmpi --machine ubuntu-latest 175 | popd 176 | # the following can be used by developers to login to the github server in case of errors 177 | # see https://github.com/marketplace/actions/debugging-with-tmate for further details 178 | # - name: Setup tmate session 179 | # if: ${{ failure() }} 180 | # uses: mxschmitt/action-tmate@v3 181 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Python compiled files 11 | *.pyc 12 | cime_config/buildnmlc 13 | cime_config/buildexec 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Compiled Dynamic libraries 20 | *.so 21 | *.dylib 22 | *.dll 23 | 24 | # Fortran module files 25 | *.mod 26 | *.smod 27 | 28 | # Compiled Static libraries 29 | *.lai 30 | *.la 31 | *.a 32 | *.lib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | exclude: ^utils/.*$ 2 | 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.0.1 6 | hooks: 7 | - id: check-xml 8 | files: cime_config/ 9 | - id: end-of-file-fixer 10 | exclude: doc/ 11 | - id: trailing-whitespace 12 | exclude: doc/ 13 | - repo: https://github.com/psf/black 14 | rev: 22.3.0 15 | hooks: 16 | - id: black 17 | files: ./ 18 | - repo: https://github.com/PyCQA/pylint 19 | rev: v2.11.1 20 | hooks: 21 | - id: pylint 22 | args: 23 | - --disable=I,C,R,logging-not-lazy,wildcard-import,unused-wildcard-import,fixme,broad-except,bare-except,eval-used,exec-used,global-statement,logging-format-interpolation,no-name-in-module,arguments-renamed,unspecified-encoding,protected-access,import-error,no-member 24 | files: cime_config 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | install: 4 | - pip install pylint 5 | 6 | python: 7 | - '3.7' 8 | - '3.8' 9 | - '3.9' 10 | 11 | branches: 12 | only: 13 | - master 14 | 15 | script: ./tcipylint 16 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | include(ExternalProject) 3 | 4 | if (DEFINED CIMEROOT) 5 | message("Using CIME in ${CIMEROOT} with compiler ${COMPILER}") 6 | include(${CASEROOT}/Macros.cmake) 7 | if (${PIO_VERSION} LESS 2) 8 | message( FATAL_ERROR "Version 2 of the PIO library required") 9 | endif() 10 | if (${MPILIB} STREQUAL "mpi-serial") 11 | set(CMAKE_C_COMPILER ${SCC}) 12 | set(CMAKE_Fortran_COMPILER ${SFC}) 13 | set(CMAKE_CXX_COMPILER ${SCXX}) 14 | else() 15 | set(CMAKE_C_COMPILER ${MPICC}) 16 | set(CMAKE_Fortran_COMPILER ${MPIFC}) 17 | set(CMAKE_CXX_COMPILER ${MPICXX}) 18 | endif() 19 | set(CMAKE_Fortran_FLAGS "${FFLAGS} -I${LIBROOT}/include -I${LIBROOT}/finclude -I${LIBROOT}/nuopc/esmf/${NINST_VALUE}/include") 20 | else() 21 | set(BLD_STANDALONE TRUE) 22 | endif() 23 | 24 | project(CMEPS LANGUAGES Fortran VERSION 0.1) 25 | 26 | list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 27 | 28 | message("CMAKE_MODULE_PATH is ${CMAKE_MODULE_PATH}") 29 | 30 | find_package(ESMF REQUIRED) 31 | if (DEFINED PIO) 32 | set(PIO_PATH ${PIO}) 33 | else() 34 | set(PIO_PATH $ENV{PIO}) 35 | endif() 36 | find_package(PIO REQUIRED COMPONENT C Fortran PATH ${PIO_PATH}) 37 | 38 | if (NOT DEFINED MPILIB OR NOT ${MPILIB} STREQUAL "mpi-serial") 39 | find_package(MPI REQUIRED) 40 | endif() 41 | 42 | if(BLD_STANDALONE) 43 | add_subdirectory(ufs) 44 | list(APPEND EXTRA_LIBS cmeps_share) 45 | list(APPEND EXTRA_INCLUDES "${CMAKE_BINARY_DIR}/ufs") 46 | endif() 47 | 48 | add_subdirectory(mediator) 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CMEPS 2 | NUOPC based Community Mediator for Earth Prediction Systems 3 | 4 | ## Overview and resources 5 | 6 | The Community Mediator for Earth Prediction Systems (CMEPS) is a 7 | NUOPC-compliant Mediator component used for coupling Earth system 8 | model components. It is currently being used in NCAR's Community 9 | Earth System Model (CESM) and NOAA's UFS subseasonal-to-seasonal 10 | coupled system application. 11 | 12 | For documentation see 13 | 14 | https://escomp.github.io/CMEPS/ 15 | -------------------------------------------------------------------------------- /cesm/driver/t_driver_timers_mod.F90: -------------------------------------------------------------------------------- 1 | module t_drv_timers_mod 2 | 3 | implicit none 4 | public :: t_drvstopf, t_drvstartf 5 | integer, private :: cpl_run_hash=0, cpl_comm_hash=0, cpl_budget_hash=0 6 | character(len=*),parameter :: strcpl = 'CPL:RUN' 7 | character(len=*),parameter :: strcom = 'CPL:COMM' 8 | character(len=*),parameter :: strbud = 'CPL:BUDGET' 9 | 10 | contains 11 | 12 | !=============================================================================== 13 | 14 | subroutine t_drvstartf(string,cplrun,cplcom,budget,barrier, hashint) 15 | use perf_mod, only : t_barrierf, t_startf, t_adj_detailf 16 | implicit none 17 | 18 | character(len=*),intent(in) :: string 19 | logical,intent(in),optional :: cplrun 20 | logical,intent(in),optional :: cplcom 21 | logical,intent(in),optional :: budget 22 | integer,intent(in),optional :: barrier 23 | integer,intent(inout), optional :: hashint 24 | 25 | character(len=128) :: strbar 26 | 27 | logical :: lcplrun,lcplcom,lbudget 28 | !------------------------------------------------------------------------------- 29 | 30 | lcplrun = .false. 31 | lcplcom = .false. 32 | lbudget = .false. 33 | if (present(cplrun)) then 34 | lcplrun = cplrun 35 | endif 36 | if (present(cplcom)) then 37 | lcplcom = cplcom 38 | endif 39 | if (present(budget)) then 40 | lbudget = budget 41 | endif 42 | 43 | if (present(barrier)) then 44 | strbar = trim(string)//'_BARRIER' 45 | call t_barrierf (trim(strbar), barrier) 46 | endif 47 | 48 | if (lcplrun) then 49 | call t_startf (trim(strcpl), cpl_run_hash) 50 | call t_adj_detailf(+1) 51 | endif 52 | 53 | if (lcplcom) then 54 | call t_startf (trim(strcom), cpl_comm_hash) 55 | call t_adj_detailf(+1) 56 | endif 57 | 58 | if (lbudget) then 59 | call t_startf (trim(strbud), cpl_budget_hash) 60 | call t_adj_detailf(+1) 61 | endif 62 | 63 | call t_startf (trim(string),hashint) 64 | call t_adj_detailf(+1) 65 | 66 | end subroutine t_drvstartf 67 | 68 | !=============================================================================== 69 | 70 | subroutine t_drvstopf(string,cplrun,cplcom,budget,hashint) 71 | use perf_mod, only : t_stopf, t_adj_detailf 72 | implicit none 73 | 74 | character(len=*),intent(in) :: string 75 | logical,intent(in),optional :: cplrun 76 | logical,intent(in),optional :: cplcom 77 | logical,intent(in),optional :: budget 78 | integer, intent(in), optional :: hashint 79 | logical :: lcplrun,lcplcom,lbudget 80 | 81 | !------------------------------------------------------------------------------- 82 | 83 | lcplrun = .false. 84 | lcplcom = .false. 85 | lbudget = .false. 86 | if (present(cplrun)) then 87 | lcplrun = cplrun 88 | endif 89 | if (present(cplcom)) then 90 | lcplcom = cplcom 91 | endif 92 | if (present(budget)) then 93 | lbudget = budget 94 | endif 95 | 96 | call t_adj_detailf(-1) 97 | call t_stopf (trim(string), hashint) 98 | 99 | if (lbudget) then 100 | call t_adj_detailf(-1) 101 | call t_stopf (trim(strbud), cpl_budget_hash) 102 | endif 103 | 104 | if (lcplrun) then 105 | call t_adj_detailf(-1) 106 | call t_stopf (trim(strcpl), cpl_run_hash) 107 | endif 108 | 109 | if (lcplcom) then 110 | call t_adj_detailf(-1) 111 | call t_stopf (trim(strcom),cpl_comm_hash) 112 | endif 113 | 114 | end subroutine t_drvstopf 115 | 116 | end module t_drv_timers_mod 117 | -------------------------------------------------------------------------------- /cesm/driver/util.F90: -------------------------------------------------------------------------------- 1 | module util 2 | 3 | !----------------------------------------------------------------------------- 4 | ! CustomFieldDictionaryProto utility module 5 | !----------------------------------------------------------------------------- 6 | 7 | use ESMF, only : ESMF_SUCCESS, ESMF_MAXSTR, ESMF_IOFmt_flag, ESMF_LogWrite 8 | use ESMF, only : ESMF_LOGMSG_INFO, ESMF_LOGERR_PASSTHRU, ESMF_LOGFoundError 9 | use NUOPC, only : nuopc_freeFormat, nuopc_freeformatLog, nuopc_fieldDictionaryEgest 10 | 11 | implicit none 12 | 13 | private 14 | 15 | public FieldDictionaryLog 16 | 17 | !----------------------------------------------------------------------------- 18 | contains 19 | !----------------------------------------------------------------------------- 20 | 21 | subroutine FieldDictionaryLog(label, iofmt, rc) 22 | 23 | character(len=*), intent(in) :: label 24 | type(ESMF_IOFmt_Flag), intent(in), optional :: iofmt 25 | integer, intent(out), optional :: rc 26 | 27 | integer :: ibeg, iend, length 28 | character(len=ESMF_MAXSTR) :: sep, title 29 | type(NUOPC_FreeFormat) :: freeFormat 30 | 31 | if (present(rc)) rc = ESMF_SUCCESS 32 | 33 | write(sep,'(64("="))') 34 | 35 | ! build section separator with title 36 | title = "> Begin Field Dictionary: " // trim(label) // " <" 37 | length = len_trim(title) 38 | 39 | ! center title within separator 40 | ibeg = max((64 - length)/2,1) 41 | iend = min(ibeg+length-1,ESMF_MAXSTR) 42 | sep(ibeg:iend) = title(1:iend-ibeg+1) 43 | 44 | call ESMF_LogWrite(sep, ESMF_LOGMSG_INFO, rc=rc) 45 | if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & 46 | line=__LINE__, & 47 | file=__FILE__)) & 48 | return ! bail out 49 | 50 | call NUOPC_FieldDictionaryEgest(freeFormat, iofmt=iofmt, rc=rc) 51 | if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & 52 | line=__LINE__, & 53 | file=__FILE__)) & 54 | return ! bail out 55 | 56 | call NUOPC_FreeFormatLog(freeFormat, rc=rc) 57 | if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & 58 | line=__LINE__, & 59 | file=__FILE__)) & 60 | return ! bail out 61 | 62 | ! build section separator with title 63 | title = "> End Field Dictionary: " // trim(label) // " <" 64 | length = len_trim(title) 65 | 66 | ! align with opening title 67 | sep = "" 68 | write(sep,'(64("="))') 69 | iend = min(ibeg+length-1,ESMF_MAXSTR) 70 | sep(ibeg:iend) = title(1:iend-ibeg+1) 71 | 72 | call ESMF_LogWrite(sep, ESMF_LOGMSG_INFO, rc=rc) 73 | if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & 74 | line=__LINE__, & 75 | file=__FILE__)) & 76 | return ! bail out 77 | 78 | end subroutine FieldDictionaryLog 79 | 80 | end module 81 | -------------------------------------------------------------------------------- /cesm/nuopc_cap_share/esm_utils_mod.F90: -------------------------------------------------------------------------------- 1 | module esm_utils_mod 2 | 3 | implicit none 4 | public 5 | 6 | logical :: maintask 7 | integer :: logunit 8 | integer :: dbug_flag = 0 9 | 10 | character(*), parameter :: u_FILE_u = & 11 | __FILE__ 12 | 13 | !=============================================================================== 14 | contains 15 | !=============================================================================== 16 | 17 | logical function ChkErr(rc, line, file, mpierr) 18 | #ifndef NO_MPI2 19 | use mpi, only : MPI_ERROR_STRING, MPI_MAX_ERROR_STRING, MPI_SUCCESS 20 | #else 21 | use mpi, only : MPI_SUCCESS 22 | #endif 23 | use ESMF, only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_LOGMSG_INFO 24 | use ESMF, only : ESMF_FAILURE, ESMF_LogWrite 25 | 26 | integer, intent(in) :: rc 27 | integer, intent(in) :: line 28 | 29 | character(len=*), intent(in) :: file 30 | logical, optional, intent(in) :: mpierr 31 | #ifdef NO_MPI2 32 | integer, parameter :: MPI_MAX_ERROR_STRING=80 33 | #endif 34 | character(MPI_MAX_ERROR_STRING) :: lstring 35 | integer :: dbrc, lrc, len, ierr 36 | 37 | ChkErr = .false. 38 | lrc = rc 39 | if (present(mpierr)) then 40 | if(mpierr) then 41 | if (rc == MPI_SUCCESS) return 42 | #ifdef USE_MPI2 43 | call MPI_ERROR_STRING(rc, lstring, len, ierr) 44 | #else 45 | write(lstring,*) "ERROR in mct mpi-serial library rc=",rc 46 | #endif 47 | call ESMF_LogWrite("ERROR: "//trim(lstring), ESMF_LOGMSG_INFO, line=line, file=file, rc=dbrc) 48 | lrc = ESMF_FAILURE 49 | endif 50 | endif 51 | 52 | if (ESMF_LogFoundError(rcToCheck=lrc, msg=ESMF_LOGERR_PASSTHRU, line=line, file=file)) then 53 | ChkErr = .true. 54 | endif 55 | end function ChkErr 56 | 57 | end module esm_utils_mod 58 | -------------------------------------------------------------------------------- /cesm/nuopc_cap_share/shr_carma_mod.F90: -------------------------------------------------------------------------------- 1 | module shr_carma_mod 2 | 3 | !================================================================================ 4 | ! This reads the carma_inparm namelist in drv_flds_in and makes the relavent 5 | ! information available to CAM, CLM, and driver. 6 | !================================================================================ 7 | 8 | use shr_kind_mod , only : r8 => shr_kind_r8, CX => SHR_KIND_CX 9 | use shr_sys_mod , only : shr_sys_abort 10 | use shr_log_mod , only : shr_log_getLogUnit 11 | use shr_nl_mod , only : shr_nl_find_group_name 12 | 13 | implicit none 14 | private 15 | 16 | public :: shr_carma_readnl ! reads carma_inparm namelist 17 | 18 | !------------------------------------------------------------------------- 19 | contains 20 | !------------------------------------------------------------------------- 21 | 22 | subroutine shr_carma_readnl( NLFileName, carma_fields) 23 | 24 | !------------------------------------------------------------------------- 25 | ! This reads the carma_emis_nl namelist group in drv_flds_in and parses the 26 | ! namelist information for the driver, CLM, and CAM. 27 | !------------------------------------------------------------------------- 28 | 29 | use ESMF, only : ESMF_VM, ESMF_VMGetCurrent, ESMF_VMGet, ESMF_VMBroadcast 30 | 31 | character(len=*) , intent(in) :: NLFileName 32 | character(len=CX), intent(out) :: carma_fields 33 | 34 | type(ESMF_VM) :: vm 35 | integer :: localPet 36 | integer :: rc 37 | integer :: unitn ! namelist unit number 38 | integer :: ierr ! error code 39 | logical :: exists ! if file exists or not 40 | integer :: i, tmp(1) 41 | integer :: logunit 42 | character(*),parameter :: F00 = "('(shr_carma_readnl) ',2a)" 43 | 44 | namelist /carma_inparm/ carma_fields 45 | call shr_log_getLogUnit(logunit) 46 | 47 | carma_fields = ' ' 48 | call ESMF_VMGetCurrent(vm, rc=rc) 49 | call ESMF_VMGet(vm, localpet=localpet, rc=rc) 50 | tmp = 0 51 | if (localpet==0) then 52 | inquire( file=trim(NLFileName), exist=exists) 53 | if ( exists ) then 54 | open(newunit=unitn, file=trim(NLFilename), status='old' ) 55 | write(logunit,F00) 'Read in carma_inparm namelist from: ', trim(NLFilename) 56 | call shr_nl_find_group_name(unitn, 'carma_inparm', status=ierr) 57 | if (ierr == 0) then 58 | read(unitn, carma_inparm, iostat=ierr) 59 | if (ierr > 0) then 60 | call shr_sys_abort( 'problem on read of carma_inparm namelist in shr_carma_readnl' ) 61 | endif 62 | else 63 | write(logunit,*) 'shr_carma_readnl: no carma_inparm namelist found in ',NLFilename 64 | end if 65 | close( unitn ) 66 | else 67 | write(logunit,*) 'shr_carma_readnl: no file ',NLFilename, ' found' 68 | end if 69 | if (len_trim(carma_fields) > 0) tmp(1)=1 70 | end if 71 | call ESMF_VMBroadcast(vm, tmp, 1, 0, rc=rc) 72 | if(tmp(1) == 1) then 73 | call ESMF_VMBroadcast(vm, carma_fields, CX, 0, rc=rc) 74 | endif 75 | 76 | end subroutine shr_carma_readnl 77 | 78 | endmodule shr_carma_mod 79 | -------------------------------------------------------------------------------- /cesm/nuopc_cap_share/shr_expr_parser_mod.F90: -------------------------------------------------------------------------------- 1 | !============================================================================= 2 | ! expression parser utility -- 3 | ! for parsing simple linear mathematical expressions of the form 4 | ! X = a*R + b*S + c*(X + Y + Z) ... 5 | ! 6 | !============================================================================= 7 | module shr_expr_parser_mod 8 | use shr_kind_mod,only : r8 => shr_kind_r8 9 | use shr_kind_mod,only : CXX => shr_kind_cxx 10 | 11 | implicit none 12 | private 13 | 14 | public :: shr_exp_parse ! parses simple strings which contain expressions 15 | public :: shr_exp_item_t ! user defined type which contains an expression component 16 | public :: shr_exp_list_destroy ! destroy the linked list returned by shr_exp_parse 17 | 18 | ! contains componets of expression 19 | type shr_exp_item_t 20 | character(len=64) :: name 21 | character(len=64),pointer :: vars(:) => null() 22 | real(r8) ,pointer :: coeffs(:) => null() 23 | integer :: n_terms = 0 24 | type(shr_exp_item_t), pointer :: next_item => null() 25 | end type shr_exp_item_t 26 | 27 | contains 28 | 29 | ! ----------------------------------------------------------------- 30 | ! parses expressions provided in array of strings 31 | ! ----------------------------------------------------------------- 32 | function shr_exp_parse( exp_array, nitems ) result(exp_items_list) 33 | 34 | character(len=*), intent(in) :: exp_array(:) ! contains a expressions 35 | integer, optional, intent(out) :: nitems ! number of expressions parsed 36 | type(shr_exp_item_t), pointer :: exp_items_list ! linked list of items returned 37 | 38 | integer :: i,j, n_exp_items 39 | type(shr_exp_item_t), pointer :: exp_item, list_item 40 | integer :: ndxs(512) 41 | integer :: nelem, j1,j2,k 42 | character(len=CXX) :: tmp_str, tmp_name 43 | character(len=8) :: xchr ! multipler 44 | real(r8) :: xdbl 45 | real(r8) :: coeff0 46 | logical :: more_to_come 47 | character(len=CXX), allocatable :: sums_grps(:) 48 | character(len=CXX) :: sum_string 49 | 50 | allocate(sums_grps(size(exp_array))) 51 | 52 | nullify( exp_items_list ) 53 | nullify( exp_item ) 54 | nullify( list_item ) 55 | 56 | sums_grps(:) = ' ' 57 | 58 | ! combine lines that have a trailing "+" with the next line 59 | i=1 60 | j=1 61 | loop1: do while( len_trim(exp_array(i)) > 0 ) 62 | 63 | k = scan(exp_array(i), '+', back=.true. ) 64 | more_to_come = k == len_trim(exp_array(i)) ! line ends with "+" 65 | 66 | if ( more_to_come ) then 67 | sums_grps(j) = trim(sums_grps(j)) // trim(adjustl(exp_array(i))) 68 | else 69 | sums_grps(j) = trim(sums_grps(j)) // trim(adjustl(exp_array(i))) 70 | j = j+1 71 | endif 72 | 73 | i = i+1 74 | if ( i > size(exp_array) ) exit loop1 75 | 76 | end do loop1 77 | 78 | n_exp_items = j-1 79 | 80 | ! a group is a summation of terms 81 | 82 | ! parse the individual sum strings... and form the groupings 83 | has_grps: if (n_exp_items>0) then 84 | 85 | ! from shr_megan_mod ... should be generalized and shared... 86 | grploop: do i = 1,n_exp_items 87 | 88 | ! parse out the term names 89 | ! from first parsing out the terms in the summation equation ("+" separates the terms) 90 | 91 | sum_string = sums_grps(i) 92 | j = scan( sum_string, '=' ) 93 | nelem = 1 94 | ndxs(nelem) = j ! ndxs stores the index of each term of the equation 95 | 96 | ! find indices of all the terms in the equation 97 | tmp_str = trim( sum_string(j+1:) ) 98 | j = scan( tmp_str, '+' ) 99 | do while(j>0) 100 | nelem = nelem+1 101 | ndxs(nelem) = ndxs(nelem-1) + j 102 | tmp_str = tmp_str(j+1:) 103 | j = scan( tmp_str, '+' ) 104 | enddo 105 | ndxs(nelem+1) = len(sum_string)+1 106 | 107 | allocate( exp_item ) 108 | 109 | exp_item%n_terms = nelem ! number of terms 110 | 111 | exp_item%name = trim(adjustl( sum_string(:ndxs(1)-1))) ! thing to the left of the "=" is used as the name of the group 112 | 113 | ! now that we have the number of terms in the summation allocate memory for the terms 114 | allocate( exp_item%vars(nelem) ) 115 | allocate( exp_item%coeffs(nelem) ) 116 | 117 | coeff0 = 1._r8 ! default multiplier 118 | 119 | ! now parse out the multiplier from the terms 120 | elmloop: do k = 1,nelem 121 | 122 | exp_item%coeffs(k) = coeff0 123 | 124 | ! get the term name which follows the '*' operator if the is one 125 | tmp_name = adjustl(sum_string(ndxs(k)+1:ndxs(k+1)-1)) 126 | 127 | j = scan( tmp_name, '*' ) 128 | if (j>0) then 129 | 130 | xchr = tmp_name(1:j-1) ! get the multipler (left of the '*') 131 | read( xchr, * ) xdbl ! convert the string to a real 132 | exp_item%coeffs(k) = xdbl ! store the multiplier 133 | 134 | j1 = scan( tmp_name, '(' ) 135 | if (j1>0) then 136 | coeff0 = xdbl 137 | tmp_name = trim(adjustl(tmp_name(j1+1:))) ! get the term name (right of the '*') 138 | else 139 | coeff0 = 1._r8 140 | tmp_name = trim(adjustl(tmp_name(j+1:))) ! get the term name (right of the '*') 141 | endif 142 | 143 | endif 144 | 145 | j2 = scan( tmp_name, ')' ) 146 | if (j2>0) then 147 | coeff0 = 1._r8 148 | tmp_name = tmp_name(1:j2-1) 149 | endif 150 | 151 | exp_item%vars(k) = trim(tmp_name) 152 | 153 | enddo elmloop 154 | 155 | if (associated(exp_item)) then 156 | if (associated(exp_items_list)) then 157 | list_item => exp_items_list 158 | do while(associated(list_item%next_item)) 159 | list_item => list_item%next_item 160 | enddo 161 | list_item%next_item => exp_item 162 | else 163 | exp_items_list => exp_item 164 | endif 165 | endif 166 | 167 | 168 | enddo grploop 169 | endif has_grps 170 | 171 | if ( present(nitems) ) then 172 | nitems = n_exp_items 173 | endif 174 | 175 | deallocate(sums_grps) 176 | 177 | end function shr_exp_parse 178 | 179 | ! ----------------------------------------------------------------- 180 | ! deallocates memory occupied by linked list 181 | ! ----------------------------------------------------------------- 182 | subroutine shr_exp_list_destroy( list ) 183 | type(shr_exp_item_t), pointer, intent(inout) :: list 184 | 185 | type(shr_exp_item_t), pointer :: item, next 186 | 187 | item => list 188 | do while(associated(item)) 189 | next => item%next_item 190 | if (associated(item%vars)) then 191 | deallocate(item%vars) 192 | nullify(item%vars) 193 | deallocate(item%coeffs) 194 | nullify(item%coeffs) 195 | endif 196 | deallocate(item) 197 | nullify(item) 198 | item => next 199 | enddo 200 | 201 | end subroutine shr_exp_list_destroy 202 | 203 | end module shr_expr_parser_mod 204 | -------------------------------------------------------------------------------- /cesm/nuopc_cap_share/shr_lightning_coupling_mod.F90: -------------------------------------------------------------------------------- 1 | module shr_lightning_coupling_mod 2 | 3 | !======================================================================== 4 | ! Module for handling namelist variables related to lightning coupling 5 | !======================================================================== 6 | 7 | use ESMF , only : ESMF_VMGetCurrent, ESMF_VM, ESMF_VMGet 8 | use ESMF , only : ESMF_LOGERR_PASSTHRU, ESMF_SUCCESS 9 | use ESMF , only : ESMF_VMBroadCast, ESMF_Logical, assignment(=) 10 | use shr_sys_mod , only : shr_sys_abort 11 | use shr_log_mod , only : shr_log_getLogUnit 12 | use shr_nl_mod , only : shr_nl_find_group_name 13 | use nuopc_shr_methods, only : chkerr 14 | 15 | implicit none 16 | private 17 | 18 | ! !PUBLIC MEMBER FUNCTIONS 19 | public shr_lightning_coupling_readnl ! Read namelist 20 | 21 | character(len=*), parameter :: & 22 | u_FILE_u=__FILE__ 23 | 24 | !==================================================================================== 25 | CONTAINS 26 | !==================================================================================== 27 | 28 | subroutine shr_lightning_coupling_readnl(NLFilename, atm_provides_lightning_out) 29 | 30 | !======================================================================== 31 | ! reads lightning_coupling_nl namelist and returns a variable specifying 32 | ! if atmosphere model provides lightning flash frequency field to mediator 33 | !======================================================================== 34 | 35 | ! input/output variables 36 | character(len=*), intent(in) :: NLFilename ! Namelist filename 37 | logical, intent(out) :: atm_provides_lightning_out ! if TRUE atm will provide lightning flash frequency 38 | 39 | !----- local ----- 40 | logical :: atm_provides_lightning 41 | type(ESMF_VM) :: vm 42 | integer :: unitn ! namelist unit number 43 | integer :: ierr ! error code 44 | logical :: exists ! if file exists or not 45 | type(ESMF_Logical):: ltmp(1) 46 | integer :: rc 47 | integer :: localpet 48 | integer :: mpicom 49 | integer :: s_logunit 50 | character(len=*), parameter :: atm_ozone_frequency_not_present = 'NOT_PRESENT' 51 | character(len=*), parameter :: subname = '(shr_lightning_coupling_readnl) ' 52 | ! ------------------------------------------------------------------ 53 | 54 | namelist /lightning_coupling_nl/ atm_provides_lightning 55 | 56 | rc = ESMF_SUCCESS 57 | 58 | atm_provides_lightning_out = .false. 59 | ltmp(1) = .false. 60 | 61 | !--- Open and read namelist --- 62 | if ( len_trim(NLFilename) == 0 ) then 63 | call shr_sys_abort( subname//'ERROR: nlfilename not set' ) 64 | end if 65 | call shr_log_getLogUnit(s_logunit) 66 | call ESMF_VMGetCurrent(vm, rc=rc) 67 | if (chkerr(rc,__LINE__,u_FILE_u)) return 68 | 69 | call ESMF_VMGet(vm, localPet=localpet, mpiCommunicator=mpicom, rc=rc) 70 | if (chkerr(rc,__LINE__,u_FILE_u)) return 71 | 72 | if (localpet==0) then 73 | ! ------------------------------------------------------------------------ 74 | ! Set default values in case namelist file doesn't exist, lightning_coupling_nl group 75 | ! doesn't exist within the file, or a given variable isn't present in the namelist 76 | ! group in the file. 77 | ! ------------------------------------------------------------------------ 78 | atm_provides_lightning = .false. 79 | 80 | ! ------------------------------------------------------------------------ 81 | ! Read namelist file 82 | ! ------------------------------------------------------------------------ 83 | inquire( file=trim(NLFileName), exist=exists) 84 | if ( exists ) then 85 | open(newunit=unitn, file=trim(NLFilename), status='old' ) 86 | write(s_logunit,'(a)') subname,'Read in lightning_coupling_nl namelist from: ', trim(NLFilename) 87 | call shr_nl_find_group_name(unitn, 'lightning_coupling_nl', ierr) 88 | if (ierr == 0) then 89 | ! Note that ierr /= 0 means no namelist is present. 90 | read(unitn, lightning_coupling_nl, iostat=ierr) 91 | if (ierr > 0) then 92 | call shr_sys_abort(subname//'problem reading lightning_coupling_nl') 93 | end if 94 | end if 95 | close( unitn ) 96 | end if 97 | 98 | ltmp(1) = atm_provides_lightning 99 | 100 | end if 101 | 102 | ! ------------------------------------------------------------------------ 103 | ! Broadcast values to all tasks 104 | ! ------------------------------------------------------------------------ 105 | call ESMF_VMBroadcast(vm, ltmp, count=1, rootPet=0, rc=rc) 106 | if (chkerr(rc,__LINE__,u_FILE_u)) return 107 | 108 | atm_provides_lightning_out = ltmp(1) 109 | 110 | end subroutine shr_lightning_coupling_readnl 111 | 112 | end module shr_lightning_coupling_mod 113 | -------------------------------------------------------------------------------- /cesm/nuopc_cap_share/shr_ndep_mod.F90: -------------------------------------------------------------------------------- 1 | module shr_ndep_mod 2 | 3 | !======================================================================== 4 | ! Module for handling nitrogen depostion of tracers. 5 | ! This module is shared by land and atmosphere models for the computations of 6 | ! dry deposition of tracers 7 | !======================================================================== 8 | 9 | use ESMF , only : ESMF_VMGetCurrent, ESMF_VM, ESMF_VMGet 10 | use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_SUCCESS 11 | use shr_sys_mod , only : shr_sys_abort 12 | use shr_log_mod , only : shr_log_getLogUnit 13 | use shr_kind_mod , only : r8 => shr_kind_r8 14 | use shr_nl_mod , only : shr_nl_find_group_name 15 | use shr_mpi_mod , only : shr_mpi_bcast 16 | 17 | implicit none 18 | private 19 | 20 | ! !PUBLIC MEMBER FUNCTIONS 21 | public :: shr_ndep_readnl ! Read namelist 22 | 23 | character(len=*), parameter :: & 24 | u_FILE_u=__FILE__ 25 | 26 | !==================================================================================== 27 | CONTAINS 28 | !==================================================================================== 29 | 30 | subroutine shr_ndep_readnl(NLFilename, ndep_nflds) 31 | 32 | !======================================================================== 33 | ! reads ndep_inparm namelist and sets up driver list of fields for 34 | ! atmosphere -> land and atmosphere -> ocn communications. 35 | !======================================================================== 36 | 37 | ! input/output variables 38 | character(len=*), intent(in) :: NLFilename ! Namelist filename 39 | integer , intent(out) :: ndep_nflds 40 | 41 | !----- local ----- 42 | type(ESMF_VM) :: vm 43 | integer :: i ! Indices 44 | integer :: unitn ! namelist unit number 45 | integer :: ierr ! error code 46 | logical :: exists ! if file exists or not 47 | integer :: rc 48 | integer, parameter :: maxspc = 100 ! Maximum number of species 49 | character(len=32) :: ndep_list(maxspc) = '' ! List of ndep species 50 | integer :: localpet 51 | integer :: mpicom 52 | integer :: logunit 53 | character(*),parameter :: subName = '(shr_ndep_readnl) ' 54 | character(*),parameter :: F00 = "('(shr_ndep_readnl) ',8a)" 55 | ! ------------------------------------------------------------------ 56 | 57 | namelist /ndep_inparm/ ndep_list 58 | 59 | !----------------------------------------------------------------------------- 60 | ! Read namelist and figure out the ndep field list to pass 61 | ! First check if file exists and if not, n_ndep will be zero 62 | !----------------------------------------------------------------------------- 63 | 64 | rc = ESMF_SUCCESS 65 | 66 | !--- Open and read namelist --- 67 | if ( len_trim(NLFilename) == 0 ) then 68 | call shr_sys_abort( subName//'ERROR: nlfilename not set' ) 69 | end if 70 | call shr_log_getLogUnit(logunit) 71 | call ESMF_VMGetCurrent(vm, rc=rc) 72 | if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return 73 | 74 | call ESMF_VMGet(vm, localPet=localPet, mpiCommunicator=mpicom, rc=rc) 75 | if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return 76 | 77 | ! Note the following still needs to be called on all processors since the mpi_bcast is a collective 78 | ! call on all the pes of mpicom 79 | if (localpet==0) then 80 | inquire( file=trim(NLFileName), exist=exists) 81 | if ( exists ) then 82 | open(newunit=unitn, file=trim(NLFilename), status='old' ) 83 | write(logunit,F00) 'Read in ndep_inparm namelist from: ', trim(NLFilename) 84 | call shr_nl_find_group_name(unitn, 'ndep_inparm', ierr) 85 | if (ierr == 0) then 86 | ! Note that ierr /= 0, no namelist is present. 87 | read(unitn, ndep_inparm, iostat=ierr) 88 | if (ierr > 0) then 89 | call shr_sys_abort(trim(subName) //'problem of read of ndep_inparm ') 90 | endif 91 | endif 92 | close( unitn ) 93 | end if 94 | end if 95 | call shr_mpi_bcast( ndep_list, mpicom ) 96 | 97 | ndep_nflds = 0 98 | do i=1,maxspc 99 | if (len_trim(ndep_list(i)) > 0) then 100 | ndep_nflds = ndep_nflds+1 101 | endif 102 | enddo 103 | 104 | end subroutine shr_ndep_readnl 105 | 106 | end module shr_ndep_mod 107 | -------------------------------------------------------------------------------- /cesm/nuopc_cap_share/shr_ozone_coupling_mod.F90: -------------------------------------------------------------------------------- 1 | module shr_ozone_coupling_mod 2 | 3 | !======================================================================== 4 | ! Module for handling namelist variables related to ozone coupling 5 | !======================================================================== 6 | 7 | use ESMF , only : ESMF_VMGetCurrent, ESMF_VM, ESMF_VMGet 8 | use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_SUCCESS 9 | use shr_sys_mod , only : shr_sys_abort 10 | use shr_log_mod , only : shr_log_getLogUnit 11 | use shr_nl_mod , only : shr_nl_find_group_name 12 | use shr_mpi_mod , only : shr_mpi_bcast 13 | 14 | implicit none 15 | private 16 | 17 | ! !PUBLIC MEMBER FUNCTIONS 18 | public shr_ozone_coupling_readnl ! Read namelist 19 | 20 | ! !PUBLIC DATA MEMBERS 21 | ! atm_ozone_frequency can be one of the following values 22 | integer, parameter, public :: atm_ozone_frequency_unset = 0 23 | integer, parameter, public :: atm_ozone_frequency_subdaily = 1 24 | integer, parameter, public :: atm_ozone_frequency_multiday_average = 2 25 | 26 | character(len=*), parameter :: & 27 | u_FILE_u=__FILE__ 28 | 29 | !==================================================================================== 30 | CONTAINS 31 | !==================================================================================== 32 | 33 | subroutine shr_ozone_coupling_readnl(NLFilename, atm_ozone_frequency_val) 34 | 35 | !======================================================================== 36 | ! reads ozone_coupling_nl namelist and returns a variable specifying the frequency at 37 | ! which the atmosphere model computes surface ozone 38 | !======================================================================== 39 | 40 | ! input/output variables 41 | character(len=*), intent(in) :: NLFilename ! Namelist filename 42 | ! atm_ozone_frequency will be one of the above constants (atm_ozone_frequency_*), 43 | ! specifying the frequency at which the atmosphere model computes surface ozone 44 | integer , intent(out) :: atm_ozone_frequency_val 45 | 46 | !----- local ----- 47 | character(len=64) :: atm_ozone_frequency 48 | type(ESMF_VM) :: vm 49 | integer :: unitn ! namelist unit number 50 | integer :: ierr ! error code 51 | logical :: exists ! if file exists or not 52 | integer :: rc 53 | integer :: localpet 54 | integer :: mpicom 55 | integer :: s_logunit 56 | character(len=*), parameter :: atm_ozone_frequency_not_present = 'NOT_PRESENT' 57 | character(len=*), parameter :: subname = '(shr_ozone_coupling_readnl) ' 58 | ! ------------------------------------------------------------------ 59 | 60 | namelist /ozone_coupling_nl/ atm_ozone_frequency 61 | 62 | rc = ESMF_SUCCESS 63 | 64 | !--- Open and read namelist --- 65 | if ( len_trim(NLFilename) == 0 ) then 66 | call shr_sys_abort( subname//'ERROR: nlfilename not set' ) 67 | end if 68 | call shr_log_getLogUnit(s_logunit) 69 | call ESMF_VMGetCurrent(vm, rc=rc) 70 | if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return 71 | 72 | call ESMF_VMGet(vm, localPet=localpet, mpiCommunicator=mpicom, rc=rc) 73 | if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return 74 | 75 | if (localpet==0) then 76 | ! ------------------------------------------------------------------------ 77 | ! Set default values in case namelist file doesn't exist, ozone_coupling_nl group 78 | ! doesn't exist within the file, or a given variable isn't present in the namelist 79 | ! group in the file. 80 | ! ------------------------------------------------------------------------ 81 | atm_ozone_frequency = atm_ozone_frequency_not_present 82 | 83 | ! ------------------------------------------------------------------------ 84 | ! Read namelist file 85 | ! ------------------------------------------------------------------------ 86 | inquire( file=trim(NLFileName), exist=exists) 87 | if ( exists ) then 88 | open(newunit=unitn, file=trim(NLFilename), status='old' ) 89 | write(s_logunit,'(a)') '(shr_ozone_coupling_readnl) Read in ozone_coupling_nl namelist from: ', trim(NLFilename) 90 | call shr_nl_find_group_name(unitn, 'ozone_coupling_nl', ierr) 91 | if (ierr == 0) then 92 | ! Note that ierr /= 0 means no namelist is present. 93 | read(unitn, ozone_coupling_nl, iostat=ierr) 94 | if (ierr > 0) then 95 | call shr_sys_abort(trim(subname)//'problem reading ozone_coupling_nl ') 96 | end if 97 | end if 98 | close( unitn ) 99 | end if 100 | 101 | ! ------------------------------------------------------------------------ 102 | ! Translate read-in values to appropriate return values 103 | ! ------------------------------------------------------------------------ 104 | select case(atm_ozone_frequency) 105 | case(atm_ozone_frequency_not_present) 106 | atm_ozone_frequency_val = atm_ozone_frequency_unset 107 | case("subdaily") 108 | atm_ozone_frequency_val = atm_ozone_frequency_subdaily 109 | case("multiday_average") 110 | atm_ozone_frequency_val = atm_ozone_frequency_multiday_average 111 | case default 112 | call shr_sys_abort(trim(subname)//'unknown value for atm_ozone_frequency: '// & 113 | trim(atm_ozone_frequency)) 114 | end select 115 | end if 116 | 117 | ! ------------------------------------------------------------------------ 118 | ! Broadcast values to all processors 119 | ! ------------------------------------------------------------------------ 120 | call shr_mpi_bcast(atm_ozone_frequency_val, mpicom) 121 | 122 | end subroutine shr_ozone_coupling_readnl 123 | 124 | end module shr_ozone_coupling_mod 125 | -------------------------------------------------------------------------------- /cime_config/ExpectedTestFails.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | FAIL 36 | Mom restarts are offset 37 | 38 | 39 | 40 | 41 | FAIL 42 | Mom restarts are offset 43 | 44 | 45 | 46 | 47 | FAIL 48 | Mom restarts are offset 49 | 50 | 51 | 52 | 53 | FAIL 54 | Debug run fails due to esmf issue 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /cime_config/buildexe: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | build model executable 5 | """ 6 | 7 | import sys, os 8 | 9 | _CIMEROOT = os.environ.get("CIMEROOT") 10 | if _CIMEROOT is None: 11 | raise SystemExit("ERROR: must set CIMEROOT environment variable") 12 | 13 | sys.path.append(os.path.join(_CIMEROOT, "scripts", "Tools")) 14 | 15 | from standard_script_setup import * 16 | from CIME.buildlib import parse_input 17 | from CIME.build import get_standard_makefile_args 18 | from CIME.case import Case 19 | from CIME.utils import expect, run_cmd 20 | 21 | #pylint: disable=undefined-variable 22 | logger = logging.getLogger(__name__) 23 | 24 | ############################################################################### 25 | def _main_func(): 26 | ############################################################################### 27 | 28 | caseroot, _, _ = parse_input(sys.argv) 29 | 30 | logger.info("Building a single executable version of target coupled model") 31 | 32 | with Case(caseroot) as case: 33 | casetools = case.get_value("CASETOOLS") 34 | exeroot = case.get_value("EXEROOT") 35 | gmake = case.get_value("GMAKE") 36 | gmake_j = case.get_value("GMAKE_J") 37 | cime_model = case.get_value("MODEL") 38 | num_esp = case.get_value("NUM_COMP_INST_ESP") 39 | ocn_model = case.get_value("COMP_OCN") 40 | gmake_args = get_standard_makefile_args(case) 41 | link_libs = case.get_value("CAM_LINKED_LIBS", subgroup="build_component_cam") 42 | esmf_aware_threading = case.get_value("ESMF_AWARE_THREADING") 43 | 44 | # Determine valid components 45 | valid_comps = [] 46 | comp_classes = case.get_values("COMP_CLASSES") 47 | for item in comp_classes: 48 | comp = case.get_value("COMP_" + item) 49 | valid = True 50 | if comp == 's' + item.lower(): 51 | valid = False 52 | if valid: 53 | valid_comps.append(item) 54 | 55 | datamodel_in_compset = False 56 | for comp in comp_classes: 57 | dcompname = "d"+comp.lower() 58 | if dcompname in case.get_value("COMP_{}".format(comp)): 59 | datamodel_in_compset = True 60 | 61 | if len(valid_comps) == 2 and not datamodel_in_compset: 62 | skip_mediator = True 63 | else: 64 | skip_mediator = False 65 | 66 | if ocn_model == 'mom': 67 | gmake_args += "USE_FMS=TRUE" 68 | 69 | if link_libs is not None: 70 | gmake_args += 'USER_SLIBS="{}"'.format(link_libs) 71 | 72 | comp_classes = case.get_values("COMP_CLASSES") 73 | for comp in comp_classes: 74 | model = case.get_value("COMP_{}".format(comp)) 75 | stubcomp = "s{}".format(comp.lower()) 76 | if model == stubcomp: 77 | gmake_args += " {}_PRESENT=FALSE".format(comp) 78 | if skip_mediator: 79 | gmake_args += " MED_PRESENT=FALSE" 80 | if esmf_aware_threading: 81 | gmake_args += " USER_CPPDEFS=-DESMF_AWARE_THREADING" 82 | 83 | gmake_args += " IAC_PRESENT=FALSE" 84 | expect((num_esp is None) or (int(num_esp) == 1), "ESP component restricted to one instance") 85 | 86 | bld_root = os.path.join(exeroot,'cpl','obj') 87 | if not os.path.isdir(bld_root): 88 | os.makedirs(bld_root) 89 | 90 | with open(os.path.join(bld_root,'Filepath'), 'w', encoding="utf-8") as out: 91 | cmeps_dir = os.path.join(os.path.dirname(__file__), os.pardir) 92 | # SourceMods dir needs to be first listed 93 | out.write(os.path.join(caseroot, "SourceMods", "src.drv") + "\n") 94 | if not skip_mediator: 95 | out.write(os.path.join(cmeps_dir, "mediator") + "\n") 96 | out.write(os.path.join(cmeps_dir, "cesm", "flux_atmocn") + "\n") 97 | out.write(os.path.join(cmeps_dir, "cesm", "driver") + "\n") 98 | 99 | # build model executable 100 | makefile = os.path.join(casetools, "Makefile") 101 | exename = os.path.join(exeroot, cime_model + ".exe") 102 | 103 | # always rebuild file esm.F90 this is because cpp macros in that file may have changed 104 | esm = os.path.join(bld_root,"esm.o") 105 | if os.path.isfile(esm): 106 | os.remove(esm) 107 | 108 | # always relink 109 | if os.path.isfile(exename): 110 | os.remove(exename) 111 | exename = os.path.relpath(exename, bld_root) 112 | cmd = "{} exec_se -j {} EXEC_SE={} COMP_NAME=driver {} -f {} "\ 113 | .format(gmake, gmake_j, exename, gmake_args, makefile) 114 | pio = os.environ.get("PIO") 115 | if pio: 116 | os.environ["PIO_LIBDIR"] = os.path.join(pio,"lib") 117 | 118 | rc, out, err = run_cmd(cmd,from_dir=bld_root) 119 | expect(rc==0,"Command {} failed rc={}\nout={}\nerr={}".format(cmd,rc,out,err)) 120 | if err: 121 | logger.info(err) 122 | logger.info(out) 123 | 124 | ############################################################################### 125 | 126 | if __name__ == "__main__": 127 | _main_func() 128 | -------------------------------------------------------------------------------- /cime_config/config_archive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | r 4 | h[ix]?\d*\..*\.nc(\.gz)?$ 5 | unset 6 | 7 | rpointer.cpl$NINST_STRING.$DATENAME 8 | $CASE.cpl$NINST_STRING.r.$DATENAME.nc 9 | 10 | 11 | cpl_0001.log.5548574.chadmin1.180228-124723.gz 12 | casename.cpl.r.1976-01-01-00000.nc 13 | rpointer.cpl_0001.1976-01-01-00000 14 | rpointer.cpl_0001.1976-01-01-43200 15 | rpointer.cpl.1976-01-01-00000 16 | casenamenot.cpl.r.1976-01-01-00000.nc 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /cime_config/config_compsets.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ========================================= 7 | compset naming convention 8 | ========================================= 9 | The compset longname below has the specified order 10 | atm, lnd, ice, ocn, river, glc wave esp cesm-options 11 | 12 | The notation for the compset longname below is 13 | TIME_ATM[%phys]_LND[%phys]_ICE[%phys]_OCN[%phys]_ROF[%phys]_GLC[%phys]_WAV[%phys][_ESP][_BGC%phys] 14 | 15 | The following compsets are those that can be tested in CIME stand-alone configurations 16 | without any prognostic components. 17 | For the compsets below the following are the only allowable values of the components. 18 | 19 | TIME = Time period (e.g. 2000, HIST, RCP8...) 20 | ATM = [DATM, SATM, XATM] 21 | LND = [DLND, SLND, XLND] 22 | ICE = [DICE, SICE, XICE] 23 | OCN = [DOCN, SOCN, XOCN] 24 | ROF = [DROF, SROF, XROF] 25 | GLC = [ SGLC ] 26 | WAV = [DWAV, SWAV ] 27 | ESP = [DESP, SESP ] 28 | 29 | The OPTIONAL %phys attributes specify submodes of the given system 30 | For example DOCN%DOM is the data ocean model for DOCN 31 | ALL data models must have a %phys option that corresponds to the data model mode 32 | 33 | Each compset node is associated with the following elements 34 | - lname 35 | - alias 36 | - support (optional description of the support level for this compset) 37 | Each compset node can also have the following attributes 38 | - grid (optional regular expression match for grid to work with the compset) 39 | 40 | 41 | 42 | AA 43 | 2000_DATM%NYF_DLND%LCPL_DICE%SSMI_DOCN%DOM_DROF%NYF_SGLC_DWAV 44 | 45 | 46 | 47 | A 48 | 2000_DATM%NYF_SLND_DICE%SSMI_DOCN%DOM_DROF%NYF_SGLC_SWAV 49 | 50 | 51 | 52 | ADSOM 53 | 2000_DATM%NYF_SLND_DICE%SSMI_DOCN%SOM_DROF%NYF_SGLC_SWAV_TEST 54 | 55 | 56 | 57 | ADSOMAQP 58 | 2000_DATM%NYF_SLND_SICE_DOCN%SOMAQP_SROF_SGLC_SWAV 59 | 60 | 61 | 62 | ADAQP3 63 | 2000_DATM%NYF_SLND_SICE_DOCN%AQP3_SROF_SGLC_SWAV 64 | 65 | 66 | 67 | ADAQPFILE 68 | 2000_DATM%NYF_SLND_SICE_DOCN%AQPFILE_SROF_SGLC_SWAV 69 | 70 | 71 | 72 | A1850DLND 73 | 1850_SATM_DLND%SCPL_SICE_SOCN_SROF_SGLC_SWAV 74 | 75 | 76 | 77 | ADWAV 78 | 2000_SATM_SLND_SICE_SOCN_SROF_SGLC_DWAV%CLIMO 79 | 80 | 81 | 82 | ADESP 83 | 2000_DATM%NYF_SLND_SICE_DOCN%SOMAQP_SROF_SGLC_SWAV_DESP%NOOP 84 | 85 | 86 | 87 | ADESP_TEST 88 | 2000_DATM%NYF_SLND_SICE_DOCN%SOMAQP_SROF_SGLC_SWAV_DESP%TEST 89 | 90 | 91 | 92 | AIAF 93 | 2000_DATM%IAF_SLND_DICE%IAF_DOCN%IAF_DROF%IAF_SGLC_SWAV 94 | 95 | 96 | 97 | S 98 | 2000_SATM_SLND_SICE_SOCN_SROF_SGLC_SWAV_SESP 99 | 100 | 101 | 102 | X 103 | 2000_XATM_XLND_XICE_XOCN_XROF_XGLC_XWAV 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /cime_config/config_pes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | none 9 | 10 | -1 11 | -1 12 | -1 13 | -1 14 | -1 15 | -1 16 | -1 17 | -1 18 | -1 19 | 20 | 21 | 1 22 | 1 23 | 1 24 | 1 25 | 1 26 | 1 27 | 1 28 | 1 29 | 1 30 | 31 | 32 | 0 33 | 0 34 | 0 35 | 0 36 | 0 37 | 0 38 | 0 39 | 0 40 | 0 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | none 50 | 51 | 60 52 | 60 53 | 60 54 | 60 55 | 60 56 | 60 57 | 60 58 | 60 59 | 60 60 | 61 | 62 | 2 63 | 2 64 | 2 65 | 2 66 | 2 67 | 2 68 | 2 69 | 2 70 | 2 71 | 72 | 73 | 0 74 | 0 75 | 0 76 | 0 77 | 0 78 | 0 79 | 0 80 | 0 81 | 0 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | none 91 | 92 | -8 93 | -8 94 | -8 95 | -8 96 | -8 97 | -8 98 | -8 99 | -8 100 | -8 101 | 102 | 103 | 2 104 | 2 105 | 2 106 | 2 107 | 2 108 | 2 109 | 2 110 | 2 111 | 1 112 | 113 | 114 | 0 115 | 0 116 | 0 117 | 0 118 | 0 119 | 0 120 | 0 121 | 0 122 | 0 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | none 132 | 133 | -1 134 | -1 135 | -1 136 | -1 137 | -1 138 | -1 139 | -1 140 | -1 141 | -1 142 | 143 | 144 | 8 145 | 8 146 | 8 147 | 8 148 | 8 149 | 8 150 | 8 151 | 8 152 | 8 153 | 154 | 155 | 0 156 | 0 157 | 0 158 | 0 159 | 0 160 | 0 161 | 0 162 | 0 163 | 0 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | PE layout for tests 173 | 174 | 64 175 | 64 176 | 64 177 | 64 178 | 64 179 | 64 180 | 64 181 | 64 182 | 64 183 | 184 | 185 | 16 186 | 16 187 | 16 188 | 16 189 | 16 190 | 16 191 | 16 192 | 16 193 | 16 194 | 195 | 196 | 0 197 | 0 198 | 0 199 | 0 200 | 0 201 | 0 202 | 0 203 | 0 204 | 0 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /cime_config/runseq/driver_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Inherit from the dictionary class 4 | class DriverConfig(dict): 5 | 6 | ############################################### 7 | def __init__(self, case, coupling_times): 8 | ############################################### 9 | # this initializes the dictionary 10 | super(DriverConfig,self).__init__() 11 | 12 | self['atm'] = self.__compute_atm(case, coupling_times) 13 | self['glc'] = self.__compute_glc(case, coupling_times) 14 | self['ice'] = self.__compute_ice(case, coupling_times) 15 | self['lnd'] = self.__compute_lnd(case, coupling_times) 16 | self['ocn'] = self.__compute_ocn(case, coupling_times) 17 | self['rof'] = self.__compute_rof(case, coupling_times) 18 | self['wav'] = self.__compute_wav(case, coupling_times) 19 | 20 | ############################################### 21 | def __compute_atm(self, case, coupling_times): 22 | ############################################### 23 | 24 | comp_atm = case.get_value("COMP_ATM") 25 | 26 | run_atm = True 27 | med_to_atm = True 28 | if (comp_atm == 'satm'): 29 | run_atm = False 30 | med_to_atm = False 31 | elif (comp_atm == 'datm'): 32 | # TODO: check of data model prognostic flag is on - this is a new xml variable 33 | # If the prognostic flag is on, then should set med_to_atm to True 34 | if_prognostic = False 35 | med_to_atm = if_prognostic 36 | 37 | # TODO: need to put in special logical for adiabatic mode - where the atmosphere does 38 | # does not really send anything to the mediator 39 | # This will be the case if (case.get_value('COMP_OCN') == 'socn'): 40 | # In this case - a special run sequence should be written 41 | 42 | return (run_atm, med_to_atm, coupling_times["atm_cpl_dt"]) 43 | 44 | ############################################### 45 | def __compute_glc(self, case, coupling_times): 46 | ############################################### 47 | 48 | # In the mediator the glc_avg_period will be set as an alarm 49 | # on the on the prep_glc_clock. When this alarm rings - the 50 | # averaging will be done. 51 | 52 | comp_glc = case.get_value("COMP_GLC") 53 | 54 | run_glc = True 55 | med_to_glc = True 56 | if (comp_glc == 'sglc'): 57 | run_glc = False 58 | med_to_glc = False 59 | elif (comp_glc == 'cism'): 60 | if not case.get_value("CISM_EVOLVE"): 61 | run_glc = False 62 | 63 | # If CISM is not evolving only get data back from cism at the initial time 64 | # However will still need to call the exchange at the end if the stop_option 65 | # is nsteps or days - or otherwise just every ndays 66 | # Note that nsteps is the minimum component coupling time 67 | if comp_glc == 'cism': 68 | glc_coupling_time = coupling_times["glc_cpl_dt"] 69 | if not case.get_value("CISM_EVOLVE"): 70 | stop_option = case.get_value('STOP_OPTION') 71 | stop_n = case.get_value('STOP_N') 72 | if stop_option == 'nyears': 73 | glc_coupling_time = coupling_times["glc_cpl_dt"] 74 | elif stop_option == 'nsteps': 75 | glc_coupling_time = stop_n * coupling_times["glc_cpl_dt"] 76 | elif stop_option == 'ndays': 77 | glc_coupling_time = stop_n * 86400 78 | else: 79 | glc_coupling_time = 86400 80 | elif comp_glc == 'dglc' or comp_glc == 'xglc': 81 | glc_coupling_time = coupling_times["glc_cpl_dt"] 82 | else: 83 | glc_coupling_time = 0 84 | 85 | return (run_glc, med_to_glc, glc_coupling_time) 86 | 87 | ############################################### 88 | def __compute_ice(self, case, coupling_times): 89 | ############################################### 90 | 91 | comp_ice = case.get_value("COMP_ICE") 92 | 93 | run_ice = True 94 | med_to_ice = True # this is the case for dice 95 | if (comp_ice == 'sice'): 96 | run_ice = False 97 | med_to_ice = False 98 | 99 | return (run_ice, med_to_ice, coupling_times["ice_cpl_dt"]) 100 | 101 | ############################################### 102 | def __compute_lnd(self, case, coupling_times): 103 | ############################################### 104 | 105 | comp_lnd = case.get_value("COMP_LND") 106 | 107 | run_lnd = True 108 | med_to_lnd = True 109 | if (comp_lnd == 'slnd'): 110 | run_lnd = False 111 | med_to_lnd = False 112 | elif (comp_lnd == 'dlnd'): 113 | # TODO: check of data model prognostic flag is on - this is a new xml variable 114 | # If the prognostic flag is on, then should set med_to_lnd to True 115 | if_prognostic = False 116 | med_to_lnd = if_prognostic 117 | 118 | return (run_lnd, med_to_lnd, coupling_times["lnd_cpl_dt"]) 119 | 120 | ############################################### 121 | def __compute_ocn(self, case, coupling_times): 122 | ############################################### 123 | 124 | comp_ocn = case.get_value("COMP_OCN") 125 | 126 | run_ocn = True 127 | med_to_ocn = True 128 | if (comp_ocn == 'socn'): 129 | run_ocn = False 130 | med_to_ocn = False 131 | elif (comp_ocn == 'docn'): 132 | # TODO: check of data model prognostic flag is on - this is a new xml variable 133 | # If the prognostic flag is on, then should set med_to_wav to True 134 | docn_mode = case.get_value("DOCN_MODE") 135 | docn_import_fields = case.get_value("DOCN_IMPORT_FIELDS") 136 | med_to_ocn = ('som' in docn_mode or 'interannual' in docn_mode or docn_import_fields != 'none') 137 | 138 | return (run_ocn, med_to_ocn, coupling_times["ocn_cpl_dt"]) 139 | 140 | ############################################### 141 | def __compute_rof(self, case, coupling_times): 142 | ############################################### 143 | 144 | comp_rof = case.get_value("COMP_ROF") 145 | 146 | run_rof = True 147 | med_to_rof = True 148 | if (comp_rof == 'srof'): 149 | run_rof = False 150 | med_to_rof = False 151 | elif (comp_rof == 'drof'): 152 | # TODO: check of data model prognostic flag is on - this is a new xml variable 153 | # If the prognostic flag is on, then should set med_to_rof to True 154 | if_prognostic = False 155 | med_to_rof = if_prognostic 156 | else: 157 | # this is active runoff - determine if the mode or the grid is null - and in that case 158 | # remove all interactions with rof from the run sequence 159 | if ((case.get_value("COMP_ROF") == 'mosart' and case.get_value("MOSART_MODE") == 'NULL') or 160 | (case.get_value("COMP_ROF") == 'rtm' and case.get_value("RTM_MODE") == 'NULL') or 161 | (case.get_value("ROF_GRID") == 'null')): 162 | run_rof = False 163 | med_to_rof = False 164 | 165 | return (run_rof, med_to_rof, coupling_times["rof_cpl_dt"]) 166 | 167 | ############################################### 168 | def __compute_wav(self, case, coupling_times): 169 | ############################################### 170 | 171 | comp_wav = case.get_value("COMP_WAV") 172 | 173 | run_wav = True 174 | med_to_wav = True 175 | if (comp_wav == 'swav'): 176 | run_wav = False 177 | med_to_wav = False 178 | elif (comp_wav == 'dwav'): 179 | # TODO: check of data model prognostic flag is on - this is a new xml variable 180 | # If the prognostic flag is on, then should set med_to_wav to True 181 | if_prognostic = False 182 | med_to_wav = if_prognostic 183 | 184 | return (run_wav, med_to_wav, coupling_times["wav_cpl_dt"]) 185 | -------------------------------------------------------------------------------- /cime_config/runseq/gen_runseq.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | class RunSeq: 4 | def __init__(self, outfile): 5 | self.__time_loop = list() 6 | self.__outfile_name = outfile 7 | self.__outfile = None 8 | 9 | def __enter__(self): 10 | self.__outfile = open(self.__outfile_name, "w", encoding="utf-8") 11 | self.__outfile.write("runSeq:: \n") 12 | return self 13 | 14 | def __exit__(self, *_): 15 | self.__exit_sequence() 16 | self.__outfile.close() 17 | return False 18 | 19 | @property 20 | def time_loop(self): 21 | if self.__time_loop: 22 | return self.__time_loop[-1][0] # this is the first element of the last tuple 23 | else: 24 | return 0 25 | 26 | @property 27 | def active_depth(self): 28 | if self.__time_loop: 29 | return self.__time_loop[-1][1] 30 | else: 31 | return -1 32 | 33 | def enter_time_loop(self, coupling_time, active=True, newtime=True, addextra_atsign=False): 34 | if newtime: 35 | if addextra_atsign: 36 | self.__outfile.write ("@@" + str(coupling_time) + " \n" ) 37 | else: 38 | self.__outfile.write ("@" + str(coupling_time) + " \n" ) 39 | if active: 40 | self.__time_loop.append((self.time_loop+1, self.active_depth+1)) 41 | else: 42 | self.__time_loop.append((self.time_loop+1, self.active_depth)) 43 | 44 | def add_action(self, action, if_add): 45 | if if_add: 46 | self.__outfile.write (" {}\n".format(action)) 47 | 48 | def leave_time_loop(self, leave_time, if_write_hist_rest=False, addextra_atsign=False ): 49 | if leave_time and self.__time_loop: 50 | _, active_depth = self.__time_loop.pop() 51 | if if_write_hist_rest or active_depth == 0: 52 | self.__outfile.write (" MED med_phases_history_write \n" ) 53 | self.__outfile.write (" MED med_phases_restart_write \n" ) 54 | self.__outfile.write (" MED med_phases_profile \n" ) 55 | if addextra_atsign: 56 | self.__outfile.write ("@@ \n" ) 57 | else: 58 | self.__outfile.write ("@ \n" ) 59 | 60 | def __exit_sequence(self): 61 | while self.__time_loop: 62 | self.leave_time_loop(True) 63 | self.__outfile.write ("::\n" ) 64 | -------------------------------------------------------------------------------- /cime_config/runseq/runseq_D.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os, shutil, sys 4 | from CIME.utils import expect 5 | from gen_runseq import RunSeq 6 | from driver_config import DriverConfig 7 | 8 | _CIMEROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir,os.pardir,os.pardir,os.pardir)) 9 | sys.path.append(os.path.join(_CIMEROOT, "scripts", "Tools")) 10 | 11 | from standard_script_setup import * 12 | 13 | #pylint:disable=undefined-variable 14 | logger = logging.getLogger(__name__) 15 | 16 | def gen_runseq(case, coupling_times): 17 | 18 | rundir = case.get_value("RUNDIR") 19 | caseroot = case.get_value("CASEROOT") 20 | 21 | driver_config = DriverConfig(case, coupling_times) 22 | run_atm, med_to_atm, atm_cpl_time = driver_config['atm'] 23 | run_ice, med_to_ice, ice_cpl_time = driver_config['ice'] 24 | run_ocn, med_to_ocn, ocn_cpl_time = driver_config['ocn'] 25 | run_rof, _ , _ = driver_config['rof'] 26 | 27 | if ice_cpl_time != atm_cpl_time: 28 | expect(False,"for D compsets require that ice_cpl_time equal atm_cpl_time") 29 | 30 | with RunSeq(os.path.join(caseroot, "CaseDocs", "nuopc.runseq")) as runseq: 31 | 32 | runseq.enter_time_loop(ocn_cpl_time, newtime=((ocn_cpl_time))) 33 | 34 | runseq.add_action("MED med_phases_prep_ocn_avg" , med_to_ocn) 35 | runseq.add_action("MED -> OCN :remapMethod=redist" , med_to_ocn) 36 | 37 | runseq.enter_time_loop(atm_cpl_time, newtime=((atm_cpl_time < ocn_cpl_time))) 38 | 39 | runseq.add_action ("MED med_phases_aofluxes_run" , run_ocn and run_atm and (med_to_ocn or med_to_atm)) 40 | runseq.add_action ("MED med_phases_prep_ocn_accum" , med_to_ocn) 41 | runseq.add_action ("MED med_phases_ocnalb_run" , med_to_ocn) 42 | 43 | runseq.add_action ("MED med_phases_prep_ice" , med_to_ice) 44 | runseq.add_action ("MED -> ICE :remapMethod=redist" , med_to_ice) 45 | 46 | runseq.add_action ("ICE" , run_ice) 47 | runseq.add_action ("ROF" , run_rof) 48 | runseq.add_action ("ATM" , run_atm) 49 | 50 | runseq.add_action ("ICE -> MED :remapMethod=redist" , run_ice) 51 | runseq.add_action("MED med_phases_post_ice" , run_ice) 52 | 53 | runseq.add_action ("ROF -> MED :remapMethod=redist" , run_rof) 54 | runseq.add_action("MED med_phases_post_rof" , run_rof) 55 | 56 | runseq.add_action ("ATM -> MED :remapMethod=redist" , run_atm) 57 | runseq.add_action ("MED med_phases_history_write" , atm_cpl_time == ocn_cpl_time) 58 | runseq.add_action ("MED med_phases_post_atm" , run_atm) 59 | 60 | runseq.leave_time_loop(run_rof and (atm_cpl_time < ocn_cpl_time)) 61 | 62 | runseq.add_action ("OCN" , run_ocn) 63 | runseq.add_action ("OCN -> MED :remapMethod=redist" , run_ocn) 64 | runseq.add_action ("MED med_phases_history_write" , atm_cpl_time < ocn_cpl_time) 65 | runseq.add_action ("MED med_phases_post_ocn" , run_ocn) 66 | 67 | runseq.leave_time_loop(True) 68 | 69 | shutil.copy(os.path.join(caseroot, "CaseDocs", "nuopc.runseq"), rundir) 70 | -------------------------------------------------------------------------------- /cime_config/runseq/runseq_TG.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os, shutil, sys 4 | from CIME.utils import expect 5 | from gen_runseq import RunSeq 6 | from driver_config import DriverConfig 7 | 8 | _CIMEROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir,os.pardir,os.pardir,os.pardir)) 9 | sys.path.append(os.path.join(_CIMEROOT, "scripts", "Tools")) 10 | 11 | from standard_script_setup import * 12 | 13 | #pylint:disable=undefined-variable 14 | logger = logging.getLogger(__name__) 15 | 16 | def gen_runseq(case, coupling_times): 17 | 18 | rundir = case.get_value("RUNDIR") 19 | caseroot = case.get_value("CASEROOT") 20 | 21 | driver_config = DriverConfig(case, coupling_times) 22 | run_glc, med_to_glc, glc_cpl_time = driver_config['glc'] 23 | run_lnd, _ , lnd_cpl_time = driver_config['lnd'] 24 | 25 | if lnd_cpl_time != glc_cpl_time: 26 | expect(False,"for TG compset require that lnd_cpl_time equal glc_cpl_time") 27 | 28 | with RunSeq(os.path.join(caseroot, "CaseDocs", "nuopc.runseq")) as runseq: 29 | 30 | runseq.enter_time_loop(glc_cpl_time, True) 31 | 32 | runseq.add_action ("LND" , run_lnd) 33 | runseq.add_action ("LND -> MED :remapMethod=redist" , run_lnd) 34 | runseq.add_action ("MED med_phases_post_lnd" , run_lnd) 35 | runseq.add_action ("MED med_phases_prep_glc" , med_to_glc) 36 | runseq.add_action ("MED -> GLC :remapMethod=redist" , med_to_glc) 37 | runseq.add_action ("GLC" , run_glc) 38 | # Need to do GLC -> MED even if not running GLC; otherwise, we get a 39 | # failure in InitializeRealize ("Object being used before creation") 40 | runseq.add_action ("GLC -> MED :remapMethod=redist" , med_to_glc) 41 | runseq.add_action ("MED med_phases_history_write" , True) 42 | 43 | runseq.leave_time_loop(True) 44 | 45 | shutil.copy(os.path.join(caseroot, "CaseDocs", "nuopc.runseq"), rundir) 46 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/5steps/shell_commands: -------------------------------------------------------------------------------- 1 | ./xmlchange STOP_OPTION="nsteps" 2 | 3 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/aoflux_ogrid/user_nl_cpl: -------------------------------------------------------------------------------- 1 | aoflux_grid = "ogrid" 2 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/asyncio1node/shell_commands: -------------------------------------------------------------------------------- 1 | # This will add 4 asyncio tasks on the first node 2 | ./xmlchange PIO_ASYNCIO_ROOTPE=0 3 | ./xmlchange PIO_ASYNCIO_STRIDE=1 4 | ./xmlchange PIO_ASYNCIO_NTASKS=4 5 | ./xmlchange PIO_REARRANGER=2 6 | ./xmlchange PIO_ASYNC_INTERFACE=TRUE 7 | for comp in ATM OCN LND ICE CPL GLC ROF 8 | do 9 | rootpe=`./xmlquery --value ROOTPE_$comp` 10 | let newrootpe=rootpe+4 11 | ./xmlchange ROOTPE_$comp=$newrootpe 12 | done 13 | comp_ocn=`./xmlquery --value COMP_OCN` 14 | # MOM ocn has no pio interface 15 | if [[ "$comp_ocn" == "mom" ]]; then 16 | ./xmlchange PIO_ASYNC_INTERFACE_OCN=FALSE; 17 | fi 18 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/asyncio1pernode/shell_commands: -------------------------------------------------------------------------------- 1 | # This will add one async pio task per node to a test 2 | # does not work for all cases 3 | max2() { printf '%d' $(( $1 > $2 ? $1 : $2 )); } 4 | let totaltasks=0 5 | ./xmlchange --force --force PIO_ASYNC_INTERFACE=TRUE 6 | for comp in ATM OCN LND ICE CPL GLC ROF 7 | do 8 | ntasks=`./xmlquery --value NTASKS_$comp` 9 | rootpe=`./xmlquery --value ROOTPE_$comp` 10 | let maxpe=ntasks+rootpe 11 | totaltasks=$(( $totaltasks > $maxpe ? $totaltasks : $maxpe )) 12 | done 13 | echo "totaltasks is $totaltasks" 14 | tpn=`./xmlquery --value MAX_MPITASKS_PER_NODE` 15 | ./xmlchange --force --force PIO_ASYNCIO_STRIDE=$tpn 16 | let piontasks=totaltasks/tpn 17 | echo "piontasks=$piontasks" 18 | ./xmlchange --force --force PIO_ASYNCIO_NTASKS=$piontasks 19 | let newntasks=totaltasks-piontasks 20 | echo "newntasks=$newntasks" 21 | ./xmlchange --force --force NTASKS=$newntasks 22 | ./xmlchange --force --force PIO_REARRANGER=2 23 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/default/shell_commands: -------------------------------------------------------------------------------- 1 | ./xmlchange HIST_OPTION=ndays 2 | ./xmlchange HIST_N=1 3 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/glcnec10/include_user_mods: -------------------------------------------------------------------------------- 1 | ../default 2 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/glcnec10/shell_commands: -------------------------------------------------------------------------------- 1 | ./xmlchange GLC_NEC=10 -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/som/shell_commands: -------------------------------------------------------------------------------- 1 | ./xmlchange DOCN_SOM_FILENAME="pop_frc.1x1d.090130.nc" 2 | 3 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/y100k/README: -------------------------------------------------------------------------------- 1 | This tests the ability to use 6-digit years. 2 | 3 | As of the time this test was created, the max year is about 214747 - 4 | otherwise we exceed the limit of 4-byte integers when storing dates as 5 | integers (yyyyyymmdd). 6 | -------------------------------------------------------------------------------- /cime_config/testdefs/testmods_dirs/drv/y100k/shell_commands: -------------------------------------------------------------------------------- 1 | ./xmlchange RUN_STARTDATE=99999-12-28 2 | -------------------------------------------------------------------------------- /cime_config/user_nl_cpl: -------------------------------------------------------------------------------- 1 | !------------------------------------------------------------------------ 2 | ! Users should ONLY USE user_nl_cpl to change namelists variables 3 | ! for namelist variables in drv_in (except for the ones below) and 4 | ! any keyword/values in seq_maps.rc 5 | ! Users should add ALL user specific namelist and seq_maps.rc changes below 6 | ! using the following syntax 7 | ! namelist_var = new_namelist_value 8 | ! or 9 | ! mapname = new_map_name 10 | ! For example to change the default value of ocn2atm_fmapname to 'foo' use 11 | ! ocn2atm_fmapname = 'foo' 12 | ! 13 | ! Note that some namelist variables MAY NOT be changed in user_nl_cpl - 14 | ! they are defined in a $CASEROOT xml file and must be changed with 15 | ! xmlchange. 16 | ! 17 | ! For example, rather than set username to 'foo' in user_nl_cpl, call 18 | ! ./xmlchange USER=foo 19 | !------------------------------------------------------------------------ 20 | -------------------------------------------------------------------------------- /cmake/FindESMF.cmake: -------------------------------------------------------------------------------- 1 | 2 | if (DEFINED ENV{ESMFMKFILE}) 3 | message("ESMFMKFILE: $ENV{ESMFMKFILE}") 4 | else() 5 | message(FATAL_ERROR "ESMFMKFILE env variable is not defined") 6 | endif() 7 | 8 | set(ESMFMKFILE $ENV{ESMFMKFILE}) 9 | 10 | # convert esmf.mk makefile variables to cmake variables until ESMF 11 | # provides proper cmake package 12 | file(STRINGS ${ESMFMKFILE} esmf_mk_text) 13 | foreach(line ${esmf_mk_text}) 14 | string(REGEX REPLACE "^[ ]+" "" line ${line}) # strip leading spaces 15 | if (line MATCHES "^ESMF_*") # process only line starting with ESMF_ 16 | string(REGEX MATCH "^ESMF_[^=]+" esmf_name ${line}) 17 | string(REPLACE "${esmf_name}=" "" emsf_value ${line}) 18 | set(${esmf_name} "${emsf_value}") 19 | endif() 20 | endforeach() 21 | string(REPLACE "-I" "" ESMF_F90COMPILEPATHS ${ESMF_F90COMPILEPATHS}) 22 | string(REPLACE " " ";" ESMF_F90COMPILEPATHS ${ESMF_F90COMPILEPATHS}) 23 | 24 | # We use only these 4 variables in our build system. Make sure they are all set 25 | if(ESMF_VERSION_MAJOR AND 26 | ESMF_F90COMPILEPATHS AND 27 | ESMF_F90ESMFLINKRPATHS AND 28 | ESMF_F90ESMFLINKLIBS) 29 | message(" Found ESMF:") 30 | message("ESMF_VERSION_MAJOR: ${ESMF_VERSION_MAJOR}") 31 | message("ESMF_F90COMPILEPATHS: ${ESMF_F90COMPILEPATHS}") 32 | message("ESMF_F90ESMFLINKRPATHS: ${ESMF_F90ESMFLINKRPATHS}") 33 | message("ESMF_F90ESMFLINKLIBS: ${ESMF_F90ESMFLINKLIBS}") 34 | else() 35 | message("One of the ESMF_ variables is not defined") 36 | endif() 37 | 38 | include(FindPackageHandleStandardArgs) 39 | find_package_handle_standard_args(ESMF 40 | FOUND_VAR 41 | ESMF_FOUND 42 | REQUIRED_VARS 43 | ESMF_F90COMPILEPATHS 44 | ESMF_F90ESMFLINKRPATHS 45 | ESMF_F90ESMFLINKLIBS 46 | VERSION_VAR 47 | ESMF_VERSION_STRING) 48 | -------------------------------------------------------------------------------- /cmake/FindPIO.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find PIO 2 | # 3 | # This can be controled by setting PIO_PATH or PIO__PATH Cmake variables, 4 | # where is the COMPONENT language one needs. 5 | # 6 | # Once done, this will define: 7 | # 8 | # PIO__FOUND (BOOL) - system has PIO 9 | # PIO__IS_SHARED (BOOL) - whether the library is shared/dynamic 10 | # PIO__INCLUDE_DIR (PATH) - Location of the header files and modules 11 | # PIO__LIBRARY (File) - Path to the library files 12 | # PIO__LIBRARIES (List) - link these to use PIO 13 | # 14 | # Available COMPONENTS are: C Fortran 15 | # If no components are specified only C is assumed 16 | include (LibFind) 17 | include (LibCheck) 18 | 19 | # Define PIO C Component 20 | define_package_component(PIO DEFAULT 21 | COMPONENT C 22 | INCLUDE_NAMES pio.h 23 | LIBRARY_NAMES pioc) 24 | 25 | # Define PIO Fortran Component 26 | define_package_component(PIO 27 | COMPONENT Fortran 28 | INCLUDE_NAMES pio.mod pio.inc 29 | LIBRARY_NAMES piof) 30 | 31 | # Search for list of valid components requested 32 | find_valid_components(PIO) 33 | 34 | #============================================================================== 35 | # SEARCH FOR VALIDATED COMPONENTS 36 | foreach (pcomp IN LISTS PIO_FIND_VALID_COMPONENTS) 37 | 38 | # If not found already, search... 39 | if (NOT PIO_${pcomp}_FOUND) 40 | 41 | # Manually add the MPI include and library dirs to search paths 42 | # and search for the package component 43 | if (MPI_${pcomp}_FOUND) 44 | initialize_paths (PIO_${pcomp}_PATHS 45 | INCLUDE_DIRECTORIES ${MPI_${pcomp}_INCLUDE_PATH} 46 | LIBRARIES ${MPI_${pcomp}_LIBRARIES}) 47 | find_package_component(PIO COMPONENT ${pcomp} 48 | PATHS ${PIO_${pcomp}_PATHS}) 49 | else () 50 | find_package_component(PIO COMPONENT ${pcomp} HINT PIO_${pcomp}_PATH=${PIO_PATH}) 51 | endif () 52 | 53 | # Continue only if component found 54 | if (PIO_${pcomp}_FOUND) 55 | 56 | # Checks 57 | if (pcomp STREQUAL C) 58 | 59 | # Check version 60 | check_version (PIO 61 | NAME "pio_meta.h" 62 | HINTS ${PIO_C_INCLUDE_DIRS} 63 | MACRO_REGEX "PIO_VERSION_") 64 | 65 | endif () 66 | 67 | # Dependencies 68 | if (pcomp STREQUAL C AND NOT PIO_C_IS_SHARED) 69 | 70 | # DEPENDENCY: PnetCDF (if PnetCDF enabled) 71 | check_macro (PIO_HAS_PNETCDF 72 | NAME TryPIO_PNETCDF.c 73 | HINTS ${CMAKE_MODULE_PATH} 74 | DEFINITIONS -I${PIO_C_INCLUDE_DIR} 75 | COMMENT "whether PIO has PnetCDF support") 76 | if (PIO_HAS_PNETCDF) 77 | find_package (PnetCDF COMPONENTS C) 78 | endif () 79 | 80 | 81 | elseif (pcomp STREQUAL Fortran AND NOT PIO_Fortran_IS_SHARED) 82 | 83 | # DEPENDENCY: PIO 84 | set (orig_comp ${pcomp}) 85 | set (orig_comps ${PIO_FIND_VALID_COMPONENTS}) 86 | find_package (PIO COMPONENTS C) 87 | set (PIO_FIND_VALID_COMPONENTS ${orig_comps}) 88 | set (pcomp ${orig_comp}) 89 | if (PIO_C_FOUND) 90 | list (APPEND PIO_Fortran_INCLUDE_DIRS ${PIO_C_INCLUDE_DIRS}) 91 | list (APPEND PIO_Fortran_LIBRARIES ${PIO_C_LIBRARIES}) 92 | endif () 93 | 94 | endif () 95 | 96 | endif () 97 | 98 | endif () 99 | 100 | endforeach () 101 | message("PIO_C_FOUND ${PIO_C_FOUND}") 102 | message("PIO_Fortran_FOUND ${PIO_Fortran_FOUND}") 103 | message("PIO_Fortran_INCLUDE_DIR ${PIO_Fortran_INCLUDE_DIR}") 104 | -------------------------------------------------------------------------------- /cmake/LibCheck.cmake: -------------------------------------------------------------------------------- 1 | include (CMakeParseArguments) 2 | include (CheckFunctionExists) 3 | #============================================================================== 4 | # 5 | # FUNCTIONS TO HELP WITH Check* MODULES 6 | # 7 | #============================================================================== 8 | 9 | #______________________________________________________________________________ 10 | # - Basic function to check a property of a package using a try_compile step 11 | # 12 | # SYNTAX: check_macro ( 13 | # NAME 14 | # HINTS ... 15 | # DEFINITIONS ... 16 | # COMMENT ) 17 | # 18 | function (check_macro VARIABLE) 19 | 20 | # Parse the input arguments 21 | set (oneValueArgs COMMENT NAME) 22 | set (multiValueArgs HINTS DEFINITIONS) 23 | cmake_parse_arguments (${VARIABLE} "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 24 | 25 | # If the return variable is defined, already, don't continue 26 | if (NOT DEFINED ${VARIABLE}) 27 | 28 | message (STATUS "Checking ${${VARIABLE}_COMMENT}") 29 | find_file (${VARIABLE}_TRY_FILE 30 | NAMES ${${VARIABLE}_NAME} 31 | HINTS ${${VARIABLE}_HINTS}) 32 | if (${VARIABLE}_TRY_FILE) 33 | try_compile (COMPILE_RESULT 34 | ${CMAKE_CURRENT_BINARY_DIR}/try${VARIABLE} 35 | SOURCES ${${VARIABLE}_TRY_FILE} 36 | COMPILE_DEFINITIONS ${${VARIABLE}_DEFINITIONS} 37 | OUTPUT_VARIABLE TryOUT) 38 | if (COMPILE_RESULT) 39 | message (STATUS "Checking ${${VARIABLE}_COMMENT} - yes") 40 | else () 41 | message (STATUS "Checking ${${VARIABLE}_COMMENT} - no") 42 | endif () 43 | 44 | set (${VARIABLE} ${COMPILE_RESULT} 45 | CACHE BOOL "${${VARIABLE}_COMMENT}") 46 | 47 | else () 48 | message (STATUS "Checking ${${VARIABLE}_COMMENT} - failed") 49 | endif () 50 | 51 | unset (${VARIABLE}_TRY_FILE CACHE) 52 | endif () 53 | 54 | endfunction () 55 | 56 | #______________________________________________________________________________ 57 | # - Basic function to check the version of a package using a try_run step 58 | # 59 | # SYNTAX: check_version ( 60 | # NAME 61 | # HINTS ... 62 | # DEFINITIONS ...) 63 | # 64 | function (check_version PKG) 65 | 66 | # Parse the input arguments 67 | set (oneValueArgs NAME MACRO_REGEX) 68 | set (multiValueArgs HINTS) 69 | cmake_parse_arguments (${PKG} "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 70 | 71 | # If the return variable is defined, already, don't continue 72 | if (NOT DEFINED ${PKG}_VERSION) 73 | 74 | message (STATUS "Checking ${PKG} version") 75 | find_file (${PKG}_VERSION_HEADER 76 | NAMES ${${PKG}_NAME} 77 | HINTS ${${PKG}_HINTS}) 78 | if (${PKG}_VERSION_HEADER) 79 | set (def) 80 | file (STRINGS ${${PKG}_VERSION_HEADER} deflines 81 | REGEX "^#define[ \\t]+${${PKG}_MACRO_REGEX}") 82 | foreach (defline IN LISTS deflines) 83 | string (REPLACE "\"" "" defline "${defline}") 84 | string (REPLACE "." "" defline "${defline}") 85 | string (REGEX REPLACE "[ \\t]+" ";" deflist "${defline}") 86 | list (GET deflist 2 arg) 87 | list (APPEND def ${arg}) 88 | endforeach () 89 | string (REPLACE ";" "." vers "${def}") 90 | message (STATUS "Checking ${PKG} version - ${vers}") 91 | set (${PKG}_VERSION ${vers} 92 | CACHE STRING "${PKG} version string") 93 | if (${PKG}_VERSION VERSION_LESS ${PKG}_FIND_VERSION}) 94 | message (FATAL_ERROR "${PKG} version insufficient") 95 | endif () 96 | else () 97 | message (STATUS "Checking ${PKG} version - failed") 98 | endif () 99 | 100 | unset (${PKG}_VERSION_HEADER CACHE) 101 | 102 | endif () 103 | 104 | endfunction () -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore auto-generated documentation for the addendum 2 | build 3 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = CMEPS 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /doc/source/CMEPS-grid1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ESCOMP/CMEPS/57e5026521b939209236b3a5dd09574ce8af87e8/doc/source/CMEPS-grid1.png -------------------------------------------------------------------------------- /doc/source/CMEPS-grid2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ESCOMP/CMEPS/57e5026521b939209236b3a5dd09574ce8af87e8/doc/source/CMEPS-grid2.png -------------------------------------------------------------------------------- /doc/source/CMEPS-grid3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ESCOMP/CMEPS/57e5026521b939209236b3a5dd09574ce8af87e8/doc/source/CMEPS-grid3.png -------------------------------------------------------------------------------- /doc/source/_static/pop_ver.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | /* For a URL that looks like 3 | https://blah.github.io/versions/VERSIONFOO/html/bar/index.html, set cur_version_dir to 4 | 'VERSIONFOO' (i.e., the portion of the path following 'versions'). 5 | */ 6 | var proj_end = document.baseURI.indexOf("versions") + 9; 7 | var end = document.baseURI.indexOf("/", proj_end); 8 | var cur_version_dir = document.baseURI.substring(proj_end, end); 9 | var mylist = $("#version-list"); 10 | mylist.empty(); 11 | $.getJSON(version_json_loc, function(data) { 12 | if (data.hasOwnProperty(cur_version_dir)) { 13 | /* First add the current version so that it appears first in the drop-down 14 | menu and starts as the selected element of the menu. If you click on the 15 | current version, you should stay at the current page. 16 | 17 | The conditional around this block should generally be true, but we check it 18 | just in case the current version is missing from the versions.json file for 19 | some reason. 20 | */ 21 | cur_version_name = data[cur_version_dir]; 22 | mylist.append($("