From 7f9cb285ca1ac3e422452117886901181a03f6e9 Mon Sep 17 00:00:00 2001 From: Rob Kooper Date: Thu, 22 Aug 2024 07:12:10 -0400 Subject: [PATCH] fix docker build (#357) * fix docker build - push to dockerhub if setup - push to github - build arm (mac) container as well as x86 - use intel compiler 2023.1 --- .github/workflows/ci.yml | 16 +- .github/workflows/docker.yml | 220 +++++++++++++++++++------- Dockerfile | 55 ------- Dockerfile.gnu | 50 ++++++ Dockerfile.intel | 46 ++++++ ED/build/make/include.mk.docker | 4 +- ED/build/make/include.mk.docker.gnu | 117 ++++++++++++++ ED/build/make/include.mk.docker.intel | 157 ++++++++++++++++++ ED/src/utils/random_utils.F90 | 2 +- README.md | 23 ++- 10 files changed, 572 insertions(+), 118 deletions(-) delete mode 100644 Dockerfile create mode 100644 Dockerfile.gnu create mode 100644 Dockerfile.intel create mode 100644 ED/build/make/include.mk.docker.gnu create mode 100644 ED/build/make/include.mk.docker.intel diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3381f063..eb8349c91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,18 @@ name: CI -on: [push, pull_request] +on: + push: + branches: + - master + - main + + pull_request: jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Install dependencies run: sudo apt-get install -y --no-install-recommends gfortran libhdf5-openmpi-dev libopenmpi-dev - name: Install ED2 @@ -23,7 +29,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Retrieve compiled binary uses: actions/download-artifact@v1 with: @@ -40,7 +46,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Retrieve compiled binary uses: actions/download-artifact@v1 with: @@ -57,7 +63,7 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Retrieve compiled binary uses: actions/download-artifact@v1 with: diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 824ab0ab9..35d4c6019 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,7 +1,7 @@ name: Docker # This will run when: -# - when new code is pushed to master to push the tags latest. +# - when new code is pushed to master/main to push the tags latest. # - when a pull request is created and updated to make sure the # Dockerfile is still valid. @@ -19,77 +19,189 @@ on: push: branches: - master + - main + + release: + types: + - published pull_request: -# Certain actions will only run when this is the master repo. +# Certain actions will only run when this is the master/main repo. env: - MASTER_REPO: EDModel/ED2 - DOCKERHUB_ORG: pecan + MAIN_REPO: EDmodel/ED2 + DOCKERHUB_ORG: edmodel jobs: docker: runs-on: ubuntu-latest + permissions: + packages: write + + strategy: + fail-fast: false + matrix: + include: + - name: gnu + PLATFORM: "linux/amd64,linux/arm64" + - name: intel + PLATFORM: "linux/amd64" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + # free up space + - name: Free Disk Space (Ubuntu) + uses: jlumbroso/free-disk-space@main + with: + tool-cache: true + android: true + dotnet: true + haskell: true + large-packages: true + docker-images: false + swap-storage: true # calculate some variables that are used later - - name: github branch + - name: version information run: | - BRANCH=${GITHUB_REF##*/} - if [ "$BRANCH" == "master" ]; then - TAGS="latest" + # find out what the BRANCH is, in case of a PR we will use the PR- + if [ "${{ github.event.release.target_commitish }}" != "" ]; then + BRANCH="${{ github.event.release.target_commitish }}" + elif [[ $GITHUB_REF =~ pull ]]; then + BRANCH="$(echo $GITHUB_REF | sed 's#refs/pull/\([0-9]*\)/merge#PR-\1#')" else - TAGS="$BRANCH" + BRANCH=${GITHUB_REF##*/} fi - echo "TAGS=${TAGS}" >> $GITHUB_ENV - echo "GITHUB_BRANCH=${BRANCH}" >> $GITHUB_ENV - # build the docker image, this will always run to make sure - # the Dockerfile still works. - - name: Build image - uses: elgohr/Publish-Docker-Github-Action@2.22 - env: - BRANCH: ${{ env.GITHUB_BRANCH }} - BUILDNUMBER: ${{ github.run_number }} - GITSHA1: ${{ github.sha }} + # calculate the version and all tags + if [ "$BRANCH" == "main" -o "$BRANCH" == "master" ]; then + VERSION="latest" + tags="${{ matrix.name }}" + if [ "${{ matrix.name }}" == "intel" ]; then + tags="${tags} latest" + fi + else + VERSION="${{ matrix.name }}-$BRANCH" + tags="${{ matrix.name }}-$BRANCH" + fi + + # should we push to dockerhub, and is there a README + DOCKERHUB_PUSH="false" + DOCKERHUB_README="false" + if [ "${{ github.repository }}" == "${{ env.MAIN_REPO }}" ]; then + if [ "${{ secrets.DOCKERHUB_USERNAME }}" != "" -a "${{ secrets.DOCKERHUB_PASSWORD }}" != "" ]; then + DOCKERHUB_PUSH="true" + if [ -e "README.md" ]; then + DOCKERHUB_README="true" + fi + fi + fi + + # create a list of all images to be pushed + REPO="${{ github.repository_owner }}" + REPO="${REPO,,}" + IMAGE="${{ github.event.repository.name }}" + IMAGE="${IMAGE,,}" + DEV_IMAGES="" + IMAGES="" + for tag in ${tags}; do + if [ "$DOCKERHUB_PUSH" == "true" ]; then + DEV_IMAGES="${DEV_IMAGES}${{ env.DOCKERHUB_ORG }}/${IMAGE}-dev:${tag}," + IMAGES="${IMAGES}${{ env.DOCKERHUB_ORG }}/${IMAGE}:${tag}," + fi + DEV_IMAGES="${DEV_IMAGES}ghcr.io/${REPO}/${IMAGE}-dev:${tag}," + IMAGES="${IMAGES}ghcr.io/${REPO}/${IMAGE}:${tag}," + done + IMAGES="${IMAGES%,*}" + + # save the results in env + echo "BRANCH=${BRANCH}" + echo "VERSION=${VERSION}" + echo "DOCKERHUB_README=${DOCKERHUB_README}" + echo "DOCKERHUB_PUSH=${DOCKERHUB_PUSH}" + echo "IMAGES=${IMAGES}" + + echo "BRANCH=${BRANCH}" >> $GITHUB_ENV + echo "VERSION=${VERSION}" >> $GITHUB_ENV + echo "DOCKERHUB_README=${DOCKERHUB_README}" >> $GITHUB_ENV + echo "DOCKERHUB_PUSH=${DOCKERHUB_PUSH}" >> $GITHUB_ENV + echo "DEV_IMAGES=${DEV_IMAGES}" >> $GITHUB_ENV + echo "IMAGES=${IMAGES}" >> $GITHUB_ENV + + # setup docker build + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + + - name: Inspect Builder + run: | + echo "Name: ${{ steps.buildx.outputs.name }}" + echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}" + echo "Status: ${{ steps.buildx.outputs.status }}" + echo "Flags: ${{ steps.buildx.outputs.flags }}" + echo "Platforms: ${{ steps.buildx.outputs.platforms }}" + + # login to registries + - name: Login to DockerHub + if: env.DOCKERHUB_PUSH == 'true' + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 with: - registry: docker.pkg.github.com - name: ${{ github.repository_owner }}/${{ github.event.repository.name }}/ed + registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - tags: "${{ env.TAGS }}" - buildargs: BRANCH,BUILDNUMBER,GITSHA1 - no_push: true - - # this will publish to github container registry - - name: Publish to GitHub - if: github.event_name == 'push' && github.repository == env.MASTER_REPO - uses: elgohr/Publish-Docker-Github-Action@2.22 - env: - BRANCH: ${{ env.GITHUB_BRANCH }} - BUILDNUMBER: ${{ github.run_number }} - GITSHA1: ${{ github.sha }} + + - name: DF + run: df -h . + + # build the dev docker images + - name: Build and push docker + uses: docker/build-push-action@v4 with: - registry: ghcr.io - name: ${{ github.repository_owner }}/ed - username: ${{ secrets.GHCR_USERNAME }} - password: ${{ secrets.GHCR_PASSWORD }} - tags: "${{ env.TAGS }}" - buildargs: BRANCH,BUILDNUMBER,GITSHA1 - - # this will publish to the pecan dockerhub repo - - name: Publish to Docker Hub - if: github.event_name == 'push' && github.repository == env.MASTER_REPO - uses: elgohr/Publish-Docker-Github-Action@2.22 - env: - BRANCH: ${{ env.GITHUB_BRANCH }} - BUILDNUMBER: ${{ github.run_number }} - GITSHA1: ${{ github.sha }} + push: true + platforms: ${{ matrix.PLATFORM }} + file: Dockerfile.${{ matrix.name }} + target: build + cache-from: type=gha,scope=ed-${{ matrix.name }}-build + cache-to: type=gha,scope=ed-${{ matrix.name }}-build,mode=max + tags: ${{ env.DEV_IMAGES }} + build-args: | + BRANCH: ${{ env.BRANCH }} + VERSION=${{ env.VERSION }} + BUILDNUMBER=${{ github.run_number }} + GITSHA1=${{ github.sha }} + + # build the docker images + - name: Build and push docker + uses: docker/build-push-action@v4 with: - name: ${{ env.DOCKERHUB_ORG }}/ed - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_PASSWORD }} - tags: "${{ env.TAGS }}" - buildargs: BRANCH,BUILDNUMBER,GITSHA1 + push: true + platforms: ${{ matrix.PLATFORM }} + file: Dockerfile.${{ matrix.name }} + cache-from: type=gha,scope=ed-${{ matrix.name }}-build + cache-to: type=gha,scope=ed-${{ matrix.name }}-build,mode=max + tags: ${{ env.IMAGES }} + build-args: | + BRANCH: ${{ env.BRANCH }} + VERSION=${{ env.VERSION }} + BUILDNUMBER=${{ github.run_number }} + GITSHA1=${{ github.sha }} + + # this will update the README of the dockerhub repo + - name: Docker Hub Description + if: env.DOCKERHUB_README == 'true' + uses: peter-evans/dockerhub-description@v3 + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + DOCKERHUB_REPOSITORY: ${{ env.DOCKERHUB_ORG }}/${{ github.event.repository.name }} + README_FILEPATH: README.md diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index cfce22303..000000000 --- a/Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -# ---------------------------------------------------------------------- -# BUILD MODEL BINARY -# ---------------------------------------------------------------------- -FROM debian:buster-slim AS builder - -# Some variables that can be used to set control the docker build -ARG MODEL_VERSION="2.2.0" -ARG BINARY_VERSION="2.2" - -# specify fortran compiler -ENV FC_TYPE=GNU - -# install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - build-essential \ - curl \ - gfortran \ - git \ - libhdf5-dev \ - libopenmpi-dev \ - && rm -rf /var/lib/apt/lists/* - -# download, unzip and build ed2 -COPY . /src/ -WORKDIR /src/ED/build -RUN ./install.sh -g -p docker && mv ed_*-opt ed - -######################################################################## - -# ---------------------------------------------------------------------- -# BUILD PECAN FOR MODEL -# ---------------------------------------------------------------------- -FROM debian:buster-slim - -# ---------------------------------------------------------------------- -# INSTALL MODEL SPECIFIC PIECES -# ---------------------------------------------------------------------- - -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - libhdf5-103 \ - libopenmpi3 \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /data - -# Some variables that can be used to set control the docker build -ARG MODEL_VERSION="2.2.0" -ENV MODEL_VERSION="${MODEL_VERSION}" - -# COPY model binary -COPY --from=builder /src/ED/build/ed /usr/local/bin/ed - - diff --git a/Dockerfile.gnu b/Dockerfile.gnu new file mode 100644 index 000000000..ff3c155c3 --- /dev/null +++ b/Dockerfile.gnu @@ -0,0 +1,50 @@ +# ---------------------------------------------------------------------- +# Build ED2 model +# ---------------------------------------------------------------------- +FROM ubuntu:22.04 AS build + +# Some variables that can be used to set control the docker build +ARG ED2_KIND=E + +# environment variables controlling the build +ENV FC_TYPE=GNU \ + ED2_KIND=${ED2_KIND} \ + TZ=America/Chicago \ + DEBIAN_FRONTEND=noninteractive + +# install dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + build-essential \ + gfortran \ + libhdf5-openmpi-dev \ + && rm -rf /var/lib/apt/lists/* + +# copy the source only, this prevents a full rebuild in case of changes to Dockerfile or non source files +COPY BRAMS /ED2/BRAMS +COPY ED /ED2/ED +COPY EDR /ED2/EDR +COPY RAPP /ED2/RAPP +COPY Ramspost /ED2/Ramspost + +WORKDIR /ED2/ED/build +RUN ./install.sh -k ${ED2_KIND} -g -p docker.gnu +RUN if [ -e ed_*-opt ]; then mv ed_*-opt ed2; else mv ed_*-dbg ed2; fi + +######################################################################## + +# ---------------------------------------------------------------------- +# Minimal image with just ED2 model +# ---------------------------------------------------------------------- +FROM ubuntu:22.04 + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + libhdf5-openmpi-103 \ + libgomp1 \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /data +COPY --from=build /ED2/ED/build/ed2 /usr/bin + +CMD /usr/bin/ed2 diff --git a/Dockerfile.intel b/Dockerfile.intel new file mode 100644 index 000000000..5b42d6dbf --- /dev/null +++ b/Dockerfile.intel @@ -0,0 +1,46 @@ +# ---------------------------------------------------------------------- +# Build ED2 model +# ---------------------------------------------------------------------- +FROM intel/oneapi-hpckit:2023.1.0-devel-ubuntu22.04 AS build + +# Some variables that can be used to set control the docker build +ARG ED2_KIND=E + +# environment variables controlling the build +ENV ED2_KIND=${ED2_KIND} + +# compile HDF5 with intel +RUN wget -q https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.9/src/CMake-hdf5-1.10.9.tar.gz && \ + tar xf CMake-hdf5-1.10.9.tar.gz && \ + cd CMake-hdf5-1.10.9 && \ + sed -e 's/^#*\(.*BUILD_FORTRAN:BOOL=ON.*\)/\1/' \ + -e 's/^#*\(.*BUILD_FORTRAN:BOOL=OFF.*\)/#\1/' \ + -e 's/^#*\(.*intel.cmake.*\)/\1/' \ + -i HDF5options.cmake && \ + ctest -S HDF5config.cmake,BUILD_GENERATOR=Unix,INSTALLDIR=/opt/hdf5 -C Release -V -O hdf5.log && \ + ./HDF5-1.10.9-Linux.sh --skip-license --exclude-subdir --prefix=/opt && \ + cd && \ + rm -rf CMake-hdf5-1.10.9.tar.gz CMake-hdf5-1.10.9 + +# copy the source only, this prevents a full rebuild in case of changes to Dockerfile or non source files +COPY BRAMS /ED2/BRAMS +COPY ED /ED2/ED +COPY EDR /ED2/EDR +COPY RAPP /ED2/RAPP +COPY Ramspost /ED2/Ramspost + +WORKDIR /ED2/ED/build +RUN ./install.sh -k ${ED2_KIND} -g -p docker.intel +RUN if [ -e ed_*-opt ]; then mv ed_*-opt ed2; else mv ed_*-dbg ed2; fi + +######################################################################## + +# ---------------------------------------------------------------------- +# Minimal image with just ED2 model +# ---------------------------------------------------------------------- +FROM ubuntu:22.04 + +WORKDIR /data +COPY --from=build /ED2/ED/build/ed2 /usr/bin + +CMD ["/usr/bin/ed2"] diff --git a/ED/build/make/include.mk.docker b/ED/build/make/include.mk.docker index d3e40b250..a291b0bb2 100644 --- a/ED/build/make/include.mk.docker +++ b/ED/build/make/include.mk.docker @@ -9,8 +9,8 @@ BASE=$(ED_ROOT)/build/ # HDF 5 Libraries USE_HDF5=1 -HDF5_INCS=-I/usr/include/hdf5/serial -HDF5_LIBS=-L/usr/lib/x86_64-linux-gnu/hdf5/serial -lz -lhdf5_fortran -lhdf5 -lhdf5_hl +HDF5_INCS=-I/usr/include/hdf5/openmpi +HDF5_LIBS=-L/usr/lib/x86_64-linux-gnu/hdf5/openmpi -lz -lhdf5_fortran -lhdf5 -lhdf5_hl #HDF5_INCS=-I/usr/include #HDF5_LIBS=-lz -lhdf5_fortran -lhdf5 -lhdf5_hl USE_COLLECTIVE_MPIO=0 diff --git a/ED/build/make/include.mk.docker.gnu b/ED/build/make/include.mk.docker.gnu new file mode 100644 index 000000000..02a5559dd --- /dev/null +++ b/ED/build/make/include.mk.docker.gnu @@ -0,0 +1,117 @@ +#==========================================================================================# +#==========================================================================================# +# Make file include.mk.docker.gnu # +#------------------------------------------------------------------------------------------# + +#----- Define make (gnu make works best). -------------------------------------------------# +MAKE=/usr/bin/make +#------------------------------------------------------------------------------------------# + +#----- Libraries. -------------------------------------------------------------------------# +BASE=$(ED_ROOT)/build/ +#------------------------------------------------------------------------------------------# + +#------------------------------------------------------------------------------------------# +# HDF5 libraries # +# # +# Since ED-2.1, this is no longer optional for real simulations. You must have HDF5 # +# libraries compiled with the same compiler you set for F_COMP and C_COMP. You may still # +# be able to compile without HDF5 but it will not run. # +#------------------------------------------------------------------------------------------# +HDF5_INCS=-I/usr/include/hdf5/openmpi +HDF5_LIBS= -L/usr/lib/$(shell uname -m)-linux-gnu/hdf5/openmpi -lhdf5_fortran -lhdf5_hl -lhdf5 -lz -lm + +#------------------------------------------------------------------------------------------# + +#------------------------------------------------------------------------------------------# +# If you have a version of hdf5 compiled in parallel, then you may benefit from # +# collective I/O, then use this flag = 1. Otherwise, set it to zero. # +#------------------------------------------------------------------------------------------# +USE_COLLECTIVE_MPIO=0 +#------------------------------------------------------------------------------------------# + +#------------------------------------------------------------------------------------------# +# This should be 1 unless you are running with -gen-interfaces. Interfaces usually # +# make the compilation to crash when the -gen-interfaces option are on, so this flag # +# bypass all interfaces in the code. # +#------------------------------------------------------------------------------------------# +USE_INTERF=1 +#------------------------------------------------------------------------------------------# + +#################################### COMPILER SETTINGS ##################################### +CMACH=DOCKER_GNU +FC_TYPE=GNU +#F_COMP=gfortran +F_COMP=mpif90.openmpi +#C_COMP=gcc +C_COMP=mpicc.openmpi +#LOADER=gfortran +LOADER=mpif90.openmpi +#C_LOADER=gcc +C_LOADER=mpicc.openmpi +LIBS= +MOD_EXT=mod +############################################################################################ + + + + + +##################################### COMPILER OPTIONS ##################################### +#------------------------------------------------------------------------------------------# +# A. Pickiest - Use this whenever you change arguments on functions and subroutines. # +# This will perform the same tests as B but it will also check whether all # +# arguments match between subroutine declaration and subroutine calls. # +# WARNING: In order to really check all interfaces you must compile with # +# this option twice: # +# 1. Compile (./install.sh A) # +# 2. Prepare second compilation(./2ndcomp.sh) # +# 3. Compile one more time (./install.sh B) # +# If the compilation fails either at step 3, then your code has interface # +# problems. If it successfully compiles, then the code is fine for # +# interfaces. # +# E. Fast - This is all about performance, use only when you are sure that the model has # +# no code problem, and you want results asap. This will not check for any # +# problems, which means that this is an option suitable for end users, not de- # +# velopers. # +#------------------------------------------------------------------------------------------# +ifeq ($(KIND_COMP),) + KIND_COMP=E +endif +#------------------------------------------------------------------------------------------# +ifeq ($(KIND_COMP),A) + F_OPTS= -O0 -ffree-line-length-none -g -fimplicit-none -Wall -finit-real=snan \ + -finit-integer=-2147483648 -ffpe-trap=invalid,zero,overflow,underflow \ + -fcheck=all -frecursive -fsignaling-nans -Werror -fopenmp -static + C_OPTS= -O0 -DLITTLE -g -static + LOADER_OPTS= -O0 -ffree-line-length-none -g -fimplicit-none -Wall -finit-real=snan \ + -finit-integer=-2147483648 -ffpe-trap=invalid,zero,overflow,underflow \ + -fcheck=all -frecursive -fsignaling-nans -Werror -fopenmp + #---------------------------------------------------------------------------------------# +endif +ifeq ($(KIND_COMP),E) + F_OPTS= -O3 -ffree-line-length-none -frecursive -fopenmp -static + C_OPTS= -O0 -DLITTLE -g -static + LOADER_OPTS= -O3 -ffree-line-length-none -frecursive -fopenmp + #---------------------------------------------------------------------------------------# +endif +#------------------------------------------------------------------------------------------# +############################################################################################ + +#------------------------------------------------------------------------------------------# +# If using mpicc and mpif90 as compilers (recommended), leave MPI_PATH, PAR_INCS, and # +# PAR_LIBS blank, otherwise provide the includes and libraries for mpi. Either way, don't # +# change PAR_DEFS. # +#------------------------------------------------------------------------------------------# +MPI_PATH= +PAR_INCS= +PAR_LIBS= +PAR_DEFS= +#------------------------------------------------------------------------------------------# + +#------------------------------------------------------------------------------------------# +# Archive options. # +#------------------------------------------------------------------------------------------# +#ARCHIVE=libtool -c -static -stack_size 0x1000000 -o +ARCHIVE=ar rs +#------------------------------------------------------------------------------------------# diff --git a/ED/build/make/include.mk.docker.intel b/ED/build/make/include.mk.docker.intel new file mode 100644 index 000000000..6defd47fe --- /dev/null +++ b/ED/build/make/include.mk.docker.intel @@ -0,0 +1,157 @@ +#==========================================================================================# +#==========================================================================================# +# Makefile include.mk.docker.intel # +#------------------------------------------------------------------------------------------# + +#----- Define make (gnu make works best). -------------------------------------------------# +MAKE=/usr/bin/make +#------------------------------------------------------------------------------------------# + +#----- Main path for compilation. ---------------------------------------------------------# +BASE=$(ED_ROOT)/build/ +#------------------------------------------------------------------------------------------# + +#------------------------------------------------------------------------------------------# +# HDF 5 libraries. # +# # +# Since ED-2.1, this is no longer optional for real simulations. You must have the # +# HDF5 libraries compiled with the same compiler you set for F_COMP and C_COMP. You may # +# still be able to compile without HDF5 but the code is not going to run. # +#------------------------------------------------------------------------------------------# +HDF5_PATH=/opt/HDF_Group/HDF5/1.10.9 +HDF5_INCS=-I$(HDF5_PATH)/include/static +HDF5_LIBS=-L$(HDF5_PATH)/lib -lhdf5_fortran -lhdf5_f90cstub -lhdf5_hl -lhdf5 \ + -lz -lszaec -laec -lm +#------------------------------------------------------------------------------------------# + +#------------------------------------------------------------------------------------------# +# If you have a version of hdf5 compiled in parallel, then you may benefit from # +# collective I/O, then use this flag = 1. Otherwise, set it to zero. # +#------------------------------------------------------------------------------------------# +USE_COLLECTIVE_MPIO=0 +#------------------------------------------------------------------------------------------# + +#------------------------------------------------------------------------------------------# +# This should be 1 unless you are running with -gen-interfaces. Interfaces usually # +# make the compilation to crash when the -gen-interfaces option are on, so this flag # +# bypass all interfaces in the code. # +#------------------------------------------------------------------------------------------# +USE_INTERF=1 +#------------------------------------------------------------------------------------------# + +#################################### COMPILER SETTINGS ##################################### +CMACH=DOCKER_INTEL +FC_TYPE=INTEL +F_COMP=ifort +C_COMP=icc +LOADER=ifort +LIBS= +MOD_EXT=mod +#------------------------------------------------------------------------------------------# + +##################################### COMPILER OPTIONS ##################################### +#------------------------------------------------------------------------------------------# +# A/B. Pickiest - Use this whenever you change arguments on functions and subroutines. # +# This will perform the same tests as B but it will also check whether all # +# arguments match between subroutine declaration and subroutine calls. # +# WARNING: In order to really check all interfaces you must compile with # +# this option twice: # +# 1. Compile (./install.sh A) # +# 2. Prepare second compilation(./2ndcomp.sh) # +# 3. Compile one more time (./install.sh B) # +# If the compilation fails either at step 3, then your code has interface # +# problems. If it successfully compiles, then the code is fine for # +# interfaces. # +# C. Pickiest with no interface - This will compile fast but the run will be slow due to # +# the -O0 option. However, by setting -O0 you will take full advantage of the intel # +# debugger. # +# Ideally, you should compile your code with this option whenever you make any changes. # +# Note, however, that if you change arguments you should first try A. # +# D. Fast check - This will check pretty much the same as C, but it will not set up # +# anything for the debugger. Use this only if you really don't want to deal with idb or # +# if you have a good idea of which problem you are dealing with. # +# E. Fast - This is all about performance, use only when you are sure that the model has # +# no code problem, and you want results asap. This will not check for any # +# problems, which means that this is an option suitable for end users, not de- # +# velopers. # +#------------------------------------------------------------------------------------------# +ifeq ($(KIND_COMP),) + KIND_COMP=E +endif +#------------------------------------------------------------------------------------------# +ifeq ($(KIND_COMP),A) + USE_INTERF=0 + F_OPTS= -FR -O0 -recursive -check all,noarg_temp_created -g -debug extended \ + -debug-parameters all -fpe0 -no-ftz -traceback -ftrapuv -fp-stack-check \ + -implicitnone -assume byterecl -warn unused -warn uncalled -warn usage \ + -warn declarations -gen-interfaces -qopenmp -diag-error=all -static + C_OPTS= -O0 -DLITTLE -g -traceback -qopenmp -static + LOADER_OPTS=-FR -O0 -recursive -check all,noarg_temp_created -g -debug extended \ + -debug-parameters all -fpe0 -no-ftz -traceback -ftrapuv -fp-stack-check \ + -implicitnone -assume byterecl -warn unused -warn uncalled -warn usage \ + -warn declarations -gen-interfaces -qopenmp -diag-error=all -static + #---------------------------------------------------------------------------------------# +endif +ifeq ($(KIND_COMP),B) + USE_INTERF=0 + F_OPTS= -FR -O0 -recursive -check all,noarg_temp_created -g -debug extended \ + -debug-parameters all -fpe0 -no-ftz -traceback -ftrapuv -fp-stack-check \ + -implicitnone -assume byterecl -warn unused -warn uncalled -warn usage \ + -warn interfaces -warn declarations -qopenmp -diag-error=all -static + C_OPTS= -O0 -DLITTLE -g -traceback -qopenmp -static + LOADER_OPTS=-FR -O0 -recursive -check all,noarg_temp_created -g -debug extended \ + -debug-parameters all -fpe0 -no-ftz -traceback -ftrapuv -fp-stack-check \ + -implicitnone -assume byterecl -warn unused -warn uncalled -warn usage \ + -warn interfaces -warn declarations -qopenmp -diag-error=all -static + #---------------------------------------------------------------------------------------# +endif +ifeq ($(KIND_COMP),C) + USE_INTERF=1 + F_OPTS= -FR -O0 -recursive -check all,noarg_temp_created -g -debug extended \ + -debug-parameters all -fpe0 -no-ftz -traceback -ftrapuv -fp-stack-check \ + -implicitnone -assume byterecl -qopenmp -diag-error=all -static + C_OPTS= -O0 -DLITTLE -g -traceback -qopenmp -static + LOADER_OPTS=-FR -O0 -recursive -check all,noarg_temp_created -g -debug extended \ + -debug-parameters all -fpe0 -no-ftz -traceback -ftrapuv -fp-stack-check \ + -implicitnone -assume byterecl -qopenmp -diag-error=all -static + #---------------------------------------------------------------------------------------# +endif +ifeq ($(KIND_COMP),D) + USE_INTERF=1 + F_OPTS= -FR -O0 -recursive -check all,noarg_temp_created -fpe0 -no-ftz -traceback \ + -ftrapuv -fp-stack-check -implicitnone -assume byterecl -qopenmp \ + -diag-error=all -static + C_OPTS= -O0 -DLITTLE -g -traceback -qopenmp -static + LOADER_OPTS=-FR -O0 -recursive -check all,noarg_temp_created -fpe0 -no-ftz -traceback \ + -ftrapuv -fp-stack-check -implicitnone -assume byterecl -qopenmp \ + -diag-error=all -static + #---------------------------------------------------------------------------------------# +endif +ifeq ($(KIND_COMP),E) + USE_INTERF=1 + F_OPTS=-FR -O3 -recursive -traceback -assume byterecl -qopenmp -static + C_OPTS=-O3 -DLITTLE -traceback -qopenmp -static + F_LOWO_OPTS=-FR -O2 -recursive -traceback -assume byterecl -qopenmp -static + LOADER_OPTS=-FR -O3 -recursive -traceback -assume byterecl -qopenmp -static + #---------------------------------------------------------------------------------------# +endif +#------------------------------------------------------------------------------------------# +############################################################################################ + +#------------------------------------------------------------------------------------------# +# If using mpicc and mpif90 as compilers (recommended), leave MPI_PATH, PAR_INCS, and # +# PAR_LIBS blank, otherwise provide the includes and libraries for mpi. Either way, don't # +# change PAR_DEFS unless you know what you are doing. # +#------------------------------------------------------------------------------------------# +MPI_PATH= +PAR_INCS= +PAR_LIBS= +PAR_DEFS= +#------------------------------------------------------------------------------------------# + +#------------------------------------------------------------------------------------------# +# Archive options. # +#------------------------------------------------------------------------------------------# +#------ For IBM, HP, SGI, ALPHA, LINUX, and MAC_OS_X use these. ---------------------------# +ARCHIVE=ar rs +#------------------------------------------------------------------------------------------# diff --git a/ED/src/utils/random_utils.F90 b/ED/src/utils/random_utils.F90 index 77b1044b7..13aaf4089 100644 --- a/ED/src/utils/random_utils.F90 +++ b/ED/src/utils/random_utils.F90 @@ -31,7 +31,7 @@ subroutine init_random_seed() ! case you create a new name, please be creative so it doesn't conflict with other ! ! user's choice. ! !------------------------------------------------------------------------------------! -#if defined(ODYSSEY) || defined(SUNHPC) || defined(PC_INTEL) +#if defined(ODYSSEY) || defined(SUNHPC) || defined(PC_INTEL) || defined(DOCKER_INTEL) use ifport, only : getpid #endif !------------------------------------------------------------------------------------! diff --git a/README.md b/README.md index cb0bdb99a..d0d7881de 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ 4. Implementation Notes 5. Further Information 6. Code Development, Pull Requests, and Commits +7. Using Docker ## Model Overview @@ -38,7 +39,7 @@ The primary data structure in ED, which can be found in ed_state_vars.F90, is a - site: A collection of patches sharing a common soil system and ground hydrology. - patch: A collection of cohorts sharing a disturbance history and age. - cohort: A collection of plants of identical PFT and height. - + Note: height and age, being continuous variables, are "binned". "Identical" in this context means sufficiently similar to be placed in the same bin. These bins are dynamically defined, based on the number of classes sought by the user and the similarity along the age and height axes. ## Further Information @@ -53,3 +54,23 @@ If you plan to develop the code, please refer to the Wiki entries on Doxygen instructions, and especially the Doxygen and Git commits section, so additional documentation can be automatically generated from the source code comments. +## Using Docker + +To use ED2 with Docker use either the `Dockerfile.gnu` for the GNU compiler (works with both x86 and arm64) or `Dockerfile.intel` which compiled ED2 using the intel compiler (x86 only). For example the following command builds the GNU version (run this in the root of the ED2 source code): + +``` +docker build -t edmodel/ed2:gnu -f Dockerfile.gnu . +``` + +Once you have build ED2 model you can run it using: + +```bash +docker run -ti --rm --ulimit stack=-1 --volume ${PWD}:/data edmodel/ed2:gnu +``` + +`-ti` : tells docker to use an interactive shell session +`--rm` : will remove the container after it finishes running, make sure outputs are written to /data or current folder +`--ulimit stack=-1` : set the stack to be unlimited in size, this is needed otherwise ED2 will coredump +`--volume ${PWD}:/data` : mounts the current folder to the /data folder. This is where the container starts + +If no arguments are given it will run `ed2` in the /data folder. Otherwise you can pass in any arguments, for example you can use `ed2 -f Templates/ED2IN-tonzi.harvest` to run ed2 with the input file Templates/ED2IN-tonzi.harvest.