diff --git a/.github/workflows/containerized-ci.yml b/.github/workflows/containerized-ci.yml new file mode 100644 index 0000000000..b58eacf581 --- /dev/null +++ b/.github/workflows/containerized-ci.yml @@ -0,0 +1,148 @@ +name: Continuous integration in containers +on: [push, pull_request, workflow_dispatch] + +jobs: + Containerized-CI: + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + compiler: [ifort, ifx, nvfortran] + include: + # Set flags for Intel Fortran Compiler Classic + - compiler: ifort + fcflags: -m64 -g -traceback -heap-arrays -assume realloc_lhs -extend-source 132 -check bounds,uninit,pointers,stack -stand f08 + # Set flags for Intel Fortran Compiler + - compiler: ifx + fcflags: -debug -traceback -O0 -heap-arrays -assume realloc_lhs -extend-source 132 -stand f08 + # Set flags for NVIDIA Fortran compiler + - compiler: nvfortran + fcflags: -Mallocatable=03 -Mstandard -Mbounds -Mchkptr -Kieee -Mchkstk + # Set container images + - compiler: ifort + image: ghcr.io/earth-system-radiation/rte-rrtmgp-ci:oneapi + - compiler: ifx + image: ghcr.io/earth-system-radiation/rte-rrtmgp-ci:oneapi + - compiler: nvfortran + image: ghcr.io/earth-system-radiation/rte-rrtmgp-ci:nvhpc + container: + image: ${{ matrix.image }} + env: + F90: ${{ matrix.compiler }} + FC: ${{ matrix.compiler }} + F90FLAGS: ${{ fcflags }} + # Make variables: + NFHOME: /opt/netcdf-fortran + ATOL: 0.0 + RTOL: 0.0 + KGO_VERSION: v002 + + steps: + ############################################################################### + # Build COSP and retrieve input and test files + ############################################################################### + # Build COSP2 driver. Intel Fortran stores automatic arrays in the stack + # by default, whereas GNU Fortran stores them in the heap. This can cause + # segmentation faults with ifort, especially in memory-intensive applications + # like COSP. We tell ifort to use heap arrays. + - name: Build driver + run: | + source /opt/intel/oneapi/setvars.sh || true + ${F90} --version + cd build + make -j driver + # Retrieve and expand large data files + - name: Retrieve data files + run: | + GDFILE='https://docs.google.com/uc?export=download&id=17eK4_DVEvFOE9Uf6siXJDpWZJKT1aqkU' + OUTPATH=driver/data/inputs/UKMO/cosp_input.um_global.nc.gz + wget --no-check-certificate $GDFILE -O $OUTPATH + gunzip ${OUTPATH} + cd driver/data/inputs/UKMO + md5sum -c cosp_input.um_global.nc.md5 + cd ${GITHUB_WORKSPACE} + GDFILE='https://docs.google.com/uc?export=download&id=1s5Ha6Hqnv_hWbRUs8KQpJ4Lxy8uvJDar' + OUTPATH=driver/data/outputs/UKMO/cosp2_output.um_global.gfortran.kgo.$KGO_VERSION.nc.gz + wget --no-check-certificate $GDFILE -O $OUTPATH + gunzip ${OUTPATH} + cd driver/data/outputs/UKMO + md5sum -c cosp2_output.um_global.gfortran.kgo.$KGO_VERSION.nc.md5 + cd ${GITHUB_WORKSPACE} + GDFILE='https://docs.google.com/uc?export=download&id=11dKcIL3EQr7s6jbo4f9GsoW0SufesGbq' + OUTPATH=driver/data/outputs/UKMO/cosp2_output_um.gfortran.kgo.$KGO_VERSION.nc.gz + wget --no-check-certificate $GDFILE -O $OUTPATH + gunzip ${OUTPATH} + cd driver/data/outputs/UKMO + md5sum -c cosp2_output_um.gfortran.kgo.$KGO_VERSION.nc.md5 + cd ${GITHUB_WORKSPACE} + GDFILE='https://docs.google.com/uc?export=download&id=1kY1lRgzd0UhDiQef2u-VgTQql_iut3U2' + OUTPATH=driver/data/outputs/UKMO/cosp2_output.um_global_model_levels.gfortran.kgo.$KGO_VERSION.nc.gz + wget --no-check-certificate $GDFILE -O $OUTPATH + gunzip ${OUTPATH} + cd driver/data/outputs/UKMO + md5sum -c cosp2_output.um_global_model_levels.gfortran.kgo.$KGO_VERSION.nc.md5 + ############################################################################### + # Run COSP2 tests. We could run both tests in one step, but + # doing it this way the output is easier to interpret. + ############################################################################### + # 1. Basic test + - name: Basic test, UM global snapshot + run: | + cd driver/run + ./cosp2_test cosp2_input_nl.txt + ./cosp2_test cosp2_input_nl.um_global.txt + ############################################################################### + # Compare results against known good outputs. As above, + # we split it in as many steps as tests. + ############################################################################### + # 1. Basic test + - name: Basic against known good output (KGO) + run: | + cd driver + KGO=data/outputs/UKMO/cosp2_output_um.gfortran.kgo.$KGO_VERSION.nc + TST=data/outputs/UKMO/cosp2_output_um.nc + python compare_to_kgo.py ${KGO} ${TST} --atol=${ATOL} --rtol=${RTOL} + # 2. UM global snapshot. The approach used for the basic test would needed + # large tolerances for the ifort compiler. We keep tolerances small for ifort, + # and then we test against the output table. + - name: UM global against known good output (KGO) + run: | + cd driver + KGO=data/outputs/UKMO/cosp2_output.um_global.gfortran.kgo.$KGO_VERSION.nc + TST=data/outputs/UKMO/cosp2_output.um_global.nc + ATOL=1.0e-20 + RTOL=0.0006 + OUTTST=data/outputs/UKMO/cosp2_output.um_global.out + OUTKGO=data/outputs/UKMO/cosp2_output.um_global.${F90}.kgo.${KGO_VERSION}.out + python compare_to_kgo.py ${KGO} ${TST} --atol=${ATOL} --rtol=${RTOL} \ + --noerror=True --stats_file=${OUTTST} + diff ${OUTKGO} ${OUTTST} + ############################################################################### + # Produce plots when it fails during global snapshot tests, + # and create a tarball with outputs. + ############################################################################### + - name: Produce plots and create tarball + if: failure() + run: | + TST_MLEV=data/outputs/UKMO/cosp2_output.um_global_model_levels.nc + cd driver + if [[ -e data/outputs/UKMO/cosp2_output.um_global.nc ]]; then + python plot_test_outputs.py + fi + if [[ -e data/outputs/UKMO/cosp2_output.um_global_model_levels.nc ]]; then + python plot_test_outputs.py --tst_file=$TST_MLEV + fi + cd data/outputs/UKMO + tar --ignore-failed-read -czf outputs.UKMO.tgz cosp2_output.um_global.nc \ + cosp2_output_um.nc cosp2_output.um_global_model_levels.nc *.png \ + cosp2_output.um_global.out + ls -lh + ############################################################################### + # Make output files available if any test fails + ############################################################################### + - name: Upload output file if test fails + if: failure() + uses: actions/upload-artifact@v1.0.0 + with: + name: outputs.UKMO.tgz + path: driver/data/outputs/UKMO/outputs.UKMO.tgz