diff --git a/.github/modelErc b/.github/modelErc new file mode 100644 index 0000000..ef42870 --- /dev/null +++ b/.github/modelErc @@ -0,0 +1,111 @@ +# This file contains global options for modelE. +# By default it assumes that the directory structure for modelE runs +# is set under /home/joe/data/giss-gc . + +## Directory structure ## + +# DECKS_REPOSITORY - a directory for permanenet storage of run info. +# All rundecks that you create will be copied to this directory. +DECKS_REPOSITORY=/__w/GISS-GC/GISS-GC/run/prod_decks + +# CMRUNDIR - directory to which all run directories will be linked. +# This directory will be searched by most scripts for locations of +# specific runs. +CMRUNDIR=/__w/GISS-GC/GISS-GC/run/prod_runs + +# GCMSEARCHPATH - directory to search for gcm input files. +# All necessary input files should be copied or linked to this directory. +GCMSEARCHPATH=/__w/GISS-GC/GISS-GC/run/prod_input_files + +# EXECDIR - path to directory with modelE scripts and with some +# executables. This directory should contain the scripts from modelE/exec. +EXECDIR=/__w/GISS-GC/GISS-GC/run/exec + +# SAVEDISK - a directory where all run directories (which will contain +# all output files such as rsf, acc etc.) will be created. This should +# be big enough to accomodate all model output. +SAVEDISK=/__w/GISS-GC/GISS-GC/run/huge_space + +## External libraries ## + +# Some of these options can be provided by environment modules (if you +# use them). Specify here only what is necessary. Options specified +# here will overwrite options proviided by environment modules. + +# NETCDFHOME - path to location of netcdf installation directory. +NETCDFHOME=${NETCDF_F_HOME} + +# MPI - set to YES if you want to compile the model for parallel +# execution on multiple CPU cores. Keep in mind, that functional +# MPI library should be installed on your computer and its type +# and location should be specified below. +# This option can be overwritten from the compile line. +MPI=YES + +# MPIDISTR - the MPI distribution you are using. Currently supported +# distributions are: 'intel, 'openmpi', 'mpich2', 'mvapich2', 'SCALI', +# 'mpt' +MPIDISTR=openmpi + +# MPIDIR - path to the MPI installation directory. (Needs to be set +# only if compiler can't find correct MPI library and include files by +# default) +# MPIDIR=/opt/openmpi +MPIDIR=${MPI_ROOT} + +# MPILIBDIR - path to the location of MPI library. Set it only if +# it is different from the default $MPIDIR/lib +# MPILIBDIR=/opt/openmpi/lib + +# MPIINCLUDEDIR - path to location of MPI include files. Set it only +# if it is different from the default $MPIDIR/include +# MPIINCLUDEDIR=/opt/openmpi/include + +# ESMF5_DIR - path to the installation directory of ESMF (version 5) +# library. (Required only for Cubed Sphere simulations) +# ESMF5_DIR= + +# ESMF_BOPT - optimization level of ESMF library. (Should only be used +# togeteher with ESMF5_DIR) +# ESMF_BOPT=O +ESMF=NO + +## Architecture and compiler + +# ABI - Application Binary Interfaces. This variable specifies the +# architecture you are using. The valid values are '64' and '32'. +# On most modern systems you should use '64'. Use '32' if your +# hardware or compiler support only 32-bit binaries. +ABI=64 + +# COMPILER - specifies the Fortran compiler you are using. Currently +# only 'intel' and 'gfortran' are supported. ('nag' has partial +# support on development branch.) If you are using Modules for +# Environment Management, then this variable may already be set in the +# environment. In this case you don't need to set it here. +COMPILER=gfortran + +## General User Preferences ## + +# MAILTO - email address of the user. When the program ends/crashes +# all notifications will be sent to this address. Leave empty +# or unset if you don't want to receive these emails +MAILTO= + +# UMASK - the value of 'umask' you want to use for model runs. The files +# inside the run directory will have permissions set according to this +# mask. +UMASK=002 + +# OVERWRITE - can "gmake rundeck" overwrite files already in repository? +# (i.e. in the directory DECKS_REPOSITORY) +OVERWRITE=NO + +# OUTPUT_TO_FILES - if set to YES all errors and warnings will be sent +# to files with the names .ERR +OUTPUT_TO_FILES=NO + +# VERBOSE_OUTPUT - if set to YES gmake will show compilation commands +# and some other information. Otherwise most of the output will be +# suppressed +VERBOSE_OUTPUT=YES diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml new file mode 100644 index 0000000..bd5dbd0 --- /dev/null +++ b/.github/workflows/test_suite.yml @@ -0,0 +1,131 @@ +name: Test suite + +on: + # Trigger the CI whenever a commit is pushed to main or develop, i.e., a PR is merged + push: + branches: [main, develop] + + # Trigger the CI whenever a commit is pushed to an open PR + pull_request: + +env: + # Environment variables for GISS modelE + GISS_HOME: /__w/GISS-GC/GISS-GC + ModelE_Support: /__w/GISS-GC/GISS-GC/run + DATA: /__w/GISS-GC/GISS-GC/run/prod_input_files + # Environment variables for compiler + CC: gcc + CXX: g++ + FC: gfortran + F90: gfortran + F77: gfortran + # Misc. environment variables + F_UFMTENDIAN: big + KMP_STACKSIZE: 100000000 + OMP_NUM_THREADS: 36 + +jobs: + # Test that GISS-GC can be compiled without error + compile: + runs-on: ubuntu-22.04 + container: + image: ghcr.io/fetch4/giss-gc-dev-env:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.github_token }} + + steps: + - uses: actions/checkout@v2 + + - name: Setup submodules + run: | + git config --global --add safe.directory ${GISS_HOME} + git submodule init + git submodule update + + - name: Create fake inputs + run: | + # Make run directories + mkdir -p ${DATA} + mkdir -p ${ModelE_Support}/exec + mkdir -p ${ModelE_Support}/huge_space + mkdir -p ${ModelE_Support}/prod_decks + mkdir -p ${ModelE_Support}/prod_runs + # Fake input files + touch ${DATA}/CD144X90.ext.nc + touch ${DATA}/cloud.epsilon4.72x46 + touch ${DATA}/CO2profile.Jul16-2017.txt + touch ${DATA}/CROPS_and_pastures_Pongratz_to_Hurtt_144X90N_nocasp.nc + touch ${DATA}/dH2O_by_CH4_monthly + touch ${DATA}/GHG.CMIP6.1-2014.txt + touch ${DATA}/GIC.144X90.DEC01.1.ext_1.nc + touch ${DATA}/GLMELT_144X90_gas.OCN.nc + touch ${DATA}/H2Ocont_MT_CKD + touch ${DATA}/Irrig144x90_1848to2100_FixedFuture_v3.nc + touch ${DATA}/ISCCP.tautables + touch ${DATA}/LWCorrTables33k + touch ${DATA}/LWTables33k_lowH2O_CO2_O3_planck_1-800 + touch ${DATA}/miescatpar.abcdv2 + touch ${DATA}/MSU_SSU_RSS_weights.txt + touch ${DATA}/NCARIC.144x90.D7712010_ext.nc + touch ${DATA}/o3_2010_shindell_144x90x49_April1850.nc + touch ${DATA}/oct2003.relhum.nr.Q633G633.table + touch ${DATA}/OST_144x90.1876-1885avg.CMIP6.nc + touch ${DATA}/RD_Fd.nc + touch ${DATA}/RD_Fd.names.txt + touch ${DATA}/REG2X2.5 + touch ${DATA}/S144X900098M.ext.nc + touch ${DATA}/sgpgxg.table8 + touch ${DATA}/SICE_144x90.1876-1885avg.CMIP6.nc + touch ${DATA}/soil_textures_top30cm_2x2.5 + touch ${DATA}/soilcarb_top30cm_2x2.5.nc + touch ${DATA}/solar.CMIP6official.ann1850-2299_with_E3_fastJ.nc + touch ${DATA}/STRATAER.VOL.1850-2014_CMIP6_hdr + touch ${DATA}/top_index_144x90_a.ij.ext.nc + touch ${DATA}/topcld.trscat8 + touch ${DATA}/V144x90_EntMM16_height_trimmed_scaled_ext.nc + touch ${DATA}/V144x90_EntMM16_lai_max_trimmed_scaled_ext.nc + touch ${DATA}/V144x90_EntMM16_lai_trimmed_scaled_ext.nc + touch ${DATA}/V144x90_EntMM16_lc_max_trimmed_scaled_nocrops.ext.nc + touch ${DATA}/Z2HX2fromZ1QX1N.BS1.nc + touch ${DATA}/ZSIfac_144x90.1876-1885avg.CMIP6.nc + touch ${DATA}/ZVAR2X25A.nc + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/BCA + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/BCB + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/BCdalbsn + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/DUST + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/NIT + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/O3 + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/OCA + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/SSA + mkdir -p ${DATA}/cmip6_nint_inputs_E14TomaOCNf10_4av_decadal/SUL + mkdir -p ${DATA}/nudging/merra2 + touch ${DATA}/nudging/merra2/uwnd.2014.MERRA2onGISSE2.nc4 + touch ${DATA}/nudging/merra2/vwnd.2014.MERRA2onGISSE2.nc4 + touch ${DATA}/nudging/merra2/uwnd.2015.MERRA2onGISSE2.nc4 + touch ${DATA}/nudging/merra2/vwnd.2015.MERRA2onGISSE2.nc4 + touch ${DATA}/nudging/merra2/uwnd.2016.MERRA2onGISSE2.nc4 + touch ${DATA}/nudging/merra2/vwnd.2016.MERRA2onGISSE2.nc4 + + - name: Build GISS-GC with GISS_GC_14 rundeck + run: | + . /opt/spack-environment/activate.sh + export RUNID=GISS_GC_14 + # Environment variables for passing NetCDF-C paths to GEOS-Chem + export NETCDF_HOME=$(nc-config --prefix) + export GC_BIN=${NETCDF_HOME}/bin + export GC_INCLUDE=${NETCDF_HOME}/include + export GC_LIB=${NETCDF_HOME}/lib + # Environment variables for passing NetCDF-Fortran paths to GEOS-Chem + export NETCDF_F_HOME=$(nf-config --prefix) + export GC_F_BIN=${NETCDF_F_HOME}/bin + export GC_F_INCLUDE=${NETCDF_F_HOME}/include + export GC_F_LIB=${NETCDF_F_HOME}/lib + # Environment variable for OpenMPI build + export MPI_ROOT=/opt/software/linux-ubuntu22.04-skylake/gcc-11.4.0/openmpi-4.1.6-s3fu5gvaasgjy4jecnb6rvemx7oofexx + # Copy over rundeck and modelErc + cp .github/rundecks/${RUNID}.R decks + cp .github/modelErc ~/.modelErc + # Build the model + cd decks + make -j setup RUN=${RUNID} F90=mpif90 GC=YES diff --git a/.gitmodules b/.gitmodules index 909db83..13aaf9d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,12 @@ -[submodule "model/geos-chem/src"] - path = model/geos-chem/src - url = git@github.com:fetch4/geos-chem.git - branch = dev/giss-gc +[submodule "model/geos-chem/src/GEOS-Chem"] + path = model/geos-chem/src/GEOS-Chem + url = https://github.com/fetch4/geos-chem.git + branch = dev/giss-gc-14 +[submodule "model/geos-chem/src/HEMCO"] + path = model/geos-chem/src/HEMCO + url = https://github.com/fetch4/HEMCO.git + branch = dev/giss-gc-14 +[submodule "model/geos-chem/src/Cloud-J"] + path = model/geos-chem/src/Cloud-J + url = https://github.com/fetch4/Cloud-J.git + branch = dev/giss-gc-14 diff --git a/config/compiler.gfortran.mk b/config/compiler.gfortran.mk index d21f4fc..2bf9e41 100644 --- a/config/compiler.gfortran.mk +++ b/config/compiler.gfortran.mk @@ -25,8 +25,16 @@ endif FMAKEDEP = $(SCRIPTS_DIR)/sfmakedepend CPPFLAGS += -DCOMPILER_G95 FFLAGS = -g -cpp -fconvert=big-endian -O2 -fno-range-check -fallow-argument-mismatch -F90FLAGS = -g -cpp -fconvert=big-endian -O2 -fno-range-check -ffree-line-length-none -fallow-argument-mismatch +F90FLAGS = $(FFLAGS) -ffree-line-length-none LFLAGS = +ifeq ($(GC),YES) +LFLAGS += -nostartfiles -Wno-main +endif +ifeq ($(MP),YES) +FFLAGS += -fopenmp +F90FLAGS += -fopenmp +LFLAGS += -fopenmp +endif F90_VERSION = $(shell $(F90) --version | head -1) diff --git a/config/compiler.intel.mk b/config/compiler.intel.mk index c9b9710..2c64132 100644 --- a/config/compiler.intel.mk +++ b/config/compiler.intel.mk @@ -4,15 +4,18 @@ IFORT_RELEASE := $(shell ifort --version | perl -e \ 'while(<>){ if(/ifort.* (\d+\.\d+)/) { print "$$1"; } }') FMAKEDEP = $(SCRIPTS_DIR)/sfmakedepend CMP_MOD = $(SCRIPTS_DIR)/compare_module_file.pl -compiler INTEL-ifort-9-0-on-LINUX -FFLAGS = -fpp -O2 -ftz -convert big_endian -F90FLAGS = -fpp -O2 -ftz -convert big_endian -free +FFLAGS = -fpp -O2 -ftz -convert big_endian +F90FLAGS = $(FFLAGS) -free LFLAGS = -O2 -ftz +ifeq ($(GC),YES) +LFLAGS += -nostartfiles -nofor-main +endif CPPFLAGS += -DCOMPILER_Intel8 -DCONVERT_BIGENDIAN F90_VERSION = $(shell $(F90) -v 2>&1) ifeq ($(MP),YES) -FFLAGS += -openmp -F90FLAGS += -openmp -LFLAGS += -openmp +FFLAGS += -qopenmp +F90FLAGS += -qopenmp +LFLAGS += -qopenmp endif R8 = -r8 EXTENDED_SOURCE = -extend_source diff --git a/config/rules.mk b/config/rules.mk index ec41508..d981c80 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -229,36 +229,43 @@ endif ifneq ($(CUBED_SPHERE),YES) -ifdef NETCDFHOME - ifneq ($(wildcard $(NETCDFHOME)/include/netcdf.inc),) - NETCDFINCLUDEDIR ?= $(NETCDFHOME)/include - else - ifneq ($(wildcard $(NETCDFHOME)/include/netcdf-3/netcdf.inc),) - NETCDFINCLUDEDIR ?= $(NETCDFHOME)/include/netcdf-3 +ifneq ($(and $(NETCDF_HOME),$(NETCDF_F_HOME)),) + LIBS += -L$(NETCDF_HOME)/lib -lnetcdf -L$(NETCDF_F_HOME)/lib -lnetcdff + FFLAGS += -I$(NETCDF_HOME)/include -I$(NETCDF_F_HOME)/include + F90FLAGS += -I$(NETCDF_HOME)/include -I$(NETCDF_F_HOME)/include + INCS += -I$(NETCDF_HOME)/include -I$(NETCDF_F_HOME)/include +else + ifdef NETCDFHOME + ifneq ($(wildcard $(NETCDFHOME)/include/netcdf.inc),) + NETCDFINCLUDEDIR ?= $(NETCDFHOME)/include else - $(error NetCDF include files not found) + ifneq ($(wildcard $(NETCDFHOME)/include/netcdf-3/netcdf.inc),) + NETCDFINCLUDEDIR ?= $(NETCDFHOME)/include/netcdf-3 + else + $(error NetCDF include files not found) + endif endif - endif - ifneq ($(wildcard $(NETCDFHOME)/$(LIBABI)/libnetcdf*),) - NETCDFLIBDIR ?= $(NETCDFHOME)/$(LIBABI) - else - NETCDFLIBDIR ?= $(NETCDFHOME)/lib + ifneq ($(wildcard $(NETCDFHOME)/$(LIBABI)/libnetcdf*),) + NETCDFLIBDIR ?= $(NETCDFHOME)/$(LIBABI) + else + NETCDFLIBDIR ?= $(NETCDFHOME)/lib + endif endif -endif -ifdef NETCDFINCLUDEDIR - FFLAGS += -I$(NETCDFINCLUDEDIR) - F90FLAGS += -I$(NETCDFINCLUDEDIR) - INCS += -I$(NETCDFINCLUDEDIR) -endif + ifdef NETCDFINCLUDEDIR + FFLAGS += -I$(NETCDFINCLUDEDIR) + F90FLAGS += -I$(NETCDFINCLUDEDIR) + INCS += -I$(NETCDFINCLUDEDIR) + endif -ifdef NETCDFLIBDIR - LIBS += -L$(NETCDFLIBDIR) -lnetcdf - ifeq ($(wildcard $(NETCDFLIBDIR)/libnetcdff.*),) + ifdef NETCDFLIBDIR LIBS += -L$(NETCDFLIBDIR) -lnetcdf - else - LIBS += -L$(NETCDFLIBDIR) -L/opt/local/lib -lnetcdff -lnetcdf + ifeq ($(wildcard $(NETCDFLIBDIR)/libnetcdff.*),) + LIBS += -L$(NETCDFLIBDIR) -lnetcdf + else + LIBS += -L$(NETCDFLIBDIR) -L/opt/local/lib -lnetcdff -lnetcdf + endif endif endif diff --git a/decks/Makefile b/decks/Makefile index c0386ea..da418ab 100644 --- a/decks/Makefile +++ b/decks/Makefile @@ -28,6 +28,8 @@ else MODEL_E_BUILD_DIR = $(MODEL_E_ROOT) endif MODEL_DIR = $(MODEL_E_BUILD_DIR)/model +GC_BUILD_DIR = $(MODEL_DIR)/geos-chem/build +GC_LIB_DIR = $(MODEL_DIR)/geos-chem/lib AUX_DIR = $(MODEL_E_ROOT)/aux SCRIPTS_DIR = $(MODEL_E_ROOT)/exec DECKS_DIR = $(shell pwd) @@ -127,9 +129,34 @@ ifeq ($(GC),YES) @echo "***************************************************************" @echo "Compiling GEOS-Chem" @echo "***************************************************************" - cd $(MODEL_DIR)/geos-chem/src && make FC=$(FC) EXTERNAL_GRID=y EXTERNAL_FORCING=y GISS=y OMP=n NO_EXE=y all MAKEFLAGS= - #cd $(MODEL_DIR)/geos-chem/src && make FC=$(FC) EXTERNAL_GRID=y EXTERNAL_FORCING=y GISS=y OMP=n DEBUG=y TRACEBACK=y NO_EXE=y all MAKEFLAGS= - cp $(MODEL_DIR)/geos-chem/src/mod/* $(MODEL_DIR)/mod/ + mkdir -p $(GC_BUILD_DIR) + mkdir -p $(GC_LIB_DIR) + cd $(GC_BUILD_DIR) && cmake ../ -DINSTALLCOPY=.. \ + -DOMP=$(MP) \ + -DCMAKE_Fortran_FLAGS="$(F90FLAGS)" \ + -DCMAKE_EXE_LINKER_FLAGS="$(LFLAGS)" + cd $(GC_BUILD_DIR) && make -j install + cp $(GC_BUILD_DIR)/mod/*.mod $(MODEL_DIR)/mod/ + cp $(GC_BUILD_DIR)/src/HEMCO/mod/*.mod $(MODEL_DIR)/mod/ + cp $(GC_BUILD_DIR)/src/Cloud-J/mod/*.mod $(MODEL_DIR)/mod/ + cp $(GC_BUILD_DIR)/src/HEMCO/src/Core/libHCO.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/HEMCO/src/Extensions/libHCOX.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/HEMCO/src/Shared/Headers/libHeadersHco.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/HEMCO/src/Shared/GeosUtil/libJulDayHco.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/HEMCO/src/Shared/GeosUtil/libGeosUtilHco.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/HEMCO/src/Shared/NcdfUtil/libNcdfUtilHco.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/HEMCO/src/Interfaces/Shared/libHCOI_Shared.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/ISORROPIA/libIsorropia.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/Headers/libHeaders.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/ObsPack/libObsPack.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/History/libHistory.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/KPP/fullchem/libKPP_FirstPass.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/KPP/fullchem/libKPP.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/GeosCore/libGeosCore.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/GeosUtil/libGeosUtil.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/GeosUtil/libJulDay.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/GEOS-Chem/NcdfUtil/libNcdfUtil.a $(GC_LIB_DIR)/ + cp $(GC_BUILD_DIR)/src/Cloud-J/src/Core/libCloudJ_Core.a $(GC_LIB_DIR)/ endif $(MAKE) -C $(MODEL_DIR) gcm RUN=$(RUN) DECKS_DIR=$(DECKS_DIR) $(OPTS_MAIN) -mv $(MODEL_DIR)/$(RUN).bin $(BIN_DIR)/$(RUN).exe @@ -225,9 +252,7 @@ ifneq ($(PFUNIT),) $(MAKE) -C $(TESTS_DIR) clean endif $(MAKE) -C $(AUX_DIR) $@ $(OPTS_MAIN) -ifeq ($(GC),YES) - cd $(MODEL_DIR)/geos-chem/src && make realclean -endif + rm -rf $(GC_BUILD_DIR) exe: $(RUN)/$(RUN) gcm @if [ ! -s $(CMRUNDIR)/$(RUN)/I ] ; then \ diff --git a/docker/Dockerfile.devenv b/docker/Dockerfile.devenv new file mode 100644 index 0000000..0233a40 --- /dev/null +++ b/docker/Dockerfile.devenv @@ -0,0 +1,62 @@ +# Build stage with Spack pre-installed and ready to be used +FROM spack/ubuntu-jammy:0.21 AS builder + +# What we want to install and how we want to install it +# is specified in a manifest file (spack.yaml) +RUN mkdir /opt/spack-environment \ +&& (echo spack: \ +&& echo ' packages:' \ +&& echo ' all:' \ +&& echo ' compiler: [gcc@11.4.0]' \ +&& echo ' specs:' \ +&& echo ' - cmake@3.27.7' \ +&& echo ' - gmake' \ +&& echo ' - hdf5@1.14.3' \ +&& echo ' - netcdf-c@4.9.2+mpi+parallel-netcdf' \ +&& echo ' - netcdf-fortran' \ +&& echo ' - openmpi@4.1.6' \ +&& echo ' concretizer:' \ +&& echo ' unify: true' \ +&& echo ' config:' \ +&& echo ' install_missing_compilers: true' \ +&& echo ' install_tree: /opt/software' \ +&& echo ' view: /opt/views/view') > /opt/spack-environment/spack.yaml + +# Install the software, remove unnecessary deps +RUN cd /opt/spack-environment && spack env activate . && spack install --fail-fast && spack gc -y + +# Install perl URI lib +RUN apt update && apt install -y libany-uri-escape-perl + +# Strip all the binaries +RUN find -L /opt/views/view/* -type f -exec readlink -f '{}' \; | \ + xargs file -i | \ + grep 'charset=binary' | \ + grep 'x-executable\|x-archive\|x-sharedlib' | \ + awk -F: '{print $1}' | xargs strip + +# Modifications to the environment that are necessary to run +RUN cd /opt/spack-environment && \ + spack env activate --sh -d . > activate.sh + +# Bare OS image to run the installed executables +FROM ubuntu:22.04 + +COPY --from=builder /opt/spack-environment /opt/spack-environment +COPY --from=builder /opt/software /opt/software +COPY --from=builder /usr /usr + +# paths.view is a symlink, so copy the parent to avoid dereferencing and duplicating it +COPY --from=builder /opt/views /opt/views + +RUN { \ + echo '#!/bin/sh' \ + && echo '.' /opt/spack-environment/activate.sh \ + && echo 'exec "$@"'; \ + } > /entrypoint.sh \ +&& chmod a+x /entrypoint.sh \ +&& ln -s /opt/views/view /opt/view \ +&& apt update && apt install -y ca-certificates cpp m4 + +ENTRYPOINT [ "/entrypoint.sh" ] +CMD [ "/bin/bash" ] diff --git a/docker/Makefile b/docker/Makefile new file mode 100644 index 0000000..b26aa68 --- /dev/null +++ b/docker/Makefile @@ -0,0 +1,20 @@ +all: build + +DOCKERFILE = Dockerfile.devenv +NAMESPACE = ghcr.io/fetch4 +IMAGE_NAME = giss-gc-dev-env +TAG = latest + +IMAGE = $(NAMESPACE)/$(IMAGE_NAME):$(TAG) + +pull: + docker pull $(IMAGE) + +build: + docker build -f $(DOCKERFILE) -t $(IMAGE) --no-cache . + +run: + docker run --rm -it -v ${HOME}:${HOME} $(IMAGE) + +push: + docker push $(IMAGE) diff --git a/model/CHEM_COM.F90 b/model/CHEM_COM.F90 index e5f6cd4..766a366 100644 --- a/model/CHEM_COM.F90 +++ b/model/CHEM_COM.F90 @@ -48,28 +48,6 @@ module CHEM_COM !@var ijlt_power: power of 10 used for tracer IJL 3D diags INTEGER, DIMENSION(kgcaijl) :: ijlt_power - ! Indices to radiatively active species - INTEGER :: i_H2O = 0 - INTEGER :: i_CO2 = 0 - INTEGER :: i_O3 = 0 - INTEGER :: i_O2 = 0 - INTEGER :: i_NO2 = 0 - INTEGER :: i_N2O = 0 - INTEGER :: i_CH4 = 0 - INTEGER :: i_CFC11 = 0 - INTEGER :: i_CFC12 = 0 - INTEGER :: i_N2 = 0 - INTEGER :: i_CFCY = 0 - INTEGER :: i_CFCZ = 0 - INTEGER :: i_SO2 = 0 - INTEGER :: i_SO4 = 0 - INTEGER :: i_NIT = 0 - INTEGER :: i_OCPI = 0 - INTEGER :: i_OCPO = 0 - INTEGER :: i_BCPI = 0 - INTEGER :: i_BCPO = 0 - INTEGER :: i_SOAS = 0 - ! This section declares arrays used to write tracer ! diagnostics accumulations in a format suitable for offline ! postprocessing. The size of these arrays cannot be known diff --git a/model/CHEM_DRV.F90 b/model/CHEM_DRV.F90 index 3210111..8e19330 100644 --- a/model/CHEM_DRV.F90 +++ b/model/CHEM_DRV.F90 @@ -18,6 +18,7 @@ module CHEM_DRV USE State_Met_Mod, ONLY : MetState USE State_Diag_Mod, ONLY : DgnState USE DiagList_Mod, ONLY : DgnList + USE TaggedDiagList_Mod, ONLY : TaggedDgnList USE HCO_Types_Mod, ONLY : ConfigObj USE Precision_Mod @@ -41,6 +42,7 @@ module CHEM_DRV TYPE(ChmState) :: State_Chm ! Chemistry state TYPE(DgnState) :: State_Diag ! Diagnostics state TYPE(DgnList) :: Diag_List ! Diagnostics state + TYPE(TaggedDgnList) :: TaggedDiag_List ! Diagnostics state TYPE(GrdState) :: State_Grid ! Grid state TYPE(ConfigObj), POINTER :: HcoConfig @@ -118,7 +120,8 @@ SUBROUTINE DO_CHEM USE CONSTANT, ONLY : bygrav, lhe, tf, teeny ! GEOS-Chem modules - USE HCO_Interface_Mod, ONLY : SetHcoTime + USE HCO_State_GC_Mod, ONLY : HcoState, ExtState + USE HCO_Interface_Common, ONLY : SetHcoTime USE Time_Mod, ONLY : Accept_External_Date_Time USE Emissions_Mod, ONLY : Emissions_Run USE State_Chm_Mod, ONLY : Ind_ @@ -127,9 +130,10 @@ SUBROUTINE DO_CHEM USE Pressure_Mod, ONLY : Set_Floating_Pressures USE Pressure_Mod, ONLY : Accept_External_Pedge USE Calc_Met_Mod, ONLY : Set_Dry_Surface_Pressure - USE Calc_Met_Mod, ONLY : GIGC_Cap_Tropopause_Prs + USE Calc_Met_Mod, ONLY : GCHP_Cap_Tropopause_Prs USE PBL_Mix_Mod, ONLY : Compute_PBL_Height USE ERROR_MOD, ONLY : Safe_Div, IT_IS_NAN + USE UnitConv_Mod IMPLICIT NONE @@ -141,7 +145,7 @@ SUBROUTINE DO_CHEM REAL*4 :: MINUTES, hElapsed, UTC REAL*8 :: sElapsed LOGICAL :: IsChemTime - CHARACTER(LEN=63) :: OrigUnit + INTEGER :: OrigUnit ! External functions (from shared/Utilities.F90) REAL*8 SLP @@ -241,7 +245,7 @@ SUBROUTINE DO_CHEM if ( si_ocn%snowi(i,j) > 0. ) & State_Met%FRSNO(II,JJ) = si_atm%rsi(i,j)*flake(i,j) if ( atmlnd%SNOWE(i,j) > 0. ) & - State_Met%FRSNO(II,JJ) = State_Met%FRSNO(II,JJ) + atmlnd%snowfr(i,j)*fearth(i,j) + State_Met%FRSNO(II,JJ) = State_Met%FRSNO(I,J) + atmlnd%snowfr(i,j)*fearth(i,j) State_Met%FRSNO(II,JJ) = min( 1.0, State_Met%FRSNO(II,JJ) ) ! Root soil wetness [1] @@ -267,9 +271,10 @@ SUBROUTINE DO_CHEM State_Met%LAI (II,JJ) = lai_save(i,j) ! Land/water/ice indices [1] - State_Met%LWI (II,JJ) = 1 - if ( focean(i,j) > fearth(i,j) ) State_Met%LWI(II,JJ) = 0 - if ( si_atm%rsi(i,j)*focean(i,j) > 0.5 ) State_Met%LWI(II,JJ) = 2 + ! TODO: Uncomment or drop the following + ! State_Met%LWI (II,JJ) = 1 + ! if ( focean(i,j) > fearth(i,j) ) State_Met%LWI(II,JJ) = 0 + ! if ( si_atm%rsi(i,j)*focean(i,j) > 0.5 ) State_Met%LWI(II,JJ) = 2 ! Direct photsynthetically active radiation [W/m2] State_Met%PARDR (II,JJ) = 0.82*srvissurf(i,j)*(fsrdir(i,j))*cosz1(i,j) @@ -521,10 +526,10 @@ SUBROUTINE DO_CHEM ENDDO ! Set the pressure at level edges [hPa] from the GCM - CALL Accept_External_Pedge( State_Met = State_Met, & - RC = RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Accept_External_Pedge", 255 ) - + CALL Accept_External_Pedge( State_Met = State_Met, & + State_Grid = State_Grid, & + RC = RC ) + ! Set dry surface pressure (PS1_DRY) from State_Met%PS1_WET CALL SET_DRY_SURFACE_PRESSURE( State_Grid, State_Met, 1 ) @@ -532,23 +537,25 @@ SUBROUTINE DO_CHEM CALL SET_DRY_SURFACE_PRESSURE( State_Grid, State_Met, 2 ) ! Initialize surface pressures to match the post-advection pressures + State_Met%PSC2_WET = State_Met%PS1_WET + State_Met%PSC2_DRY = State_Met%PS1_DRY CALL SET_FLOATING_PRESSURES( State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "SET_FLOATING_PRESSURES", 255 ) + IF ( RC /= GC_SUCCESS ) RETURN ! Define airmass and related quantities - CALL AirQnt( Input_Opt, State_Chm, State_Grid, State_Met, RC, .FALSE. ) + CALL AirQnt( Input_Opt, State_Chm, State_Grid, State_Met, RC, .FALSE. ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "AirQnt", 255 ) ! Cap the polar tropopause pressures at 200 hPa, in order to avoid ! tropospheric chemistry from happening too high up (cf. J. Logan) - CALL GIGC_Cap_Tropopause_Prs( Input_Opt = Input_Opt, & + CALL GCHP_Cap_Tropopause_Prs( Input_Opt = Input_Opt, & State_Grid = State_Grid, & State_Met = State_Met, & RC = RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "GIGC_Cap_Tropopause_Prs", 255 ) + IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "GCHP_Cap_Tropopause_Prs", 255 ) ! Call PBL quantities. Those are always needed - CALL COMPUTE_PBL_HEIGHT( State_Grid, State_Met, RC ) + CALL Compute_Pbl_Height( Input_Opt, State_Grid, State_Met, RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "COMPUTE_PBL_HEIGHT", 255 ) IF ( FIRST_CHEM ) THEN @@ -572,7 +579,9 @@ SUBROUTINE DO_CHEM IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Accept_External_Date_Time", 255 ) ! Set initial HEMCO time - CALL SetHcoTime ( .true., RC ) + ! NOTE: DoEmis not defined yet, set to true + CALL SetHcoTime ( HcoState, ExtState, year, month, day, & + DOY, hour, minute, second, .true., RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "SetHcoTime", 255 ) !======================================================================= @@ -583,7 +592,13 @@ SUBROUTINE DO_CHEM State_Grid, State_Met, .True., 0, RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "EMISSIONS_RUN - Phase 0", 255 ) - CALL Convert_Spc_Units( Input_Opt, State_Chm, State_Grid, State_Met, 'kg', RC ) + CALL Convert_Spc_Units( & + Input_Opt = Input_Opt, & + State_Chm = State_Chm, & + State_Grid = State_Grid, & + State_Met = State_Met, & + outUnit = KG_SPECIES, & + RC = RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Convert_Spc_Units", 255 ) ! Copy initial conditions into TrM if absolute beginning @@ -594,7 +609,7 @@ SUBROUTINE DO_CHEM DO I=I_0,I_1 II = I - I_0 + 1 JJ = J - J_0 + 1 - TrM( I, J, L, N ) = State_Chm%Species(II,JJ,L,N) + TrM( I, J, L, N ) = State_Chm%Species(N)%Conc(II,JJ,L) !TrMom( I, J, L, :, N ) = 0d0 ! Assuming initially uniformly distributed ! Hack until HALO_UPDATE works for initial conditions if ( J_0 .ne. J_0H .and. J .eq. J_0 ) TrM( I, J_0H, L, N ) = TrM(I,J,L,N) @@ -634,36 +649,22 @@ SUBROUTINE DO_CHEM DO I=I_0,I_1 II = I - I_0 + 1 JJ = J - J_0 + 1 - State_Chm%Species(II,JJ,L,N) = TrM( I, J, L, N ) + State_Chm%Species(N)%Conc(II,JJ,L) = TrM( I, J, L, N ) ENDDO ENDDO ENDDO ENDDO - State_Chm%Spc_Units = 'kg' ! Convert to v/v dry - CALL Convert_Spc_Units( Input_Opt, State_Chm, State_Grid, State_Met, & - 'v/v dry', RC ) + CALL Convert_Spc_Units( & + Input_Opt = Input_Opt, & + State_Chm = State_Chm, & + State_Grid = State_Grid, & + State_Met = State_Met, & + outUnit = MOLES_SPECIES_PER_MOLES_DRY_AIR, & + RC = RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Convert_Spc_Units", 255 ) - IF ( Am_I_Root() .and. .false. ) THEN - print*,NTM ! 278 in 12.9.0 (199 advected) - print*,i_H2O ! 61 - print*,i_CO2 ! 200 - print*,i_O3 ! 164 - print*,i_O2 ! 277 - print*,i_NO2 ! 161 - print*,i_N2O ! 154 - print*,i_CH4 ! 154 - print*,i_CFC11 ! 36 - print*,i_CFC12 ! 21 - print*,i_N2 ! 276 - print*,i_CFCY ! 0 - print*,i_CFCZ ! 0 - print*,i_SO2 ! 191 - CALL FLUSH(6) - ENDIF - !===================== ! Call GEOS-Chem !===================== @@ -676,8 +677,13 @@ SUBROUTINE DO_CHEM IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Chem_Chunk_Run", 255 ) ! Convert back to kg for GCM advection - CALL Convert_Spc_Units( Input_Opt, State_Chm, State_Grid, State_Met, & - 'kg', RC ) + CALL Convert_Spc_Units( & + Input_Opt = Input_Opt, & + State_Chm = State_Chm, & + State_Grid = State_Grid, & + State_Met = State_Met, & + outUnit = KG_SPECIES, & + RC = RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Convert_Spc_Units", 255 ) ! Copy State_Chm back in TrM @@ -687,7 +693,7 @@ SUBROUTINE DO_CHEM DO I=I_0,I_1 II = I - I_0 + 1 JJ = J - J_0 + 1 - TrM( I, J, L, N ) = State_Chm%Species(II,JJ,L,N) + TrM( I, J, L, N ) = State_Chm%Species(N)%Conc(II,JJ,L) ENDDO ENDDO ENDDO @@ -718,7 +724,6 @@ SUBROUTINE TrDYNAM ! Uses the fluxes MUs,MVs,MWs from DYNAM and QDYNAM DO N=1,NTM - !IF ( Am_I_Root() ) WRITE(6,*) TrName(N), IsAdvected(N) IF ( IsAdvected(N) ) THEN CALL AADVQ( TrM(:,:,:,n), TrMom(:,:,:,:,n), .true., TrName(n) ) ENDIF @@ -739,7 +744,7 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & ! Based on GIGC_Chunk_Run ! GEOS-Chem state objects - USE HCO_Interface_Mod, ONLY : HcoState + USE HCO_State_GC_Mod, ONLY : HcoState, ExtState USE Input_Opt_Mod, ONLY : OptInput USE State_Chm_Mod, ONLY : ChmState USE State_Diag_Mod @@ -753,16 +758,19 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & USE Emissions_Mod, ONLY : Emissions_Run USE Mixing_Mod, ONLY : Do_Tend, Do_Mixing USE WetScav_Mod, ONLY : Setup_WetScav, Do_WetDep + USE UnitConv_Mod ! Specialized subroutines USE Calc_Met_Mod, ONLY : AirQnt, Set_Dry_Surface_Pressure - USE Calc_Met_Mod, ONLY : GIGC_Cap_Tropopause_Prs + USE Calc_Met_Mod, ONLY : GCHP_Cap_Tropopause_Prs, GET_COSINE_SZA USE Set_Global_CH4_Mod, ONLY : Set_CH4 USE MODIS_LAI_Mod, ONLY : Compute_XLAI USE PBL_Mix_Mod, ONLY : Compute_PBL_Height USE Pressure_Mod, ONLY : Set_Floating_Pressures USE TOMS_Mod, ONLY : Compute_Overhead_O3 USE UCX_Mod, ONLY : Set_H2O_Trac + USE HCO_Interface_GC_Mod, ONLY : Compute_Sflx_For_Vdiff + USE Vdiff_Mod, ONLY : Max_PblHt_for_Vdiff ! Utilities USE ErrCode_Mod @@ -771,11 +779,11 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & USE State_Chm_Mod, ONLY : IND_ USE Time_Mod, ONLY : Accept_External_Date_Time USE UnitConv_Mod, ONLY : Convert_Spc_Units - USE HCO_Interface_Mod, ONLY : SetHcoTime + USE HCO_Interface_Common, ONLY : SetHcoTime ! Diagnostics USE Diagnostics_Mod, ONLY : Set_Diagnostics_EndofTimestep - USE Aerosol_Mod, ONLY : Set_AerMass_Diagnostic + USE Diagnostics_Mod, ONLY : Set_AerMass_Diagnostic USE CHEM_COM, ONLY : gcaijl_out !, ijlt_vmr !, gcaijs=>gcaijs_loc USE DOMAIN_DECOMP_ATM, ONLY : GRID, getDomainBounds, am_I_Root @@ -811,8 +819,8 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & ! First call? LOGICAL, SAVE :: FIRST = .TRUE. - CHARACTER(LEN=255) :: Iam, OrigUnit - INTEGER :: STATUS, HCO_PHASE, RST + CHARACTER(LEN=255) :: Iam + INTEGER :: STATUS, HCO_PHASE, RST, OrigUnit ! Local logicals to turn on/off individual components ! The parts to be executed are based on the input options, @@ -834,12 +842,16 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & ! Whether to scale mixing ratio with meteorology update in AirQnt LOGICAL, SAVE :: scaleMR = .FALSE. - INTEGER :: N, I, J, K, L, II, JJ + INTEGER :: N, I, J, K, L, II, JJ, PHASE !======================================================================= ! GIGC_CHUNK_RUN begins here !======================================================================= + ! -1: Phase -1 is the standard setting in GCHP. It executes all components. + ! Phase is -1 if number of phases is set to 1 in config file GCHP.rc. + PHASE = -1 + ! By default, do processes as defined in rundeck DoConv = DoGCConv ! dynamic time step DoDryDep = DOGCDryDep .AND. IsChemTime ! chemistry time step @@ -886,44 +898,104 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Accept_External_Date_Time", 255 ) ! Set HEMCO time - CALL SetHcoTime ( DoEmis, RC ) + CALL SetHcoTime ( HcoState, ExtState, year, month, day, & + dayOfYr, hour, minute, second, DoEmis, RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "SetHcoTime", 255 ) ! Calculate MODIS leaf area indexes needed for dry deposition CALL Compute_XLAI( Input_Opt, State_Grid, State_Met, RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Compute_XLAI", 255 ) + ! Set the pressure at level edges [hPa] from the ESMF environment + CALL Accept_External_Pedge( State_Met = State_Met, & + State_Grid = State_Grid, & + RC = RC ) + + ! Set dry surface pressure (PS1_DRY) from State_Met%PS1_WET + CALL SET_DRY_SURFACE_PRESSURE( State_Grid, State_Met, 1 ) + + ! Set dry surface pressure (PS2_DRY) from State_Met%PS2_WET + CALL SET_DRY_SURFACE_PRESSURE( State_Grid, State_Met, 2 ) + + ! Initialize surface pressures to match the post-advection pressures + State_Met%PSC2_WET = State_Met%PS1_WET + State_Met%PSC2_DRY = State_Met%PS1_DRY + CALL SET_FLOATING_PRESSURES( State_Grid, State_Met, RC ) + IF ( RC /= GC_SUCCESS ) RETURN + +! TODO: Uncomment or drop the following code +! ! Define airmass and related quantities +!#if defined( MODEL_GEOS ) +! CALL AirQnt( Input_Opt, State_Chm, State_Grid, State_Met, RC, .FALSE. ) +!#else +! ! Scale mixing ratio with changing met only if FV advection is off. +! ! Only do this the first timestep if DELP_DRY found in restart. +! IF ( FIRST .and. .not. Input_Opt%LTRAN ) THEN +! CALL MAPL_Get ( STATE, INTERNAL_ESMF_STATE=INTSTATE, __RC__ ) +! CALL ESMF_StateGet( INTSTATE, 'DELP_DRY', IntField, RC=STATUS ) +! _VERIFY(STATUS) +! CALL ESMF_AttributeGet( IntField, NAME="RESTART", VALUE=RST, RC=STATUS ) +! _VERIFY(STATUS) +! IF ( .not. ( RST == MAPL_RestartBootstrap .OR. & +! RST == MAPL_RestartSkipInitial ) ) scaleMR = .TRUE. +! CALL AirQnt( Input_Opt, State_Chm, State_Grid, State_Met, RC, scaleMR ) +! scaleMR = .TRUE. +! ELSE +! CALL AirQnt( Input_Opt, State_Chm, State_Grid, State_Met, RC, scaleMR ) +! ENDIF +!#endif + + ! Initialize/reset wetdep after air quantities computed + IF ( DoConv .OR. DoChem .OR. DoWetDep ) THEN + CALL SETUP_WETSCAV( Input_Opt, State_Chm, State_Grid, State_Met, RC ) + ENDIF + + ! Cap the polar tropopause pressures at 200 hPa, in order to avoid + ! tropospheric chemistry from happening too high up (cf. J. Logan) + CALL GCHP_Cap_Tropopause_Prs( Input_Opt = Input_Opt, & + State_Grid = State_Grid, & + State_Met = State_Met, & + RC = RC ) + + ! Call PBL quantities. Those are always needed + CALL Compute_Pbl_Height( Input_Opt, State_Grid, State_Met, RC ) + ! Convert to dry mixing ratio - CALL Convert_Spc_Units ( Input_Opt, State_Chm, State_Grid, State_Met, & - 'kg/kg dry', RC, OrigUnit=OrigUnit ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Convert_Spc_Units", 255 ) + CALL Convert_Spc_Units( & + Input_Opt = Input_Opt, & + State_Chm = State_Chm, & + State_Grid = State_Grid, & + State_Met = State_Met, & + outUnit = KG_SPECIES_PER_KG_DRY_AIR, & + origUnit = origUnit, & + RC = RC ) + !======================================================================= + ! Always prescribe H2O in both the stratosphere and troposhere in GEOS. + ! This is now done right after passing the species from the internal + ! state to State_Chm (in Chem_GridCompMod.F90). It is important to do it + ! there to make sure that any H2O tendencies are properly calculated + ! cakelle2, 2023/10/14 + !======================================================================= ! SDE 05/28/13: Set H2O to STT if relevant IF ( IND_('H2O','A') > 0 ) THEN - SetStratH2O = .FALSE. - IF ( Input_Opt%LSETH2O .OR. .NOT. Input_Opt%LUCX ) THEN + IF ( Input_Opt%LSETH2O ) THEN SetStratH2O = .TRUE. ENDIF CALL SET_H2O_TRAC( SetStratH2O, Input_Opt, State_Chm, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "SET_H2O_TRAC", 255 ) - - ! Only force strat once if using UCX - IF (Input_Opt%LSETH2O) Input_Opt%LSETH2O = .FALSE. + State_Grid, State_Met, RC ) + ! Only force strat once + IF ( Input_Opt%LSETH2O ) Input_Opt%LSETH2O = .FALSE. ENDIF - ! LTM - !IF ( State_Grid%NY .eq. 2 ) THEN - !WRITE(6,'(A6,2(F8.2),8X,3X,A8,2(F8.2),8X,3X,A8,3(F8.2),8X)') "YMID: ", State_Grid%YMID(1,:), "YMID_R: ", State_Grid%YMID_R(1,:), "YEDGE", State_Grid%YEDGE(1,:) - !ENDIF - - !IF ( State_Grid%NY .eq. 3 ) THEN - !WRITE(6,'(A6,3(F8.2),3X,A8,3(F8.2),3X,A8,4(F8.2))') "YMID: ", State_Grid%YMID(1,:), "YMID_R: ", State_Grid%YMID_R(1,:), "YEDGE:", State_Grid%YEDGE(1,:) - !ENDIF - - !CALL FLUSH(6) + ! Compute the cosine of the solar zenith angle array: + ! State_Met%SUNCOS => COS(SZA) at the current time + ! State_Met%SUNCOSmid => COS(SZA) at the midpt of the chem timestep + ! COS(SZA) at the midpt of the chem timestep 5hrs ago is now + ! calculated elsewhere, in the HEMCO PARANOx extension + CALL GET_COSINE_SZA( Input_Opt, State_Grid, State_Met, RC ) !======================================================================= ! EMISSIONS. Pass HEMCO Phase 1 which only updates the HEMCO clock @@ -932,24 +1004,25 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & !======================================================================= HCO_PHASE = 1 CALL EMISSIONS_RUN( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, DoEmis, HCO_PHASE, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "EMISSIONS_RUN - Phase 1", 255 ) + State_Grid, State_Met, DoEmis, HCO_PHASE, RC ) + +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +!!! PHASE 1 or -1 !!! +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% !======================================================================= ! 1. Convection ! ! Call GEOS-Chem internal convection routines if convection is enabled - ! in input.geos. This should only be done if convection is not covered - ! by another gridded component and/or the GC species are not made + ! in geoschem_config.yml. This should only be done if convection is not + ! covered by another gridded component and/or the GC species are not made ! friendly to this component!! !======================================================================= IF ( DoConv ) THEN - if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do convection now' CALL DO_CONVECTION ( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "DO_CONVECTION", 255 ) + State_Grid, State_Met, RC ) if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Convection done!' ENDIF @@ -968,11 +1041,9 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & ! Do dry deposition CALL Do_DryDep ( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "DO_DryDep", 255 ) + State_Grid, State_Met, RC ) if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Drydep done!' - ENDIF !======================================================================= @@ -986,51 +1057,61 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do emissions now' ! Do emissions. Pass HEMCO Phase 2 which performs the emissions - ! calculations. Note that this does not apply the emissions. + ! calculations. HCO_PHASE = 2 CALL EMISSIONS_RUN( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, DoEmis, HCO_PHASE, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "EMISSIONS_RUN - Phase 2", 255 ) + State_Grid, State_Met, DoEmis, HCO_PHASE, RC ) + if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Emissions done!' ENDIF - !======================================================================= - ! If physics covers turbulence, simply add the emission and dry - ! deposition fluxes calculated above to the tracer array, without caring - ! about the vertical distribution. The tracer tendencies are only added - ! to the tracers array after emissions, drydep. So we need to use the - ! emissions time step here. - !======================================================================= - ! Not implemented +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +!!! PHASE 2 or -1 !!! +!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% !======================================================================= ! 4. Turbulence ! ! Call GEOS-Chem internal turbulence routines if turbulence is enabled - ! in input.geos. This should only be done if turbulence is not covered - ! by another gridded component and/or the GC species are not made + ! in geoschem_config.yml. This should only be done if turbulence is not + ! covered by another gridded component and/or the GC species are not made ! friendly to this component!! !======================================================================= IF ( DoTurb ) THEN if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do turbulence now' + ! Only do the following for the non-local PBL mixing + IF ( Input_Opt%LNLPBL ) THEN + + ! Once the initial met fields have been read in, we need to find + ! the maximum PBL level for the non-local mixing algorithm. + ! This only has to be done once. (bmy, 5/28/20) + IF ( FIRST ) THEN + CALL Max_PblHt_For_Vdiff( Input_Opt, State_Grid, State_Met, RC ) + ENDIF + + ! Compute the surface flux for the non-local mixing, + ! (which means getting emissions & drydep from HEMCO) + ! and store it in State_Chm%Surface_Flux + CALL Compute_Sflx_For_Vdiff( Input_Opt, State_Chm, State_Diag, & + State_Grid, State_Met, RC ) + ENDIF + ! Do mixing and apply tendencies. This will use the dynamic time step, ! which is fine since this call will be executed on every time step. - !CALL DO_MIXING ( Input_Opt, State_Chm, State_Diag, & - ! State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "DO_MIXING", 255 ) + CALL DO_MIXING ( Input_Opt, State_Chm, State_Diag, & + State_Grid, State_Met, RC ) if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Turbulence done!' ENDIF ! Set tropospheric CH4 concentrations and fill species array with ! current values. - IF ( Input_Opt%ITS_A_FULLCHEM_SIM & + IF ( Phase /= 2 .AND. Input_Opt%ITS_A_FULLCHEM_SIM & .AND. IND_('CH4','A') > 0 ) THEN CALL SET_CH4 ( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "SET_CH4", 255 ) + State_Grid, State_Met, RC ) ENDIF !======================================================================= @@ -1039,23 +1120,22 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & IF ( DoChem ) THEN if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do chemistry now' - ! Calculate TOMS O3 overhead. For now, always use it from the - ! Met field. State_Met%TO3 is imported from PCHEM (ckeller, 10/21/2014). - CALL COMPUTE_OVERHEAD_O3( Input_Opt, State_Grid, State_Chm, DAY, .TRUE., & - State_Met%TO3, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "COMPUTE_OVERHEAD_O3", 255 ) + IF ( Input_Opt%ITS_A_FULLCHEM_SIM ) THEN + ! Calculate TOMS O3 overhead. For now, always use it from the + ! Met field. State_Met%TO3 is imported from PCHEM (ckeller, 10/21/2014). + CALL COMPUTE_OVERHEAD_O3( Input_Opt, State_Grid, State_Chm, DAY, & + .TRUE., State_Met%TO3, RC ) + ENDIF ! Set H2O to species value if H2O is advected IF ( IND_('H2O','A') > 0 ) THEN - CALL SET_H2O_TRAC( (.not. Input_Opt%LUCX), Input_Opt, & - State_Chm, State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "SET_H2O_TRAC", 255 ) + CALL SET_H2O_TRAC( .FALSE., Input_Opt, & + State_Chm, State_Grid, State_Met, RC ) ENDIF ! Do chemistry CALL Do_Chemistry( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Do_Chemistry", 255 ) + State_Grid, State_Met, RC ) if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Chemistry done!' @@ -1070,11 +1150,9 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & ! Do wet deposition CALL DO_WETDEP( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Do_WetDep", 255 ) + State_Grid, State_Met, RC ) if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Wetdep done!' - ENDIF !======================================================================= @@ -1090,23 +1168,27 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & ! (skim, 02/05/11) IF ( DoChem ) THEN CALL RECOMPUTE_OD ( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "RECOMPUTE_OD", 255 ) + State_Grid, State_Met, RC ) ENDIF +!#if defined( RRTMG ) +! TODO: Add in later +!#endif + if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do diagnostics now' ! Set certain diagnostics dependent on state at end of step. This ! includes species concentration and dry deposition flux. + ! For GEOS, this is now done in Chem_GridCompMod.F90. This makes sure + ! that the diagnostics include any post-run updates (e.g., if assimilation + ! increments are being applied (ckeller, 2/7/22). CALL Set_Diagnostics_EndofTimestep( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Set_Diagnostics_EndofTimestep", 255 ) + State_Grid, State_Met, RC ) ! Archive aerosol mass and PM2.5 diagnostics IF ( State_Diag%Archive_AerMass ) THEN CALL Set_AerMass_Diagnostic( Input_Opt, State_Chm, State_Diag, & - State_Grid, State_Met, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Set_AerMass_Diagnostic", 255 ) + State_Grid, State_Met, RC ) ENDIF if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Diagnostics done!' @@ -1114,43 +1196,20 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & !======================================================================= ! Convert State_Chm%Species units !======================================================================= - CALL Convert_Spc_Units ( Input_Opt, State_Chm, State_Grid, State_Met, & - OrigUnit, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Convert_Spc_Units @ end of CHEM_CHUNK_RUN", 255 ) - - if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Unit conversion done!' - - !======================================================================= - ! Accumulate diagnostics - !======================================================================= - - !IF ( .not. FIRST ) THEN - call getDomainBounds( grid, I_STRT = I_0, I_STOP = I_1, J_STRT = J_0, J_STOP = J_1 ) - DO N=1,NTM - !IF ( ijlt_vmr(N) == 0 ) CALL STOP_MODEL( "Error with ijlt_vmr(N)", 255 ) - DO L=1,LM - DO J=J_0,J_1 - DO I=I_0,I_1 - II = I - I_0 + 1 - JJ = J - J_0 + 1 - ! Archive volumetric mixing ratio in ppbv - gcaijl_out( I, J, L, N ) = gcaijl_out( I, J, L, N ) + & - State_Chm%Species(II,JJ,L,N) * 1d9 - !IF ( N .eq. 1 .and. I .eq. 1 .and. L .eq. 1 ) WRITE(6,*) 'LTM:', n, i, j, l, gcaijl_out(i,j,l,n) - ENDDO - ENDDO - ENDDO - ENDDO - !ENDIF - - if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Diagnostic accumulation done!' + CALL Convert_Spc_Units( & + Input_Opt = Input_Opt, & + State_Chm = State_Chm, & + State_Grid = State_Grid, & + State_Met = State_Met, & + outUnit = origUnit, & + RC = RC ) !======================================================================= ! Clean up !======================================================================= ! testing only - IF ( NCALLS < 10 ) NCALLS = NCALLS + 1 + IF ( PHASE /= 1 .AND. NCALLS < 10 ) NCALLS = NCALLS + 1 ! First call is done FIRST = .FALSE. @@ -1158,6 +1217,244 @@ SUBROUTINE CHEM_CHUNK_RUN( nymd, nhms, year, month, & ! Return success RC = GC_SUCCESS +! TODO: Uncomment or drop the following code +! +! !CALL FLUSH(6) +! +! !======================================================================= +! ! EMISSIONS. Pass HEMCO Phase 1 which only updates the HEMCO clock +! ! and the HEMCO data list. Should be called every time to make sure +! ! that the HEMCO clock and the HEMCO data list are up to date. +! !======================================================================= +! HCO_PHASE = 1 +! CALL EMISSIONS_RUN( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, DoEmis, HCO_PHASE, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "EMISSIONS_RUN - Phase 1", 255 ) +! +! !======================================================================= +! ! 1. Convection +! ! +! ! Call GEOS-Chem internal convection routines if convection is enabled +! ! in input.geos. This should only be done if convection is not covered +! ! by another gridded component and/or the GC species are not made +! ! friendly to this component!! +! !======================================================================= +! IF ( DoConv ) THEN +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do convection now' +! +! CALL DO_CONVECTION ( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "DO_CONVECTION", 255 ) +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Convection done!' +! ENDIF +! +! !======================================================================= +! ! 2. Dry deposition +! ! +! ! Calculates the deposition rates in [s-1]. +! !======================================================================= +! IF ( DoDryDep ) THEN +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) THEN +! write(*,*) ' --- Do drydep now' +! write(*,*) ' Use FULL PBL: ', Input_Opt%PBL_DRYDEP +! endif +! +! ! Do dry deposition +! CALL Do_DryDep ( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "DO_DryDep", 255 ) +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Drydep done!' +! +! ENDIF +! +! !======================================================================= +! ! 3. Emissions (HEMCO) +! ! +! ! HEMCO must be called on first time step to make sure that the HEMCO +! ! data lists are all properly set up. +! !======================================================================= +! IF ( DoEmis ) THEN +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do emissions now' +! +! ! Do emissions. Pass HEMCO Phase 2 which performs the emissions +! ! calculations. Note that this does not apply the emissions. +! HCO_PHASE = 2 +! CALL EMISSIONS_RUN( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, DoEmis, HCO_PHASE, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "EMISSIONS_RUN - Phase 2", 255 ) +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Emissions done!' +! +! ENDIF +! +! !======================================================================= +! ! If physics covers turbulence, simply add the emission and dry +! ! deposition fluxes calculated above to the tracer array, without caring +! ! about the vertical distribution. The tracer tendencies are only added +! ! to the tracers array after emissions, drydep. So we need to use the +! ! emissions time step here. +! !======================================================================= +! ! Not implemented +! +! !======================================================================= +! ! 4. Turbulence +! ! +! ! Call GEOS-Chem internal turbulence routines if turbulence is enabled +! ! in input.geos. This should only be done if turbulence is not covered +! ! by another gridded component and/or the GC species are not made +! ! friendly to this component!! +! !======================================================================= +! IF ( DoTurb ) THEN +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do turbulence now' +! +! ! Do mixing and apply tendencies. This will use the dynamic time step, +! ! which is fine since this call will be executed on every time step. +! !CALL DO_MIXING ( Input_Opt, State_Chm, State_Diag, & +! ! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "DO_MIXING", 255 ) +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Turbulence done!' +! ENDIF +! +! ! Set tropospheric CH4 concentrations and fill species array with +! ! current values. +! IF ( Input_Opt%ITS_A_FULLCHEM_SIM & +! .AND. IND_('CH4','A') > 0 ) THEN +! CALL SET_CH4 ( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "SET_CH4", 255 ) +! ENDIF +! +! !======================================================================= +! ! 5. Chemistry +! !======================================================================= +! IF ( DoChem ) THEN +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do chemistry now' +! +! ! Calculate TOMS O3 overhead. For now, always use it from the +! ! Met field. State_Met%TO3 is imported from PCHEM (ckeller, 10/21/2014). +! CALL COMPUTE_OVERHEAD_O3( Input_Opt, State_Grid, State_Chm, DAY, .TRUE., & +! State_Met%TO3 ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "COMPUTE_OVERHEAD_O3", 255 ) +! +! ! LTM: Check this +! ! ! Set H2O to species value if H2O is advected +! !IF ( IND_('H2O','A') > 0 ) THEN +! ! CALL SET_H2O_TRAC( (.not. Input_Opt%LUCX), Input_Opt, & +! ! State_Chm, State_Grid, State_Met, RC ) +! ! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "SET_H2O_TRAC", 255 ) +! !ENDIF +! +! ! Do chemistry +! CALL Do_Chemistry( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Do_Chemistry", 255 ) +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Chemistry done!' +! +! ENDIF +! +! !======================================================================= +! ! 6. Wet deposition +! !======================================================================= +! IF ( DoWetDep ) THEN +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do wetdep now' +! +! ! Do wet deposition +! CALL DO_WETDEP( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Do_WetDep", 255 ) +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Wetdep done!' +! +! ENDIF +! +! !======================================================================= +! ! Diagnostics +! !======================================================================= +! +! !============================================================== +! ! ***** U P D A T E O P T I C A L D E P T H ***** +! !============================================================== +! ! Recalculate the optical depth at the wavelength(s) specified +! ! in the Radiation Menu. This must be done before the call to any +! ! diagnostic and only on a chemistry timestep. +! ! (skim, 02/05/11) +! IF ( DoChem ) THEN +! CALL RECOMPUTE_OD ( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "RECOMPUTE_OD", 255 ) +! ENDIF +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Do diagnostics now' +! +! ! Set certain diagnostics dependent on state at end of step. This +! ! includes species concentration and dry deposition flux. +! CALL Set_Diagnostics_EndofTimestep( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Set_Diagnostics_EndofTimestep", 255 ) +! +! ! Archive aerosol mass and PM2.5 diagnostics +! IF ( State_Diag%Archive_AerMass ) THEN +! CALL Set_AerMass_Diagnostic( Input_Opt, State_Chm, State_Diag, & +! State_Grid, State_Met, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Set_AerMass_Diagnostic", 255 ) +! ENDIF +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Diagnostics done!' +! +! !======================================================================= +! ! Convert State_Chm%Species units +! !======================================================================= +! CALL Convert_Spc_Units ( Input_Opt, State_Chm, State_Grid, State_Met, & +! OrigUnit, RC ) +! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Convert_Spc_Units @ end of CHEM_CHUNK_RUN", 255 ) +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Unit conversion done!' +! +! !======================================================================= +! ! Accumulate diagnostics +! !======================================================================= +! +! !IF ( .not. FIRST ) THEN +! call getDomainBounds( grid, I_STRT = I_0, I_STOP = I_1, J_STRT = J_0, J_STOP = J_1 ) +! DO N=1,NTM +! !IF ( ijlt_vmr(N) == 0 ) CALL STOP_MODEL( "Error with ijlt_vmr(N)", 255 ) +! DO L=1,LM +! DO J=J_0,J_1 +! DO I=I_0,I_1 +! II = I - I_0 + 1 +! JJ = J - J_0 + 1 +! ! Archive volumetric mixing ratio in ppbv +! gcaijl_out( I, J, L, N ) = gcaijl_out( I, J, L, N ) + & +! State_Chm%Species(II,JJ,L,N) * 1d9 +! !IF ( N .eq. 1 .and. I .eq. 1 .and. L .eq. 1 ) WRITE(6,*) 'LTM:', n, i, j, l, gcaijl_out(i,j,l,n) +! ENDDO +! ENDDO +! ENDDO +! ENDDO +! !ENDIF +! +! if(Input_Opt%AmIRoot.and.NCALLS<10) write(*,*) ' --- Diagnostic accumulation done!' +! +! !======================================================================= +! ! Clean up +! !======================================================================= +! +! ! testing only +! IF ( NCALLS < 10 ) NCALLS = NCALLS + 1 +! +! ! First call is done +! FIRST = .FALSE. +! +! ! Return success +! RC = GC_SUCCESS + END SUBROUTINE CHEM_CHUNK_RUN !========================================================================================================== @@ -1178,11 +1475,12 @@ SUBROUTINE INIT_CHEM( grid ) USE Input_Mod, ONLY : Read_Input_File USE Time_Mod, ONLY : Set_Timesteps - USE Chemistry_Mod, ONLY : Init_Chemistry + ! TODO-LTM: Check + ! USE Chemistry_Mod, ONLY : Init_Chemistry USE Emissions_Mod, ONLY : Emissions_Init USE GC_Environment_Mod USE GC_Grid_Mod, ONLY : SetGridFromCtr - USE PBL_Mix_Mod, ONLY : Init_PBL_Mix + ! USE PBL_Mix_Mod, ONLY : Init_PBL_Mix USE Pressure_Mod, ONLY : Init_Pressure, Accept_External_ApBp USE UCX_MOD, ONLY : Init_UCX USE UnitConv_Mod, ONLY : Convert_Spc_Units @@ -1201,7 +1499,8 @@ SUBROUTINE INIT_CHEM( grid ) REAL*8 :: DT INTEGER :: I, J, L, N, NN, II, JJ, I_0H, I_1H - INTEGER :: NYMDb, NHMSb, NYMDe, NHMSe, NSP, PLC + INTEGER :: NYMDb, NHMSb, NYMDe, NHMSe + INTEGER :: NSP ! Fill Input_Opt with input.geos WRITE(6,*) "Calling Set_Input_Opt" @@ -1230,7 +1529,7 @@ SUBROUTINE INIT_CHEM( grid ) CALL sync_param( "DoGCDryDep", DoGCDryDep ) CALL sync_param( "DoGCWetDep", DoGCWetDep ) - ! LTM: Debug Overrides + ! TODO-LTM: Debug Overrides !DoGCConv = .true. ! Works !DoGCEmis = .true. ! Works (make sure 3-D emissions on correct vert grid) !DoGCTend = .false. @@ -1251,17 +1550,12 @@ SUBROUTINE INIT_CHEM( grid ) NI = I_1 - I_0 + 1 NJ = J_1 - J_0 + 1 - !WRITE(6,*) i_0, i_1, NI - !WRITE(6,*) j_0, j_1, NJ - !WRITE(6,*) SHAPE(lon2d_dg) - !CALL FLUSH(6) - State_Grid%DX = 2.5e+0_fp State_Grid%DY = 2.0e+0_fp - State_Grid%XMin = lon2d_dg(i_0,j_0) - State_Grid%XMax = lon2d_dg(i_1,j_0) - State_Grid%YMin = max( lat2d_dg(i_0,j_0), -89.0_fp ) - State_Grid%YMax = min( lat2d_dg(i_0,j_1), 89.0_fp ) + State_Grid%XMin = lon2d_dg(i_0,1) + State_Grid%XMax = lon2d_dg(i_1,1) + State_Grid%YMin = max( lat2d_dg(1,j_0), -89.0_fp ) + State_Grid%YMax = min( lat2d_dg(1,j_1), 89.0_fp ) State_Grid%NX = NI State_Grid%NY = NJ @@ -1479,8 +1773,8 @@ SUBROUTINE INIT_CHEM( grid ) ! Initialize State_Met, State_Chm, and State_Diag objects WRITE(6,*) "Calling GC_Init_StateObj" - CALL GC_Init_StateObj( Diag_List, Input_Opt, State_Chm, & - State_Diag, State_Grid, State_Met, RC ) + CALL GC_Init_StateObj( Diag_List, TaggedDiag_List, Input_Opt, & + State_Chm, State_Diag, State_Grid, State_Met, RC ) CALL sync_param( "DTsrc", DTsrc ) CALL sync_param( "DT", DT ) @@ -1492,9 +1786,9 @@ SUBROUTINE INIT_CHEM( grid ) Input_Opt%TS_DIAG = INT( DTsrc ) ! Set start and finish time from rundeck - Input_Opt%NYMDb = 20160701 ! nymdB + Input_Opt%NYMDb = 20141201 ! nymdB Input_Opt%NHMSb = 000000 ! nhmsB - Input_Opt%NYMDe = 20160801 ! nymdE + Input_Opt%NYMDe = 20141202 ! nymdE Input_Opt%NHMSe = 000000 ! nhmsE ! Set GEOS-Chem timesteps on all CPUs @@ -1523,29 +1817,32 @@ SUBROUTINE INIT_CHEM( grid ) CALL Accept_External_ApBp( State_Grid, Ap, Bp, RC ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Accept_External_ApBp", 255 ) - ! Initialize the PBL mixing module - CALL INIT_PBL_MIX( Input_Opt, State_Grid, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Init_PBL_Mix", 255 ) + ! TODO-LTM: Check + ! ! Initialize the PBL mixing module + ! CALL INIT_PBL_MIX( Input_Opt, State_Grid, RC ) + ! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Init_PBL_Mix", 255 ) - ! Initialize chemistry mechanism - IF ( Input_Opt%ITS_A_FULLCHEM_SIM .OR. Input_Opt%ITS_AN_AEROSOL_SIM ) THEN - CALL INIT_CHEMISTRY ( Input_Opt, State_Chm, State_Diag, & - State_Grid, RC ) - IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Init_Chemistry", 255 ) - ENDIF + ! LTM: Check + ! ! Initialize chemistry mechanism + ! IF ( Input_Opt%ITS_A_FULLCHEM_SIM .OR. Input_Opt%ITS_AN_AEROSOL_SIM ) THEN + ! CALL INIT_CHEMISTRY ( Input_Opt, State_Chm, State_Diag, & + ! State_Grid, RC ) + ! IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Init_Chemistry", 255 ) + ! ENDIF ! Initialize HEMCO CALL EMISSIONS_INIT( Input_Opt, State_Chm, State_Grid, State_Met, RC, & HcoConfig=HcoConfig ) IF ( RC /= GC_SUCCESS ) CALL STOP_MODEL( "Emissions_Init", 255 ) - ! Stratosphere - can't be initialized without HEMCO because of STATE_PSC - IF ( Input_Opt%LUCX ) THEN + ! TODO-LTM: Check + ! ! Stratosphere - can't be initialized without HEMCO because of STATE_PSC + ! IF ( Input_Opt%LUCX ) THEN ! Initialize stratospheric routines CALL INIT_UCX( Input_Opt, State_Chm, State_Diag, State_Grid ) - ENDIF + ! ENDIF NSP = State_Chm%nSpecies NTM = State_Chm%nAdvect + 1 @@ -1562,46 +1859,13 @@ SUBROUTINE INIT_CHEM( grid ) IF ( State_Chm%SpcData(N)%Info%Is_Advected .or. & TRIM( State_Chm%SpcData(N)%Info%Name ) .eq. "OH" ) THEN - TrName(NN) = TRIM( State_Chm%SpcData(N)%Info%Name ) - TrFullName(NN) = TRIM( State_Chm%SpcData(N)%Info%FullName ) // " (" // & - TRIM( State_Chm%SpcData(N)%Info%Formula ) // ")" - IsAdvected(NN) = State_Chm%SpcData(N)%Info%Is_Advected - SELECT CASE ( TrName(NN) ) - CASE('H2O') - i_H2O = N - CASE('CO2') - i_CO2 = N - CASE('O3') - i_O3 = N - CASE('O2') - i_O2 = N - CASE('NO2') - i_NO2 = N - CASE('N2O') - i_N2O = N - CASE('CH4') - i_CH4 = N - CASE('CFC11') - i_CFC11 = N - CASE('CFC12') - i_CFC12 = N - CASE('N2') - i_N2 = N - CASE('CFCY') - i_CFCY = N - CASE('CFCZ') - i_CFCZ = N - CASE('SO2') - i_SO2 = N - CASE DEFAULT - plc = 0 - END SELECT - + TrName(NN) = TRIM( State_Chm%SpcData(N)%Info%Name ) + TrFullName(NN) = TRIM( State_Chm%SpcData(N)%Info%FullName ) // " (" // & + TRIM( State_Chm%SpcData(N)%Info%Formula ) // ")" + IsAdvected(NN) = State_Chm%SpcData(N)%Info%Is_Advected IF ( Am_I_Root() ) WRITE(6,*) NN, N, TrName(NN) - NN = NN + 1 - - ENDIF + ENDIF ENDDO t_qlimit(:) = .true. TrM = 0d0 diff --git a/model/CLOUDS2_DRV.F90 b/model/CLOUDS2_DRV.F90 index 95cc22a..c6469d5 100644 --- a/model/CLOUDS2_DRV.F90 +++ b/model/CLOUDS2_DRV.F90 @@ -215,6 +215,8 @@ subroutine CONDSE use CLOUDS, only : mc_up_mf, mc_dd_mf, mc_up_ent, mc_dd_ent, mc_up_det, mc_dd_det use CLOUDS, only : mc_dqcond, mc_dqevap, ls_dqcond, ls_dqevap use CLOUDS, only : mc_pflx_l, mc_pflx_i, ls_pflx_l, ls_pflx_i + use CLOUDS_COM, only : pficu, pflcu, pfilsan, pfllsan + use CLOUDS_COM, only : dtrain, dqrcu, dqrlsan, reevapcn, reevapls, cmfmc #endif use PBLCOM, only : dclev,egcm,w2gcm,pblht,pblptop use ATM_COM, only : pk,pek,pmid,pedn,gz,PMIDOLD,pdsig,MWs, & diff --git a/model/Makefile b/model/Makefile index 877a602..b0b6588 100644 --- a/model/Makefile +++ b/model/Makefile @@ -97,8 +97,12 @@ do_main $(RUN).bin: main.o $(OBJS) # $(COMPONENTS:=_dir) ar rcs libmodel.a $(OBJS) @echo "===> linking" ifeq ($(GC),YES) - $(F90) main.o $(LFLAGS) $(EXTRA_LFLAGS) $(OBJS) $(F90OBJS) $(ESMF_OBJS) \ - $(COMPLIBS) $(LIBS) -L./geos-chem/src/lib -lGeosCore -lIsorropia -lObsPack -lHistory -lHCOI -lHCOX -lHCO -lGeosUtil -lHeaders -lKpp -lNcUtils -lnetcdff -lnetcdf -o $(RUN).bin $(LINK_OUTPUT) + $(F90) -I./mod main.o $(LFLAGS) $(EXTRA_LFLAGS) $(OBJS) $(F90OBJS) $(ESMF_OBJS) \ + $(COMPLIBS) $(LIBS) \ + -L./geos-chem/lib -lGeosCore -lObsPack -lHistory -lIsorropia -lKPP -lGeosUtil \ + -lNcdfUtil -lJulDay -lHeaders -lKPP_FirstPass -lCloudJ_Core -lHCOI_Shared \ + -lHCOX -lHCO -lGeosUtilHco -lNcdfUtilHco -lJulDayHco -lHeadersHco \ + -o $(RUN).bin $(LINK_OUTPUT) else $(F90) main.o $(LFLAGS) $(EXTRA_LFLAGS) $(OBJS) $(F90OBJS) $(ESMF_OBJS) \ $(COMPLIBS) $(LIBS) -o $(RUN).bin $(LINK_OUTPUT) diff --git a/model/SUBDD.f b/model/SUBDD.f index 0f5458d..5dadb52 100644 --- a/model/SUBDD.f +++ b/model/SUBDD.f @@ -1773,6 +1773,13 @@ subroutine parse_subdd input_sizes3(k) = lm call tijph_defs(diaglists(1,k),nmax_possible,diaglens(k)) #endif +#ifdef TRACERS_GC + k = k + 1 + catshapes(k) = 'aijlh'; categories(k) = 'taijlh' + input_sizes3(k) = lm + call tijlh_defs(diaglists(1,k),nmax_possible,diaglens(k)) +#endif + #ifdef TRACERS_GC k = k + 1 diff --git a/model/geos-chem/CMakeLists.txt b/model/geos-chem/CMakeLists.txt new file mode 100644 index 0000000..567f38b --- /dev/null +++ b/model/geos-chem/CMakeLists.txt @@ -0,0 +1,357 @@ +# GCClassic high-level CMakeLists.txt + +cmake_minimum_required (VERSION 3.13) +project (geos-chem-classic + VERSION 14.3.1 + LANGUAGES Fortran +) + +#----------------------------------------------------------------------------- +# Set CMake policies. For more information, see: +# +# https://cmake.org/cmake/help/latest/policy/CMP0054.html +# https://cmake.org/cmake/help/latest/policy/CMP0057.html +# https://cmake.org/cmake/help/latest/policy/CMP0074.html +# https://cmake.org/cmake/help/latest/policy/CMP0079.html +#----------------------------------------------------------------------------- +cmake_policy(SET CMP0054 NEW) +cmake_policy(SET CMP0057 NEW) +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +endif() +if(POLICY CMP0079) + cmake_policy(SET CMP0079 NEW) +endif() + +#----------------------------------------------------------------------------- +# Add CMakeScripts/ to the module path and import helper functions +#----------------------------------------------------------------------------- +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/CMakeScripts) +include(GC-Helpers) + +#----------------------------------------------------------------------------- +# Print header with the CMake project version and the GC repo version +#----------------------------------------------------------------------------- +get_repo_version(GC_REPO_VERSION ${CMAKE_CURRENT_SOURCE_DIR}) +message("=================================================================") +message("GCClassic ${PROJECT_VERSION} (superproject wrapper)") +message("Current status: ${GC_REPO_VERSION}") +message("=================================================================") + +#----------------------------------------------------------------------------- +# Declare the GEOSChemBuildProperties +# +# All GEOS-Chem targets depend on this. This is used to control +# the compiler options and definitions for GEOS-Chem targets +# (via inheritance). +#----------------------------------------------------------------------------- +add_library(GEOSChemBuildProperties INTERFACE) + +set(GEOSChem_DETECTED_FORTRAN_COMPILER_ID ${CMAKE_Fortran_COMPILER_ID} + CACHE INTERNAL "Logging the COMPILER_ID to CMakeCache.txt" +) +set(GEOSChem_DETECTED_FORTRAN_COMPILER_VERSION ${CMAKE_Fortran_COMPILER_VERSION} + CACHE INTERNAL "Logging the compiler version to CMakeCache.txt" +) + +set(GEOSChem_Fortran_FLAGS_Intel + -cpp -w -auto -noalign "SHELL:-convert big_endian" "SHELL:-fp-model source" + -mcmodel=medium -shared-intel -traceback -DLINUX_IFORT + CACHE STRING "GEOSChem compiler flags for all build types with Intel compilers" +) +set(GEOSChem_Fortran_FLAGS_RELEASE_Intel + -O2 + CACHE STRING "GEOSChem compiler flags for build type Release with Intel compilers" +) +set(GEOSChem_Fortran_FLAGS_RELWITHDEBINFO_Intel + -O2 + CACHE STRING "GEOSChem compiler flags for build type RelWithdDebInfo with Intel compilers" +) +set(GEOSChem_Fortran_FLAGS_DEBUG_Intel + -g -O0 "SHELL:-check arg_temp_created" "SHELL:-debug all" -fpe0 -ftrapuv -check,bounds + CACHE STRING "GEOSChem compiler flags for build type Debug with Intel compilers" +) + +set(GEOSChem_Fortran_FLAGS_GNU + -cpp -w -std=legacy -fautomatic -fno-align-commons + -fconvert=big-endian -fno-range-check -mcmodel=medium + -fbacktrace -g -DLINUX_GFORTRAN -ffree-line-length-none + CACHE STRING "GEOSChem compiler flags for all build types with GNU compilers" +) +set(GEOSChem_Fortran_FLAGS_RELEASE_GNU + -O3 -funroll-loops + CACHE STRING "GEOSChem compiler flags for build type Release with GNU compilers" +) +set(GEOSChem_Fortran_FLAGS_RELWITHDEBINFO_GNU + -O3 -funroll-loops + CACHE STRING "GEOSChem compiler flags for build type RelWithDebInfo with GNU compilers" +) +set(GEOSChem_Fortran_FLAGS_DEBUG_GNU + -g -O0 -Wall -Wextra -Wconversion -Warray-temporaries + -fcheck=array-temps -ffpe-trap=invalid,zero,overflow -finit-real=snan + -fcheck=bounds -fcheck=pointer + CACHE STRING "GEOSChem compiler flags for build type Debug with GNU compilers" +) + +set(GEOSChem_SUPPORTED_COMPILER_IDS "Intel" "GNU") +if(NOT CMAKE_Fortran_COMPILER_ID IN_LIST GEOSChem_SUPPORTED_COMPILER_IDS) + message(FATAL_ERROR "GEOSChem does not support ${CMAKE_Fortran_COMPILER_ID} compilers") +endif() + +#--------------------------------------------------------------------- +# Assign comiler options to build properties +#--------------------------------------------------------------------- +target_compile_options(GEOSChemBuildProperties + INTERFACE + $<$: + ${GEOSChem_Fortran_FLAGS_Intel} + $<$:${GEOSChem_Fortran_FLAGS_DEBUG_Intel}> + $<$:${GEOSChem_Fortran_FLAGS_RELWITHDEBINFO_Intel}> + $<$:${GEOSChem_Fortran_FLAGS_RELEASE_Intel}> + > + $<$: + ${GEOSChem_Fortran_FLAGS_GNU} + $<$:${GEOSChem_Fortran_FLAGS_DEBUG_GNU}> + $<$:${GEOSChem_Fortran_FLAGS_RELWITHDEBINFO_GNU}> + $<$:${GEOSChem_Fortran_FLAGS_RELEASE_GNU}> + > +) + +#----------------------------------------------------------------------------- +# Put all of GEOS-Chem's mod files in build subdir called mod +#----------------------------------------------------------------------------- +set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mod) +target_include_directories(GEOSChemBuildProperties + INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/mod +) + +#----------------------------------------------------------------------------- +# Find nc-config and nf-config and add to CMAKE_PREFIX_PATH +#----------------------------------------------------------------------------- +find_program(NC_CONFIG NAMES "nc-config" DOC "Location of nc-config utility") +find_program(NF_CONFIG NAMES "nf-config" DOC "Location of nf-config utility") + +# A function to call nx-config with an argument, and append the resulting +# path to a list +function(inspect_netcdf_config VAR NX_CONFIG ARG) + execute_process( + COMMAND ${NX_CONFIG} ${ARG} + OUTPUT_VARIABLE NX_CONFIG_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(EXISTS "${NX_CONFIG_OUTPUT}") + list(APPEND ${VAR} ${NX_CONFIG_OUTPUT}) + set(${VAR} ${${VAR}} PARENT_SCOPE) + endif() +endfunction() + +inspect_netcdf_config(CMAKE_PREFIX_PATH "${NC_CONFIG}" "--prefix") +inspect_netcdf_config(CMAKE_PREFIX_PATH "${NF_CONFIG}" "--prefix") + +#----------------------------------------------------------------------------- +# Append GEOS-Chem's environment variables to CMAKE_PREFIX_PATH +#----------------------------------------------------------------------------- +list(APPEND CMAKE_PREFIX_PATH + # Possible NetCDF environment variables + $ENV{NetCDF_F_ROOT} $ENV{NetCDF_C_ROOT} $ENV{NetCDF_ROOT} + $ENV{NETCDF_F_ROOT} $ENV{NETCDF_C_ROOT} $ENV{NETCDF_ROOT} + $ENV{NetCDF_Fortran_ROOT} + $ENV{NETCDF_FORTRAN_ROOT} + + # Possible GEOS-Chem's environmnet variables + $ENV{GC_F_BIN} $ENV{GC_BIN} + $ENV{GC_F_INCLUDE} $ENV{GC_INCLUDE} + $ENV{GC_F_LIB} $ENV{GC_LIB} +) + +#----------------------------------------------------------------------------- +# Link NetCDF-F to GEOSChemBuildProperties +#----------------------------------------------------------------------------- +find_package(NetCDF REQUIRED) +target_include_directories(GEOSChemBuildProperties INTERFACE + ${NETCDF_INCLUDE_DIRS} +) +# Not sure if HCOI should be here... +target_link_libraries(GEOSChemBuildProperties INTERFACE + ${NETCDF_LIBRARIES} +) + +#----------------------------------------------------------------------------- +# Use the NC_HAS_COMPRESSION def if nf_def_var_deflate is in netcdf.inc +#----------------------------------------------------------------------------- +if(EXISTS ${NETCDF_F77_INCLUDE_DIR}/netcdf.inc) + file(READ ${NETCDF_F77_INCLUDE_DIR}/netcdf.inc NCINC) + if("${NCINC}" MATCHES ".*nf_def_var_deflate.*") + target_compile_definitions(GEOSChemBuildProperties + INTERFACE "NC_HAS_COMPRESSION" + ) + endif() +endif() + +#----------------------------------------------------------------------------- +# For GEOS-Chem Classic only +#----------------------------------------------------------------------------- +if(NOT GC_EXTERNAL_CONFIG) + + # This conditional block configures the GEOS-Chem build + # for GEOS-Chem Classic. As mentioned above, it sets + # GCCLASSIC_EXE_TARGETS, RRTMG, GTMM, TOMAS, MECH, and + # GCHP, and it configures the GEOSChemBuildProperties. + + # Set CMAKE_BUILD_TYPE to Release by default + if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" + CACHE STRING + "Set the build type" + FORCE + ) + endif() + + # Display CMAKE_PREFIX_PATH and CMAKE_BUILD_TYPE + gc_pretty_print(SECTION "Useful CMake variables") + gc_pretty_print(VARIABLE CMAKE_PREFIX_PATH) + gc_pretty_print(VARIABLE CMAKE_BUILD_TYPE) + + # Get the run directory + gc_pretty_print(SECTION "Run directory setup") + + # Run directory + set(RUNDIR "" CACHE PATH "Path(s) to run directory (semicolon separated list). Specifies install locations for gchp") + set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Fake CMAKE_INSTALL_PREFIX (use RUNDIR instead)" FORCE) + set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE) + gc_pretty_print(VARIABLE RUNDIR) + + # Configure for GCClassic + include(GC-ConfigureClassic) + configureGCClassic() + +endif() + +#----------------------------------------------------------------------------- +# Set high-level logicals for using this repository +#----------------------------------------------------------------------------- +set(GCCLASSIC_WRAPPER TRUE) +set(GC_EXTERNAL_CONFIG FALSE) +set(HEMCO_EXTERNAL_CONFIG TRUE) +set(CLOUDJ_EXTERNAL_CONFIG TRUE) + +#----------------------------------------------------------------------------- +# Add the directory with source code +#----------------------------------------------------------------------------- +add_subdirectory(src) + +#----------------------------------------------------------------------------- +# Write GEOSChemBuildProperties's configuration to a file +#----------------------------------------------------------------------------- +get_target_property(BT_DEFINITIONS GEOSChemBuildProperties + INTERFACE_COMPILE_DEFINITIONS +) +get_target_property(BT_OPTIONS GEOSChemBuildProperties + INTERFACE_COMPILE_OPTIONS +) +get_target_property(BT_LIBRARIES GEOSChemBuildProperties + INTERFACE_LINK_LIBRARIES +) +get_target_property(BT_INCLUDES GEOSChemBuildProperties + INTERFACE_INCLUDE_DIRECTORIES +) +file(WRITE ${CMAKE_BINARY_DIR}/GEOSChemBuildProperties.txt + "# This file shows the GEOSChemBuildProperties's configuration.\n" + "\n" + "GEOSChemBuildProperties::INTERFACE_COMPILE_DEFINITIONS:${BT_DEFINITIONS}\n" + "GEOSChemBuildProperties::INTERFACE_COMPILE_OPTIONS:${BT_OPTIONS}\n" + "GEOSChemBuildProperties::INTERFACE_LINK_LIBRARIES:${BT_LIBRARIES}\n" + "GEOSChemBuildProperties::INTERFACE_INCLUDE_DIRECTORIES:${BT_INCLUDES}\n" +) + +#----------------------------------------------------------------------------- +# Try to compile a simple program that uses NetCDF-Fortran and OpenMP +#----------------------------------------------------------------------------- +if(NOT GC_EXTERNAL_CONFIG AND NOT GC_TRY_RUN_PASSED) + + # Try to compile and run try_compile.F90 + try_run(RUN_FAILED COMPILED_OK + ${CMAKE_CURRENT_BINARY_DIR}/try_compile # binary dir + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeScripts/try_compile.F90 # test src file + LINK_LIBRARIES ${BT_LIBRARIES} + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${BT_INCLUDES}" # include dirs + COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT + RUN_OUTPUT_VARIABLE RUN_OUTPUT + ) + + # Display a warning if its compilation failed + if(NOT COMPILED_OK) + if(OMP) + set(CONDITIONAL_AND_OMP " and OpenMP") + endif() + message(WARNING + "Failed to compile a simple program that uses " + "NetCDF-Fortran ${CONDITIONAL_AND_OMP}! Could " + "your NetCDF installation be broken?\nSee " + "\"FailedCompile.txt\" for more info." + ) + file(WRITE ${CMAKE_BINARY_DIR}/FailedCompile.txt + "${COMPILE_OUTPUT}" + ) + else() + file(REMOVE ${CMAKE_BINARY_DIR}/FailedCompile.txt) + endif() + + # Display a warning if its execution failed + if(RUN_FAILED) + if(OMP) + set(CONDITIONAL_AND_OMP "and OpenMP ") + endif() + message(WARNING + "A simple program that uses NetCDF-Fortran " + "${CONDITIONAL_AND_OMP}compiled successfully, " + "but its execution failed!\n\nSee " + "\"FailedExecution.txt\" for more info." + ) + file(WRITE ${CMAKE_BINARY_DIR}/FailedEasyRun.txt + "${COMPILE_OUTPUTS}\n${RUN_OUTPUT}" + ) + else() + file(REMOVE ${CMAKE_BINARY_DIR}/FailedEasyRun.txt + ${CMAKE_BINARY_DIR}/simple_xy.nc + ) + set(GC_TRY_RUN_PASSED TRUE CACHE INTERNAL + "try_run passed" FORCE + ) + endif() +endif() + +#----------------------------------------------------------------------------- +# Copy build information files to each RUNDIR and INSTALLCOPY directory +#---------------------------------------------------------------------------- +set(COMBINED_INSTALL_DIRS "") +list(APPEND COMBINED_INSTALL_DIRS ${RUNDIR}) +list(APPEND COMBINED_INSTALL_DIRS ${INSTALLCOPY}) + +# Install to run directories +foreach(INSTALL_PATH ${COMBINED_INSTALL_DIRS}) + if(INSTALL_PATH IN_LIST RUNDIR) + set(CHECK_IS_RUNDIR TRUE) + else() + set(CHECK_IS_RUNDIR FALSE) + endif() + + # Convert INSTALL_PATH to absolute + if(NOT IS_ABSOLUTE "${INSTALL_PATH}") + get_filename_component(INSTALL_PATH "${INSTALL_PATH}" ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}") + endif() + # Issue warning and skip if geoschem_config.yml doesn't exist + # (i.e. if it doens't look like a run directory) + if(CHECK_IS_RUNDIR AND (NOT EXISTS ${INSTALL_PATH}/geoschem_config.yml)) + message(WARNING + "RUNDIR path \"${INSTALL_PATH}\" " + "doesn't have geoschem_config.yml. Is it a run directory? If it " + "isn't, and you still want to install to it, you should " + "use INSTALLCOPY rather than RUNDIR.\nSkipping installing to " + "${INSTALL_PATH}" + ) + else() + install(FILES ${CMAKE_BINARY_DIR}/CMakeCache.txt DESTINATION ${INSTALL_PATH}/build_info) + install(PROGRAMS ${CMAKE_SOURCE_DIR}/CMakeScripts/summarize_build DESTINATION ${INSTALL_PATH}/build_info) + endif() +endforeach() diff --git a/model/geos-chem/CMakeScripts/FindNetCDF.cmake b/model/geos-chem/CMakeScripts/FindNetCDF.cmake new file mode 100755 index 0000000..7db8b54 --- /dev/null +++ b/model/geos-chem/CMakeScripts/FindNetCDF.cmake @@ -0,0 +1,182 @@ +#[[ FindNetCDF.cmake + +This module finds NetCDF-C and NetCDF-F. It uses nc-config and nf-config to +get HINTS for the find_xxxx's that are used to find the files/directories +listed below. + +If a file or directory cannot be found, the user should add the appropriate +directories to CMAKE_PREFIX_PATH. + +Resulting variables: + NETCDF_F_LIBRARY: Path to libnetcdff.so + NETCDF_C_LIBRARY: Path to libnetcdf.so + NETCDF_C_INCLUDE_DIR: Path to the directory containing netcdf.h + NETCDF_F90_INCLUDE_DIR: Path to the directory containing netcdf.mod + NETCDF_F77_INCLUDE_DIR: Path to the directory containing netcdf.inc + + NETCDF_LIBRARIES: Paths to all of NetCDF's libraries + NETCDF_INCLUDE_DIRS: Paths to all of NetCDF's include directories. + +]] + + +# Find the nc-config and nf-config programs +find_program(NC_CONFIG NAMES "nc-config" DOC "Location of nc-config utility") +find_program(NF_CONFIG NAMES "nf-config" DOC "Location of nf-config utility") + + +# A function to call nx-config with an argument, and append the resulting path to a list +function(inspect_netcdf_config VAR NX_CONFIG ARG) + execute_process( + COMMAND ${NX_CONFIG} ${ARG} + RESULT_VARIABLE NX_CONFIG_RET + OUTPUT_VARIABLE NX_CONFIG_OUTPUT + ERROR_VARIABLE NX_CONFIG_STDERR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(EXISTS "${NX_CONFIG_OUTPUT}") + list(APPEND ${VAR} ${NX_CONFIG_OUTPUT}) + set(${VAR} ${${VAR}} PARENT_SCOPE) + endif() +endfunction() + +# Determine HINTS for netcdf.h +set(NC_INC_HINTS "") +inspect_netcdf_config(NC_INC_HINTS "${NC_CONFIG}" --includedir) +inspect_netcdf_config(NC_INC_HINTS "${NC_CONFIG}" --prefix) +# Find netcdf.h +find_path(NETCDF_C_INCLUDE_DIR + netcdf.h + DOC "Directory containing \"netcdf.h\"" + HINTS + ${NC_INC_HINTS} + PATH_SUFFIXES + "include" +) + +# Determine HINTS for netcdf.mod +set(NF_INC_HINTS "") +inspect_netcdf_config(NF_INC_HINTS "${NF_CONFIG}" --includedir) +inspect_netcdf_config(NF_INC_HINTS "${NF_CONFIG}" --prefix) +# Find netcdf.mod +find_path(NETCDF_F90_INCLUDE_DIR + netcdf.mod + DOC "Directory containing \"netcdf.mod\"" + HINTS + ${NF_INC_HINTS} + PATH_SUFFIXES + "include" + "mod" + "module" +) +# Find netcdf.inc +find_path(NETCDF_F77_INCLUDE_DIR + netcdf.inc + DOC "Directory containing \"netcdf.inc\"" + HINTS + ${NF_INC_HINTS} + PATH_SUFFIXES + "include" + "mod" + "module" +) + +# Determine HINTS for NetCDF-C's library +set(NC_LIBDIR_HINTS "") +inspect_netcdf_config(NC_LIBDIR_HINTS "${NC_CONFIG}" --libdir) +inspect_netcdf_config(NC_LIBDIR_HINTS "${NC_CONFIG}" --prefix) +# Find libnetcdf.so +find_library(NETCDF_C_LIBRARY + netcdf + DOC "Path to \"libnetcdf\"" + HINTS + ${NC_LIBDIR_HINTS} + PATH_SUFFIXES + "lib" +) + +# Determine HINTS for NetCDF-F's library +set(NF_LIBDIR_HINTS "") +inspect_netcdf_config(NF_LIBDIR_HINTS "${NF_CONFIG}" --libdir) +inspect_netcdf_config(NF_LIBDIR_HINTS "${NF_CONFIG}" --prefix) +# Find libnetcdff.so +find_library(NETCDF_F_LIBRARY + netcdff + DOC "Path to \"libnetcdff\"" + HINTS + ${NF_LIBDIR_HINTS} + PATH_SUFFIXES + "lib" +) + +# Make a readable error message +set(NetCDF_ERRMSG "\nCounldn't find one or more of NetCDF's files! The following files/directories weren't found:") +if(NOT NETCDF_F_LIBRARY) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_F_LIBRARY: Path to \"libnetcdff.so\"") +endif() +if(NOT NETCDF_C_LIBRARY) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_C_LIBRARY: Path to \"libnetcdf.so\"") +endif() +if(NOT NETCDF_C_INCLUDE_DIR) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_C_INCLUDE_DIR: Directory containing \"netcdf.h\"") +endif() +if(NOT NETCDF_F90_INCLUDE_DIR) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_F90_INCLUDE_DIR: Directory containing \"netcdf.mod\"") +endif() +if(NOT NETCDF_F77_INCLUDE_DIR) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_F77_INCLUDE_DIR: Directory containing \"netcdf.inc\"") +endif() +set(NetCDF_ERRMSG "${NetCDF_ERRMSG}\nFind the directories/files that are listed above. Specify the directories you want CMake to search with the CMAKE_PREFIX_PATH variable (or the NetCDF_ROOT environment variable).\n") + +# Conform to the find_package standards +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args(NetCDF + REQUIRED_VARS + NETCDF_F_LIBRARY + NETCDF_C_LIBRARY + NETCDF_C_INCLUDE_DIR + NETCDF_F90_INCLUDE_DIR + NETCDF_F77_INCLUDE_DIR + FAIL_MESSAGE "${NetCDF_ERRMSG}" +) +mark_as_advanced( + NC_CONFIG + NF_CONFIG + NETCDF_F_LIBRARY + NETCDF_C_LIBRARY + NETCDF_C_INCLUDE_DIR + NETCDF_F90_INCLUDE_DIR + NETCDF_F77_INCLUDE_DIR +) + +# Set NETCDF_LIBRARIES NETCDF_INCLUDE_DIRS +set(NETCDF_LIBRARIES ${NETCDF_F_LIBRARY} ${NETCDF_C_LIBRARY}) +set(NETCDF_INCLUDE_DIRS ${NETCDF_F90_INCLUDE_DIR} ${NETCDF_F77_INCLUDE_DIR} ${NETCDF_C_INCLUDE_DIR}) + +if(NOT TARGET NetCDF-C) + add_library(NetCDF-C SHARED IMPORTED) + set_property(TARGET NetCDF-C + PROPERTY IMPORTED_LOCATION ${NETCDF_C_LIBRARY} + ) + set_property(TARGET NetCDF-C + PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${NETCDF_C_INCLUDE_DIR} + ) +endif() + +if(NOT TARGET NetCDF-F) + add_library(NetCDF-F SHARED IMPORTED) + set_property(TARGET NetCDF-F + PROPERTY IMPORTED_LOCATION ${NETCDF_F_LIBRARY} + ) + set_property(TARGET NetCDF-F + PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${NETCDF_F90_INCLUDE_DIR} ${NETCDF_F77_INCLUDE_DIR} + ) + set_property(TARGET NetCDF-F + PROPERTY INTERFACE_LINK_LIBRARIES NetCDF-C + ) +endif() diff --git a/model/geos-chem/CMakeScripts/GC-ConfigureClassic.cmake b/model/geos-chem/CMakeScripts/GC-ConfigureClassic.cmake new file mode 100755 index 0000000..dc116d3 --- /dev/null +++ b/model/geos-chem/CMakeScripts/GC-ConfigureClassic.cmake @@ -0,0 +1,278 @@ +function(configureGCClassic) + + #------------------------------------------------------------------------- + # Find OpenMP if we're building a multithreaded executable + #------------------------------------------------------------------------- + gc_pretty_print(SECTION "Threading") + set(OMP ON CACHE STRING + "Switch to enable/disable OpenMP threading in GEOS-Chem" + ) + gc_pretty_print(VARIABLE OMP IS_BOOLEAN) + if("${OMP}") + set(NO_OMP "OFF" CACHE STRING "Boolean opposite of the OMP switch, needed for backwards compatibility") + find_package(OpenMP REQUIRED) + ####################################################################### + # NOTE: Newer versions of CMake (maybe > 3.8) prefer OpenMP::OpenMP + # rather than ${OpenMP_Fortran_FLAGS} to specify compilation options + # for OpenMP. However, this is not supported in older versions. + # For backwards compatibility, especially with Azure DevOps, we will + # leave the new syntax commented out. It can be restored later. + # + # -- Bob Yantosca (28 Jul 2020) + # target_compile_options(HEMCOBuildProperties + # INTERFACE OpenMP::OpenMP_Fortran + # ) + # target_link_libraries(HEMCOBuildProperties + # INTERFACE OpenMP::OpenMP_Fortran + # ) + ####################################################################### + target_compile_options(GEOSChemBuildProperties + INTERFACE ${OpenMP_Fortran_FLAGS} + ) + target_link_libraries(GEOSChemBuildProperties + INTERFACE ${OpenMP_Fortran_FLAGS} + ) + else() + set(NO_OMP "ON" CACHE STRING + "Boolean opposite of the OMP switch, for backwards compatibility") + target_compile_definitions(GEOSChemBuildProperties + INTERFACE "NO_OMP" + ) + endif() + + # Header for next section + gc_pretty_print(SECTION "General settings") + + #------------------------------------------------------------------------- + # Make MECH an option. This controls which KPP directory is used. + #------------------------------------------------------------------------- + set(MECH "fullchem" CACHE STRING "Name of the chemistry mechanism to use") + gc_pretty_print(VARIABLE MECH OPTIONS "fullchem" "carbon" "Hg" "custom") + + #------------------------------------------------------------------------- + # Turn on bpch diagnostics? + #------------------------------------------------------------------------- + set(BPCH_DIAG "OFF" CACHE BOOL + "Switch to enable GEOS-Chem's bpch diagnostics" + ) + gc_pretty_print(VARIABLE BPCH_DIAG IS_BOOLEAN) + if(${BPCH_DIAG}) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE BPCH_DIAG + ) + endif() + + #------------------------------------------------------------------------- + # Set USE_REAL8 as cache variable so as to not override existing definition + # See https://github.com/geoschem/geos-chem/issues/43. + #------------------------------------------------------------------------- + set(USE_REAL8 ON CACHE BOOL + "Switch to set flexible precision 8-byte floating point real" + ) + gc_pretty_print(VARIABLE USE_REAL8 IS_BOOLEAN) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE $<$:USE_REAL8> + ) + + #------------------------------------------------------------------------- + # Add code sanitization options (GNU Fortran only) + # We need to add these options to both compiler & linker. + #------------------------------------------------------------------------- + set(SANITIZE OFF CACHE BOOL + "Switch to turn on code sanitation (i.e. identify memory leaks and similar conditions)" + ) + gc_pretty_print(VARIABLE SANITIZE IS_BOOLEAN) + if(${SANITIZE}) + if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + target_compile_options(GEOSChemBuildProperties + INTERFACE "-fsanitize=address" + ) + target_link_libraries(GEOSChemBuildProperties + INTERFACE "-fsanitize=address" + ) + target_compile_options(GEOSChemBuildProperties + INTERFACE "-fsanitize=leak" + ) + target_link_libraries(GEOSChemBuildProperties + INTERFACE "-fsanitize=leak" + ) + target_compile_options(GEOSChemBuildProperties + INTERFACE "-fsanitize=undefined" + ) + target_link_libraries(GEOSChemBuildProperties + INTERFACE "-fsanitize=undefined" + ) + else() + message( FATAL_ERROR "The SANITIZE option is only defined for GNU Fortran.") + endif() + endif() + + #------------------------------------------------------------------------- + # Always set MODEL_CLASSIC when building GEOS-Chem Classic + #------------------------------------------------------------------------- + target_compile_definitions(GEOSChemBuildProperties + INTERFACE MODEL_ MODEL_GISS MODEL_CLASSIC EXTERNAL_GRID EXTERNAL_FORCINGS + ) + + # Header for next section + gc_pretty_print(SECTION "Components") + + #------------------------------------------------------------------------- + # Build TOMAS + #------------------------------------------------------------------------- + set(TOMAS "OFF" CACHE BOOL "Switch to enable TOMAS") + set(TOMAS_BINS "NA" CACHE STRING "Number of TOMAS bins (only used if TOMAS is true)") + gc_pretty_print(VARIABLE TOMAS IS_BOOLEAN) + gc_pretty_print(VARIABLE TOMAS_BINS OPTIONS "NA" "15" "40") + if(${TOMAS}) + target_compile_definitions(GEOSChemBuildProperties INTERFACE TOMAS) + if("${TOMAS_BINS}" MATCHES "NA") + message(FATAL_ERROR "TOMAS_BINS must be 15 or 40 if TOMAS is ON") + endif() + else() + if(NOT "${TOMAS_BINS}" MATCHES "NA") + message(FATAL_ERROR "TOMAS_BINS must be NA if TOMAS is OFF") + endif() + endif() + + + if("${TOMAS_BINS}" MATCHES 15) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE TOMAS15 + ) + elseif("${TOMAS_BINS}" MATCHES 40) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE TOMAS40 + ) + endif() + + #------------------------------------------------------------------------- + # Build APM? + #------------------------------------------------------------------------- + set(APM "OFF" CACHE BOOL + "Switch to build APM as a component of GEOS-Chem" + ) + gc_pretty_print(VARIABLE APM IS_BOOLEAN) + if(${APM}) + target_compile_definitions(GEOSChemBuildProperties INTERFACE APM) + endif() + + #------------------------------------------------------------------------- + # Build RRTMG? + #------------------------------------------------------------------------- + set(RRTMG "OFF" CACHE BOOL + "Switch to build RRTMG as a component of GEOS-Chem" + ) + gc_pretty_print(VARIABLE RRTMG IS_BOOLEAN) + if(${RRTMG}) + target_compile_definitions(GEOSChemBuildProperties INTERFACE RRTMG) + endif() + + #------------------------------------------------------------------------- + # Build GTMM? + # (This is a deprecated option...needs updating. Turn OFF by default.) + #------------------------------------------------------------------------- + set(GTMM OFF CACHE BOOL + "Switch to build GTMM as a component of GEOS-Chem" + ) + gc_pretty_print(VARIABLE GTMM IS_BOOLEAN) + if(${GTMM}) + target_compile_definitions(GEOSChemBuildProperties INTERFACE GTMM_Hg) + endif() + + #------------------------------------------------------------------------- + # Build HEMCO standalone? + #------------------------------------------------------------------------- + set(HCOSA "OFF" CACHE BOOL + "Switch to build the hemco-standalone (HCOSA) executable" + ) + gc_pretty_print(VARIABLE HCOSA IS_BOOLEAN) + + #------------------------------------------------------------------------- + # Build Luo et al wetdep scheme? + # (Currently a research option... turn OFF by default) + #------------------------------------------------------------------------- + set(LUO_WETDEP OFF CACHE BOOL + "Switch to build the Luo et al (2020) wetdep scheme into GEOS-Chem" + ) + gc_pretty_print(VARIABLE LUO_WETDEP IS_BOOLEAN) + if(${LUO_WETDEP}) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE LUO_WETDEP + ) + endif() + + #------------------------------------------------------------------------- + # Use Fast-JX rather than Cloud-J? + #------------------------------------------------------------------------- + + set(FASTJX OFF CACHE BOOL + "Switch to use legacy FAST-JX in GEOS-Chem" + ) + gc_pretty_print(VARIABLE FASTJX IS_BOOLEAN) + if(${FASTJX}) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE FASTJX + ) + endif() + + #------------------------------------------------------------------------- + # Export the following variables to GEOS-Chem directory's scope + #------------------------------------------------------------------------- + set(GCHP FALSE PARENT_SCOPE) + set(MODEL_CLASSIC TRUE PARENT_SCOPE) + set(MECH ${MECH} PARENT_SCOPE) + set(TOMAS ${TOMAS} PARENT_SCOPE) + set(APM ${APM} PARENT_SCOPE) + set(RRTMG ${RRTMG} PARENT_SCOPE) + set(GTMM ${GTMM} PARENT_SCOPE) + set(LUO_WETDEP ${LUO_WETDEP} PARENT_SCOPE) + set(SANITIZE ${SANITIZE} PARENT_SCOPE) + set(FASTJX ${FASTJX} PARENT_SCOPE) + + #------------------------------------------------------------------------- + # Export information about Git status + #------------------------------------------------------------------------- + + # Get branch nane in code repository + macro(get_git_branch VAR) + execute_process( + COMMAND git -C ${CMAKE_CURRENT_SOURCE_DIR} rev-parse --abbrev-ref HEAD + OUTPUT_VARIABLE ${VAR} + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endmacro() + get_git_branch(CODE_BRANCH) + set(GIT_BRANCH ${CODE_BRANCH} CACHE STRING "Current branch in code repo") + + # Get last commit name from code repository + macro(get_git_commit VAR) + execute_process( + COMMAND git -C ${CMAKE_CURRENT_SOURCE_DIR} log -n 1 --pretty=format:"%s" + OUTPUT_VARIABLE ${VAR} + ) + endmacro() + get_git_commit(LAST_COMMIT) + set(GIT_COMMIT ${LAST_COMMIT} CACHE STRING "Last commit in Git repo") + + # Get last commit hash from code repository + macro(get_git_commit_hash VAR) + execute_process( + COMMAND git -C ${CMAKE_CURRENT_SOURCE_DIR} log -n 1 --pretty=format:"%h" + OUTPUT_VARIABLE ${VAR} + ) + endmacro() + get_git_commit_hash(COMMIT_HASH) + set(GIT_COMMIT_HASH ${COMMIT_HASH} CACHE STRING "Last commit hash in Git repo") + + # Get last commit date from code repository + macro(get_git_commit_date VAR) + execute_process( + COMMAND git -C ${CMAKE_CURRENT_SOURCE_DIR} log -n 1 --pretty=format:"%cd" + OUTPUT_VARIABLE ${VAR} + ) + endmacro() + get_git_commit_date(COMMIT_DATE) + set(GIT_COMMIT_DATE ${COMMIT_DATE} CACHE STRING "Date of last Git commit") + +endfunction() diff --git a/model/geos-chem/CMakeScripts/GC-Helpers.cmake b/model/geos-chem/CMakeScripts/GC-Helpers.cmake new file mode 100755 index 0000000..142417a --- /dev/null +++ b/model/geos-chem/CMakeScripts/GC-Helpers.cmake @@ -0,0 +1,185 @@ + +#[[ stringify_list + +Stringify a list of strings. + +Usage: + stringify_list( + [PRINT] + [LINE_LENGTH ] + [HIGHLIGHT ...] + [JOIN ...] + [AFTER] + ) + +Options: + PRINT Print the stringified list to console. Highlighted text + will also be colorized. + + LINE_LENGTH When JOINing a list of string, the resulting lines will + be limited to characters. The resulting + will be a list of lines that can then be JOINed with + newlines. + + HIGHLIGHT A list of keywords to highlight. + + JOIN A list of tokens that will be used sequentially to join + list items. The last token will be used to join all + remaining items. + + AFTER Place the JOIN tokens after the item, rather than before. + +]] +function(stringify_list LIST) + cmake_parse_arguments(BETTER + "PRINT;AFTER" + "LINE_LENGTH" + "HIGHLIGHT;JOIN" + ${ARGN} + ) + + if(NOT DEFINED BETTER_LINE_LENGTH) + set(BETTER_LINE_LENGTH 1000) # Arbitrary big number + endif() + + set(STR ${${LIST}}) + + # Limit joined line length + if(DEFINED BETTER_JOIN) + set(TEMP "") + set(CUR_LEN "0") + + set(JOIN_IDX "0 - 1") + list(LENGTH BETTER_JOIN JOIN_LEN) + + foreach(ITEM ${STR}) + # Get the join token + math(EXPR JOIN_IDX "${JOIN_IDX} + 1") + if(${JOIN_IDX} LESS ${JOIN_LEN}) + list(GET BETTER_JOIN "${JOIN_IDX}" JOIN_TOKEN) + endif() + string(LENGTH "${JOIN_TOKEN}" SEP_LEN) + + # If a line length was + string(LENGTH "${ITEM}" WORD_LEN) + math(EXPR POST_LEN "${WORD_LEN} + ${CUR_LEN} + ${SEP_LEN}") + if("${POST_LEN}" LESS "${BETTER_LINE_LENGTH}") + if(${BETTER_AFTER}) + set(TEMP "${TEMP}${ITEM}${JOIN_TOKEN}") + else() + set(TEMP "${TEMP}${JOIN_TOKEN}${ITEM}") + endif() + set(CUR_LEN "${POST_LEN}") + else() + if(${BETTER_AFTER}) + set(TEMP "${TEMP};${ITEM}${JOIN_TOKEN}") + else() + set(TEMP "${TEMP};${JOIN_TOKEN}${ITEM}") + endif() + set(CUR_LEN "0") + math(EXPR CUR_LEN "${SEP_LEN} + ${WORD_LEN}") + endif() + endforeach() + + set(STR "${TEMP}") + endif() + + # Highlight selected words + if(DEFINED BETTER_HIGHLIGHT) + foreach(KEYWORD ${BETTER_HIGHLIGHT}) + string(REPLACE "${KEYWORD}" "[${KEYWORD}]" STR "${STR}") + endforeach() + endif() + + if(${BETTER_PRINT}) + string(ASCII 27 Esc) + if(${CMAKE_COLOR_MAKEFILE}) + string(REGEX REPLACE "\\[([a-zA-Z0-9_\\.]+)\\]" "${Esc}[32m\\1${Esc}[m" COLORIZED "${STR}") + else() + set(COLORIZED "${STR}") + endif() + string(REGEX REPLACE "\n$" "" COLORIZED "${COLORIZED}") + message("${COLORIZED}") + endif() + + + # Export the new string + set(${LIST} "${STR}" PARENT_SCOPE) +endfunction() + +#[[ get_repo_version + +Variable with name ${VARNAME} gets set to first 7 characters of the hash +of the last commit to the repo at ${DIR}. + +Usage: + get_repo_version(VARNAME DIR) + +]] +macro(get_repo_version VARNAME DIR) + execute_process( + COMMAND git describe --tags --dirty=.dirty + WORKING_DIRECTORY ${DIR} + OUTPUT_VARIABLE ${VARNAME} + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endmacro() + +function(gc_pretty_print) + cmake_parse_arguments(ARGS + "IS_BOOLEAN" + "VARIABLE;SECTION" + "OPTIONS" + ${ARGN} + ) + + if(DEFINED ARGS_VARIABLE) + if(ARGS_IS_BOOLEAN) + set(LOGLINE "ON" "OFF") + # Split list with " " + stringify_list(LOGLINE + JOIN " " + LINE_LENGTH 60 + ) + # Wrap lines + stringify_list(LOGLINE + JOIN " * ${ARGS_VARIABLE}:\t" "\n ... \t" + ) + if("${${ARGS_VARIABLE}}") + stringify_list(LOGLINE PRINT HIGHLIGHT "ON") + else() + stringify_list(LOGLINE PRINT HIGHLIGHT "OFF") + endif() + elseif(DEFINED ARGS_OPTIONS) + set(LOGLINE ${ARGS_OPTIONS}) + # Split list with " " + stringify_list(LOGLINE + JOIN " " + LINE_LENGTH 60 + ) + # Wrap lines + stringify_list(LOGLINE + JOIN " * ${ARGS_VARIABLE}:\t" "\n ... \t" + ) + stringify_list(LOGLINE PRINT HIGHLIGHT ${${ARGS_VARIABLE}}) + else() + if(NOT DEFINED ${ARGS_VARIABLE}) + set(LOGLINE " ") # special case for empty variable + else() + set(LOGLINE ${${ARGS_VARIABLE}}) + endif() + # Split list with " " + stringify_list(LOGLINE + JOIN " " + LINE_LENGTH 60 + ) + # Wrap lines + stringify_list(LOGLINE + JOIN " + ${ARGS_VARIABLE}:\t" "\n ... \t" + ) + stringify_list(LOGLINE PRINT) + endif() + elseif(DEFINED ARGS_SECTION) + message(STATUS "${ARGS_SECTION}:") + endif() +endfunction() \ No newline at end of file diff --git a/model/geos-chem/CMakeScripts/summarize_build b/model/geos-chem/CMakeScripts/summarize_build new file mode 100644 index 0000000..46d7f33 --- /dev/null +++ b/model/geos-chem/CMakeScripts/summarize_build @@ -0,0 +1,77 @@ +#!/bin/bash +DESCRIPTION="""Summarizes a GEOS-Chem build by scraping CMakeCache.txt. + +usage: + summarize_build [CACHEFILE] [--no-color] + CACHEFILE: Path to a CMakeCache.txt. The default value is a + CMakeCache.txt beside this script. + --no-color: Don't highlight variable names. +""" +if [[ ( $* == --help ) || ( $* == -h ) ]]; then + echo "$DESCRIPTION" + exit 0 +fi + +if [[ $* == --no-color ]]; then + LEFT_COLOR="" + RIGHT_COLOR="" +else + LEFT_COLOR="\e[1;34m" + RIGHT_COLOR="\e[m" +fi + +set -e + +THIS_SCRIPTS_DIRECTORY=$(realpath $(dirname "$0")) +CACHEFILE=${1:-$THIS_SCRIPTS_DIRECTORY/CMakeCache.txt} + +function scrape_cache() { + sed -n "s/$1:[A-Z][A-Z]*=//p" $CACHEFILE +} + +function print_item() { + printf "%-12s %s\n" "$1:" "$2" +} +function print_item_highlight() { + printf "${LEFT_COLOR}%s${RIGHT_COLOR}\"%s\"\n" "-D$1=" "$2" +} + +BUILD_TYPE=$(scrape_cache CMAKE_BUILD_TYPE) +BUILD_TYPE_UPPER=${BUILD_TYPE^^} +COMPILER_ID=$(scrape_cache GEOSChem_DETECTED_FORTRAN_COMPILER_ID) +COMPILER_VERSION=$(scrape_cache GEOSChem_DETECTED_FORTRAN_COMPILER_VERSION) +COMILER_WHICH=$(scrape_cache CMAKE_Fortran_COMPILER) + +echo "## Compiler Info" +print_item "# Family" "${COMPILER_ID}" +print_item "# Version" "${COMPILER_VERSION}" +print_item "# Which" "${COMILER_WHICH}" +echo "" + +echo "## Compiler Options (global)" +print_item_highlight "CMAKE_Fortran_FLAGS" $(scrape_cache CMAKE_Fortran_FLAGS) +print_item_highlight "CMAKE_Fortran_FLAGS_${BUILD_TYPE_UPPER}" $(scrape_cache CMAKE_Fortran_FLAGS_${BUILD_TYPE_UPPER}) +echo "" + +echo "## Compiler Options (GEOS-Chem)" +print_item_highlight "GEOSChem_Fortran_FLAGS_${COMPILER_ID}" $(scrape_cache GEOSChem_Fortran_FLAGS_${COMPILER_ID}) +print_item_highlight "GEOSChem_Fortran_FLAGS_${BUILD_TYPE_UPPER}_${COMPILER_ID}" $(scrape_cache GEOSChem_Fortran_FLAGS_${BUILD_TYPE_UPPER}_${COMPILER_ID}) +echo "" + +echo "## Compiler Options (HEMCO)" +print_item_highlight "HEMCO_Fortran_FLAGS_${COMPILER_ID}" $(scrape_cache HEMCO_Fortran_FLAGS_${COMPILER_ID}) +print_item_highlight "HEMCO_Fortran_FLAGS_${BUILD_TYPE_UPPER}_${COMPILER_ID}" $(scrape_cache HEMCO_Fortran_FLAGS_${BUILD_TYPE_UPPER}_${COMPILER_ID}) +echo "" + +echo "## GEOS-Chem Components Settings" +print_item_highlight TOMAS $(scrape_cache TOMAS) +print_item_highlight TOMAS_BINS $(scrape_cache TOMAS_BINS) +print_item_highlight APM $(scrape_cache APM) +print_item_highlight RRTMG $(scrape_cache RRTMG) +print_item_highlight GTMM $(scrape_cache GTMM) +print_item_highlight HCOSA $(scrape_cache HCOSA) +print_item_highlight LUO_WETDEP $(scrape_cache LUO_WETDEP) +print_item_highlight FASTJX $(scrape_cache FASTJX) +echo "" + +# grep --color "GEOSChem_Fortran_FLAGS_[A-Z_]*${COMPILER_ID}" $CACHEFILE \ No newline at end of file diff --git a/model/geos-chem/CMakeScripts/try_compile.F90 b/model/geos-chem/CMakeScripts/try_compile.F90 new file mode 100644 index 0000000..40eaef3 --- /dev/null +++ b/model/geos-chem/CMakeScripts/try_compile.F90 @@ -0,0 +1,57 @@ +program try_compile + use netcdf + + implicit none + + character (len = *), parameter :: FILE_NAME = "simple_xy.nc" + integer, parameter :: NDIMS = 2 + integer, parameter :: NX = 6, NY = 12 + integer :: ncid, varid, dimids(NDIMS) + integer :: x_dimid, y_dimid + integer :: data_out(NY, NX) + integer :: x, y +#ifndef NO_OMP + integer nthreads, tid, OMP_GET_THREAD_NUM + + write(*,*) 'About to start multiple threads' + ! Try OpenMP + !$OMP PARALLEL PRIVATE(nthreads, tid) + TID = OMP_GET_THREAD_NUM() + write(*,*) 'Hello from thread ', tid + !$OMP END PARALLEL +#endif + + ! Try NetCDF-F + do x = 1, NX + do y = 1, NY + data_out(y, x) = (x - 1) * NY + (y - 1) + end do + end do + write(*,*) 'Creating NetCDF file' + call check( nf90_create(FILE_NAME, NF90_CLOBBER, ncid) ) + call check( nf90_def_dim(ncid, "x", NX, x_dimid) ) + call check( nf90_def_dim(ncid, "y", NY, y_dimid) ) + + ! The dimids array is used to pass the IDs of the dimensions of + ! the variables. Note that in fortran arrays are stored in + ! column-major format. + dimids = (/ y_dimid, x_dimid /) + + call check( nf90_def_var(ncid, "data", NF90_INT, dimids, varid) ) + + call check( nf90_enddef(ncid) ) + call check( nf90_put_var(ncid, varid, data_out) ) + call check( nf90_close(ncid) ) + write(*,*) 'Finished creating the NetCDF file' + + contains + subroutine check(status) + integer, intent ( in) :: status + + if(status /= nf90_noerr) then + print *, trim(nf90_strerror(status)) + stop "Stopped" + end if + end subroutine check + +end program diff --git a/model/geos-chem/src b/model/geos-chem/src deleted file mode 160000 index 1383042..0000000 --- a/model/geos-chem/src +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 138304249fbdea261791ce4c994485b88e652e87 diff --git a/model/geos-chem/src/CMakeLists.txt b/model/geos-chem/src/CMakeLists.txt new file mode 100644 index 0000000..1dfd9f5 --- /dev/null +++ b/model/geos-chem/src/CMakeLists.txt @@ -0,0 +1,75 @@ +# src/CMakeLists.txt + +#----------------------------------------------------------------------------- +# Tell CMake to look for code in HEMCO, Cloud-J and GEOS-Chem directory trees +#----------------------------------------------------------------------------- +add_subdirectory(HEMCO EXCLUDE_FROM_ALL) +target_compile_definitions(HEMCOBuildProperties + INTERFACE + $<$:TOMAS> + $<$:TOMAS15> + $<$:TOMAS40> + "" +) +add_subdirectory(Cloud-J EXCLUDE_FROM_ALL) +add_subdirectory(GEOS-Chem EXCLUDE_FROM_ALL) + +#----------------------------------------------------------------------------- +# Define the GEOS-Chem executable: +# 1. Specify a cache variable with the default target name +# 2. Specify the location of the main program +# 3. Specify libraries that the main program depends on +# 4. Store the binary exectuable file in the bin folder (pre-install) +#----------------------------------------------------------------------------- +set(EXE_FILE_NAME gcclassic CACHE STRING + "Default name for the GEOS-Chem Classic executable file") +mark_as_advanced(EXE_FILE_NAME) + +add_executable(${EXE_FILE_NAME} + GEOS-Chem/Interfaces/GCClassic/main.F90 +) +target_link_libraries(${EXE_FILE_NAME} + PUBLIC + GeosCore +) +set_target_properties(${EXE_FILE_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +#----------------------------------------------------------------------------- +# When "make install" is run, copy the target to the destination folder +# (which is typically one directory higher than the CMake build folder) +#----------------------------------------------------------------------------- + +# Define set of installation paths to consider +set(COMBINED_INSTALL_DIRS "") +list(APPEND COMBINED_INSTALL_DIRS ${RUNDIR}) +list(APPEND COMBINED_INSTALL_DIRS ${INSTALLCOPY}) + +# Consider installation to all of the specified paths +foreach(INSTALL_PATH ${COMBINED_INSTALL_DIRS}) + if(INSTALL_PATH IN_LIST RUNDIR) + set(CHECK_IS_RUNDIR TRUE) + else() + set(CHECK_IS_RUNDIR FALSE) + endif() + + # Convert INSTALL_PATH to absolute + if(NOT IS_ABSOLUTE "${INSTALL_PATH}") + get_filename_component(INSTALL_PATH "${INSTALL_PATH}" ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}") + endif() + + # Issue warning and skip if geoschem_config.yml doesn't exist + # (i.e. if it doens't look like a run directory) + if(CHECK_IS_RUNDIR AND (NOT EXISTS ${INSTALL_PATH}/geoschem_config.yml)) + # Installation path is not a GEOS-Chem run directory + # Skip ahead -- a warning will be raised elsewhere. + continue() + else() + # Installation path is a GEOS-Chem run directory, + # Therefore we will install the executable there. + install(TARGETS ${EXE_FILE_NAME} RUNTIME DESTINATION ${INSTALL_PATH}) + endif() + +endforeach() diff --git a/model/geos-chem/src/Cloud-J b/model/geos-chem/src/Cloud-J new file mode 160000 index 0000000..8a3b925 --- /dev/null +++ b/model/geos-chem/src/Cloud-J @@ -0,0 +1 @@ +Subproject commit 8a3b92547d70bc014ff92d867f1e9b0aab7be9bf diff --git a/model/geos-chem/src/GEOS-Chem b/model/geos-chem/src/GEOS-Chem new file mode 160000 index 0000000..a540f1f --- /dev/null +++ b/model/geos-chem/src/GEOS-Chem @@ -0,0 +1 @@ +Subproject commit a540f1f91761b47be3354a062c21c18d81690fbd diff --git a/model/geos-chem/src/HEMCO b/model/geos-chem/src/HEMCO new file mode 160000 index 0000000..ce7a795 --- /dev/null +++ b/model/geos-chem/src/HEMCO @@ -0,0 +1 @@ +Subproject commit ce7a79563d425a2c6c28b0a4953b54b1db6e5a6f