diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..68769579c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +exec diff --git a/modulefiles/fv3gfs/enkf_chgres_recenter_nc.hera b/modulefiles/fv3gfs/enkf_chgres_recenter_nc.hera new file mode 100644 index 0000000000..cb1828364c --- /dev/null +++ b/modulefiles/fv3gfs/enkf_chgres_recenter_nc.hera @@ -0,0 +1,16 @@ +#%Module##################################################### +## enkf_chgres_recenter component - hera +############################################################# + +module use -a /scratch2/NCEPDEV/nwprod/NCEPLIBS/modulefiles +module load bacio/2.0.2 +module load w3nco/2.0.6 +module load ip/3.0.1 +module load sp/2.0.2 +module load hdf5_parallel/1.10.6 +module load netcdf_parallel/4.7.4 + +module use -a /contrib/cmake/modulefiles +module load cmake/3.9.0 + +export FC=ifort diff --git a/modulefiles/fv3gfs/enkf_chgres_recenter_nc.wcoss_cray b/modulefiles/fv3gfs/enkf_chgres_recenter_nc.wcoss_cray new file mode 100644 index 0000000000..9c2b52dd6a --- /dev/null +++ b/modulefiles/fv3gfs/enkf_chgres_recenter_nc.wcoss_cray @@ -0,0 +1,29 @@ +#%Module##################################################### +## enkf_chgres_recenter component - wcoss_cray +############################################################# + +module load ncep/1.0 +module load PrgEnv-intel/5.2.56 +module unload intel/15.0.3.187 +module load intel/18.1.163 +module load craype-haswell +module load cray-mpich/7.2.0 + +# Loading netcdf modules +module use /usrx/local/dev/modulefiles +module load NetCDF-intel-sandybridge/4.7.4 +module load HDF5-parallel-intel-sandybridge/1.10.6 + +module use /gpfs/hps/nco/ops/nwprod/lib/modulefiles +module load ip-intel/3.0.0 +module load sp-intel/2.0.2 +module load w3nco-intel/2.0.6 + +module use /usrx/local/nceplibs/modulefiles +module load bacio-intel/2.0.2 + +module use /usrx/local/dev/modulefiles +module load cmake/3.6.2 +module unuse /usrx/local/dev/modulefiles + +export FC=ftn diff --git a/modulefiles/fv3gfs/enkf_chgres_recenter_nc.wcoss_dell_p3 b/modulefiles/fv3gfs/enkf_chgres_recenter_nc.wcoss_dell_p3 new file mode 100644 index 0000000000..7094ffe629 --- /dev/null +++ b/modulefiles/fv3gfs/enkf_chgres_recenter_nc.wcoss_dell_p3 @@ -0,0 +1,18 @@ +#%Module##################################################### +## enkf_chgres_recenter component - wcoss_dell_p3 +############################################################# + +module load ips/18.0.1.163 +module load impi/18.0.1 + +#module load NetCDF/4.5.0 +module load bacio/2.0.2 +module load w3nco/2.0.6 +module load ip/3.0.1 +module load sp/2.0.2 +module load cmake/3.10.0 + +module load HDF5-parallel/1.10.6 +module load NetCDF-parallel/4.7.4 + +export FC=ifort diff --git a/modulefiles/gdas_navybull.wcoss_dell_p3 b/modulefiles/gdas_navybull.wcoss_dell_p3 index cb3bdead4b..cd5f03b3fb 100644 --- a/modulefiles/gdas_navybull.wcoss_dell_p3 +++ b/modulefiles/gdas_navybull.wcoss_dell_p3 @@ -7,4 +7,4 @@ module load impi/18.0.1 module load w3emc/2.3.0 module load w3nco/2.0.6 -module load bufr/11.2.0 +module load bufr/11.3.1 diff --git a/modulefiles/gdas_trpsfcmv.wcoss_dell_p3 b/modulefiles/gdas_trpsfcmv.wcoss_dell_p3 index ec2d96963b..444998ad4b 100644 --- a/modulefiles/gdas_trpsfcmv.wcoss_dell_p3 +++ b/modulefiles/gdas_trpsfcmv.wcoss_dell_p3 @@ -4,7 +4,7 @@ module load ips/18.0.1.163 module load NCL/6.4.0 -module load bufr/11.2.0 +module load bufr/11.3.1 module load ip/3.0.1 module load sp/2.0.2 module load w3nco/2.0.6 diff --git a/modulefiles/gfs_bufr.wcoss_dell_p3 b/modulefiles/gfs_bufr.wcoss_dell_p3 index 2dced7094b..cc19a24c84 100644 --- a/modulefiles/gfs_bufr.wcoss_dell_p3 +++ b/modulefiles/gfs_bufr.wcoss_dell_p3 @@ -11,7 +11,7 @@ module load nemsio/2.2.3 module load bacio/2.0.2 module load w3emc/2.3.0 module load w3nco/2.0.6 -module load bufr/11.2.0 +module load bufr/11.3.1 module load sigio/2.1.0 module use -a /gpfs/dell1/nco/ops/nwprod/modulefiles/ diff --git a/sorc/build_all.sh b/sorc/build_all.sh index 33de612e9e..8f430497f9 100755 --- a/sorc/build_all.sh +++ b/sorc/build_all.sh @@ -1,5 +1,5 @@ #!/bin/sh -set -eu +set -u #------------------------------------ # USER DEFINED STUFF: # @@ -36,136 +36,246 @@ source ./machine-setup.sh > /dev/null 2>&1 . ./partial_build.sh +#------------------------------------ +# Exception Handling Init +#------------------------------------ +ERRSCRIPT=${ERRSCRIPT:-'eval [[ $err = 0 ]]'} +err=0 + #------------------------------------ # build libraries first #------------------------------------ $Build_libs && { -echo " .... Library build not currently supported .... " -#echo " .... Building libraries .... " -#./build_libs.sh > $logs_dir/build_libs.log 2>&1 + echo " .... Library build not currently supported .... " + #echo " .... Building libraries .... " + #./build_libs.sh > $logs_dir/build_libs.log 2>&1 } #------------------------------------ # build fv3 #------------------------------------ $Build_fv3gfs && { -echo " .... Building fv3 .... " -./build_fv3.sh > $logs_dir/build_fv3.log 2>&1 + echo " .... Building fv3 .... " + ./build_fv3.sh > $logs_dir/build_fv3.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building fv3." + echo "The log file is in $logs_dir/build_fv3.log" + fi + ((err+=$rc)) } #------------------------------------ # build gsi #------------------------------------ $Build_gsi && { -echo " .... Building gsi .... " -./build_gsi.sh > $logs_dir/build_gsi.log 2>&1 + echo " .... Building gsi .... " + ./build_gsi.sh > $logs_dir/build_gsi.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gsi." + echo "The log file is in $logs_dir/build_gsi.log" + fi + ((err+=$rc)) } #------------------------------------ # build ncep_post #------------------------------------ $Build_ncep_post && { -echo " .... Building ncep_post .... " -./build_ncep_post.sh > $logs_dir/build_ncep_post.log 2>&1 + echo " .... Building ncep_post .... " + ./build_ncep_post.sh > $logs_dir/build_ncep_post.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building ncep_post." + echo "The log file is in $logs_dir/build_ncep_post.log" + fi + ((err+=$rc)) } #------------------------------------ # build ufs_utils #------------------------------------ $Build_ufs_utils && { -echo " .... Building ufs_utils .... " -./build_ufs_utils.sh > $logs_dir/build_ufs_utils.log 2>&1 + echo " .... Building ufs_utils .... " + ./build_ufs_utils.sh > $logs_dir/build_ufs_utils.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building ufs_utils." + echo "The log file is in $logs_dir/build_ufs_utils.log" + fi + ((err+=$rc)) } #------------------------------------ -# build gfs_wafs -#------------------------------------ -# Only build on WCOSS -if [ $target = wcoss -o $target = wcoss_cray -o $target = wcoss_dell_p3 ]; then - $Build_gfs_wafs && { - echo " .... Building gfs_wafs .... " - ./build_gfs_wafs.sh > $logs_dir/build_gfs_wafs .log 2>&1 - } +# build gfs_wafs - optional checkout +#------------------------------------ +if [ -d gfs_wafs.fd ]; then + $Build_gfs_wafs && { + echo " .... Building gfs_wafs .... " + ./build_gfs_wafs.sh > $logs_dir/build_gfs_wafs.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gfs_wafs." + echo "The log file is in $logs_dir/build_gfs_wafs.log" + fi + ((err+=$rc)) + } fi #------------------------------------ # build sfcanl_nsttfchg #------------------------------------ $Build_sfcanl_nsttfchg && { -echo " .... Building gaussian_sfcanl and nst_tf_chg .... " -./build_sfcanl_nsttfchg.sh > $logs_dir/build_sfcanl_nsttfchg.log 2>&1 + echo " .... Building gaussian_sfcanl and nst_tf_chg .... " + ./build_sfcanl_nsttfchg.sh > $logs_dir/build_sfcanl_nsttfchg.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building Build_sfcanl_nsttfchg." + echo "The log file is in $logs_dir/Build_sfcanl_nsttfchg.log" + fi + ((err+=$rc)) } #------------------------------------ # build enkf_chgres_recenter #------------------------------------ $Build_enkf_chgres_recenter && { -echo " .... Building enkf_chgres_recenter .... " -./build_enkf_chgres_recenter.sh > $logs_dir/build_enkf_chgres_recenter.log 2>&1 + echo " .... Building enkf_chgres_recenter .... " + ./build_enkf_chgres_recenter.sh > $logs_dir/build_enkf_chgres_recenter.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building enkf_chgres_recenter." + echo "The log file is in $logs_dir/build_enkf_chgres_recenter.log" + fi + ((err+=$rc)) +} + + +#------------------------------------ +# build enkf_chgres_recenter_nc +#------------------------------------ +$Build_enkf_chgres_recenter_nc && { + echo " .... Building enkf_chgres_recenter_nc .... " + ./build_enkf_chgres_recenter_nc.sh > $logs_dir/build_enkf_chgres_recenter_nc.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building enkf_chgres_recenter_nc." + echo "The log file is in $logs_dir/build_enkf_chgres_recenter_nc.log" + fi + ((err+=$rc)) } #------------------------------------ # build tropcy_NEMS #------------------------------------ $Build_tropcy && { -echo " .... Building tropcy_NEMS .... " -./build_tropcy_NEMS.sh > $logs_dir/build_tropcy_NEMS.log 2>&1 + echo " .... Building tropcy_NEMS .... " + ./build_tropcy_NEMS.sh > $logs_dir/build_tropcy_NEMS.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building tropcy_NEMS." + echo "The log file is in $logs_dir/build_tropcy_NEMS.log" + fi + ((err+=$rc)) } #------------------------------------ # build gdas #------------------------------------ $Build_gdas && { -echo " .... Building gdas .... " -./build_gdas.sh > $logs_dir/build_gdas.log 2>&1 + echo " .... Building gdas .... " + ./build_gdas.sh > $logs_dir/build_gdas.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gdas." + echo "The log file is in $logs_dir/build_gdas.log" + fi + ((err+=$rc)) } #------------------------------------ # build gfs_fbwndgfs #------------------------------------ $Build_gfs_fbwndgfs && { -echo " .... Building gfs_fbwndgfs .... " -./build_gfs_fbwndgfs.sh > $logs_dir/build_gfs_fbwndgfs.log 2>&1 + echo " .... Building gfs_fbwndgfs .... " + ./build_gfs_fbwndgfs.sh > $logs_dir/build_gfs_fbwndgfs.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gfs_fbwndgfs." + echo "The log file is in $logs_dir/build_gfs_fbwndgfs.log" + fi + ((err+=$rc)) } #------------------------------------ # build gfs_overpdtg2 #------------------------------------ $Build_gfs_overpdtg2 && { -echo " .... Building gfs_overpdtg2 .... " -./build_gfs_overpdtg2.sh > $logs_dir/build_gfs_overpdtg2.log 2>&1 + echo " .... Building gfs_overpdtg2 .... " + ./build_gfs_overpdtg2.sh > $logs_dir/build_gfs_overpdtg2.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gfs_overpdtg2." + echo "The log file is in $logs_dir/build_gfs_overpdtg2.log" + fi + ((err+=$rc)) } #------------------------------------ # build gfs_wintemv #------------------------------------ $Build_gfs_wintemv && { -echo " .... Building gfs_wintemv .... " -./build_gfs_wintemv.sh > $logs_dir/build_gfs_wintemv.log 2>&1 + echo " .... Building gfs_wintemv .... " + ./build_gfs_wintemv.sh > $logs_dir/build_gfs_wintemv.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gfs_wintemv." + echo "The log file is in $logs_dir/build_gfs_wintemv.log" + fi + ((err+=$rc)) } #------------------------------------ # build gfs_bufrsnd #------------------------------------ $Build_gfs_bufrsnd && { -echo " .... Building gfs_bufrsnd .... " -./build_gfs_bufrsnd.sh > $logs_dir/build_gfs_bufrsnd.log 2>&1 + echo " .... Building gfs_bufrsnd .... " + ./build_gfs_bufrsnd.sh > $logs_dir/build_gfs_bufrsnd.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gfs_bufrsnd." + echo "The log file is in $logs_dir/build_gfs_bufrsnd.log" + fi + ((err+=$rc)) } #------------------------------------ # build fv3nc2nemsio #------------------------------------ $Build_fv3nc2nemsio && { -echo " .... Building fv3nc2nemsio .... " -./build_fv3nc2nemsio.sh > $logs_dir/build_fv3nc2nemsio.log 2>&1 + echo " .... Building fv3nc2nemsio .... " + ./build_fv3nc2nemsio.sh > $logs_dir/build_fv3nc2nemsio.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building fv3nc2nemsio." + echo "The log file is in $logs_dir/build_fv3nc2nemsio.log" + fi + ((err+=$rc)) } #------------------------------------ # build regrid_nemsio #------------------------------------ $Build_regrid_nemsio && { -echo " .... Building regrid_nemsio .... " -./build_regrid_nemsio.sh > $logs_dir/build_regrid_nemsio.log 2>&1 + echo " .... Building regrid_nemsio .... " + ./build_regrid_nemsio.sh > $logs_dir/build_regrid_nemsio.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building regrid_nemsio." + echo "The log file is in $logs_dir/build_regrid_nemsio.log" + fi + ((err+=$rc)) } #------------------------------------ @@ -173,36 +283,48 @@ echo " .... Building regrid_nemsio .... " #------------------------------------ # Only build on WCOSS if [ $target = wcoss -o $target = wcoss_cray -o $target = wcoss_dell_p3 ]; then - $Build_gfs_util && { - echo " .... Building gfs_util .... " - ./build_gfs_util.sh > $logs_dir/build_gfs_util.log 2>&1 - } + $Build_gfs_util && { + echo " .... Building gfs_util .... " + ./build_gfs_util.sh > $logs_dir/build_gfs_util.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gfs_util." + echo "The log file is in $logs_dir/build_gfs_util.log" + fi + ((err+=$rc)) + } fi #------------------------------------ # build gsd_prep_chem #------------------------------------ $Build_gsd_prep_chem && { -echo " .... Building gsd_prep_chem .... " -./build_gsd_prep_chem.sh > $logs_dir/build_gsd_prep_chem.log 2>&1 + echo " .... Building gsd_prep_chem .... " + ./build_gsd_prep_chem.sh > $logs_dir/build_gsd_prep_chem.log 2>&1 + rc=$? + if [[ $rc -ne 0 ]] ; then + echo "Fatal error in building gsd_prep_chem." + echo "The log file is in $logs_dir/build_gsd_prep_chem.log" + fi + ((err+=$rc)) } #------------------------------------ # build prod_util #------------------------------------ $Build_prod_util && { -echo " .... prod_util build not currently supported .... " -#echo " .... Building prod_util .... " -#./build_prod_util.sh > $logs_dir/build_prod_util.log 2>&1 + echo " .... prod_util build not currently supported .... " + #echo " .... Building prod_util .... " + #./build_prod_util.sh > $logs_dir/build_prod_util.log 2>&1 } #------------------------------------ # build grib_util #------------------------------------ $Build_grib_util && { -echo " .... grib_util build not currently supported .... " -#echo " .... Building grib_util .... " -#./build_grib_util.sh > $logs_dir/build_grib_util.log 2>&1 + echo " .... grib_util build not currently supported .... " + #echo " .... Building grib_util .... " + #./build_grib_util.sh > $logs_dir/build_grib_util.log 2>&1 } echo;echo " .... Build system finished .... " diff --git a/sorc/build_enkf_chgres_recenter_nc.sh b/sorc/build_enkf_chgres_recenter_nc.sh new file mode 100755 index 0000000000..d401e01265 --- /dev/null +++ b/sorc/build_enkf_chgres_recenter_nc.sh @@ -0,0 +1,50 @@ +#!/bin/sh +set -eux + +source ./machine-setup.sh > /dev/null 2>&1 +cwd=`pwd` + +USE_PREINST_LIBS=${USE_PREINST_LIBS:-"true"} +if [ $USE_PREINST_LIBS = true ]; then + export MOD_PATH=/scratch3/NCEPDEV/nwprod/lib/modulefiles + source ../modulefiles/fv3gfs/enkf_chgres_recenter_nc.$target > /dev/null 2>&1 +else + export MOD_PATH=${cwd}/lib/modulefiles + if [ $target = wcoss_cray ]; then + source ../modulefiles/fv3gfs/enkf_chgres_recenter_nc.${target}_userlib > /dev/null 2>&1 + else + source ../modulefiles/fv3gfs/enkf_chgres_recenter_nc.$target > /dev/null 2>&1 + fi +fi +module list + +# Check final exec folder exists +if [ ! -d "../exec" ]; then + mkdir ../exec +fi + +cd ${cwd}/enkf_chgres_recenter_nc.fd + +rm -rf build +mkdir build +cd build + +cmake ../ +make + +# re run make now to fix reproducibility issues +# Check final exec folder exists +if [ ! -d "../exec" ]; then + mkdir ../exec +fi + +cd ${cwd}/enkf_chgres_recenter_nc.fd/src + +export FFLAGS="-O3 -qopenmp -traceback -fp-model precise" +export FV3GFS_NCIO_LIB="${cwd}/enkf_chgres_recenter_nc.fd/build/lib/libfv3gfs_ncio.a" +export FV3GFS_NCIO_INC="${cwd}/enkf_chgres_recenter_nc.fd/build/include" + +make clean +make +make install +make clean diff --git a/sorc/build_ufs_utils.sh b/sorc/build_ufs_utils.sh index 292145d764..0882eaa35a 100755 --- a/sorc/build_ufs_utils.sh +++ b/sorc/build_ufs_utils.sh @@ -7,9 +7,8 @@ cwd=`pwd` if [ $target = wcoss_dell_p3 ]; then target=dell; fi if [ $target = wcoss_cray ]; then target=cray; fi -cd ufs_utils.fd/sorc - -./build_all_ufs_utils.sh +cd ufs_utils.fd +./build_all.sh exit diff --git a/sorc/checkout.sh b/sorc/checkout.sh index b2c2d6fdab..f505ccb884 100755 --- a/sorc/checkout.sh +++ b/sorc/checkout.sh @@ -30,7 +30,7 @@ if [[ ! -d fv3gfs.fd ]] ; then rc=$? ((err+=$rc)) cd fv3gfs.fd - git checkout gefs_v12.0.1 + git checkout gefs_v12.1.0 git submodule update --init --recursive rc=$? ((err+=$rc)) @@ -46,7 +46,7 @@ if [[ ! -d gsi.fd ]] ; then rc=$? ((err+=$rc)) cd gsi.fd - git checkout gefs_v12.0.1 + git checkout gfsda.v16.0.0 git submodule update cd ${topdir} else @@ -56,11 +56,12 @@ fi echo ufs_utils checkout ... if [[ ! -d ufs_utils.fd ]] ; then rm -f ${topdir}/checkout-ufs_utils.log - git clone https://github.com/NOAA-EMC/UFS_UTILS.git ufs_utils.fd >> ${LOG_DIR}/checkout-ufs_utils.fd.log 2>&1 + git clone --recursive https://github.com/NOAA-EMC/UFS_UTILS.git ufs_utils.fd >> ${LOG_DIR}/checkout-ufs_utils.fd.log 2>&1 rc=$? ((err+=$rc)) cd ufs_utils.fd - git checkout ops-gefsv12.0.1 + git checkout ops-gefsv12.1 + git submodule update --init --recursive cd ${topdir} else echo 'Skip. Directory ufs_utils.fd already exists.' @@ -79,19 +80,6 @@ else echo 'Skip. Directory gfs_post.fd already exists.' fi -echo EMC_gfs_wafs checkout ... -if [[ ! -d gfs_wafs.fd ]] ; then - rm -f ${topdir}/checkout-gfs_wafs.log - git clone --recursive https://github.com/NOAA-EMC/EMC_gfs_wafs.git gfs_wafs.fd >> ${LOG_DIR}/checkout-gfs_wafs.log 2>&1 - rc=$? - ((err+=$rc)) - cd gfs_wafs.fd - git checkout gfs_wafs.v5.0.11 - cd ${topdir} -else - echo 'Skip. Directory gfs_wafs.fd already exists.' -fi - echo GSD-prep-chem checkout ... if [[ ! -d gsd_prep_chem.fd ]] ; then rm -f ${LOG_DIR}/checkout-gsd-prep-chem.log @@ -105,19 +93,6 @@ else echo 'Skip. Directory gsd_prep_chem.fd already exists.' fi -echo EMC_verif-global checkout ... -if [[ ! -d verif-global.fd ]] ; then - rm -f ${topdir}/checkout-verif-global.log - git clone --recursive gerrit:EMC_verif-global verif-global.fd >> ${LOG_DIR}/checkout-verif-global.log 2>&1 - rc=$? - ((err+=$rc)) - cd verif-global.fd - git checkout verif_global_v1.2.2 - cd ${topdir} -else - echo 'Skip. Directory verif-global.fd already exist.' -fi - #### Exception handling [[ $err -ne 0 ]] && echo "FATAL CHECKOUT ERROR: Please check checkout-*.log file under checkout directory for detail, ABORT!" $ERRSCRIPT || exit $err diff --git a/sorc/enkf_chgres_recenter_nc.fd/CMakeLists.txt b/sorc/enkf_chgres_recenter_nc.fd/CMakeLists.txt new file mode 100644 index 0000000000..007c97ba8a --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/CMakeLists.txt @@ -0,0 +1,144 @@ +# disable in source builds to protect against overwriting other Makefiles +#set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) +if( NOT DEFINED ENV{CC} ) + find_path( crayComp "ftn" ) + find_path( wcossIntel "mpfort" ) + find_path( intelComp "ifort" ) + find_path( pgiComp "pgf90" ) + if( crayComp ) + message("Setting CrayLinuxEnvironment") + set(CMAKE_SYSTEM_NAME "CrayLinuxEnvironment") + set(CMAKE_C_COMPILER "${crayComp}/cc") + set(CMAKE_CXX_COMPILER "${crayComp}/CC") + set(CMAKE_Fortran_COMPILER "${crayComp}/ftn") + endif() + if( intelComp ) + set(ENV{CC} "icc") + set(ENV{CXX} "icpc") + set(ENV{FC} "ifort") + endif() + if( wcossIntel ) + message("Setting env for wcoss intel") + set(ENV{CC} "mpcc") + set(ENV{CXX} "mpCC") + set(ENV{FC} "mpfort") + endif() + if( pgiComp ) + set(ENV{CC} "pgcc") + set(ENV{CXX} "pgCC") + set(ENV{FC} "pgf90") + endif() +endif() + +project(CHGRES) + enable_language (Fortran) + + option(BUILD_FV3GFS_NCIO "Build the FV3GFS_NCIO library" ON) + cmake_minimum_required(VERSION 2.8) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") + SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) + SET(ARCHIVE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + set(CMAKE_INCLUDE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/include") + set(CMAKE_INCLUDE_4_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/include4") + set(Fortran_MODULE_DIRECTORY "${PROJECT_BINARY_DIR}/include") + set(CMAKE_Fortran_MODULE_DIRECTORY "${PROJECT_BINARY_DIR}/include") + file(MAKE_DIRECTORY ${CMAKE_INCLUDE_OUTPUT_DIRECTORY}) + file(MAKE_DIRECTORY ${CMAKE_INCLUDE_4_OUTPUT_DIRECTORY}) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/setPlatformVariables.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/setIntelFlags.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/setGNUFlags.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/setPGIFlags.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/setHOST.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Cheyenne.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Discover.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Generic.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Gaea.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Jet.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/S4.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Hera.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/Orion.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/WCOSS-C.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/WCOSS-D.cmake) + include(${CMAKE_SOURCE_DIR}/cmake/Modules/platforms/WCOSS.cmake) + + cmake_policy(SET CMP0009 NEW) + find_package(OpenMP) + message("found openmp with flag ${OPENMP_Fortran_FLAGS}") + +# Set Host specific flags and options + setHOST() + + if(FIND_HDF5_HL) + find_package(HDF5 COMPONENTS C HL) + elseif(FIND_HDF5) + find_package(HDF5) + endif() + + MESSAGE(${CMAKE_CURRENT_SOURCE_DIR}) + # make sure that the default is a RELEASE + if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE RELEASE CACHE STRING + "Choose the type of build, options are: PRODUCTION Debug Release." + FORCE) + endif (NOT CMAKE_BUILD_TYPE) + + STRING(COMPARE EQUAL ${CMAKE_BUILD_TYPE} "RelWithDebInfo" BUILD_RELEASE) + STRING(COMPARE EQUAL ${CMAKE_BUILD_TYPE} "PRODUCTION" BUILD_PRODUCTION) + STRING(COMPARE EQUAL ${CMAKE_BUILD_TYPE} "PROFILE" BUILD_PROFILE) + set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/exec ) + + set(CMAKE_Fortran_FLAGS_RELEASE "") + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU*") + message("Setting GNU flags") + setGNU() + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + message("Setting Intel flags") + setIntel() + elseif(CMAKE_C_COMPILER MATCHES "pgc*") + message("Setting PGI flags") + setPGI() + endif() + + + find_package(MPI REQUIRED) + message("MPI version is ${MPI_Fortran_VERSION}") + message("MPI f90 version is ${MPI_Fortran_HAVE_F90_MODULE}") + message("MPI f08 version is ${MPI_Fortran_HAVE_F08_MODULE}") + + add_definitions(${MPI_Fortran_COMPILE_FLAGS}) + include_directories(${MPI_Fortran_INCLUDE_DIRS} ${MPI_INCLUDE_PATH} "./" ${CMAKE_INCLUDE_OUTPUT_DIRECTORY}) + link_directories(${MPI_Fortran_LIBRARIES} ${ARCHIVE_OUTPUT_PATH} ) + find_package( NetCDF REQUIRED) + if(NETCDF4) + if(CMAKE_MAJOR_VERSION GREATER 2) + find_package( ZLIB ) + endif() + find_package( CURL ) + endif() + + # default installation + get_filename_component (default_prefix ".." ABSOLUTE) +# set (CMAKE_INSTALL_PREFIX ${default_prefix} CACHE STRING "set prefix" +# FORCE) + + + # FFLAGS depend on the compiler + get_filename_component (Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME) + set(CFLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -O3 -Dfunder") + set (CMAKE_Fortran_INC_FLAGS "-I ./ -I ${CORE_INCS} -I ${NETCDF_INCLUDES} ") + set (CFLAGS_N "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -O3 -Dfunder") + + + find_package( BACIO ) + find_package( SP ) + find_package( W3NCO ) + find_package( IP ) + + if(BUILD_FV3GFS_NCIO) + set(FV3GFS_NCIO_INCS "${PROJECT_BINARY_DIR}/src/fv3gfs_ncio/include") + add_subdirectory(fv3gfs_ncio) + set(FV3GFS_NCIO_LIBRARIES fv3gfs_ncio ) + endif(BUILD_FV3GFS_NCIO) + add_subdirectory(src) diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBACIO.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBACIO.cmake new file mode 100644 index 0000000000..04410f631e --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBACIO.cmake @@ -0,0 +1,55 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{BACIO_VER}) + set(BACIO_VER $ENV{BACIO_VER}) + STRING(REGEX REPLACE "v" "" BACIO_VER ${BACIO_VER}) +endif() +if(NOT BUILD_BACIO ) + if(DEFINED ENV{BACIO_LIB4}) + set(BACIO_LIBRARY $ENV{BACIO_LIB4} ) + else() + find_library( BACIO_LIBRARY + NAMES libbacio.a libbacio_4.a libbacio_v${BACIO_VER}_4.a + HINTS $ENV{COREPATH}/lib /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/bacio/v${BACIO_VER} + ${COREPATH}/bacio/v${BACIO_VER}/intel + ${COREPATH}/bacio/v${BACIO_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH} + ) + message("Found BACIO library ${BACIO_LIBRARY}") + endif() +endif() +if( NOT BACIO_LIBRARY ) # didn't find the library, so build it from source + message("Could not find BACIO library, so building from libsrc") + if( DEFINED ENV{BACIO_SRC} ) + set( BACIO_DIR $ENV{BACIO_SRC} CACHE STRING "BACIO Source Directory" ) + else() + findSrc( "bacio" BACIO_VER BACIO_DIR ) + set(BACIOINC "${CMAKE_BINARY_DIR}/include") + endif() + set( libsuffix "_v${BACIO_VER}${debug_suffix}" ) + set( bacio "bacio${libsuffix}") + set( BUILD_BACIO "ON" CACHE INTERNAL "Build Bacio library" ) + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/bacio) + set( BACIO_LIBRARY ${bacio} ) + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${BACIO_LIBRARY} ) + else() + set( CORE_BUILT ${BACIO_LIBRARY} ) + endif() +else( NOT BACIO_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${BACIO_LIBRARY} ) + else() + set( CORE_LIBRARIES ${BACIO_LIBRARY} ) + endif() +endif( NOT BACIO_LIBRARY ) + +set( BACIO_LIBRARY_PATH ${BACIO_LIBRARY} CACHE STRING "BACIO Library Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBUFR.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBUFR.cmake new file mode 100644 index 0000000000..58527743bc --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBUFR.cmake @@ -0,0 +1,60 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{BUFR_VER}) + set(BUFR_VER $ENV{BUFR_VER}) + STRING(REGEX REPLACE "v" "" BUFR_VER ${BUFR_VER}) +endif() + +set( NO_DEFAULT_PATH ) +if(NOT BUILD_BUFR ) + if(DEFINED ENV{BUFR_LIBd} ) + set(BUFR_LIBRARY $ENV{BUFR_LIBd} ) + message("BUFR library ${BUFR_LIBRARY} set via Environment variable") + else() + find_library( BUFR_LIBRARY + NAMES libbufr.a libbufr_d_64.a libbufr_i4r8.a libbufr_v${BUFR_VER}_d_64.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/bufr/v${BUFR_VER} + ${COREPATH}/bufr/v${BUFR_VER}/intel + ${COREPATH}/bufr/v${BUFR_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( bufr "bufr_v${BUFR_VER}") + message("Found BUFR library ${BUFR_LIBRARY}") + endif() +endif() +if( NOT BUFR_LIBRARY ) # didn't find the library, so build it from source + message("Could not find BUFR library, so building from libsrc") + if( NOT DEFINED ENV{BUFR_SRC} ) + findSrc( "bufr" BUFR_VER BUFR_DIR ) + else() + set( BUFR_DIR "$ENV{BUFR_SRC}/libsrc" CACHE STRING "BUFR Source Location") + endif() + set( libsuffix "_v${BUFR_VER}${debug_suffix}" ) + set( BUFR_LIBRARY "${LIBRARY_OUTPUT_PATH}/libbufr${libsuffix}.a" CACHE STRING "BUFR Library" ) + set( bufr "bufr${libsuffix}") + set( BUILD_BUFR "ON" CACHE INTERNAL "Build the BUFR library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/bufr) + set( BUFR_LIBRARY ${bufr} ) + + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${BUFR_LIBRARY} ) + else() + set( CORE_BUILT ${BUFR_LIBRARY} ) + endif() +else( NOT BUFR_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${BUFR_LIBRARY} ) + else() + set( CORE_LIBRARIES ${BUFR_LIBRARY} ) + endif() +endif() +set( BUFR_LIBRARY_PATH ${BUFR_LIBRARY} CACHE STRING "BUFR Library Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBaselibs.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBaselibs.cmake new file mode 100644 index 0000000000..793cb9a5d4 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindBaselibs.cmake @@ -0,0 +1,68 @@ +if (NOT BASEDIR) + if(${COMPILER_TYPE} STREQUAL "intel" ) + string(REGEX MATCH "mpt" MPT ${MPI_Fortran_INCLUDE_PATH}) + string(REGEX MATCH "impi" IMPI ${MPI_Fortran_INCLUDE_PATH}) + message("REGEX returns ${MPT} ") + if( MPT MATCHES "mpt" ) + message("setting mpt paths ") + set(BASEDIR "/discover/swdev/mathomp4/Baselibs/GMAO-Baselibs-5_0_2/x86_64-unknown-linux-gnu/ifort_15.0.2.164-mpt_2.14/Linux") + elseif( IMPI MATCHES "impi" ) + set(BASEDIR "/discover/swdev/mathomp4/Baselibs/GMAO-Baselibs-5_0_2/x86_64-unknown-linux-gnu/ifort_16.0.3.210-intelmpi_5.1.3.210/Linux") + else() + message (FATAL_ERROR "ERROR: Could not find matching BASELIBS Must specify a value for BASEDIR with cmake ... -DBASEDIR=.") + endif() + message("compiler version is ${COMPILER_VERSION}") + endif() + if(${COMPILER_TYPE} STREQUAL "gnu" ) + string(REGEX MATCH "openmpi" OPENMPI ${MPI_Fortran_INCLUDE_PATH}) + message("REGEX returns ${OPENMPI} ") + if( OPENMPI MATCHES "openmpi" ) + message("setting openmpi paths ") + set(BASEDIR "/discover/swdev/mathomp4/Baselibs/GMAO-Baselibs-4_0_8/x86_64-unknown-linux-gnu/gfortran_7.2.0-openmpi_3.0.0/Linux") + else() + message (FATAL_ERROR "ERROR: Could not find matching BASELIBS Must specify a value for BASEDIR with cmake ... -DBASEDIR=.") + endif() + message("compiler version is ${COMPILER_VERSION}") + endif() + if(${COMPILER_TYPE} STREQUAL "pgi" ) + string(REGEX MATCH "openmpi" OPENMPI ${MPI_Fortran_INCLUDE_PATH}) + if( OPENMPI MATCHES "openmpi" ) + set(BASEDIR "/discover/swdev/mathomp4/Baselibs/GMAO-Baselibs-5_0_1/x86_64-unknown-linux-gnu/pgfortran_16.5-openmpi_1.10.3/Linux") + else() + message (FATAL_ERROR "ERROR: Could not find matching BASELIBS Must specify a value for BASEDIR with cmake ... -DBASEDIR=.") + endif() + message("compiler version is ${COMPILER_VERSION}") + endif() +endif () +if (ESMA_SDF) + message (FATAL_ERROR "ERROR: -hdf option was thought to be obsolete when CMake was crafted.") +endif () + +link_directories (${BASEDIR}/lib) + +#------------------------------------------------------------------ +# netcdf +# The following command provides the list of libraries that netcdf +# uses. Unfortunately it also includes the library path and "-l" +# prefixes, which CMake handles in a different manner. So we need so +# strip off that item from the list +execute_process ( + COMMAND ${BASEDIR}/bin/nf-config --flibs + OUTPUT_VARIABLE LIB_NETCDF + ) + +string(REGEX MATCHALL " -l[^ ]*" _full_libs "${LIB_NETCDF}") +set (NETCDF_LIBRARIES) +foreach (lib ${_full_libs}) + string (REPLACE "-l" "" _tmp ${lib}) + string (STRIP ${_tmp} _tmp) + list (APPEND NETCDF_LIBRARIES ${_tmp}) +endforeach() +#------------------------------------------------------------------ + +list(APPEND NETCDF_INCLUDES ${BASEDIR}/include/netcdf) +list(APPEND NETCDF_INCLUDES ${BASEDIR}/include/hdf5) + +message(STATUS "NETCDF_INCLUDES: ${NETCDF_INCLUDES}") +message(STATUS "NETCDF_LIBRARIES: ${NETCDF_LIBRARIES}") + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindCORELIBS.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindCORELIBS.cmake new file mode 100644 index 0000000000..711864ebce --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindCORELIBS.cmake @@ -0,0 +1,287 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{BUFR_VER}) + set(BUFR_VER $ENV{BUFR_VER}) + STRING(REGEX REPLACE "v" "" BUFR_VER ${BUFR_VER}) +endif() +if(DEFINED ENV{NEMSIO_VER}) + set(NEMSIO_VER $ENV{NEMSIO_VER}) + STRING(REGEX REPLACE "v" "" NEMSIO_VER ${NEMSIO_VER}) +endif() +if(DEFINED ENV{SFCIO_VER}) + set(SFCIO_VER $ENV{SFCIO_VER}) + STRING(REGEX REPLACE "v" "" SFCIO_VER ${SFCIO_VER}) +endif() +if(DEFINED ENV{SIGIO_VER}) + set(SIGIO_VER $ENV{SIGIO_VER}) + STRING(REGEX REPLACE "v" "" SIGIO_VER ${SIGIO_VER}) +endif() +if(DEFINED ENV{SP_VER}) + set(SP_VER $ENV{SP_VER}) + STRING(REGEX REPLACE "v" "" SP_VER ${SP_VER}) +endif() +if(DEFINED ENV{W3EMC_VER}) + set(W3EMC_VER $ENV{W3EMC_VER}) + STRING(REGEX REPLACE "v" "" W3EMC_VER ${W3EMC_VER}) +endif() +if(DEFINED ENV{W3NCO_VER}) + set(W3NCO_VER $ENV{W3NCO_VER}) + STRING(REGEX REPLACE "v" "" W3NCO_VER ${W3NCO_VER}) +endif() + +set (CORE_DEPS " ") +set( NO_DEFAULT_PATH ) +if(NOT BUILD_EMC ) + if(DEFINED ENV{W3EMC_LIBd} ) + set(W3EMC_LIBRARY $ENV{W3EMC_LIBd} ) + set(W3EMCINC $ENV{W3EMC_INCd} ) + else() + find_path( W3EMCINC + NAMES mersenne_twister.mod + HINTS + $ENV{COREPATH}/lib/incmod/w3emc_4 + $ENV{COREPATH}/include + /usr/local/jcsda/nwprod_gdas_2014/lib/lib/incmod/w3emc_4 + ${COREPATH}/w3emc/v${W3EMC_VER}/incmod/w3emc_v${W3EMC_VER}_d + ${COREPATH}/w3emc/v${W3EMC_VER}/intel/w3emc_v${W3EMC_VER}_d + ) + find_library( W3EMC_LIBRARY + NAMES libw3emc_4.a libw3emc_i4r8.a libw3emc_v${W3EMC_VER}_d.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/w3emc/v${W3EMC_VER} + ${COREPATH}/w3emc/v${W3EMC_VER}/intel + PATH_SUFFIXES + lib + ) + message("Found W3EMC library ${W3EMC_LIBRARY}") + endif() +else() + set( libsuffix "_v${W3EMC_VER}${debug_suffix}" ) + set( W3EMC_LIBRARY "${LIBRARY_OUTPUT_PATH}/libw3emc${libsuffix}.a" CACHE STRING "W3EMC Library" ) + set( w3emc "w3emc${libsuffix}") + if( DEFINED ENV{W3EMC_SRC} ) + set( W3EMC_DIR $ENV{W3EMC_SRC} CACHE STRING "W3EMC Source Directory" ) + else() + if( FIND_SRC ) + findSrc( "w3emc" W3EMC_VER W3EMC_DIR ) + endif() + endif() +endif() +if(NOT BUILD_NCO ) + if(DEFINED ENV{W3NCO_LIBd} ) + set(W3NCO_LIBRARY $ENV{W3NCO_LIBd} ) + else() + find_library( W3NCO_LIBRARY + NAMES libw3nco_v${W3NCO_VER}_d.a libw3nco_d.a libw3nco_i4r8.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/w3nco/v${W3NCO_VER} + ${COREPATH}/w3nco/v${W3NCO_VER}/intel + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + message("Found W3NCO library ${W3NCO_LIBRARY}") + endif() +else() + if( DEFINED ENV{W3NCO_SRC} ) + set( W3NCO_DIR $ENV{W3NCO_SRC} CACHE STRING "W3NCO Source Directory" ) + else() + if( FIND_SRC ) + findSrc( "w3nco" W3NCO_VER W3NCO_DIR ) + endif() + endif() + set( libsuffix "_v${W3NCO_VER}${debug_suffix}" ) + set( W3NCO_LIBRARY "${LIBRARY_OUTPUT_PATH}/libw3nco${libsuffix}.a" CACHE STRING "W3NCO Library" ) + set( w3nco "w3nco${libsuffix}") +endif() +if(NOT BUILD_BUFR ) + if(DEFINED ENV{BUFR_LIBd} ) + set(BUFR_LIBRARY $ENV{BUFR_LIBd} ) + else() + find_library( BUFR_LIBRARY + NAMES libbufr.a libbufr_d_64.a libbufr_i4r8.a libbufr_v${BUFR_VER}_d_64.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/bufr/v${BUFR_VER} + ${COREPATH}/bufr/v${BUFR_VER}/intel + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( bufr "bufr_v${BUFR_VER}") + message("Found BUFR library ${BUFR_LIBRARY}") + endif() +else() + if( DEFINED ENV{BUFR_SRC} ) + set( BUFR_DIR $ENV{BUFR_SRC} CACHE STRING "BUFR Source Directory" ) + else() + if( FIND_SRC ) + findSrc( "bufr" BUFR_VER BUFR_DIR ) + endif() + endif() + set( libsuffix "_v${BUFR_VER}${debug_suffix}" ) + set( BUFR_LIBRARY "${LIBRARY_OUTPUT_PATH}/libbufr${libsuffix}.a" CACHE STRING "BUFR Library" ) + set( bufr "bufr${libsuffix}") +endif() +if(NOT BUILD_SFCIO ) + if(DEFINED ENV{SFCIO_LIB4} ) + set(SFCIO_LIBRARY $ENV{SFCIO_LIB4} ) + set(SFCIOINC $ENV{SFCIO_INC4} ) + else() + findInc( sfcio SFCIO_VER SFCIOINC ) + find_library( SFCIO_LIBRARY + NAMES libsfcio.a libsfcio_4.a libsfcio_i4r4.a libsfcio_v${SFCIO_VER}_4.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/sfcio/v${SFCIO_VER} + ${COREPATH}/sfcio/v${SFCIO_VER}/intel + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( sfcio "sfcio_v${SFCIO_VER}_4") + message("Found SFCIO library ${SFCIO_LIBRARY}") + endif() +else() + if( DEFINED ENV{SFCIO_SRC} ) + set( SFCIO_DIR $ENV{SFCIO_SRC} CACHE STRING "SFCIO Source Directory" ) + else() + if( FIND_SRC ) + findSrc( "sfcio" SFCIO_VER SFCIO_DIR ) + endif() + endif() + set( libsuffix "_v${SFCIO_VER}${debug_suffix}" ) + set( SFCIO_LIBRARY "${LIBRARY_OUTPUT_PATH}/libsfcio${libsuffix}.a" CACHE STRING "SFCIO Library" ) + set( sfcio "sfcio${libsuffix}") +endif() +if(NOT BUILD_SIGIO ) + if(DEFINED ENV{SIGIO_LIB4} ) + set(SIGIO_LIBRARY $ENV{SIGIO_LIB4} ) + set(SIGIOINC $ENV{SIGIO_INC4} ) + else() + findInc( sigio SIGIO_VER SIGIOINC ) + message("SIGIOINC is ${SIGIOINC}") + find_library( SIGIO_LIBRARY + NAMES libsigio.a libsigio_4.a libsigio_i4r4.a libsigio_v${SIGIO_VER}_4.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/sigio/v${SIGIO_VER} + ${COREPATH}/sigio/v${SIGIO_VER}/intel + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( sigio "sigio_v${SIGIO_VER}_4") + message("Found SIGIO library ${SIGIO_LIBRARY}") + endif() +else() + if( DEFINED ENV{SIGIO_SRC} ) + set( SIGIO_DIR $ENV{SIGIO_SRC} CACHE STRING "SIGIO Source Directory" ) + else() + if( FIND_SRC ) + findSrc( "sigio" SIGIO_VER SIGIO_DIR ) + endif() + endif() + set( libsuffix "_v${SIGIO_VER}${debug_suffix}" ) + set( SIGIO_LIBRARY "${LIBRARY_OUTPUT_PATH}/libsigio${libsuffix}.a" CACHE STRING "SIGIO Library" ) + set( sigio "sigio${libsuffix}") + set( CORE_DEPS "${CORE_DEPS} ${baseName}" ) +endif() +if(NOT BUILD_NEMSIO ) + if(DEFINED ENV{NEMSIO_LIB} ) + set(NEMSIO_LIBRARY $ENV{NEMSIO_LIB} ) + set(NEMSIOINC $ENV{NEMSIO_INC} ) + else() + findInc( nemsio NEMSIO_VER NEMSIOINC ) + find_library( NEMSIO_LIBRARY + NAMES libnemsio.a libnemsio_v${NEMSIO_VER}.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/nemsio/v${NEMSIO_VER} + ${COREPATH}/nemsio/v${NEMSIO_VER}/intel + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( nemsio "nemsio_v${NEMSIO_VER}") + message("Found NEMSIO library ${NEMSIO_LIBRARY}") + endif() +else() + if( DEFINED ENV{NEMSIO_SRC} ) + set( NEMSIO_DIR $ENV{NEMSIO_SRC} CACHE STRING "NEMSIO Source Directory" ) + else() + if( FIND_SRC ) + findSrc( "nemsio" NEMSIO_VER NEMSIO_DIR ) + endif() + endif() + set( libsuffix "_v${NEMSIO_VER}${debug_suffix}" ) + set( NEMSIO_LIBRARY "${LIBRARY_OUTPUT_PATH}/libnemsio${libsuffix}.a" CACHE STRING "NEMSIO Library" ) + set( nemsio "nemsio${libsuffix}") +endif() +if(NOT BUILD_SP ) + if(DEFINED ENV{SP_LIBd} ) + set(SP_LIBRARY $ENV{SP_LIBd} ) + else() + find_library( SP_LIBRARY + NAMES libsp_d.a libsp_i4r8.a libsp_v${SP_VER}_d.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/sp/v${SP_VER} + ${COREPATH}/sp/v${SP_VER}/intel + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( sp "sp_v${SP_VER}_d") + message("Found SP library ${SP_LIBRARY}") + endif() +else() + if( DEFINED ENV{SP_SRC} ) + set( SP_DIR $ENV{SP_SRC} CACHE STRING "SP Source Directory" ) + else() + if( FIND_SRC ) + findSrc( "sp" SP_VER SP_DIR ) + endif() + endif() + set( libsuffix "_v${SP_VER}${debug_suffix}" ) + set( SP_LIBRARY "${LIBRARY_OUTPUT_PATH}/libsp${libsuffix}.a" CACHE STRING "SP Library" ) + set( sp "sp${libsuffix}") +endif() + +if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${SFCIO_LIBRARY} ${SIGIO_LIBRARY} + ${NEMSIO_LIBRARY} ${SP_LIBRARY} ${W3NCO_LIBRARY} ${BUFR_LIBRARY} + ${W3EMC_LIBRARY} CACHE INTERNAL "List of Core libs" ) + list( APPEND CORE_INCS ${INCLUDE_OUTPUT_PATH} ${SFCIOINC} ${SIGIOINC} ${NEMSIOINC} ${W3EMCINC} ) +else() + set( CORE_LIBRARIES ${SFCIO_LIBRARY} ${SIGIO_LIBRARY} + ${NEMSIO_LIBRARY} ${SP_LIBRARY} ${W3NCO_LIBRARY} ${BUFR_LIBRARY} + ${W3EMC_LIBRARY} CACHE INTERNAL "List of Core libs" ) + set( CORE_INCS ${INCLUDE_OUTPUT_PATH} ${SFCIOINC} ${SIGIOINC} ${NEMSIOINC} ${W3EMCINC} ) +endif() + +set( BUFR_LIBRARY_PATH ${BUFR_LIBRARY} CACHE STRING "BUFR Library Location" ) + +set( SFCIO_LIBRARY_PATH ${SFCIO_LIBRARY} CACHE STRING "SFCIO Library Location" ) +set( SFCIO_INCLUDE_PATH ${SFCIOINC} CACHE STRING "SFCIO Include Location" ) + +set( SIGIO_LIBRARY_PATH ${SIGIO_LIBRARY} CACHE STRING "SIGIO Library Location" ) +set( SIGIO_INCLUDE_PATH ${SIGIOINC} CACHE STRING "SIGIO Include Location" ) + +set( W3NCO_LIBRARY_PATH ${W3NCO_LIBRARY} CACHE STRING "W3NCO Library Location" ) + +set( W3EMC_LIBRARY_PATH ${W3EMC_LIBRARY} CACHE STRING "W3EMC Library Location" ) +set( W3EMC_INCLUDE_PATH ${W3EMCINC} CACHE STRING "W3EMC Include Location" ) + +set( NEMSIO_LIBRARY_PATH ${NEMSIO_LIBRARY} CACHE STRING "NEMSIO Library Location" ) +set( NEMSIO_INCLUDE_PATH ${NEMSIOINC} CACHE STRING "NEMSIO Include Location" ) + +set( SP_LIBRARY_PATH ${SP_LIBRARY} CACHE STRING "SP Library Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindCRTM.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindCRTM.cmake new file mode 100644 index 0000000000..ee982c1499 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindCRTM.cmake @@ -0,0 +1,81 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{CRTM_VER}) + set(CRTM_VER $ENV{CRTM_VER}) + STRING(REGEX REPLACE "v" "" CRTM_VER ${CRTM_VER}) +endif() + +set( NO_DEFAULT_PATH ) +if(NOT BUILD_CRTM ) + if(DEFINED ENV{CRTM_LIB} ) + set(CRTM_LIBRARY $ENV{CRTM_LIB} ) + set(CRTMINC $ENV{CRTM_INC} ) + message("CRTM library ${CRTM_LIBRARY} set via Environment variable") + else() + findInc( crtm CRTM_VER CRTMINC ) + find_library( CRTM_LIBRARY + NAMES libcrtm_v${CRTM_VER}.a libcrtm.a libCRTM.a + HINTS + /usr/local/jcsda/nwprod_gdas_2014/lib + ${CRTM_BASE} + ${CRTM_BASE}/lib + ${CRTM_BASE}/${CRTM_VER} + ${CRTM_BASE}/${CRTM_VER}/lib + ${CRTM_BASE}/v${CRTM_VER}/intel + ${CRTM_BASE}/v${CRTM_VER}/ips/${COMPILER_VERSION} + ${COREPATH}/v${CRTM_VER}/ips/${COMPILER_VERSION} + ${COREPATH} + ${COREPATH}/lib + $ENV{COREPATH} + $ENV{COREPATH}/lib + $ENV{COREPATH}/include + ${CORECRTM}/crtm/${CRTM_VER} + /nwprod2/lib/crtm/v${CRTM_VER} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( crtm "crtm_v${CRTM_VER}") + message("Found CRTM library ${CRTM_LIBRARY}") + endif() +endif() +if( NOT CRTM_LIBRARY ) # didn't find the library, so build it from source + message("Could not find CRTM library, so building from libsrc") + if( NOT DEFINED ENV{CRTM_SRC} ) + findSrc( "crtm" CRTM_VER CRTM_DIR ) + set(CRTMINC "${CMAKE_BINARY_DIR}/include") + else() + set( CRTM_DIR "$ENV{CRTM_SRC}/libsrc" CACHE STRING "CRTM Source Location") + set(CRTMINC "${CORECRTM}/crtm/${CRTM_VER}/incmod/crtm_v${CRTM_VER}") + endif() + set( libsuffix "_v${CRTM_VER}${debug_suffix}" ) + set( CRTM_LIBRARY "${LIBRARY_OUTPUT_PATH}/libcrtm${libsuffix}.a" CACHE STRING "CRTM Library" ) + set( crtm "crtm${libsuffix}") + set( BUILD_CRTM "ON" CACHE INTERNAL "Build the CRTM library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/crtm) + set( CRTM_LIBRARY ${crtm} ) + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${CRTM_LIBRARY} ) + else() + set( CORE_BUILT ${CRTM_LIBRARY} ) + endif() +else( NOT CRTM_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${CRTM_LIBRARY} ) + else() + set( CORE_LIBRARIES ${CRTM_LIBRARY} ) + endif() +endif( NOT CRTM_LIBRARY ) + +if( CORE_INCS ) + list( APPEND CORE_INCS ${CRTMINC} ) +else() + set( CORE_INCS ${INCLUDE_OUTPUT_PATH} ${CRTMINC} ) +endif() + +set( CRTM_LIBRARY_PATH ${CRTM_LIBRARY} CACHE STRING "CRTM Library Location" ) +set( CRTM_INCLUDE_PATH ${CRTMINC} CACHE STRING "CRTM Include Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindGSICONTROL.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindGSICONTROL.cmake new file mode 100644 index 0000000000..5b2e12280a --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindGSICONTROL.cmake @@ -0,0 +1,52 @@ +# - Find the Control version of GSI to use for regression testing + +set( NO_DEFAULT_PATH ) +message("Control path is ${CONTROLPATH}") +find_file( CONTROL_EXE + NAMES gsi.x global_gsi ${GSIEXEC} + HINTS + ${CONTROLPATH} + ${CONTROLPATH}/bin + ${CONTROLPATH}/exec + $ENV{CONTROLPATH} + $ENV{CONTROLPATH}/bin + $ENV{CONTROLPATH}/exec + $ENV{CONTROLPATH}/src + ${CMAKE_SOURCE_DIR}/../trunk/src + ${CMAKE_SOURCE_DIR}/../../trunk/src + ${PROJECT_BINARY_DIR}/../build-trunk/bin + /da/save/Michael.Lueken/svn1/build/bin + /da/save/Michael.Lueken/svn1/src + /gpfs/dell2/emc/modeling/noscrub/Michael.Lueken/svn1/build/bin + /gpfs/hps3/emc/da/noscrub/Michael.Lueken/svn1/build/bin + /gpfs/hps3/emc/da/noscrub/Michael.Lueken/svn1/src + /scratch1/NCEPDEV/da/Michael.Lueken/svn1/build/bin + + ${NO_DEFAULT_PATH}) + +set( GSICONTROL ${CONTROL_EXE} CACHE STRING "GSI control executable for regression testing" FORCE ) + +find_file( ENKF_CONTROL_EXE + NAMES enkf_gfs.x global_enkf ${ENKFEXEC} + HINTS + ${CONTROLPATH} + ${CONTROLPATH}/bin + ${CONTROLPATH}/exec + $ENV{CONTROLPATH} + $ENV{CONTROLPATH}/bin + $ENV{CONTROLPATH}/exec + ${CMAKE_SOURCE_DIR}/../trunk/src/enkf + ${PROJECT_BINARY_DIR}/../build-trunk/bin + $ENV{CONTROLPATH}/enkf + $ENV{CONTROLPATH}/src/enkf + /da/save/Michael.Lueken/svn1/build/bin + /da/save/Michael.Lueken/svn1/src/enkf + /gpfs/dell2/emc/modeling/noscrub/Michael.Lueken/svn1/build/bin + /gpfs/hps3/emc/da/noscrub/Michael.Lueken/svn1/build/bin + /gpfs/hps3/emc/da/noscrub/Michael.Lueken/svn1/src/enkf + /scratch1/NCEPDEV/da/Michael.Lueken/svn1/build/bin + + ${NO_DEFAULT_PATH}) + +set( ENKFCONTROL ${ENKF_CONTROL_EXE} CACHE STRING "ENKF control executable for regression testing" FORCE ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindHDF5.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindHDF5.cmake new file mode 100644 index 0000000000..78e3db3678 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindHDF5.cmake @@ -0,0 +1,24 @@ +# This extends CMake's FindHDF5.cmake to add support to include MPI include +# paths and libraries in the HDF5 ones if HDF5_IS_PARALLEL is ON +# (BUG #0014363). + +# include the default FindHDF5.cmake. +#if(CMAKE_VERSION VERSION_LESS 3.6.1) +if(CMAKE_VERSION VERSION_GREATER 3.0 ) + include(${CMAKE_CURRENT_LIST_DIR}/NewCMake/FindHDF5.cmake) +else() + include(${CMAKE_ROOT}/Modules/FindHDF5.cmake) +endif() +#endif() + +if(HDF5_FOUND AND (HDF5_IS_PARALLEL OR HDF5_ENABLE_PARALLEL)) + if(MPI_C_INCLUDE_PATH) + list(APPEND HDF5_INCLUDE_DIRS ${MPI_C_INCLUDE_PATH}) + endif() + if(MPI_C_LIBRARIES) + list(APPEND HDF5_LIBRARIES ${MPI_C_LIBRARIES}) + endif() + if(MPI_CXX_LIBRARIES) + list(APPEND HDF5_LIBRARIES ${MPI_CXX_LIBRARIES}) + endif() +endif() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindIP.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindIP.cmake new file mode 100644 index 0000000000..26ec21704e --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindIP.cmake @@ -0,0 +1,83 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{IP_VER}) + set(IP_VER $ENV{IP_VER}) + STRING(REGEX REPLACE "v" "" IP_VER ${IP_VER}) +endif() + +set( NO_DEFAULT_PATH ) +if(NOT BUILD_IP ) + if(DEFINED ENV{IP_LIBd} ) + set(IP_LIBRARY $ENV{IP_LIBd} ) + message("IP library ${IP_LIBRARY} set via Environment variable") + else() + find_library( IP_LIBRARY + NAMES libip_d.a libip_i4r8.a libip_v${IP_VER}_d.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/ip/v${IP_VER} + ${COREPATH}/ip/v${IP_VER}/intel + ${COREPATH}/ip/v${IP_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( ip "ip_v${IP_VER}_d") + message("Found IP library ${IP_LIBRARY}") + endif() + if(DEFINED ENV{IP_LIB4} ) + set(IP_4_LIBRARY $ENV{IP_LIB4} ) + message("IP 4 library ${IP_4_LIBRARY} set via Environment variable") + else() + find_library( IP_4_LIBRARY + NAMES libip_4.a libip_i4r4.a libip_v${IP_VER}_4.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/ip/v${IP_VER} + ${COREPATH}/ip/v${IP_VER}/intel + ${COREPATH}/ip/v${IP_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( ip "ip_v${IP_VER}_4") + message("Found IP_4 library ${IP_4_LIBRARY}") + endif() +endif() +if( NOT IP_LIBRARY ) # didn't find the library, so build it from source + message("Could not find IP library, so building from libsrc") + if( NOT DEFINED ENV{IP_SRC} ) + findSrc( "ip" IP_VER IP_DIR ) + else() + set( IP_DIR "$ENV{IP_SRC}/libsrc" CACHE STRING "IP Source Location") + endif() + set( libsuffix "_v${IP_VER}${debug_suffix}" ) + set( IP_LIBRARY "${LIBRARY_OUTPUT_PATH}/libip${libsuffix}.a" CACHE STRING "IP Library" ) + set( IP_4_LIBRARY "${LIBRARY_OUTPUT_PATH}/libip_4${libsuffix}.a" CACHE STRING "IP_4 Library" ) + set( ip "ip${libsuffix}") + set( ip4 "ip_4${libsuffix}") + set( BUILD_IP "ON" CACHE INTERNAL "Build the IP library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/ip) + set( IP_LIBRARY ${ip} ) + set( IP_4_LIBRARY ${ip4} ) + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${IP_LIBRARY} ) + else() + set( CORE_BUILT ${IP_LIBRARY} ) + endif() +else( NOT IP_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${IP_LIBRARY} ) + else() + set( CORE_LIBRARIES ${IP_LIBRARY} ) + endif() +endif( NOT IP_LIBRARY ) + + +set( IP_LIBRARY_PATH ${IP_LIBRARY} CACHE STRING "IP Library Location" ) +set( IP_4_LIBRARY_PATH ${IP_4_LIBRARY} CACHE STRING "IP_4 Library Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindMPI.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindMPI.cmake new file mode 100644 index 0000000000..8e0a0c95ba --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindMPI.cmake @@ -0,0 +1,18 @@ +# This extends CMake's FindHDF5.cmake to add support to include MPI include +# paths and libraries in the HDF5 ones if HDF5_IS_PARALLEL is ON +# (BUG #0014363). + +# include the default FindMPI.cmake. +if(CMAKE_VERSION VERSION_LESS 3.1) + include(${CMAKE_ROOT}/Modules/FindMPI.cmake) +elseif(CMAKE_VERSION VERSION_LESS 3.6) + message("Using new FindMPI") + include(${CMAKE_CURRENT_LIST_DIR}/NewCMake/FindMPI.cmake) +# set(MPI_Fortran_INCLUDE_DIRS ${MPI_Fortran_INCLUDE_PATH} CACHE INTERNAL "Deprecated Variable Name") +else() + message("Using installed FindMPI") + include(${CMAKE_ROOT}/Modules/FindMPI.cmake) +# set(MPI_Fortran_INCLUDE_DIRS ${MPI_Fortran_INCLUDE_PATH} CACHE INTERNAL "Deprecated Variable Name") + message("include dirs are ${MPI_Fortran_INCLUDE_DIRS}") + message("include PATH ${MPI_Fortran_INCLUDE_PATH}") +endif() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNDATE.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNDATE.cmake new file mode 100644 index 0000000000..44bf4f1cd5 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNDATE.cmake @@ -0,0 +1,13 @@ +# - Find the NDATE utility or build it + +set( NO_DEFAULT_PATH ) +if(DEFINED ENV{NDATE}) + set(NDATE $ENV{NDATE} ) +else() + find_file( NDATE + NAMES ndate.x ndate + HINTS + /nwprod/util/exec + $ENV{NWPROD}/util/exec + ${NO_DEFAULT_PATH}) +endif() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNEMSIO.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNEMSIO.cmake new file mode 100644 index 0000000000..1263fc516a --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNEMSIO.cmake @@ -0,0 +1,72 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{NEMSIO_VER}) + set(NEMSIO_VER $ENV{NEMSIO_VER}) + STRING(REGEX REPLACE "v" "" NEMSIO_VER ${NEMSIO_VER}) +endif() + +set( NO_DEFAULT_PATH ) +if(NOT BUILD_NEMSIO ) + if(DEFINED ENV{NEMSIO_LIB} ) + set(NEMSIO_LIBRARY $ENV{NEMSIO_LIB} ) + set(NEMSIOINC $ENV{NEMSIO_INC} ) + message("NEMSIO library ${NEMSIO_LIBRARY} set via Environment variable") + else() + findInc( nemsio NEMSIO_VER NEMSIOINC ) + find_library( NEMSIO_LIBRARY + NAMES libnemsio_v${NEMSIO_VER}.a libnemsio.a libNEMSIO.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/nemsio/v${NEMSIO_VER} + ${COREPATH}/nemsio/v${NEMSIO_VER}/intel + ${COREPATH}/nemsio/v${NEMSIO_VER}//ips/${COMPILER_VERSION}/impi/${COMPILER_VERSION} + ${COREPATH}/nemsio/v${NEMSIO_VER}//ips/${COMPILER_VERSION}/smpi/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( nemsio "nemsio_v${NEMSIO_VER}") + message("Found NEMSIO library ${NEMSIO_LIBRARY}") + endif() +endif() +if( NOT NEMSIO_LIBRARY ) # didn't find the library, so build it from source + message("Could not find NEMSIO library, so building from libsrc") + if( NOT DEFINED ENV{NEMSIO_SRC} ) + findSrc( "nemsio" NEMSIO_VER NEMSIO_DIR ) + set(NEMSIOINC "${CMAKE_BINARY_DIR}/include") + else() + set( NEMSIO_DIR "$ENV{NEMSIO_SRC}/libsrc" CACHE STRING "NEMSIO Source Location") + set(NEMSIOINC "${CORENEMSIO}/nemsio/${NEMSIO_VER}/incmod/nemsio_v${NEMSIO_VER}") + endif() + set( libsuffix "_v${NEMSIO_VER}${debug_suffix}" ) + set( NEMSIO_LIBRARY "${LIBRARY_OUTPUT_PATH}/libnemsio${libsuffix}.a" CACHE STRING "NEMSIO Library" ) + set( nemsio "nemsio${libsuffix}") + set( BUILD_NEMSIO "ON" CACHE INTERNAL "Build the NEMSIO library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/nemsio) + set( NEMSIO_LIBRARY ${nemsio} ) + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${NEMSIO_LIBRARY} ) + else() + set( CORE_BUILT ${NEMSIO_LIBRARY} ) + endif() +else( NOT NEMSIO_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${NEMSIO_LIBRARY} ) + else() + set( CORE_LIBRARIES ${NEMSIO_LIBRARY} ) + endif() +endif( NOT NEMSIO_LIBRARY ) + +if( CORE_INCS ) + list( APPEND CORE_INCS ${NEMSIOINC} ) +else() + set( CORE_INCS ${INCLUDE_OUTPUT_PATH} ${NEMSIOINC} ) +endif() + +set( NEMSIO_LIBRARY_PATH ${NEMSIO_LIBRARY} CACHE STRING "NEMSIO Library Location" ) +set( NEMSIO_INCLUDE_PATH ${NEMSIOINC} CACHE STRING "NEMSIO Include Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNetCDF.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNetCDF.cmake new file mode 100644 index 0000000000..f114c8df86 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindNetCDF.cmake @@ -0,0 +1,147 @@ +# - Find NetCDF +# Find the native NetCDF includes and library +# +# NETCDF_INCLUDES - where to find netcdf.h, etc +# NETCDF_LIBRARIES - Link these libraries when using NetCDF +# NETCDF_FOUND - True if NetCDF found including required interfaces (see below) +# +# Your package can require certain interfaces to be FOUND by setting these +# +# NETCDF_CXX - require the C++ interface and link the C++ library +# NETCDF_F77 - require the F77 interface and link the fortran library +# NETCDF_F90 - require the F90 interface and link the fortran library +# +# The following are not for general use and are included in +# NETCDF_LIBRARIES if the corresponding option above is set. +# +# NETCDF_LIBRARIES_C - Just the C interface +# NETCDF_LIBRARIES_CXX - C++ interface, if available +# NETCDF_LIBRARIES_F77 - Fortran 77 interface, if available +# NETCDF_LIBRARIES_F90 - Fortran 90 interface, if available +# +# Normal usage would be: +# set (NETCDF_F90 "YES") +# find_package (NetCDF REQUIRED) +# target_link_libraries (uses_f90_interface ${NETCDF_LIBRARIES}) +# target_link_libraries (only_uses_c_interface ${NETCDF_LIBRARIES_C}) + + +set(NETCDF_DIR $ENV{NETCDF}) +message("Enviroment NETCDF is ${NetCDF}") + +if (NETCDF_INCLUDES AND NETCDF_LIBRARIES) + # Already in cache, be silent + set (NETCDF_FIND_QUIETLY TRUE) +endif (NETCDF_INCLUDES AND NETCDF_LIBRARIES) + +if(DEFINED ENV{NETCDF4}) + message("Enviroment NETCDF4 is ${NetCDF4}") + set(NETCDF_DIR $ENV{NETCDF4}) +elseif(DEFINED ENV{NETCDF_DIR}) + set(NETCDF_DIR $ENV{NETCDF_DIR}) +elseif(DEFINED ENV{NETCDF_HOME}) + set(NETCDF_DIR $ENV{NETCDF_HOME}) +elseif( DEFINED ENV{NETCDF} ) + set(NETCDF_DIR $ENV{NETCDF}) +elseif(DEFINED ENV{SSEC_NETCDF4_DIR}) + set(NETCDF_DIR $ENV{SSEC_NETCDF4_DIR}) +elseif(DEFINED ENV{SSEC_NETCDF_DIR}) + set(NETCDF_DIR $ENV{SSEC_NETCDF_DIR}) +endif() +if(DEFINED ENV{NETCDF_FORTRAN}) + set(NETCDF_FORTRAN $ENV{NETCDF_FORTRAN}) +elseif(DEFINED ENV{NETCDF_FORTRAN_DIR}) + set(NETCDF_FORTRAN $ENV{NETCDF_FORTRAN_DIR}) +endif() +find_path (NETCDF_INCLUDES netcdf.h + HINTS ${NETCDF_DIR}/include $ENV{SSEC_NETCDF_DIR}/include ) + +find_program (NETCDF_META netcdf_meta.h + HINTS ${NETCDF_INCLUDES} ${CMAKE_INSTALL_PREFIX} + ) +if (NETCDF_META) + file (STRINGS ${NETCDF_META} NETCDF_VERSION REGEX "define NC_VERSION_MAJOR") + string (REGEX REPLACE "#define NC_VERSION_MAJOR " "" NETCDF_VERSION ${NETCDF_VERSION}) + string (REGEX REPLACE "\\/\\*\\!< netcdf-c major version. \\*\\/" "" NETCDF_VERSION ${NETCDF_VERSION}) + string (REGEX REPLACE " " "" NETCDF_VERSION ${NETCDF_VERSION} ) + if(${NETCDF_VERSION} GREATER "3") + set(NETCDF_F90 "YES") + endif() +endif (NETCDF_META) + +find_library (NETCDF_flib + names libnetcdff.a netcdff.a libnetcdff.so netcdff.so + HINTS + ${NETCDF_DIR}/lib + ${NETCDF_FORTRAN_DIR}/lib + ${NETCDF_FORTRAN}/lib + ${NETCDF_FORTRAN_ROOT}/lib +) + +if (NETCDF_flib) + set(NETCDF_F90 "YES") + +endif() +find_library (NETCDF_LIBRARIES_C + NAMES netcdf + HINTS ${NETCDF_DIR}/lib ) +mark_as_advanced(NETCDF_LIBRARIES_C) + +if("${NETCDF_DIR}" STREQUAL "") + message(FATAL_ERROR " + Cannot find NETCDF!!!! + + ") +endif() +find_file (NETCDF_NCDUMP + NAMES ncdump + HINTS ${NETCDF_DIR}/bin ) +mark_as_advanced(NETCDF_NCDUMP) +execute_process(COMMAND ${NETCDF_NCDUMP} + ERROR_VARIABLE NCDUMP_INFO) +string(FIND "${NCDUMP_INFO}" "version" VERSION_LOC REVERSE) +math(EXPR VERSION_LOC "${VERSION_LOC} + 9") +string(SUBSTRING "${NCDUMP_INFO}" ${VERSION_LOC} 1 NETCDF_MAJOR_VERSION) +if (${NETCDF_MAJOR_VERSION} LESS 4) + message(FATAL_ERROR " + Current NETCDF is ${NETCDF_DIR} + !!!! NETCDF version 4.0 and above is required !!!! + + ") +endif() + +set (NetCDF_has_interfaces "YES") # will be set to NO if we're missing any interfaces +set (NetCDF_libs ${NETCDF_LIBRARIES_C} ${NETCDF_LIBRARIES_Fortran}) +message("netcdf_libs is ${NetCDF_libs}") +get_filename_component (NetCDF_lib_dirs "${NETCDF_LIBRARIES_C}" PATH) + +macro (NetCDF_check_interface lang header libs) + if (NETCDF_${lang}) + find_path (NETCDF_INCLUDES_${lang} NAMES ${header} + HINTS ${NETCDF_INCLUDES} ${NETCDF_FORTRAN}/include NO_DEFAULT_PATH) + find_library (NETCDF_LIBRARIES_${lang} NAMES ${libs} + HINTS ${NetCDF_lib_dirs} ${NETCDF_FORTRAN}/lib NO_DEFAULT_PATH) + mark_as_advanced (NETCDF_INCLUDES_${lang} NETCDF_LIBRARIES_${lang}) + if (NETCDF_INCLUDES_${lang} AND NETCDF_LIBRARIES_${lang}) + list (INSERT NetCDF_libs 0 ${NETCDF_LIBRARIES_${lang}}) # prepend so that -lnetcdf is last + else (NETCDF_INCLUDES_${lang} AND NETCDF_LIBRARIES_${lang}) + set (NetCDF_has_interfaces "NO") + message (STATUS "Failed to find NetCDF interface for ${lang}") + endif (NETCDF_INCLUDES_${lang} AND NETCDF_LIBRARIES_${lang}) + endif (NETCDF_${lang}) +endmacro (NetCDF_check_interface) + +NetCDF_check_interface (CXX netcdfcpp.h netcdf_c++) +NetCDF_check_interface (F77 netcdf.inc netcdff) +NetCDF_check_interface (F90 netcdf.mod netcdff) +if( NETCDF_LIBRARIES_F90 ) + set( NETCDF4 "YES" ) +endif() + +set (NETCDF_LIBRARIES "${NetCDF_libs}" CACHE STRING "All NetCDF libraries required for interface level") +# handle the QUIETLY and REQUIRED arguments and set NETCDF_FOUND to TRUE if +# all listed variables are TRUE +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (NetCDF DEFAULT_MSG NETCDF_LIBRARIES NETCDF_INCLUDES NetCDF_has_interfaces) + +mark_as_advanced (NETCDF_LIBRARIES NETCDF_INCLUDES) diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSFCIO.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSFCIO.cmake new file mode 100644 index 0000000000..d8928bc210 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSFCIO.cmake @@ -0,0 +1,71 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{SFCIO_VER}) + set(SFCIO_VER $ENV{SFCIO_VER}) + STRING(REGEX REPLACE "v" "" SFCIO_VER ${SFCIO_VER}) +endif() + +set( NO_DEFAULT_PATH ) +if(NOT BUILD_SFCIO ) + if(DEFINED ENV{SFCIO_LIB4} ) + set(SFCIO_LIBRARY $ENV{SFCIO_LIB4} ) + set(SFCIOINC $ENV{SFCIO_INC4} ) + message("SFCIO library ${SFCIO_LIBRARY} set via Environment variable") + else() + findInc( sfcio SFCIO_VER SFCIOINC ) + find_library( SFCIO_LIBRARY + NAMES libsfcio.a libsfcio_4.a libsfcio_i4r4.a libsfcio_v${SFCIO_VER}_4.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/sfcio/v${SFCIO_VER} + ${COREPATH}/sfcio/v${SFCIO_VER}/intel + ${COREPATH}/sfcio/v${SFCIO_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( sfcio "sfcio_v${SFCIO_VER}") + message("Found SFCIO library ${SFCIO_LIBRARY}") + endif() +endif() +if( NOT SFCIO_LIBRARY ) # didn't find the library, so build it from source + message("Could not find SFCIO library, so building from libsrc") + if( NOT DEFINED ENV{SFCIO_SRC} ) + findSrc( "sfcio" SFCIO_VER SFCIO_DIR ) + set(SFCIOINC "${CMAKE_BINARY_DIR}/include") + else() + set( SFCIO_DIR "$ENV{SFCIO_SRC}/libsrc" CACHE STRING "SFCIO Source Location") + set(SFCIOINC "${CORESFCIO}/sfcio/${SFCIO_VER}/incmod/sfcio_v${SFCIO_VER}") + endif() + set( libsuffix "_v${SFCIO_VER}${debug_suffix}" ) + set( SFCIO_LIBRARY "${LIBRARY_OUTPUT_PATH}/libsfcio${libsuffix}.a" CACHE STRING "SFCIO Library" ) + set( sfcio "sfcio${libsuffix}") + set( BUILD_SFCIO "ON" CACHE INTERNAL "Build the SFCIO library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/sfcio) + set( SFCIO_LIBRARY ${sfcio} ) + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${SFCIO_LIBRARY} ) + else() + set( CORE_BUILT ${SFCIO_LIBRARY} ) + endif() +else( NOT SFCIO_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${SFCIO_LIBRARY} ) + else() + set( CORE_LIBRARIES ${SFCIO_LIBRARY} ) + endif() +endif( NOT SFCIO_LIBRARY ) + +if( CORE_INCS ) + list( APPEND CORE_INCS ${SFCIOINC} ) +else() + set( CORE_INCS ${INCLUDE_OUTPUT_PATH} ${SFCIOINC} ) +endif() + +set( SFCIO_LIBRARY_PATH ${SFCIO_LIBRARY} CACHE STRING "SFCIO Library Location" ) +set( SFCIO_INCLUDE_PATH ${SFCIOINC} CACHE STRING "SFCIO Include Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSIGIO.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSIGIO.cmake new file mode 100644 index 0000000000..173328c45f --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSIGIO.cmake @@ -0,0 +1,72 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{SIGIO_VER}) + set(SIGIO_VER $ENV{SIGIO_VER}) + STRING(REGEX REPLACE "v" "" SIGIO_VER ${SIGIO_VER}) +endif() + +set( NO_DEFAULT_PATH ) +if(NOT BUILD_SIGIO ) + if(DEFINED ENV{SIGIO_LIB4} ) + set(SIGIO_LIBRARY $ENV{SIGIO_LIB4} ) + set(SIGIOINC $ENV{SIGIO_INC4} ) + message("SIGIO library ${SIGIO_LIBRARY} set via Environment variable") + else() + findInc( sigio SIGIO_VER SIGIOINC ) + find_library( SIGIO_LIBRARY + NAMES libsigio.a libsigio_4.a libsigio_i4r4.a libsigio_v${SIGIO_VER}_4.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/sigio/v${SIGIO_VER} + ${COREPATH}/sigio/v${SIGIO_VER}/intel + ${COREPATH}/sigio/v${SIGIO_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( sigio "sigio_v${SIGIO_VER}") + message("Found SIGIO library ${SIGIO_LIBRARY}") + endif() +endif() +if( NOT SIGIO_LIBRARY ) # didn't find the library, so build it from source + message("Could not find SIGIO library, so building from libsrc") + if( NOT DEFINED ENV{SIGIO_SRC} ) + findSrc( "sigio" SIGIO_VER SIGIO_DIR ) + set(SIGIOINC "${CMAKE_BINARY_DIR}/include") + else() + set( SIGIO_DIR "$ENV{SIGIO_SRC}/libsrc" CACHE STRING "SIGIO Source Location") + set(SIGIOINC "${CORESIGIO}/sigio/${SIGIO_VER}/incmod/sigio_v${SIGIO_VER}") + endif() + set( libsuffix "_v${SIGIO_VER}${debug_suffix}" ) + set( SIGIO_LIBRARY "${LIBRARY_OUTPUT_PATH}/libsigio${libsuffix}.a" CACHE STRING "SIGIO Library" ) + set( sigio "sigio${libsuffix}") + set( BUILD_SIGIO "ON" CACHE INTERNAL "Build the SIGIO library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/sigio) + set( SIGIO_LIBRARY ${sigio} ) + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${SIGIO_LIBRARY} ) + else() + set( CORE_BUILT ${SIGIO_LIBRARY} ) + endif() +else( NOT SIGIO_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${SIGIO_LIBRARY} ) + else() + set( CORE_LIBRARIES ${SIGIO_LIBRARY} ) + endif() +endif( NOT SIGIO_LIBRARY ) + +if( CORE_INCS ) + list( APPEND CORE_INCS ${SIGIOINC} ) +else() + set( CORE_INCS ${INCLUDE_OUTPUT_PATH} ${SIGIOINC} ) +endif() + + +set( SIGIO_LIBRARY_PATH ${SIGIO_LIBRARY} CACHE STRING "SIGIO Library Location" ) +set( SIGIO_INCLUDE_PATH ${SIGIOINC} CACHE STRING "SIGIO Include Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSP.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSP.cmake new file mode 100644 index 0000000000..b5fba97341 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindSP.cmake @@ -0,0 +1,83 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{SP_VER}) + set(SP_VER $ENV{SP_VER}) + STRING(REGEX REPLACE "v" "" SP_VER ${SP_VER}) +endif() + +set( NO_DEFAULT_PATH ) +if(NOT BUILD_SP ) + if(DEFINED ENV{SP_LIBd} ) + set(SP_LIBRARY $ENV{SP_LIBd} ) + message("SP library ${SP_LIBRARY} set via Environment variable") + else() + find_library( SP_LIBRARY + NAMES libsp_d.a libsp_i4r8.a libsp_v${SP_VER}_d.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/sp/v${SP_VER} + ${COREPATH}/sp/v${SP_VER}/intel + ${COREPATH}/sp/v${SP_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( sp "sp_v${SP_VER}_d") + message("Found SP library ${SP_LIBRARY}") + endif() + if(DEFINED ENV{SP_LIB4} ) + set(SP_4_LIBRARY $ENV{SP_LIB4} ) + message("SP library ${SP_4_LIBRARY} set via Environment variable") + else() + find_library( SP_4_LIBRARY + NAMES libsp_4.a libsp_i4r4.a libsp_v${SP_VER}_4.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/sp/v${SP_VER} + ${COREPATH}/sp/v${SP_VER}/intel + ${COREPATH}/sp/v${SP_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + set( sp "sp_v${SP_VER}_4") + message("Found SP_4 library ${SP_4_LIBRARY}") + endif() +endif() +if( NOT SP_LIBRARY ) # didn't find the library, so build it from source + message("Could not find SP library, so building from libsrc") + if( NOT DEFINED ENV{SP_SRC} ) + findSrc( "sp" SP_VER SP_DIR ) + else() + set( SP_DIR "$ENV{SP_SRC}/libsrc" CACHE STRING "SP Source Location") + endif() + set( libsuffix "_v${SP_VER}${debug_suffix}" ) + set( SP_LIBRARY "${LIBRARY_OUTPUT_PATH}/libsp${libsuffix}.a" CACHE STRING "SP Library" ) + set( SP_4_LIBRARY "${LIBRARY_OUTPUT_PATH}/libsp_4${libsuffix}.a" CACHE STRING "SP_4 Library" ) + set( sp "sp${libsuffix}") + set( sp4 "sp_4${libsuffix}") + set( BUILD_SP "ON" CACHE INTERNAL "Build the SP library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/sp) + set( SP_LIBRARY ${sp} ) + set( SP_4_LIBRARY ${sp4} ) + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${SP_LIBRARY} ) + else() + set( CORE_BUILT ${SP_LIBRARY} ) + endif() +else( NOT SP_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${SP_LIBRARY} ) + else() + set( CORE_LIBRARIES ${SP_LIBRARY} ) + endif() +endif( NOT SP_LIBRARY ) + + +set( SP_LIBRARY_PATH ${SP_LIBRARY} CACHE STRING "SP Library Location" ) +set( SP_4_LIBRARY_PATH ${SP_4_LIBRARY} CACHE STRING "SP_4 Library Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindW3EMC.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindW3EMC.cmake new file mode 100644 index 0000000000..3cbce42a6d --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindW3EMC.cmake @@ -0,0 +1,124 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{W3EMC_VER}) + set(W3EMC_VER $ENV{W3EMC_VER}) + set(W3EMCINC $ENV{W3EMC_INCd} ) + set(W3EMC4INC $ENV{W3EMC_INC4} ) + STRING(REGEX REPLACE "v" "" W3EMC_VER ${W3EMC_VER}) +endif() +if(DEFINED ENV{W3EMC_LIBd}) + set(W3EMC_LIBRARY $ENV{W3EMC_LIBd} ) + set(W3EMCINC $ENV{W3EMC_INCd} ) + set(W3EMC_4_LIBRARY $ENV{W3EMC_LIB4} ) + set(W3EMC4INC $ENV{W3EMC_INC4} ) + message("Setting W3EMC library via environment variable ${W3EMC_LIBRARY}") +endif() + +set( NO_DEFAULT_PATH ) +if((NOT BUILD_W3EMC ) AND ( NOT DEFINED W3EMC_LIBRARY )) + if(DEFINED ENV{W3EMC_LIB} ) + set(W3EMC_LIBRARY $ENV{W3EMC_LIB} ) + set(W3EMCINC $ENV{W3EMC_INC} ) + set(W3EMC_4_LIBRARY $ENV{W3EMC_LIB4} ) + set(W3EMC4INC $ENV{W3EMC_INC4} ) + message("W3EMC library ${W3EMC_LIBRARY} set via Environment variable") + message("W3EMC_4 library ${W3EMC_4_LIBRARY} set via Environment variable") + else() + find_path( W3EMCINC + NAMES mersenne_twister.mod + HINTS + $ENV{COREPATH}/lib/incmod/w3emc_d + $ENV{COREPATH}/include + /usr/local/jcsda/nwprod_gdas_2014/lib/incmod/w3emc_d + ${COREPATH}/w3emc/v${W3EMC_VER}/incmod/w3emc_v${W3EMC_VER}_d + ${COREPATH}/w3emc/v${W3EMC_VER}/intel/w3emc_v${W3EMC_VER}_d + ${COREPATH}/w3emc/v${W3EMC_VER}/ips/${COMPILER_VERSION}/impi/${COMPILER_VERSION}/include/w3emc_v${W3EMC_VER}_d + ${COREPATH}/w3emc/v${W3EMC_VER}/ips/${COMPILER_VERSION}/smpi/${COMPILER_VERSION}/include/w3emc_v${W3EMC_VER}_d + ) + find_path( W3EMC4INC + NAMES mersenne_twister.mod + HINTS + $ENV{COREPATH}/lib/incmod/w3emc_4 + $ENV{COREPATH}/include + /usr/local/jcsda/nwprod_gdas_2014/lib/incmod/w3emc_4 + ${COREPATH}/w3emc/v${W3EMC_VER}/incmod/w3emc_v${W3EMC_VER}_4 + ${COREPATH}/w3emc/v${W3EMC_VER}/intel/w3emc_v${W3EMC_VER}_4 + ${COREPATH}/w3emc/v${W3EMC_VER}/ips/${COMPILER_VERSION}/impi/${COMPILER_VERSION}/include/w3emc_v${W3EMC_VER}_4 + ${COREPATH}/w3emc/v${W3EMC_VER}/ips/${COMPILER_VERSION}/smpi/${COMPILER_VERSION}/include/w3emc_v${W3EMC_VER}_4 + ) + find_library( W3EMC_LIBRARY + NAMES libw3emc_d.a libw3emc_v${W3EMC_VER}_d.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014 + ${COREPATH}/w3emc/v${W3EMC_VER} + ${COREPATH}/w3emc/v${W3EMC_VER}/intel + ${COREPATH}/w3emc/v${W3EMC_VER}/ips/${COMPILER_VERSION}/impi/${COMPILER_VERSION} + ${COREPATH}/w3emc/v${W3EMC_VER}/ips/${COMPILER_VERSION}/smpi/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + find_library( W3EMC_4_LIBRARY + NAMES libw3emc_4.a libw3emc_i4r4.a libw3emc_v${W3EMC_VER}_4.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014 + ${COREPATH}/w3emc/v${W3EMC_VER} + ${COREPATH}/w3emc/v${W3EMC_VER}/intel + ${COREPATH}/w3emc/v${W3EMC_VER}/ips/${COMPILER_VERSION}/impi/${COMPILER_VERSION} + ${COREPATH}/w3emc/v${W3EMC_VER}/ips/${COMPILER_VERSION}/smpi/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + message("Found W3EMC_4 library ${W3EMC_4_LIBRARY}") + endif() +endif() +if( NOT W3EMC_LIBRARY ) # didn't find the library, so build it from source + message("Could not find W3EMC library, so building from libsrc") + if( NOT DEFINED ENV{W3EMC_SRC} ) + findSrc( "w3emc" W3EMC_VER W3EMC_DIR ) + set(W3EMCINC "${CMAKE_BINARY_DIR}/include" CACHE STRING "W3EMC Include Directory") + set(W3EMC4INC "${CMAKE_BINARY_DIR}/include" CACHE STRING "W3EMC4 Include Directory") + else() + set( W3EMC_DIR "$ENV{W3EMC_SRC}/libsrc" CACHE STRING "W3EMC Source Location") + endif() + set( libsuffix "_v${W3EMC_VER}${debug_suffix}" ) + set( W3EMC_LIBRARY "${LIBRARY_OUTPUT_PATH}/libw3emc${libsuffix}.a" CACHE STRING "W3EMC Library" ) + set( w3emc "w3emc${libsuffix}") + set( w3emc4 "w3emc_4${libsuffix}") + set( BUILD_W3EMC "ON" CACHE INTERNAL "Build the W3EMC library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/w3emc) + set( W3EMC_LIBRARY ${w3emc} ) + set( W3EMC_4_LIBRARY ${w3emc} ) + set(W3EMCINC "${CMAKE_BINARY_DIR}/include" CACHE STRING "W3EMC Include Directory") + set(W3EMC4INC ${CMAKE_INCLUDE_4_OUTPUT_DIRECTORY} CACHE STRING "W3EMC4 Include Directory") + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${W3EMC_LIBRARY} ) + list( APPEND CORE_BUILT ${W3EMC_4_LIBRARY} ) + else() + set( CORE_BUILT ${W3EMC_LIBRARY} ) + set( CORE_BUILT ${W3EMC_4_LIBRARY} ) + endif() +else( NOT W3EMC_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${W3EMC_LIBRARY} ) + else() + set( CORE_LIBRARIES ${W3EMC_LIBRARY} ) + endif() +endif( NOT W3EMC_LIBRARY ) + +if( CORE_INCS ) + list( APPEND CORE_INCS ${W3EMCINC} ) +else() + set( CORE_INCS ${INCLUDE_OUTPUT_PATH} ${W3EMCINC} ) +endif() + +set( W3EMC_LIBRARY_PATH ${W3EMC_LIBRARY} CACHE STRING "W3EMC Library Location" ) +set( W3EMC_INCLUDE_PATH ${W3EMCINC} CACHE STRING "W3EMC Include Location" ) +set( W3EMC_4_LIBRARY_PATH ${W3EMC_4_LIBRARY} CACHE STRING "W3EMC_4 Library Location" ) +set( W3EMC_INCLUDE_4_PATH ${W3EMC4INC} CACHE STRING "W3EMC_4 Include Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindW3NCO.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindW3NCO.cmake new file mode 100644 index 0000000000..aef2126c8f --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindW3NCO.cmake @@ -0,0 +1,81 @@ +# This module defines +# CORE_INCS +# List of include file paths for all required modules for GSI +# CORE_LIBRARIES +# Full list of libraries required to link GSI executable +include(findHelpers) +if(DEFINED ENV{W3NCO_VER}) + set(W3NCO_VER $ENV{W3NCO_VER}) + STRING(REGEX REPLACE "v" "" W3NCO_VER ${W3NCO_VER}) +endif() + +set( NO_DEFAULT_PATH ) +if(NOT BUILD_W3NCO ) + if(DEFINED ENV{W3NCO_LIBd} ) + set(W3NCO_LIBRARY $ENV{W3NCO_LIBd} ) + set(W3NCO_4_LIBRARY $ENV{W3NCO_LIB4} ) + message("W3NCO library ${W3NCO_LIBRARY} set via Environment variable") + message("W3NCO_4 library ${W3NCO_4_LIBRARY} set via Environment variable") + else() + find_library( W3NCO_LIBRARY + NAMES libw3nco_v${W3NCO_VER}_d.a libw3nco_d.a libw3nco_i4r8.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/w3nco/v${W3NCO_VER} + ${COREPATH}/w3nco/v${W3NCO_VER}/intel + ${COREPATH}/w3nco/v${W3NCO_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + message("Found W3NCO library ${W3NCO_LIBRARY}") + set( w3nco ${W3NCO_LIBRARY}) + + find_library( W3NCO_4_LIBRARY + NAMES libw3nco_v${W3NCO_VER}_4.a libw3nco_4.a + HINTS + $ENV{COREPATH}/lib + /usr/local/jcsda/nwprod_gdas_2014/lib + ${COREPATH}/w3nco/v${W3NCO_VER} + ${COREPATH}/w3nco/v${W3NCO_VER}/intel + ${COREPATH}/w3nco/v${W3NCO_VER}/ips/${COMPILER_VERSION} + PATH_SUFFIXES + lib + ${NO_DEFAULT_PATH}) + message("Found W3NCO_4 library ${W3NCO_4_LIBRARY}") + set( w3nco4 ${W3NCO_4_LIBRARY}) + endif() +endif() +if( NOT W3NCO_LIBRARY ) # didn't find the library, so build it from source + message("Could not find W3NCO library, so building from libsrc") + if( NOT DEFINED ENV{W3NCO_SRC} ) + findSrc( "w3nco" W3NCO_VER W3NCO_DIR ) + else() + set( W3NCO_DIR "$ENV{W3NCO_SRC}/libsrc" CACHE STRING "W3NCO Source Location") + endif() + set( libsuffix "_v${W3NCO_VER}${debug_suffix}" ) + set( W3NCO_LIBRARY "${LIBRARY_OUTPUT_PATH}/libw3nco${libsuffix}.a" CACHE STRING "W3NCO Library" ) + set( w3nco "w3nco${libsuffix}") + set( w3nco4 "w3nco_4${libsuffix}") + set( BUILD_W3NCO "ON" CACHE INTERNAL "Build the W3NCO library") + add_subdirectory(${CMAKE_SOURCE_DIR}/libsrc/w3nco) + set( W3NCO_LIBRARY ${w3nco} ) + set( W3NCO_4_LIBRARY ${w3nco4} ) + if( CORE_BUILT ) + list( APPEND CORE_BUILT ${W3NCO_LIBRARY} ) + list( APPEND CORE_BUILT ${W3NCO_4_LIBRARY} ) + else() + set( CORE_BUILT ${W3NCO_LIBRARY} ) + set( CORE_BUILT ${W3NCO_4_LIBRARY} ) + endif() +else( NOT W3NCO_LIBRARY ) + if( CORE_LIBRARIES ) + list( APPEND CORE_LIBRARIES ${W3NCO_LIBRARY} ) + else() + set( CORE_LIBRARIES ${W3NCO_LIBRARY} ) + endif() +endif( NOT W3NCO_LIBRARY ) + +set( W3NCO_DIR ${CMAKE_SOURCE_DIR}/libsrc/w3nco CACHE STRING "W3NCO Source Location") +set( W3NCO_LIBRARY_PATH ${W3NCO_LIBRARY} CACHE STRING "W3NCO Library Location" ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindWRF.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindWRF.cmake new file mode 100644 index 0000000000..43faf46643 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/FindWRF.cmake @@ -0,0 +1,36 @@ +# - Find the WRF modules + +set( NO_DEFAULT_PATH ) +find_library( IOINT_LIB + NAMES libwrfio_int.a + HINTS + ${WRFPATH}/external/io_int + $ENV{WRFPATH}/external/io_int + /usr/local/jcsda/nwprod_gdas_2014/lib/sorc/nam_nmm_real_fcst.fd/external/io_int + /scratch3/NCEPDEV/nceplibs/ext/WRF/3.7/WRFV3/external/io_int + ${NO_DEFAULT_PATH}) + +find_library( WRFNETCDF_LIB + NAMES libwrfio_nf.a + HINTS + ${WRFPATH}/external/io_netcdf /usr/local/jcsda/nwprod_gdas_2014/lib/sorc/nam_nmm_real_fcst.fd/external/io_netcdf + $ENV{WRFPATH}/external/io_netcdf /usr/local/jcsda/nwprod_gdas_2014/lib/sorc/nam_nmm_real_fcst.fd/external/io_netcdf + /scratch3/NCEPDEV/nceplibs/ext/WRF/3.7/WRFV3/external/io_netcdf + ${NO_DEFAULT_PATH}) +find_file( FRAMEPACK + NAMES pack_utils.o + HINTS + ${WRFPATH}/frame /usr/local/jcsda/nwprod_gdas_2014/lib/sorc/nam_nmm_real_fcst.fd/frame + $ENV{WRFPATH}/frame /usr/local/jcsda/nwprod_gdas_2014/lib/sorc/nam_nmm_real_fcst.fd/frame + /scratch3/NCEPDEV/nceplibs/ext/WRF/3.7/WRFV3/frame + ${NO_DEFAULT_PATH}) +find_file( FRAMEMODULE + NAMES module_machine.o + HINTS + ${WRFPATH}/frame /usr/local/jcsda/nwprod_gdas_2014/lib/sorc/nam_nmm_real_fcst.fd/frame + $ENV{WRFPATH}/frame /usr/local/jcsda/nwprod_gdas_2014/lib/sorc/nam_nmm_real_fcst.fd/frame + /scratch3/NCEPDEV/nceplibs/ext/WRF/3.7/WRFV3/frame + ${NO_DEFAULT_PATH}) + +set( WRF_LIBRARIES ${IOINT_LIB} ${WRFNETCDF_LIB} ${FRAMEPACK} ${FRAMEMODULE} ) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/CMakeParseArguments.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/CMakeParseArguments.cmake new file mode 100644 index 0000000000..7ee2bbacef --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/CMakeParseArguments.cmake @@ -0,0 +1,11 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# CMakeParseArguments +# ------------------- +# +# This module once implemented the :command:`cmake_parse_arguments` command +# that is now implemented natively by CMake. It is now an empty placeholder +# for compatibility with projects that include it to get the command from +# CMake 3.4 and lower. diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindHDF5.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindHDF5.cmake new file mode 100644 index 0000000000..fd8891cf20 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindHDF5.cmake @@ -0,0 +1,934 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindHDF5 +# -------- +# +# Find HDF5, a library for reading and writing self describing array data. +# +# +# +# This module invokes the HDF5 wrapper compiler that should be installed +# alongside HDF5. Depending upon the HDF5 Configuration, the wrapper +# compiler is called either h5cc or h5pcc. If this succeeds, the module +# will then call the compiler with the -show argument to see what flags +# are used when compiling an HDF5 client application. +# +# The module will optionally accept the COMPONENTS argument. If no +# COMPONENTS are specified, then the find module will default to finding +# only the HDF5 C library. If one or more COMPONENTS are specified, the +# module will attempt to find the language bindings for the specified +# components. The only valid components are C, CXX, Fortran, HL, and +# Fortran_HL. If the COMPONENTS argument is not given, the module will +# attempt to find only the C bindings. +# +# This module will read the variable +# HDF5_USE_STATIC_LIBRARIES to determine whether or not to prefer a +# static link to a dynamic link for HDF5 and all of it's dependencies. +# To use this feature, make sure that the HDF5_USE_STATIC_LIBRARIES +# variable is set before the call to find_package. +# +# To provide the module with a hint about where to find your HDF5 +# installation, you can set the environment variable HDF5_ROOT. The +# Find module will then look in this path when searching for HDF5 +# executables, paths, and libraries. +# +# Both the serial and parallel HDF5 wrappers are considered and the first +# directory to contain either one will be used. In the event that both appear +# in the same directory the serial version is preferentially selected. This +# behavior can be reversed by setting the variable HDF5_PREFER_PARALLEL to +# true. +# +# In addition to finding the includes and libraries required to compile +# an HDF5 client application, this module also makes an effort to find +# tools that come with the HDF5 distribution that may be useful for +# regression testing. +# +# This module will define the following variables: +# +# :: +# +# HDF5_FOUND - true if HDF5 was found on the system +# HDF5_VERSION - HDF5 version in format Major.Minor.Release +# HDF5_INCLUDE_DIRS - Location of the hdf5 includes +# HDF5_INCLUDE_DIR - Location of the hdf5 includes (deprecated) +# HDF5_DEFINITIONS - Required compiler definitions for HDF5 +# HDF5_LIBRARIES - Required libraries for all requested bindings +# HDF5_HL_LIBRARIES - Required libraries for the HDF5 high level API for all +# bindings, if the HL component is enabled +# +# Available components are: C CXX Fortran and HL. For each enabled language +# binding, a corresponding HDF5_${LANG}_LIBRARIES variable, and potentially +# HDF5_${LANG}_DEFINITIONS, will be defined. +# If the HL component is enabled, then an HDF5_${LANG}_HL_LIBRARIES will +# also be defined. With all components enabled, the following variables will be defined: +# +# :: +# +# HDF5_C_DEFINITIONS -- Required compiler definitions for HDF5 C bindings +# HDF5_CXX_DEFINITIONS -- Required compiler definitions for HDF5 C++ bindings +# HDF5_Fortran_DEFINITIONS -- Required compiler definitions for HDF5 Fortran bindings +# HDF5_C_INCLUDE_DIRS -- Required include directories for HDF5 C bindings +# HDF5_CXX_INCLUDE_DIRS -- Required include directories for HDF5 C++ bindings +# HDF5_Fortran_INCLUDE_DIRS -- Required include directories for HDF5 Fortran bindings +# HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings +# HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings +# HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings +# HDF5_C_HL_LIBRARIES - Required libraries for the high level C bindings +# HDF5_CXX_HL_LIBRARIES - Required libraries for the high level C++ bindings +# HDF5_Fortran_HL_LIBRARIES - Required libraries for the high level Fortran +# bindings. +# +# HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support +# HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler +# HDF5_CXX_COMPILER_EXECUTABLE - the path to the HDF5 C++ wrapper compiler +# HDF5_Fortran_COMPILER_EXECUTABLE - the path to the HDF5 Fortran wrapper compiler +# HDF5_C_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary C compiler +# which is also the HDF5 wrapper +# HDF5_CXX_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary C++ +# compiler which is also +# the HDF5 wrapper +# HDF5_Fortran_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary +# Fortran compiler which +# is also the HDF5 wrapper +# HDF5_DIFF_EXECUTABLE - the path to the HDF5 dataset comparison tool +# +# The following variable can be set to guide the search for HDF5 libraries and includes: +# +# ``HDF5_ROOT`` +# Specify the path to the HDF5 installation to use. +# +# ``HDF5_FIND_DEBUG`` +# Set to a true value to get some extra debugging output. +# +# ``HDF5_NO_FIND_PACKAGE_CONFIG_FILE`` +# Set to a true value to skip trying to find ``hdf5-config.cmake``. + +# This module is maintained by Will Dicharry . + +include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +# List of the valid HDF5 components +set(HDF5_VALID_LANGUAGE_BINDINGS C CXX Fortran) + +# Validate the list of find components. +if(NOT HDF5_FIND_COMPONENTS) + set(HDF5_LANGUAGE_BINDINGS "C") +else() + set(HDF5_LANGUAGE_BINDINGS) + # add the extra specified components, ensuring that they are valid. + set(FIND_HL OFF) + foreach(component IN LISTS HDF5_FIND_COMPONENTS) + list(FIND HDF5_VALID_LANGUAGE_BINDINGS ${component} component_location) + if(NOT component_location EQUAL -1) + list(APPEND HDF5_LANGUAGE_BINDINGS ${component}) + elseif(component STREQUAL "HL") + set(FIND_HL ON) + elseif(component STREQUAL "Fortran_HL") # only for compatibility + list(APPEND HDF5_LANGUAGE_BINDINGS Fortran) + set(FIND_HL ON) + set(HDF5_FIND_REQUIRED_Fortran_HL False) + set(HDF5_FIND_REQUIRED_Fortran True) + set(HDF5_FIND_REQUIRED_HL True) + else() + message(FATAL_ERROR "${component} is not a valid HDF5 component.") + endif() + endforeach() + if(NOT HDF5_LANGUAGE_BINDINGS) + get_property(__langs GLOBAL PROPERTY ENABLED_LANGUAGES) + foreach(__lang IN LISTS __langs) + if(__lang MATCHES "^(C|CXX|Fortran)$") + list(APPEND HDF5_LANGUAGE_BINDINGS ${__lang}) + endif() + endforeach() + endif() + list(REMOVE_ITEM HDF5_FIND_COMPONENTS Fortran_HL) # replaced by Fortran and HL + list(REMOVE_DUPLICATES HDF5_LANGUAGE_BINDINGS) +endif() + +# Determine whether to search for serial or parallel executable first +if(HDF5_PREFER_PARALLEL) + set(HDF5_C_COMPILER_NAMES h5pcc h5cc) + set(HDF5_CXX_COMPILER_NAMES h5pc++ h5c++) + set(HDF5_Fortran_COMPILER_NAMES h5pfc h5fc) +else() + set(HDF5_C_COMPILER_NAMES h5cc h5pcc) + set(HDF5_CXX_COMPILER_NAMES h5c++ h5pc++) + set(HDF5_Fortran_COMPILER_NAMES h5fc h5pfc) +endif() + +# We may have picked up some duplicates in various lists during the above +# process for the language bindings (both the C and C++ bindings depend on +# libz for example). Remove the duplicates. It appears that the default +# CMake behavior is to remove duplicates from the end of a list. However, +# for link lines, this is incorrect since unresolved symbols are searched +# for down the link line. Therefore, we reverse the list, remove the +# duplicates, and then reverse it again to get the duplicates removed from +# the beginning. +macro(_HDF5_remove_duplicates_from_beginning _list_name) + if(${_list_name}) + list(REVERSE ${_list_name}) + list(REMOVE_DUPLICATES ${_list_name}) + list(REVERSE ${_list_name}) + endif() +endmacro() + + +# Test first if the current compilers automatically wrap HDF5 + +function(_HDF5_test_regular_compiler_C success version is_parallel) + set(scratch_directory + ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5) + if(NOT ${success} OR + NOT EXISTS ${scratch_directory}/compiler_has_h5_c) + set(test_file ${scratch_directory}/cmake_hdf5_test.c) + file(WRITE ${test_file} + "#include \n" + "#include \n" + "const char* info_ver = \"INFO\" \":\" H5_VERSION;\n" + "#ifdef H5_HAVE_PARALLEL\n" + "const char* info_parallel = \"INFO\" \":\" \"PARALLEL\";\n" + "#endif\n" + "int main(int argc, char **argv) {\n" + " int require = 0;\n" + " require += info_ver[argc];\n" + "#ifdef H5_HAVE_PARALLEL\n" + " require += info_parallel[argc];\n" + "#endif\n" + " hid_t fid;\n" + " fid = H5Fcreate(\"foo.h5\",H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);\n" + " return 0;\n" + "}") + try_compile(${success} ${scratch_directory} ${test_file} + COPY_FILE ${scratch_directory}/compiler_has_h5_c + ) + endif() + if(${success}) + file(STRINGS ${scratch_directory}/compiler_has_h5_c INFO_STRINGS + REGEX "^INFO:" + ) + string(REGEX MATCH "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?" + INFO_VER "${INFO_STRINGS}" + ) + set(${version} ${CMAKE_MATCH_1}) + if(CMAKE_MATCH_3) + set(${version} ${HDF5_C_VERSION}.${CMAKE_MATCH_3}) + endif() + set(${version} ${${version}} PARENT_SCOPE) + + if(INFO_STRINGS MATCHES "INFO:PARALLEL") + set(${is_parallel} TRUE PARENT_SCOPE) + else() + set(${is_parallel} FALSE PARENT_SCOPE) + endif() + endif() +endfunction() + +function(_HDF5_test_regular_compiler_CXX success version is_parallel) + set(scratch_directory ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5) + if(NOT ${success} OR + NOT EXISTS ${scratch_directory}/compiler_has_h5_cxx) + set(test_file ${scratch_directory}/cmake_hdf5_test.cxx) + file(WRITE ${test_file} + "#include \n" + "#ifndef H5_NO_NAMESPACE\n" + "using namespace H5;\n" + "#endif\n" + "const char* info_ver = \"INFO\" \":\" H5_VERSION;\n" + "#ifdef H5_HAVE_PARALLEL\n" + "const char* info_parallel = \"INFO\" \":\" \"PARALLEL\";\n" + "#endif\n" + "int main(int argc, char **argv) {\n" + " int require = 0;\n" + " require += info_ver[argc];\n" + "#ifdef H5_HAVE_PARALLEL\n" + " require += info_parallel[argc];\n" + "#endif\n" + " H5File file(\"foo.h5\", H5F_ACC_TRUNC);\n" + " return 0;\n" + "}") + try_compile(${success} ${scratch_directory} ${test_file} + COPY_FILE ${scratch_directory}/compiler_has_h5_cxx + ) + endif() + if(${success}) + file(STRINGS ${scratch_directory}/compiler_has_h5_cxx INFO_STRINGS + REGEX "^INFO:" + ) + string(REGEX MATCH "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?" + INFO_VER "${INFO_STRINGS}" + ) + set(${version} ${CMAKE_MATCH_1}) + if(CMAKE_MATCH_3) + set(${version} ${HDF5_CXX_VERSION}.${CMAKE_MATCH_3}) + endif() + set(${version} ${${version}} PARENT_SCOPE) + + if(INFO_STRINGS MATCHES "INFO:PARALLEL") + set(${is_parallel} TRUE PARENT_SCOPE) + else() + set(${is_parallel} FALSE PARENT_SCOPE) + endif() + endif() +endfunction() + +function(_HDF5_test_regular_compiler_Fortran success is_parallel) + if(NOT ${success}) + set(scratch_directory + ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5) + set(test_file ${scratch_directory}/cmake_hdf5_test.f90) + file(WRITE ${test_file} + "program hdf5_hello\n" + " use hdf5\n" + " use h5lt\n" + " use h5ds\n" + " integer error\n" + " call h5open_f(error)\n" + " call h5close_f(error)\n" + "end\n") + try_compile(${success} ${scratch_directory} ${test_file}) + if(${success}) + execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -showconfig + OUTPUT_VARIABLE config_output + ERROR_VARIABLE config_error + RESULT_VARIABLE config_result + ) + if(config_output MATCHES "Parallel HDF5: yes") + set(${is_parallel} TRUE PARENT_SCOPE) + else() + set(${is_parallel} FALSE PARENT_SCOPE) + endif() + endif() + endif() +endfunction() + +# Invoke the HDF5 wrapper compiler. The compiler return value is stored to the +# return_value argument, the text output is stored to the output variable. +macro( _HDF5_invoke_compiler language output return_value version is_parallel) + set(${version}) + if(HDF5_USE_STATIC_LIBRARIES) + set(lib_type_args -noshlib) + else() + set(lib_type_args -shlib) + endif() + set(scratch_dir ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5) + if("${language}" STREQUAL "C") + set(test_file ${scratch_dir}/cmake_hdf5_test.c) + elseif("${language}" STREQUAL "CXX") + set(test_file ${scratch_dir}/cmake_hdf5_test.cxx) + elseif("${language}" STREQUAL "Fortran") + set(test_file ${scratch_dir}/cmake_hdf5_test.f90) + endif() + exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE} + ARGS -show ${lib_type_args} ${test_file} + OUTPUT_VARIABLE ${output} + RETURN_VALUE ${return_value} + ) + if(NOT ${${return_value}} EQUAL 0) + message(STATUS + "Unable to determine HDF5 ${language} flags from HDF5 wrapper.") + endif() + exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE} + ARGS -showconfig + OUTPUT_VARIABLE config_output + RETURN_VALUE config_return + ) + if(NOT ${return_value} EQUAL 0) + message( STATUS + "Unable to determine HDF5 ${language} version from HDF5 wrapper.") + endif() + string(REGEX MATCH "HDF5 Version: ([a-zA-Z0-9\\.\\-]*)" version_match "${config_output}") + if(version_match) + string(REPLACE "HDF5 Version: " "" ${version} "${version_match}") + string(REPLACE "-patch" "." ${version} "${${version}}") + endif() + if(config_output MATCHES "Parallel HDF5: yes") + set(${is_parallel} TRUE) + else() + set(${is_parallel} FALSE) + endif() +endmacro() + +# Parse a compile line for definitions, includes, library paths, and libraries. +macro( _HDF5_parse_compile_line + compile_line_var + include_paths + definitions + library_paths + libraries + libraries_hl) + + separate_arguments(_HDF5_COMPILE_ARGS UNIX_COMMAND "${${compile_line_var}}") + + foreach(arg IN LISTS _HDF5_COMPILE_ARGS) + if("${arg}" MATCHES "^-I(.*)$") + # include directory + list(APPEND ${include_paths} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-D(.*)$") + # compile definition + list(APPEND ${definitions} "-D${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-L(.*)$") + # library search path + list(APPEND ${library_paths} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(hdf5.*hl.*)$") + # library name (hl) + list(APPEND ${libraries_hl} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(.*)$") + # library name + list(APPEND ${libraries} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^(.:)?[/\\].*\\.(a|so|dylib|sl|lib)$") + # library file + if(NOT EXISTS "${arg}") + continue() + endif() + get_filename_component(_HDF5_LPATH "${arg}" DIRECTORY) + get_filename_component(_HDF5_LNAME "${arg}" NAME_WE) + string(REGEX REPLACE "^lib" "" _HDF5_LNAME "${_HDF5_LNAME}") + list(APPEND ${library_paths} "${_HDF5_LPATH}") + if(_HDF5_LNAME MATCHES "hdf5.*hl") + list(APPEND ${libraries_hl} "${_HDF5_LNAME}") + else() + list(APPEND ${libraries} "${_HDF5_LNAME}") + endif() + endif() + endforeach() +endmacro() + +# Select a preferred imported configuration from a target +function(_HDF5_select_imported_config target imported_conf) + # We will first assign the value to a local variable _imported_conf, then assign + # it to the function argument at the end. + get_target_property(_imported_conf ${target} MAP_IMPORTED_CONFIG_${CMAKE_BUILD_TYPE}) + if (NOT _imported_conf) + # Get available imported configurations by examining target properties + get_target_property(_imported_conf ${target} IMPORTED_CONFIGURATIONS) + if(HDF5_FIND_DEBUG) + message(STATUS "Found imported configurations: ${_imported_conf}") + endif() + # Find the imported configuration that we prefer. + # We do this by making list of configurations in order of preference, + # starting with ${CMAKE_BUILD_TYPE} and ending with the first imported_conf + set(_preferred_confs ${CMAKE_BUILD_TYPE}) + list(GET _imported_conf 0 _fallback_conf) + list(APPEND _preferred_confs RELWITHDEBINFO RELEASE DEBUG ${_fallback_conf}) + if(HDF5_FIND_DEBUG) + message(STATUS "Start search through imported configurations in the following order: ${_preferred_confs}") + endif() + # Now find the first of these that is present in imported_conf + cmake_policy(PUSH) + cmake_policy(SET CMP0057 NEW) # support IN_LISTS + foreach (_conf IN LISTS _preferred_confs) + if (${_conf} IN_LIST _imported_conf) + set(_imported_conf ${_conf}) + break() + endif() + endforeach() + cmake_policy(POP) + endif() + if(HDF5_FIND_DEBUG) + message(STATUS "Selected imported configuration: ${_imported_conf}") + endif() + # assign value to function argument + set(${imported_conf} ${_imported_conf} PARENT_SCOPE) +endfunction() + + +if(NOT HDF5_ROOT) + set(HDF5_ROOT $ENV{HDF5_ROOT}) +endif() +if(HDF5_ROOT) + set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH) +else() + set(_HDF5_SEARCH_OPTS) +endif() + +# Try to find HDF5 using an installed hdf5-config.cmake +if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE) + find_package(HDF5 QUIET NO_MODULE + HINTS ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS} + ) + if( HDF5_FOUND) + if(HDF5_FIND_DEBUG) + message(STATUS "Found HDF5 at ${HDF5_DIR} via NO_MODULE. Now trying to extract locations etc.") + endif() + set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL}) + set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR}) + set(HDF5_LIBRARIES) + if (NOT TARGET hdf5 AND NOT TARGET hdf5-static AND NOT TARGET hdf5-shared) + # Some HDF5 versions (e.g. 1.8.18) used hdf5::hdf5 etc + set(_target_prefix "hdf5::") + endif() + set(HDF5_C_TARGET ${_target_prefix}hdf5) + set(HDF5_C_HL_TARGET ${_target_prefix}hdf5_hl) + set(HDF5_CXX_TARGET ${_target_prefix}hdf5_cpp) + set(HDF5_CXX_HL_TARGET ${_target_prefix}hdf5_hl_cpp) + set(HDF5_Fortran_TARGET ${_target_prefix}hdf5_fortran) + set(HDF5_Fortran_HL_TARGET ${_target_prefix}hdf5_hl_fortran) + set(HDF5_DEFINITIONS "") + if(HDF5_USE_STATIC_LIBRARIES) + set(_suffix "-static") + else() + set(_suffix "-shared") + endif() + foreach(_lang ${HDF5_LANGUAGE_BINDINGS}) + + #Older versions of hdf5 don't have a static/shared suffix so + #if we detect that occurrence clear the suffix + if(_suffix AND NOT TARGET ${HDF5_${_lang}_TARGET}${_suffix}) + if(NOT TARGET ${HDF5_${_lang}_TARGET}) + #cant find this component with or without the suffix + #so bail out, and let the following locate HDF5 + set(HDF5_FOUND FALSE) + break() + endif() + set(_suffix "") + endif() + + if(HDF5_FIND_DEBUG) + message(STATUS "Trying to get properties of target ${HDF5_${_lang}_TARGET}${_suffix}") + endif() + # Find library for this target. Complicated as on Windows with a DLL, we need to search for the import-lib. + _HDF5_select_imported_config(${HDF5_${_lang}_TARGET}${_suffix} _hdf5_imported_conf) + get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} ) + if (NOT _hdf5_lang_location) + # no import lib, just try LOCATION + get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION_${_hdf5_imported_conf}) + if (NOT _hdf5_lang_location) + get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION) + endif() + endif() + if( _hdf5_lang_location ) + set(HDF5_${_lang}_LIBRARY ${_hdf5_lang_location}) + list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix}) + set(HDF5_${_lang}_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix}) + set(HDF5_${_lang}_FOUND True) + endif() + if(FIND_HL) + get_target_property(__lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} ) + if (NOT _hdf5_lang_hl_location) + get_target_property(_hdf5_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION_${_hdf5_imported_conf}) + if (NOT _hdf5_hl_lang_location) + get_target_property(_hdf5_hl_lang_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION) + endif() + endif() + if( _hdf5_lang_hl_location ) + set(HDF5_${_lang}_HL_LIBRARY ${_hdf5_lang_hl_location}) + list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_HL_TARGET}${_suffix}) + set(HDF5_${_lang}_HL_LIBRARIES ${HDF5_${_lang}_HL_TARGET}${_suffix}) + set(HDF5_HL_FOUND True) + endif() + unset(_hdf5_lang_hl_location) + endif() + unset(_hdf5_imported_conf) + unset(_hdf5_lang_location) + endforeach() + endif() +endif() + +if(NOT HDF5_FOUND) + set(_HDF5_NEED_TO_SEARCH False) + set(HDF5_COMPILER_NO_INTERROGATE True) + # Only search for languages we've enabled + foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS) + # First check to see if our regular compiler is one of wrappers + if(__lang STREQUAL "C") + _HDF5_test_regular_compiler_C( + HDF5_${__lang}_COMPILER_NO_INTERROGATE + HDF5_${__lang}_VERSION + HDF5_${__lang}_IS_PARALLEL) + elseif(__lang STREQUAL "CXX") + _HDF5_test_regular_compiler_CXX( + HDF5_${__lang}_COMPILER_NO_INTERROGATE + HDF5_${__lang}_VERSION + HDF5_${__lang}_IS_PARALLEL) + elseif(__lang STREQUAL "Fortran") + _HDF5_test_regular_compiler_Fortran( + HDF5_${__lang}_COMPILER_NO_INTERROGATE + HDF5_${__lang}_IS_PARALLEL) + else() + continue() + endif() + if(HDF5_${__lang}_COMPILER_NO_INTERROGATE) + message(STATUS "HDF5: Using hdf5 compiler wrapper for all ${__lang} compiling") + set(HDF5_${__lang}_FOUND True) + set(HDF5_${__lang}_COMPILER_EXECUTABLE_NO_INTERROGATE + "${CMAKE_${__lang}_COMPILER}" + CACHE FILEPATH "HDF5 ${__lang} compiler wrapper") + set(HDF5_${__lang}_DEFINITIONS) + set(HDF5_${__lang}_INCLUDE_DIRS) + set(HDF5_${__lang}_LIBRARIES) + set(HDF5_${__lang}_HL_LIBRARIES) + + mark_as_advanced(HDF5_${__lang}_COMPILER_EXECUTABLE_NO_INTERROGATE) + + set(HDF5_${__lang}_FOUND True) + set(HDF5_HL_FOUND True) + else() + set(HDF5_COMPILER_NO_INTERROGATE False) + # If this language isn't using the wrapper, then try to seed the + # search options with the wrapper + find_program(HDF5_${__lang}_COMPILER_EXECUTABLE + NAMES ${HDF5_${__lang}_COMPILER_NAMES} NAMES_PER_DIR + HINTS ${HDF5_ROOT} + PATH_SUFFIXES bin Bin + DOC "HDF5 ${__lang} Wrapper compiler. Used only to detect HDF5 compile flags." + ${_HDF5_SEARCH_OPTS} + ) + mark_as_advanced( HDF5_${__lang}_COMPILER_EXECUTABLE ) + unset(HDF5_${__lang}_COMPILER_NAMES) + + if(HDF5_${__lang}_COMPILER_EXECUTABLE) + _HDF5_invoke_compiler(${__lang} HDF5_${__lang}_COMPILE_LINE + HDF5_${__lang}_RETURN_VALUE HDF5_${__lang}_VERSION HDF5_${__lang}_IS_PARALLEL) + if(HDF5_${__lang}_RETURN_VALUE EQUAL 0) + message(STATUS "HDF5: Using hdf5 compiler wrapper to determine ${__lang} configuration") + _HDF5_parse_compile_line( HDF5_${__lang}_COMPILE_LINE + HDF5_${__lang}_INCLUDE_DIRS + HDF5_${__lang}_DEFINITIONS + HDF5_${__lang}_LIBRARY_DIRS + HDF5_${__lang}_LIBRARY_NAMES + HDF5_${__lang}_HL_LIBRARY_NAMES + ) + set(HDF5_${__lang}_LIBRARIES) + + foreach(L IN LISTS HDF5_${__lang}_LIBRARY_NAMES) + set(_HDF5_SEARCH_NAMES_LOCAL) + if("x${L}" MATCHES "hdf5") + # hdf5 library + set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + if(HDF5_USE_STATIC_LIBRARIES) + if(WIN32) + set(_HDF5_SEARCH_NAMES_LOCAL lib${L}) + else() + set(_HDF5_SEARCH_NAMES_LOCAL lib${L}.a) + endif() + endif() + else() + # external library + set(_HDF5_SEARCH_OPTS_LOCAL) + endif() + find_library(HDF5_${__lang}_LIBRARY_${L} + NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${L} NAMES_PER_DIR + HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS_LOCAL} + ) + unset(_HDF5_SEARCH_OPTS_LOCAL) + unset(_HDF5_SEARCH_NAMES_LOCAL) + if(HDF5_${__lang}_LIBRARY_${L}) + list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) + else() + list(APPEND HDF5_${__lang}_LIBRARIES ${L}) + endif() + endforeach() + if(FIND_HL) + set(HDF5_${__lang}_HL_LIBRARIES) + foreach(L IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES) + set(_HDF5_SEARCH_NAMES_LOCAL) + if("x${L}" MATCHES "hdf5") + # hdf5 library + set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + if(HDF5_USE_STATIC_LIBRARIES) + if(WIN32) + set(_HDF5_SEARCH_NAMES_LOCAL lib${L}) + else() + set(_HDF5_SEARCH_NAMES_LOCAL lib${L}.a) + endif() + endif() + else() + # external library + set(_HDF5_SEARCH_OPTS_LOCAL) + endif() + find_library(HDF5_${__lang}_LIBRARY_${L} + NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${L} NAMES_PER_DIR + HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS_LOCAL} + ) + unset(_HDF5_SEARCH_OPTS_LOCAL) + unset(_HDF5_SEARCH_NAMES_LOCAL) + if(HDF5_${__lang}_LIBRARY_${L}) + list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) + else() + list(APPEND HDF5_${__lang}_HL_LIBRARIES ${L}) + endif() + endforeach() + set(HDF5_HL_FOUND True) + endif() + + set(HDF5_${__lang}_FOUND True) + _HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_DEFINITIONS) + _HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_INCLUDE_DIRS) + _HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_LIBRARIES) + _HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_HL_LIBRARIES) + else() + set(_HDF5_NEED_TO_SEARCH True) + endif() + else() + set(_HDF5_NEED_TO_SEARCH True) + endif() + endif() + if(HDF5_${__lang}_VERSION) + if(NOT HDF5_VERSION) + set(HDF5_VERSION ${HDF5_${__lang}_VERSION}) + elseif(NOT HDF5_VERSION VERSION_EQUAL HDF5_${__lang}_VERSION) + message(WARNING "HDF5 Version found for language ${__lang}, ${HDF5_${__lang}_VERSION} is different than previously found version ${HDF5_VERSION}") + endif() + endif() + if(DEFINED HDF5_${__lang}_IS_PARALLEL) + if(NOT DEFINED HDF5_IS_PARALLEL) + set(HDF5_IS_PARALLEL ${HDF5_${__lang}_IS_PARALLEL}) + elseif(NOT HDF5_IS_PARALLEL AND HDF5_${__lang}_IS_PARALLEL) + message(WARNING "HDF5 found for language ${__lang} is parallel but previously found language is not parallel.") + elseif(HDF5_IS_PARALLEL AND NOT HDF5_${__lang}_IS_PARALLEL) + message(WARNING "HDF5 found for language ${__lang} is not parallel but previously found language is parallel.") + endif() + endif() + endforeach() +else() + set(_HDF5_NEED_TO_SEARCH True) +endif() + +if(NOT HDF5_FOUND AND HDF5_COMPILER_NO_INTERROGATE) + # No arguments necessary, all languages can use the compiler wrappers + set(HDF5_FOUND True) + set(HDF5_METHOD "Included by compiler wrappers") + set(HDF5_REQUIRED_VARS HDF5_METHOD) +elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH) + # Compiler wrappers aren't being used by the build but were found and used + # to determine necessary include and library flags + set(HDF5_INCLUDE_DIRS) + set(HDF5_LIBRARIES) + set(HDF5_HL_LIBRARIES) + foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS) + if(HDF5_${__lang}_FOUND) + if(NOT HDF5_${__lang}_COMPILER_NO_INTERROGATE) + list(APPEND HDF5_DEFINITIONS ${HDF5_${__lang}_DEFINITIONS}) + list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIRS}) + list(APPEND HDF5_LIBRARIES ${HDF5_${__lang}_LIBRARIES}) + if(FIND_HL) + list(APPEND HDF5_HL_LIBRARIES ${HDF5_${__lang}_HL_LIBRARIES}) + endif() + endif() + endif() + endforeach() + _HDF5_remove_duplicates_from_beginning(HDF5_DEFINITIONS) + _HDF5_remove_duplicates_from_beginning(HDF5_INCLUDE_DIRS) + _HDF5_remove_duplicates_from_beginning(HDF5_LIBRARIES) + _HDF5_remove_duplicates_from_beginning(HDF5_HL_LIBRARIES) + set(HDF5_FOUND True) + set(HDF5_REQUIRED_VARS HDF5_LIBRARIES) + if(FIND_HL) + list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES) + endif() +endif() + +find_program( HDF5_DIFF_EXECUTABLE + NAMES h5diff + HINTS ${HDF5_ROOT} + PATH_SUFFIXES bin Bin + ${_HDF5_SEARCH_OPTS} + DOC "HDF5 file differencing tool." ) +mark_as_advanced( HDF5_DIFF_EXECUTABLE ) + +if( NOT HDF5_FOUND ) + # seed the initial lists of libraries to find with items we know we need + set(HDF5_C_LIBRARY_NAMES hdf5) + set(HDF5_C_HL_LIBRARY_NAMES hdf5_hl) + + set(HDF5_CXX_LIBRARY_NAMES hdf5_cpp ${HDF5_C_LIBRARY_NAMES}) + set(HDF5_CXX_HL_LIBRARY_NAMES hdf5_hl_cpp ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_CXX_LIBRARY_NAMES}) + + set(HDF5_Fortran_LIBRARY_NAMES hdf5_fortran ${HDF5_C_LIBRARY_NAMES}) + set(HDF5_Fortran_HL_LIBRARY_NAMES hdf5hl_fortran ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_Fortran_LIBRARY_NAMES}) + + foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS) + # find the HDF5 include directories + if("${__lang}" STREQUAL "Fortran") + set(HDF5_INCLUDE_FILENAME hdf5.mod) + elseif("${__lang}" STREQUAL "CXX") + set(HDF5_INCLUDE_FILENAME H5Cpp.h) + else() + set(HDF5_INCLUDE_FILENAME hdf5.h) + endif() + + find_path(HDF5_${__lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME} + HINTS ${HDF5_ROOT} + PATHS $ENV{HOME}/.local/include + PATH_SUFFIXES include Include + ${_HDF5_SEARCH_OPTS} + ) + mark_as_advanced(HDF5_${__lang}_INCLUDE_DIR) + # set the _DIRS variable as this is what the user will normally use + set(HDF5_${__lang}_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) + list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) + + # find the HDF5 libraries + foreach(LIB IN LISTS HDF5_${__lang}_LIBRARY_NAMES) + if(HDF5_USE_STATIC_LIBRARIES) + # According to bug 1643 on the CMake bug tracker, this is the + # preferred method for searching for a static library. + # See https://gitlab.kitware.com/cmake/cmake/issues/1643. We search + # first for the full static library name, but fall back to a + # generic search on the name if the static search fails. + set( THIS_LIBRARY_SEARCH_DEBUG + lib${LIB}d.a lib${LIB}_debug.a lib${LIB}d lib${LIB}_D lib${LIB}_debug + lib${LIB}d-static.a lib${LIB}_debug-static.a ${LIB}d-static ${LIB}_D-static ${LIB}_debug-static ) + set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a lib${LIB} lib${LIB}-static.a ${LIB}-static) + else() + set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ${LIB}_D ${LIB}_debug ${LIB}d-shared ${LIB}_D-shared ${LIB}_debug-shared) + set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ${LIB}-shared) + if(WIN32) + list(APPEND HDF5_DEFINITIONS "-DH5_BUILT_AS_DYNAMIC_LIB") + endif() + endif() + find_library(HDF5_${LIB}_LIBRARY_DEBUG + NAMES ${THIS_LIBRARY_SEARCH_DEBUG} + HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib + ${_HDF5_SEARCH_OPTS} + ) + find_library( HDF5_${LIB}_LIBRARY_RELEASE + NAMES ${THIS_LIBRARY_SEARCH_RELEASE} + HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib + ${_HDF5_SEARCH_OPTS} + ) + select_library_configurations( HDF5_${LIB} ) + list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${LIB}_LIBRARY}) + endforeach() + if(HDF5_${__lang}_LIBRARIES) + set(HDF5_${__lang}_FOUND True) + endif() + + # Append the libraries for this language binding to the list of all + # required libraries. + list(APPEND HDF5_LIBRARIES ${HDF5_${__lang}_LIBRARIES}) + + if(FIND_HL) + foreach(LIB IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES) + if(HDF5_USE_STATIC_LIBRARIES) + # According to bug 1643 on the CMake bug tracker, this is the + # preferred method for searching for a static library. + # See https://gitlab.kitware.com/cmake/cmake/issues/1643. We search + # first for the full static library name, but fall back to a + # generic search on the name if the static search fails. + set( THIS_LIBRARY_SEARCH_DEBUG + lib${LIB}d.a lib${LIB}_debug.a lib${LIB}d lib${LIB}_D lib${LIB}_debug + lib${LIB}d-static.a lib${LIB}_debug-static.a lib${LIB}d-static lib${LIB}_D-static lib${LIB}_debug-static ) + set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a ${LIB} lib${LIB}-static.a lib${LIB}-static) + else() + set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ${LIB}_D ${LIB}_debug ${LIB}d-shared ${LIB}_D-shared ${LIB}_debug-shared) + set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ${LIB}-shared) + endif() + find_library(HDF5_${LIB}_LIBRARY_DEBUG + NAMES ${THIS_LIBRARY_SEARCH_DEBUG} + HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib + ${_HDF5_SEARCH_OPTS} + ) + find_library( HDF5_${LIB}_LIBRARY_RELEASE + NAMES ${THIS_LIBRARY_SEARCH_RELEASE} + HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib + ${_HDF5_SEARCH_OPTS} + ) + select_library_configurations( HDF5_${LIB} ) + list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${LIB}_LIBRARY}) + endforeach() + + # Append the libraries for this language binding to the list of all + # required libraries. + list(APPEND HDF5_HL_LIBRARIES ${HDF5_${__lang}_HL_LIBRARIES}) + endif() + endforeach() + if(FIND_HL AND HDF5_HL_LIBRARIES) + set(HDF5_HL_FOUND True) + endif() + + _HDF5_remove_duplicates_from_beginning(HDF5_DEFINITIONS) + _HDF5_remove_duplicates_from_beginning(HDF5_INCLUDE_DIRS) + _HDF5_remove_duplicates_from_beginning(HDF5_LIBRARIES) + _HDF5_remove_duplicates_from_beginning(HDF5_HL_LIBRARIES) + + # If the HDF5 include directory was found, open H5pubconf.h to determine if + # HDF5 was compiled with parallel IO support + set( HDF5_IS_PARALLEL FALSE ) + set( HDF5_VERSION "" ) + foreach( _dir IN LISTS HDF5_INCLUDE_DIRS ) + foreach(_hdr "${_dir}/H5pubconf.h" "${_dir}/H5pubconf-64.h" "${_dir}/H5pubconf-32.h") + if( EXISTS "${_hdr}" ) + file( STRINGS "${_hdr}" + HDF5_HAVE_PARALLEL_DEFINE + REGEX "HAVE_PARALLEL 1" ) + if( HDF5_HAVE_PARALLEL_DEFINE ) + set( HDF5_IS_PARALLEL TRUE ) + endif() + unset(HDF5_HAVE_PARALLEL_DEFINE) + + file( STRINGS "${_hdr}" + HDF5_VERSION_DEFINE + REGEX "^[ \t]*#[ \t]*define[ \t]+H5_VERSION[ \t]+" ) + if( "${HDF5_VERSION_DEFINE}" MATCHES + "H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?\"" ) + set( HDF5_VERSION "${CMAKE_MATCH_1}" ) + if( CMAKE_MATCH_3 ) + set( HDF5_VERSION ${HDF5_VERSION}.${CMAKE_MATCH_3}) + endif() + endif() + unset(HDF5_VERSION_DEFINE) + endif() + endforeach() + endforeach() + set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL + "HDF5 library compiled with parallel IO support" ) + mark_as_advanced( HDF5_IS_PARALLEL ) + + set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS) + if(FIND_HL) + list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES) + endif() +endif() + +# For backwards compatibility we set HDF5_INCLUDE_DIR to the value of +# HDF5_INCLUDE_DIRS +if( HDF5_INCLUDE_DIRS ) + set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" ) +endif() + +# If HDF5_REQUIRED_VARS is empty at this point, then it's likely that +# something external is trying to explicitly pass already found +# locations +if(NOT HDF5_REQUIRED_VARS) + set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS) +endif() + +find_package_handle_standard_args(HDF5 + REQUIRED_VARS ${HDF5_REQUIRED_VARS} + VERSION_VAR HDF5_VERSION + HANDLE_COMPONENTS +) + +unset(_HDF5_SEARCH_OPTS) + +if( HDF5_FOUND AND NOT HDF5_DIR) + # hide HDF5_DIR for the non-advanced user to avoid confusion with + # HDF5_DIR-NOT_FOUND while HDF5 was found. + mark_as_advanced(HDF5_DIR) +endif() + +if (HDF5_FIND_DEBUG) + message(STATUS "HDF5_DIR: ${HDF5_DIR}") + message(STATUS "HDF5_DEFINITIONS: ${HDF5_DEFINITIONS}") + message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}") + message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}") + message(STATUS "HDF5_HL_LIBRARIES: ${HDF5_HL_LIBRARIES}") + foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS) + message(STATUS "HDF5_${__lang}_DEFINITIONS: ${HDF5_${__lang}_DEFINITIONS}") + message(STATUS "HDF5_${__lang}_INCLUDE_DIR: ${HDF5_${__lang}_INCLUDE_DIR}") + message(STATUS "HDF5_${__lang}_INCLUDE_DIRS: ${HDF5_${__lang}_INCLUDE_DIRS}") + message(STATUS "HDF5_${__lang}_LIBRARY: ${HDF5_${__lang}_LIBRARY}") + message(STATUS "HDF5_${__lang}_LIBRARIES: ${HDF5_${__lang}_LIBRARIES}") + message(STATUS "HDF5_${__lang}_HL_LIBRARY: ${HDF5_${__lang}_HL_LIBRARY}") + message(STATUS "HDF5_${__lang}_HL_LIBRARIES: ${HDF5_${__lang}_HL_LIBRARIES}") + endforeach() +endif() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI.cmake new file mode 100644 index 0000000000..5cd2a2afe7 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI.cmake @@ -0,0 +1,1514 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindMPI +# ------- +# +# Find a Message Passing Interface (MPI) implementation. +# +# The Message Passing Interface (MPI) is a library used to write +# high-performance distributed-memory parallel applications, and is +# typically deployed on a cluster. MPI is a standard interface (defined +# by the MPI forum) for which many implementations are available. +# +# Variables for using MPI +# ^^^^^^^^^^^^^^^^^^^^^^^ +# +# The module exposes the components ``C``, ``CXX``, ``MPICXX`` and ``Fortran``. +# Each of these controls the various MPI languages to search for. +# The difference between ``CXX`` and ``MPICXX`` is that ``CXX`` refers to the +# MPI C API being usable from C++, whereas ``MPICXX`` refers to the MPI-2 C++ API +# that was removed again in MPI-3. +# +# Depending on the enabled components the following variables will be set: +# +# ``MPI_FOUND`` +# Variable indicating that MPI settings for all requested languages have been found. +# If no components are specified, this is true if MPI settings for all enabled languages +# were detected. Note that the ``MPICXX`` component does not affect this variable. +# ``MPI_VERSION`` +# Minimal version of MPI detected among the requested languages, or all enabled languages +# if no components were specified. +# +# This module will set the following variables per language in your +# project, where ```` is one of C, CXX, or Fortran: +# +# ``MPI__FOUND`` +# Variable indicating the MPI settings for ```` were found and that +# simple MPI test programs compile with the provided settings. +# ``MPI__COMPILER`` +# MPI compiler for ```` if such a program exists. +# ``MPI__COMPILE_OPTIONS`` +# Compilation options for MPI programs in ````, given as a :ref:`;-list `. +# ``MPI__COMPILE_DEFINITIONS`` +# Compilation definitions for MPI programs in ````, given as a :ref:`;-list `. +# ``MPI__INCLUDE_DIRS`` +# Include path(s) for MPI header. +# ``MPI__LINK_FLAGS`` +# Linker flags for MPI programs. +# ``MPI__LIBRARIES`` +# All libraries to link MPI programs against. +# +# Additionally, the following :prop_tgt:`IMPORTED` targets are defined: +# +# ``MPI::MPI_`` +# Target for using MPI from ````. +# +# The following variables indicating which bindings are present will be defined: +# +# ``MPI_MPICXX_FOUND`` +# Variable indicating whether the MPI-2 C++ bindings are present (introduced in MPI-2, removed with MPI-3). +# ``MPI_Fortran_HAVE_F77_HEADER`` +# True if the Fortran 77 header ``mpif.h`` is available. +# ``MPI_Fortran_HAVE_F90_MODULE`` +# True if the Fortran 90 module ``mpi`` can be used for accessing MPI (MPI-2 and higher only). +# ``MPI_Fortran_HAVE_F08_MODULE`` +# True if the Fortran 2008 ``mpi_f08`` is available to MPI programs (MPI-3 and higher only). +# +# If possible, the MPI version will be determined by this module. The facilities to detect the MPI version +# were introduced with MPI-1.2, and therefore cannot be found for older MPI versions. +# +# ``MPI__VERSION_MAJOR`` +# Major version of MPI implemented for ```` by the MPI distribution. +# ``MPI__VERSION_MINOR`` +# Minor version of MPI implemented for ```` by the MPI distribution. +# ``MPI__VERSION`` +# MPI version implemented for ```` by the MPI distribution. +# +# Note that there's no variable for the C bindings being accessible through ``mpi.h``, since the MPI standards +# always have required this binding to work in both C and C++ code. +# +# For running MPI programs, the module sets the following variables +# +# ``MPIEXEC_EXECUTABLE`` +# Executable for running MPI programs, if such exists. +# ``MPIEXEC_NUMPROC_FLAG`` +# Flag to pass to ``mpiexec`` before giving it the number of processors to run on. +# ``MPIEXEC_MAX_NUMPROCS`` +# Number of MPI processors to utilize. Defaults to the number +# of processors detected on the host system. +# ``MPIEXEC_PREFLAGS`` +# Flags to pass to ``mpiexec`` directly before the executable to run. +# ``MPIEXEC_POSTFLAGS`` +# Flags to pass to ``mpiexec`` after other flags. +# +# Variables for locating MPI +# ^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# This module performs a three step search for an MPI implementation: +# +# 1. Check if the compiler has MPI support built-in. This is the case if the user passed a +# compiler wrapper as ``CMAKE__COMPILER`` or if they're on a Cray system. +# 2. Attempt to find an MPI compiler wrapper and determine the compiler information from it. +# 3. Try to find an MPI implementation that does not ship such a wrapper by guessing settings. +# Currently, only Microsoft MPI and MPICH2 on Windows are supported. +# +# For controlling the second step, the following variables may be set: +# +# ``MPI__COMPILER`` +# Search for the specified compiler wrapper and use it. +# ``MPI__COMPILER_FLAGS`` +# Flags to pass to the MPI compiler wrapper during interrogation. Some compiler wrappers +# support linking debug or tracing libraries if a specific flag is passed and this variable +# may be used to obtain them. +# ``MPI_COMPILER_FLAGS`` +# Used to initialize ``MPI__COMPILER_FLAGS`` if no language specific flag has been given. +# Empty by default. +# ``MPI_EXECUTABLE_SUFFIX`` +# A suffix which is appended to all names that are being looked for. For instance you may set this +# to ``.mpich`` or ``.openmpi`` to prefer the one or the other on Debian and its derivatives. +# +# In order to control the guessing step, the following variable may be set: +# +# ``MPI_GUESS_LIBRARY_NAME`` +# Valid values are ``MSMPI`` and ``MPICH2``. If set, only the given library will be searched for. +# By default, ``MSMPI`` will be preferred over ``MPICH2`` if both are available. +# This also sets ``MPI_SKIP_COMPILER_WRAPPER`` to ``true``, which may be overridden. +# +# Each of the search steps may be skipped with the following control variables: +# +# ``MPI_ASSUME_NO_BUILTIN_MPI`` +# If true, the module assumes that the compiler itself does not provide an MPI implementation and +# skips to step 2. +# ``MPI_SKIP_COMPILER_WRAPPER`` +# If true, no compiler wrapper will be searched for. +# ``MPI_SKIP_GUESSING`` +# If true, the guessing step will be skipped. +# +# Additionally, the following control variable is available to change search behavior: +# +# ``MPI_CXX_SKIP_MPICXX`` +# Add some definitions that will disable the MPI-2 C++ bindings. +# Currently supported are MPICH, Open MPI, Platform MPI and derivatives thereof, +# for example MVAPICH or Intel MPI. +# +# If the find procedure fails for a variable ``MPI__WORKS``, then the settings detected by or passed to +# the module did not work and even a simple MPI test program failed to compile. +# +# If all of these parameters were not sufficient to find the right MPI implementation, a user may +# disable the entire autodetection process by specifying both a list of libraries in ``MPI__LIBRARIES`` +# and a list of include directories in ``MPI__ADDITIONAL_INCLUDE_DIRS``. +# Any other variable may be set in addition to these two. The module will then validate the MPI settings and store the +# settings in the cache. +# +# Cache variables for MPI +# ^^^^^^^^^^^^^^^^^^^^^^^ +# +# The variable ``MPI__INCLUDE_DIRS`` will be assembled from the following variables. +# For C and CXX: +# +# ``MPI__HEADER_DIR`` +# Location of the ``mpi.h`` header on disk. +# +# For Fortran: +# +# ``MPI_Fortran_F77_HEADER_DIR`` +# Location of the Fortran 77 header ``mpif.h``, if it exists. +# ``MPI_Fortran_MODULE_DIR`` +# Location of the ``mpi`` or ``mpi_f08`` modules, if available. +# +# For all languages the following variables are additionally considered: +# +# ``MPI__ADDITIONAL_INCLUDE_DIRS`` +# A :ref:`;-list ` of paths needed in addition to the normal include directories. +# ``MPI__INCLUDE_DIR`` +# Path variables for include folders referred to by ````. +# ``MPI__ADDITIONAL_INCLUDE_VARS`` +# A :ref:`;-list ` of ```` that will be added to the include locations of ````. +# +# The variable ``MPI__LIBRARIES`` will be assembled from the following variables: +# +# ``MPI__LIBRARY`` +# The location of a library called ```` for use with MPI. +# ``MPI__LIB_NAMES`` +# A :ref:`;-list ` of ```` that will be added to the include locations of ````. +# +# Usage of mpiexec +# ^^^^^^^^^^^^^^^^ +# +# When using ``MPIEXEC_EXECUTABLE`` to execute MPI applications, you should typically +# use all of the ``MPIEXEC_EXECUTABLE`` flags as follows: +# +# :: +# +# ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_MAX_NUMPROCS} +# ${MPIEXEC_PREFLAGS} EXECUTABLE ${MPIEXEC_POSTFLAGS} ARGS +# +# where ``EXECUTABLE`` is the MPI program, and ``ARGS`` are the arguments to +# pass to the MPI program. +# +# Advanced variables for using MPI +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# The module can perform some advanced feature detections upon explicit request. +# +# **Important notice:** The following checks cannot be performed without *executing* an MPI test program. +# Consider the special considerations for the behavior of :command:`try_run` during cross compilation. +# Moreover, running an MPI program can cause additional issues, like a firewall notification on some systems. +# You should only enable these detections if you absolutely need the information. +# +# If the following variables are set to true, the respective search will be performed: +# +# ``MPI_DETERMINE_Fortran_CAPABILITIES`` +# Determine for all available Fortran bindings what the values of ``MPI_SUBARRAYS_SUPPORTED`` and +# ``MPI_ASYNC_PROTECTS_NONBLOCKING`` are and make their values available as ``MPI_Fortran__SUBARRAYS`` +# and ``MPI_Fortran__ASYNCPROT``, where ```` is one of ``F77_HEADER``, ``F90_MODULE`` and +# ``F08_MODULE``. +# ``MPI_DETERMINE_LIBRARY_VERSION`` +# For each language, find the output of ``MPI_Get_library_version`` and make it available as ``MPI__LIBRARY_VERSION``. +# This information is usually tied to the runtime component of an MPI implementation and might differ depending on ````. +# Note that the return value is entirely implementation defined. This information might be used to identify +# the MPI vendor and for example pick the correct one of multiple third party binaries that matches the MPI vendor. +# +# Backward Compatibility +# ^^^^^^^^^^^^^^^^^^^^^^ +# +# For backward compatibility with older versions of FindMPI, these +# variables are set, but deprecated: +# +# :: +# +# MPI_COMPILER MPI_LIBRARY MPI_EXTRA_LIBRARY +# MPI_COMPILE_FLAGS MPI_INCLUDE_PATH MPI_LINK_FLAGS +# MPI_LIBRARIES +# +# In new projects, please use the ``MPI__XXX`` equivalents. +# Additionally, the following variables are deprecated: +# +# ``MPI__COMPILE_FLAGS`` +# Use ``MPI__COMPILE_OPTIONS`` and ``MPI__COMPILE_DEFINITIONS`` instead. +# ``MPI__INCLUDE_PATH`` +# For consumption use ``MPI__INCLUDE_DIRS`` and for specifying folders use ``MPI__ADDITIONAL_INCLUDE_DIRS`` instead. +# ``MPIEXEC`` +# Use ``MPIEXEC_EXECUTABLE`` instead. + +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +# Generic compiler names +set(_MPI_C_GENERIC_COMPILER_NAMES mpicc mpcc mpicc_r mpcc_r) +set(_MPI_CXX_GENERIC_COMPILER_NAMES mpicxx mpiCC mpcxx mpCC mpic++ mpc++ + mpicxx_r mpiCC_r mpcxx_r mpCC_r mpic++_r mpc++_r) +set(_MPI_Fortran_GENERIC_COMPILER_NAMES mpif95 mpif95_r mpf95 mpf95_r + mpif90 mpif90_r mpf90 mpf90_r + mpif77 mpif77_r mpf77 mpf77_r + mpifc) + +# GNU compiler names +set(_MPI_GNU_C_COMPILER_NAMES mpigcc mpgcc mpigcc_r mpgcc_r) +set(_MPI_GNU_CXX_COMPILER_NAMES mpig++ mpg++ mpig++_r mpg++_r mpigxx) +set(_MPI_GNU_Fortran_COMPILER_NAMES mpigfortran mpgfortran mpigfortran_r mpgfortran_r + mpig77 mpig77_r mpg77 mpg77_r) + +# Intel MPI compiler names on Windows +if(WIN32) + list(APPEND _MPI_C_GENERIC_COMPILER_NAMES mpicc.bat) + list(APPEND _MPI_CXX_GENERIC_COMPILER_NAMES mpicxx.bat) + list(APPEND _MPI_Fortran_GENERIC_COMPILER_NAMES mpifc.bat) + + # Intel MPI compiler names + set(_MPI_Intel_C_COMPILER_NAMES mpiicc.bat) + set(_MPI_Intel_CXX_COMPILER_NAMES mpiicpc.bat) + set(_MPI_Intel_Fortran_COMPILER_NAMES mpiifort.bat mpif77.bat mpif90.bat) + + # Intel MPI compiler names for MSMPI + set(_MPI_MSVC_C_COMPILER_NAMES mpicl.bat) + set(_MPI_MSVC_CXX_COMPILER_NAMES mpicl.bat) +else() + # Intel compiler names + set(_MPI_Intel_C_COMPILER_NAMES mpiicc) + set(_MPI_Intel_CXX_COMPILER_NAMES mpiicpc mpiicxx mpiic++) + set(_MPI_Intel_Fortran_COMPILER_NAMES mpiifort mpiif95 mpiif90 mpiif77) +endif() + +# PGI compiler names +set(_MPI_PGI_C_COMPILER_NAMES mpipgcc mppgcc) +set(_MPI_PGI_CXX_COMPILER_NAMES mpipgCC mppgCC) +set(_MPI_PGI_Fortran_COMPILER_NAMES mpipgf95 mpipgf90 mppgf95 mppgf90 mpipgf77 mppgf77) + +# XLC MPI Compiler names +set(_MPI_XL_C_COMPILER_NAMES mpxlc mpxlc_r mpixlc mpixlc_r) +set(_MPI_XL_CXX_COMPILER_NAMES mpixlcxx mpixlC mpixlc++ mpxlcxx mpxlc++ mpixlc++ mpxlCC + mpixlcxx_r mpixlC_r mpixlc++_r mpxlcxx_r mpxlc++_r mpixlc++_r mpxlCC_r) +set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95_r + mpixlf90 mpixlf90_r mpxlf90 mpxlf90_r + mpixlf77 mpixlf77_r mpxlf77 mpxlf77_r + mpixlf mpixlf_r mpxlf mpxlf_r) + +# Prepend vendor-specific compiler wrappers to the list. If we don't know the compiler, +# attempt all of them. +# By attempting vendor-specific compiler names first, we should avoid situations where the compiler wrapper +# stems from a proprietary MPI and won't know which compiler it's being used for. For instance, Intel MPI +# controls its settings via the I_MPI_CC environment variables if the generic name is being used. +# If we know which compiler we're working with, we can use the most specialized wrapper there is in order to +# pick up the right settings for it. +foreach (LANG IN ITEMS C CXX Fortran) + set(_MPI_${LANG}_COMPILER_NAMES "") + foreach (id IN ITEMS GNU Intel MSVC PGI XL) + if (NOT CMAKE_${LANG}_COMPILER_ID OR CMAKE_${LANG}_COMPILER_ID STREQUAL id) + list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_MPI_${id}_${LANG}_COMPILER_NAMES}${MPI_EXECUTABLE_SUFFIX}) + endif() + unset(_MPI_${id}_${LANG}_COMPILER_NAMES) + endforeach() + list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_MPI_${LANG}_GENERIC_COMPILER_NAMES}${MPI_EXECUTABLE_SUFFIX}) + unset(_MPI_${LANG}_GENERIC_COMPILER_NAMES) +endforeach() + +# Names to try for mpiexec +# Only mpiexec commands are guaranteed to behave as described in the standard, +# mpirun commands are not covered by the standard in any way whatsoever. +# lamexec is the executable for LAM/MPI, srun is for SLURM or Open MPI with SLURM support. +# srun -n X is however a valid command, so it behaves 'like' mpiexec. +set(_MPIEXEC_NAMES_BASE mpiexec mpiexec.hydra mpiexec.mpd mpirun lamexec srun) + +unset(_MPIEXEC_NAMES) +foreach(_MPIEXEC_NAME IN LISTS _MPIEXEC_NAMES_BASE) + list(APPEND _MPIEXEC_NAMES "${_MPIEXEC_NAME}${MPI_EXECUTABLE_SUFFIX}") +endforeach() +unset(_MPIEXEC_NAMES_BASE) + +function (_MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE) + if(DEFINED MPI_${LANG}_COMPILER_FLAGS) +# separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_${LANG}_COMPILER_FLAGS}") + separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS "${MPI_${LANG}_COMPILER_FLAGS}") + else() + separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_COMPILER_FLAGS}") + endif() + execute_process( + COMMAND ${MPI_${LANG}_COMPILER} ${_MPI_COMPILER_WRAPPER_OPTIONS} ${QUERY_FLAG} + OUTPUT_VARIABLE WRAPPER_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE WRAPPER_OUTPUT ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE WRAPPER_RETURN) + # Some compiler wrappers will yield spurious zero return values, for example + # Intel MPI tolerates unknown arguments and if the MPI wrappers loads a shared + # library that has invalid or missing version information there would be warning + # messages emitted by ld.so in the compiler output. In either case, we'll treat + # the output as invalid. + if("${WRAPPER_OUTPUT}" MATCHES "undefined reference|unrecognized|need to set|no version information available") + set(WRAPPER_RETURN 255) + endif() + # Ensure that no error output might be passed upwards. + if(NOT WRAPPER_RETURN EQUAL 0) + unset(WRAPPER_OUTPUT) + endif() + set(${OUTPUT_VARIABLE} "${WRAPPER_OUTPUT}" PARENT_SCOPE) + set(${RESULT_VARIABLE} "${WRAPPER_RETURN}" PARENT_SCOPE) +endfunction() + +function (_MPI_interrogate_compiler lang) + unset(MPI_COMPILE_CMDLINE) + unset(MPI_LINK_CMDLINE) + + unset(MPI_COMPILE_OPTIONS_WORK) + unset(MPI_COMPILE_DEFINITIONS_WORK) + unset(MPI_INCLUDE_DIRS_WORK) + unset(MPI_LINK_FLAGS_WORK) + unset(MPI_LIB_NAMES_WORK) + unset(MPI_LIB_FULLPATHS_WORK) + + # Check whether the -showme:compile option works. This indicates that we have either Open MPI + # or a newer version of LAM/MPI, and implies that -showme:link will also work. + # Open MPI also supports -show, but separates linker and compiler information + _MPI_check_compiler(${LANG} "-showme:compile" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) + if (MPI_COMPILER_RETURN EQUAL 0) + _MPI_check_compiler(${LANG} "-showme:link" MPI_LINK_CMDLINE MPI_COMPILER_RETURN) + + if (NOT MPI_COMPILER_RETURN EQUAL 0) + unset(MPI_COMPILE_CMDLINE) + endif() + endif() + + # MPICH and MVAPICH offer -compile-info and -link-info. + # For modern versions, both do the same as -show. However, for old versions, they do differ + # when called for mpicxx and mpif90 and it's necessary to use them over -show in order to find the + # removed MPI C++ bindings. + if (NOT MPI_COMPILER_RETURN EQUAL 0) + _MPI_check_compiler(${LANG} "-compile-info" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) + + if (MPI_COMPILER_RETURN EQUAL 0) + _MPI_check_compiler(${LANG} "-link-info" MPI_LINK_CMDLINE MPI_COMPILER_RETURN) + + if (NOT MPI_COMPILER_RETURN EQUAL 0) + unset(MPI_COMPILE_CMDLINE) + endif() + endif() + endif() + + # MPICH, MVAPICH2 and Intel MPI just use "-show". Open MPI also offers this, but the + # -showme commands are more specialized. + if (NOT MPI_COMPILER_RETURN EQUAL 0) + _MPI_check_compiler(${LANG} "-show" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) + endif() + + # Older versions of LAM/MPI have "-showme". Open MPI also supports this. + # Unknown to MPICH, MVAPICH and Intel MPI. + if (NOT MPI_COMPILER_RETURN EQUAL 0) + _MPI_check_compiler(${LANG} "-showme" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) + endif() + + if (NOT (MPI_COMPILER_RETURN EQUAL 0) OR NOT (DEFINED MPI_COMPILE_CMDLINE)) + # Cannot interrogate this compiler, so exit. + set(MPI_${LANG}_WRAPPER_FOUND FALSE PARENT_SCOPE) + return() + endif() + unset(MPI_COMPILER_RETURN) + + # We have our command lines, but we might need to copy MPI_COMPILE_CMDLINE + # into MPI_LINK_CMDLINE, if we didn't find the link line. + if (NOT DEFINED MPI_LINK_CMDLINE) + set(MPI_LINK_CMDLINE "${MPI_COMPILE_CMDLINE}") + endif() + + # At this point, we obtained some output from a compiler wrapper that works. + # We'll now try to parse it into variables with meaning to us. + if("${LANG}" STREQUAL "Fortran") + # Some MPICH-1 and MVAPICH-1 versions return a three command answer for Fortran, consisting + # out of a symlink command for mpif.h, the actual compiler command and a deletion of the + # created symlink. We need to detect that case, remember the include path and drop the + # symlink/deletion operation to obtain the link/compile lines we'd usually expect. + if("${MPI_COMPILE_CMDLINE}" MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h") + get_filename_component(MPI_INCLUDE_DIRS_WORK "${CMAKE_MATCH_1}" DIRECTORY) + string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") + string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") + string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") + string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") + endif() + endif() + + # The Intel MPI wrapper on Linux will emit some objcopy commands after its compile command + # if -static_mpi was passed to the wrapper. To avoid spurious matches, we need to drop these lines. + if(UNIX) + string(REGEX REPLACE "(^|\n)objcopy[^\n]+(\n|$)" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") + string(REGEX REPLACE "(^|\n)objcopy[^\n]+(\n|$)" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") + endif() + + # Extract compile options from the compile command line. + string(REGEX MATCHALL "(^| )-f([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_OPTIONS "${MPI_COMPILE_CMDLINE}") + + foreach(_MPI_COMPILE_OPTION IN LISTS MPI_ALL_COMPILE_OPTIONS) + string(REGEX REPLACE "^ " "" _MPI_COMPILE_OPTION "${_MPI_COMPILE_OPTION}") + # Ignore -fstack-protector directives: These occur on MPICH and MVAPICH when the libraries + # themselves were built with this flag. However, this flag is unrelated to using MPI, and + # we won't match the accompanying --param-ssp-size and -Wp,-D_FORTIFY_SOURCE flags and therefore + # produce inconsistent results with the regularly flags. + # Similarly, aliasing flags do not belong into our flag array. + if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f(stack-protector|(no-|)strict-aliasing|PI[CE]|pi[ce])") + list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}") + endif() + endforeach() + + # Same deal, with the definitions. We also treat arguments passed to the preprocessor directly. + string(REGEX MATCHALL "(^| )(-Wp,|-Xpreprocessor |)[-/]D([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_DEFINITIONS "${MPI_COMPILE_CMDLINE}") + + foreach(_MPI_COMPILE_DEFINITION IN LISTS MPI_ALL_COMPILE_DEFINITIONS) + string(REGEX REPLACE "^ ?(-Wp,|-Xpreprocessor )?[-/]D" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") + string(REPLACE "\"" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") + if(NOT "${_MPI_COMPILE_DEFINITION}" MATCHES "^_FORTIFY_SOURCE.*") + list(APPEND MPI_COMPILE_DEFINITIONS_WORK "${_MPI_COMPILE_DEFINITION}") + endif() + endforeach() + + # Extract include paths from compile command line + string(REGEX MATCHALL "(^| )[-/]I([^\" ]+|\"[^\"]+\")" MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}") + + # If extracting failed to work, we'll try using -showme:incdirs. + if (NOT MPI_ALL_INCLUDE_PATHS) + _MPI_check_compiler(${LANG} "-showme:incdirs" MPI_INCDIRS_CMDLINE MPI_INCDIRS_COMPILER_RETURN) + if(MPI_INCDIRS_COMPILER_RETURN) + separate_arguments(MPI_ALL_INCLUDE_PATHS NATIVE_COMMAND "${MPI_INCDIRS_CMDLINE}") + endif() + endif() + + foreach(_MPI_INCLUDE_PATH IN LISTS MPI_ALL_INCLUDE_PATHS) + string(REGEX REPLACE "^ ?[-/]I" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}") + string(REPLACE "\"" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}") + get_filename_component(_MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}" REALPATH) + list(APPEND MPI_INCLUDE_DIRS_WORK "${_MPI_INCLUDE_PATH}") + endforeach() + + # Extract linker paths from the link command line + string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker |)(-L|[/-]LIBPATH:|[/-]libpath:)([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_PATHS "${MPI_LINK_CMDLINE}") + + # If extracting failed to work, we'll try using -showme:libdirs. + if (NOT MPI_ALL_LINK_PATHS) + _MPI_check_compiler(${LANG} "-showme:libdirs" MPI_LIBDIRS_CMDLINE MPI_LIBDIRS_COMPILER_RETURN) + if(MPI_LIBDIRS_COMPILER_RETURN) + separate_arguments(MPI_ALL_LINK_PATHS NATIVE_COMMAND "${MPI_LIBDIRS_CMDLINE}") + endif() + endif() + + foreach(_MPI_LPATH IN LISTS MPI_ALL_LINK_PATHS) + string(REGEX REPLACE "^ ?(-Wl,|-Xlinker )?(-L|[/-]LIBPATH:|[/-]libpath:)" "" _MPI_LPATH "${_MPI_LPATH}") + string(REPLACE "\"" "" _MPI_LPATH "${_MPI_LPATH}") + get_filename_component(_MPI_LPATH "${_MPI_LPATH}" REALPATH) + list(APPEND MPI_LINK_DIRECTORIES_WORK "${_MPI_LPATH}") + endforeach() + + # Extract linker flags from the link command line + string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker )([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE}") + + foreach(_MPI_LINK_FLAG IN LISTS MPI_ALL_LINK_FLAGS) + string(STRIP "${_MPI_LINK_FLAG}" _MPI_LINK_FLAG) + # MPI might be marked to build with non-executable stacks but this should not propagate. + if (NOT "${_MPI_LINK_FLAG}" MATCHES "(-Wl,|-Xlinker )-z,noexecstack") + if (MPI_LINK_FLAGS_WORK) + string(APPEND MPI_LINK_FLAGS_WORK " ${_MPI_LINK_FLAG}") + else() + set(MPI_LINK_FLAGS_WORK "${_MPI_LINK_FLAG}") + endif() + endif() + endforeach() + + # Extract the set of libraries to link against from the link command + # line + string(REGEX MATCHALL "(^| )-l([^\" ]+|\"[^\"]+\")" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") + + foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) + string(REGEX REPLACE "^ ?-l" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) + if(NOT "${_MPI_LIB_PATH}" STREQUAL "") + list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") + else() + list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") + endif() + endforeach() + + if(WIN32) + # A compiler wrapper on Windows will just have the name of the + # library to link on its link line, potentially with a full path + string(REGEX MATCHALL "(^| )([^\" ]+\\.lib|\"[^\"]+\\.lib\")" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") + foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) + string(REGEX REPLACE "^ " "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) + if(NOT "${_MPI_LIB_PATH}" STREQUAL "") + list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") + else() + list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") + endif() + endforeach() + else() + # On UNIX platforms, archive libraries can be given with full path. + string(REGEX MATCHALL "(^| )([^\" ]+\\.a|\"[^\"]+\\.a\")" MPI_LIBFULLPATHS "${MPI_LINK_CMDLINE}") + foreach(_MPI_LIB_NAME IN LISTS MPI_LIBFULLPATHS) + string(REGEX REPLACE "^ " "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") + get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) + if(NOT "${_MPI_LIB_PATH}" STREQUAL "") + list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") + else() + list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") + endif() + endforeach() + endif() + + # An MPI compiler wrapper could have its MPI libraries in the implictly + # linked directories of the compiler itself. + if(DEFINED CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES) + list(APPEND MPI_LINK_DIRECTORIES_WORK "${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}") + endif() + + # Determine full path names for all of the libraries that one needs + # to link against in an MPI program + unset(MPI_PLAIN_LIB_NAMES_WORK) + foreach(_MPI_LIB_NAME IN LISTS MPI_LIB_NAMES_WORK) + get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB_NAME}" NAME_WE) + list(APPEND MPI_PLAIN_LIB_NAMES_WORK "${_MPI_PLAIN_LIB_NAME}") + find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY + NAMES "${_MPI_LIB_NAME}" "lib${_MPI_LIB_NAME}" + HINTS ${MPI_LINK_DIRECTORIES_WORK} + DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" + ) + mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) + endforeach() + + # Deal with the libraries given with full path next + unset(MPI_DIRECT_LIB_NAMES_WORK) + foreach(_MPI_LIB_FULLPATH IN LISTS MPI_LIB_FULLPATHS_WORK) + get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB_FULLPATH}" NAME_WE) + get_filename_component(_MPI_LIB_NAME "${_MPI_LIB_FULLPATH}" NAME) + get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_FULLPATH}" DIRECTORY) + list(APPEND MPI_DIRECT_LIB_NAMES_WORK "${_MPI_PLAIN_LIB_NAME}") + find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY + NAMES "${_MPI_LIB_NAME}" + HINTS ${_MPI_LIB_PATH} + DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" + ) + mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) + endforeach() + if(MPI_DIRECT_LIB_NAMES_WORK) + set(MPI_PLAIN_LIB_NAMES_WORK "${MPI_DIRECT_LIB_NAMES_WORK};${MPI_PLAIN_LIB_NAMES_WORK}") + endif() + + # MPI might require pthread to work. The above mechanism wouldn't detect it, but we need to + # link it in that case. -lpthread is covered by the normal library treatment on the other hand. + if("${MPI_COMPILE_CMDLINE}" MATCHES "-pthread") + list(APPEND MPI_COMPILE_OPTIONS_WORK "-pthread") + if(MPI_LINK_FLAGS_WORK) + string(APPEND MPI_LINK_FLAGS_WORK " -pthread") + else() + set(MPI_LINK_FLAGS_WORK "-pthread") + endif() + endif() + + if(MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS) + list(APPEND MPI_COMPILE_DEFINITIONS_WORK "${MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS}") + endif() + if(MPI_${LANG}_EXTRA_COMPILE_OPTIONS) + list(APPEND MPI_COMPILE_OPTIONS_WORK "${MPI_${LANG}_EXTRA_COMPILE_OPTIONS}") + endif() + if(MPI_${LANG}_EXTRA_LIB_NAMES) + list(APPEND MPI_PLAIN_LIB_NAMES_WORK "${MPI_${LANG}_EXTRA_LIB_NAMES}") + endif() + + # If we found MPI, set up all of the appropriate cache entries + if(NOT MPI_${LANG}_COMPILE_OPTIONS) + set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_COMPILE_OPTIONS_WORK} CACHE STRING "MPI ${LANG} compilation options" FORCE) + endif() + if(NOT MPI_${LANG}_COMPILE_DEFINITIONS) + set(MPI_${LANG}_COMPILE_DEFINITIONS ${MPI_COMPILE_DEFINITIONS_WORK} CACHE STRING "MPI ${LANG} compilation definitions" FORCE) + endif() + if(NOT MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) + set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS ${MPI_INCLUDE_DIRS_WORK} CACHE STRING "MPI ${LANG} additional include directories" FORCE) + endif() + if(NOT MPI_${LANG}_LINK_FLAGS) + set(MPI_${LANG}_LINK_FLAGS ${MPI_LINK_FLAGS_WORK} CACHE STRING "MPI ${LANG} linker flags" FORCE) + endif() + if(NOT MPI_${LANG}_LIB_NAMES) + set(MPI_${LANG}_LIB_NAMES ${MPI_PLAIN_LIB_NAMES_WORK} CACHE STRING "MPI ${LANG} libraries to link against" FORCE) + endif() + set(MPI_${LANG}_WRAPPER_FOUND TRUE PARENT_SCOPE) +endfunction() + +function(_MPI_guess_settings LANG) + set(MPI_GUESS_FOUND FALSE) + # Currently only MSMPI and MPICH2 on Windows are supported, so we can skip this search if we're not targeting that. + if(WIN32) + # MSMPI + + # The environment variables MSMPI_INC and MSMPILIB32/64 are the only ways of locating the MSMPI_SDK, + # which is installed separately from the runtime. Thus it's possible to have mpiexec but not MPI headers + # or import libraries and vice versa. + if(NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MSMPI") + # We first attempt to locate the msmpi.lib. Should be find it, we'll assume that the MPI present is indeed + # Microsoft MPI. + if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + set(MPI_MSMPI_LIB_PATH "$ENV{MSMPI_LIB64}") + set(MPI_MSMPI_INC_PATH_EXTRA "$ENV{MSMPI_INC}/x64") + else() + set(MPI_MSMPI_LIB_PATH "$ENV{MSMPI_LIB32}") + set(MPI_MSMPI_INC_PATH_EXTRA "$ENV{MSMPI_INC}/x86") + endif() + + find_library(MPI_msmpi_LIBRARY + NAMES msmpi + HINTS ${MPI_MSMPI_LIB_PATH} + DOC "Location of the msmpi library for Microsoft MPI") + mark_as_advanced(MPI_msmpi_LIBRARY) + + if(MPI_msmpi_LIBRARY) + # Next, we attempt to locate the MPI header. Note that for Fortran we know that mpif.h is a way + # MSMPI can be used and therefore that header has to be present. + if(NOT MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) + get_filename_component(MPI_MSMPI_INC_DIR "$ENV{MSMPI_INC}" REALPATH) + set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_MSMPI_INC_DIR}" CACHE STRING "MPI ${LANG} additional include directories" FORCE) + unset(MPI_MSMPI_INC_DIR) + endif() + + # For MSMPI, one can compile the MPI module by building the mpi.f90 shipped with the MSMPI SDK, + # thus it might be present or provided by the user. Figuring out which is supported is done later on. + # The PGI Fortran compiler for instance ships a prebuilt set of modules in its own include folder. + # Should a user be employing PGI or have built its own set and provided it via cache variables, the + # splitting routine would have located the module files. + + # For C and C++, we're done here (MSMPI does not ship the MPI-2 C++ bindings) - however, for Fortran + # we need some extra library to glue Fortran support together: + # MSMPI ships 2-4 Fortran libraries, each for different Fortran compiler behaviors. The library names + # ending with a c are using the cdecl calling convention, whereas those ending with an s are for Fortran + # implementations using stdcall. Therefore, the 64-bit MSMPI only ships those ending in 'c', whereas the 32-bit + # has both variants available. + # The second difference is the last but one letter, if it's an e(nd), the length of a string argument is + # passed by the Fortran compiler after all other arguments on the parameter list, if it's an m(ixed), + # it's passed immediately after the string address. + + # To summarize: + # - msmpifec: CHARACTER length passed after the parameter list and using cdecl calling convention + # - msmpifmc: CHARACTER length passed directly after string address and using cdecl calling convention + # - msmpifes: CHARACTER length passed after the parameter list and using stdcall calling convention + # - msmpifms: CHARACTER length passed directly after string address and using stdcall calling convention + # 32-bit MSMPI ships all four libraries, 64-bit MSMPI ships only the first two. + + # As is, Intel Fortran and PGI Fortran both use the 'ec' variant of the calling convention, whereas + # the old Compaq Visual Fortran compiler defaulted to the 'ms' version. It's possible to make Intel Fortran + # use the CVF calling convention using /iface:cvf, but we assume - and this is also assumed in FortranCInterface - + # this isn't the case. It's also possible to make CVF use the 'ec' variant, using /iface=(cref,nomixed_str_len_arg). + + # Our strategy is now to locate all libraries, but enter msmpifec into the LIB_NAMES array. + # Should this not be adequate it's a straightforward way for a user to change the LIB_NAMES array and + # have his library found. Still, this should not be necessary outside of exceptional cases, as reasoned. + if ("${LANG}" STREQUAL "Fortran") + set(MPI_MSMPI_CALLINGCONVS c) + if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4) + list(APPEND MPI_MSMPI_CALLINGCONVS s) + endif() + foreach(mpistrlenpos IN ITEMS e m) + foreach(mpicallingconv IN LISTS MPI_MSMPI_CALLINGCONVS) + find_library(MPI_msmpif${mpistrlenpos}${mpicallingconv}_LIBRARY + NAMES msmpif${mpistrlenpos}${mpicallingconv} + HINTS "${MPI_MSMPI_LIB_PATH}" + DOC "Location of the msmpi${mpistrlenpos}${mpicallingconv} library for Microsoft MPI") + mark_as_advanced(MPI_msmpif${mpistrlenpos}${mpicallingconv}_LIBRARY) + endforeach() + endforeach() + if(NOT MPI_${LANG}_LIB_NAMES) + set(MPI_${LANG}_LIB_NAMES "msmpi;msmpifec" CACHE STRING "MPI ${LANG} libraries to link against" FORCE) + endif() + + # At this point we're *not* done. MSMPI requires an additional include file for Fortran giving the value + # of MPI_AINT. This file is called mpifptr.h located in the x64 and x86 subfolders, respectively. + find_path(MPI_mpifptr_INCLUDE_DIR + NAMES "mpifptr.h" + HINTS "${MPI_MSMPI_INC_PATH_EXTRA}" + DOC "Location of the mpifptr.h extra header for Microsoft MPI") + if(NOT MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) + set(MPI_${LANG}_ADDITIONAL_INCLUDE_VARS "mpifptr" CACHE STRING "MPI ${LANG} additional include directory variables, given in the form MPI__INCLUDE_DIR." FORCE) + endif() + mark_as_advanced(MPI_${LANG}_ADDITIONAL_INCLUDE_VARS MPI_mpifptr_INCLUDE_DIR) + else() + if(NOT MPI_${LANG}_LIB_NAMES) + set(MPI_${LANG}_LIB_NAMES "msmpi" CACHE STRING "MPI ${LANG} libraries to link against" FORCE) + endif() + endif() + mark_as_advanced(MPI_${LANG}_LIB_NAMES) + set(MPI_GUESS_FOUND TRUE) + endif() + endif() + + # At this point there's not many MPIs that we could still consider. + # OpenMPI 1.6.x and below supported Windows, but these ship compiler wrappers that still work. + # The only other relevant MPI implementation without a wrapper is MPICH2, which had Windows support in 1.4.1p1 and older. + if(NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MPICH2") + set(MPI_MPICH_PREFIX_PATHS + "$ENV{ProgramW6432}/MPICH2/lib" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH\\SMPD;binary]/../lib" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH2;Path]/lib" + ) + + # All of C, C++ and Fortran will need mpi.lib, so we'll look for this first + find_library(MPI_mpi_LIBRARY + NAMES mpi + HINTS ${MPI_MPICH_PREFIX_PATHS}) + mark_as_advanced(MPI_mpi_LIBRARY) + # If we found mpi.lib, we detect the rest of MPICH2 + if(MPI_mpi_LIBRARY) + set(MPI_MPICH_LIB_NAMES "mpi") + # If MPI-2 C++ bindings are requested, we need to locate cxx.lib as well. + # Otherwise, MPICH_SKIP_MPICXX will be defined and these bindings aren't needed. + if("${LANG}" STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX) + find_library(MPI_cxx_LIBRARY + NAMES cxx + HINTS ${MPI_MPICH_PREFIX_PATHS}) + mark_as_advanced(MPI_cxx_LIBRARY) + list(APPEND MPI_MPICH_LIB_NAMES "cxx") + # For Fortran, MPICH2 provides three different libraries: + # fmpich2.lib which uses uppercase symbols and cdecl, + # fmpich2s.lib which uses uppercase symbols and stdcall (32-bit only), + # fmpich2g.lib which uses lowercase symbols with double underscores and cdecl. + # fmpich2s.lib would be useful for Compaq Visual Fortran, fmpich2g.lib has to be used with GNU g77 and is also + # provided in the form of an .a archive for MinGW and Cygwin. From our perspective, fmpich2.lib is the only one + # we need to try, and if it doesn't work with the given Fortran compiler we'd find out later on during validation + elseif("${LANG}" STREQUAL "Fortran") + find_library(MPI_fmpich2_LIBRARY + NAMES fmpich2 + HINTS ${MPI_MPICH_PREFIX_PATHS}) + find_library(MPI_fmpich2s_LIBRARY + NAMES fmpich2s + HINTS ${MPI_MPICH_PREFIX_PATHS}) + find_library(MPI_fmpich2g_LIBRARY + NAMES fmpich2g + HINTS ${MPI_MPICH_PREFIX_PATHS}) + mark_as_advanced(MPI_fmpich2_LIBRARY MPI_fmpich2s_LIBRARY MPI_fmpich2g_LIBRARY) + list(APPEND MPI_MPICH_LIB_NAMES "fmpich2") + endif() + + if(NOT MPI_${LANG}_LIB_NAMES) + set(MPI_${LANG}_LIB_NAMES "${MPI_MPICH_LIB_NAMES}" CACHE STRING "MPI ${LANG} libraries to link against" FORCE) + endif() + unset(MPI_MPICH_LIB_NAMES) + + if(NOT MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) + # For MPICH2, the include folder would be in ../include relative to the library folder. + get_filename_component(MPI_MPICH_ROOT_DIR "${MPI_mpi_LIBRARY}" DIRECTORY) + get_filename_component(MPI_MPICH_ROOT_DIR "${MPI_MPICH_ROOT_DIR}" DIRECTORY) + if(IS_DIRECTORY "${MPI_MPICH_ROOT_DIR}/include") + set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_MPICH_ROOT_DIR}/include" CACHE STRING "MPI ${LANG} additional include directory variables, given in the form MPI__INCLUDE_DIR." FORCE) + endif() + unset(MPI_MPICH_ROOT_DIR) + endif() + set(MPI_GUESS_FOUND TRUE) + endif() + unset(MPI_MPICH_PREFIX_PATHS) + endif() + endif() + set(MPI_${LANG}_GUESS_FOUND "${MPI_GUESS_FOUND}" PARENT_SCOPE) +endfunction() + +function(_MPI_adjust_compile_definitions LANG) + if("${LANG}" STREQUAL "CXX") + # To disable the C++ bindings, we need to pass some definitions since the mpi.h header has to deal with both C and C++ + # bindings in MPI-2. + if(MPI_CXX_SKIP_MPICXX AND NOT MPI_${LANG}_COMPILE_DEFINITIONS MATCHES "SKIP_MPICXX") + # MPICH_SKIP_MPICXX is being used in MPICH and derivatives like MVAPICH or Intel MPI + # OMPI_SKIP_MPICXX is being used in Open MPI + # _MPICC_H is being used for IBM Platform MPI + list(APPEND MPI_${LANG}_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX" "OMPI_SKIP_MPICXX" "_MPICC_H") + set(MPI_${LANG}_COMPILE_DEFINITIONS "${MPI_${LANG}_COMPILE_DEFINITIONS}" CACHE STRING "MPI ${LANG} compilation definitions" FORCE) + endif() + endif() +endfunction() + +macro(_MPI_assemble_libraries LANG) + set(MPI_${LANG}_LIBRARIES "") + # Only for libraries do we need to check whether the compiler's linking stage is separate. + if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_${LANG}_WORKS_IMPLICIT) + foreach(mpilib IN LISTS MPI_${LANG}_LIB_NAMES) + list(APPEND MPI_${LANG}_LIBRARIES ${MPI_${mpilib}_LIBRARY}) + endforeach() + endif() +endmacro() + +macro(_MPI_assemble_include_dirs LANG) + if("${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") + set(MPI_${LANG}_INCLUDE_DIRS "") + else() + set(MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS}") + if("${LANG}" MATCHES "(C|CXX)") + if(MPI_${LANG}_HEADER_DIR) + list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}") + endif() + else() # Fortran + if(MPI_${LANG}_F77_HEADER_DIR) + list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_F77_HEADER_DIR}") + endif() + if(MPI_${LANG}_MODULE_DIR AND NOT "${MPI_${LANG}_MODULE_DIR}" IN_LIST MPI_${LANG}_INCLUDE_DIRS) + list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_MODULE_DIR}") + endif() + endif() + if(MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) + foreach(MPI_ADDITIONAL_INC_DIR IN LISTS MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) + list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${MPI_ADDITIONAL_INC_DIR}_INCLUDE_DIR}") + endforeach() + endif() + endif() +endmacro() + +function(_MPI_split_include_dirs LANG) + if("${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") + return() + endif() + # Backwards compatibility: Search INCLUDE_PATH if given. + if(MPI_${LANG}_INCLUDE_PATH) + list(APPEND MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_${LANG}_INCLUDE_PATH}") + endif() + + # We try to find the headers/modules among those paths (and system paths) + # For C/C++, we just need to have a look for mpi.h. + if("${LANG}" MATCHES "(C|CXX)") + find_path(MPI_${LANG}_HEADER_DIR "mpi.h" + HINTS ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} + ) + mark_as_advanced(MPI_${LANG}_HEADER_DIR) + if(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) + list(REMOVE_ITEM MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}") + endif() + # Fortran is more complicated here: An implementation could provide + # any of the Fortran 77/90/2008 APIs for MPI. For example, MSMPI + # only provides Fortran 77 and - if mpi.f90 is built - potentially + # a Fortran 90 module. + elseif("${LANG}" STREQUAL "Fortran") + find_path(MPI_${LANG}_F77_HEADER_DIR "mpif.h" + HINTS ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} + ) + find_path(MPI_${LANG}_MODULE_DIR + NAMES "mpi.mod" "mpi_f08.mod" + HINTS ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} + ) + if(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) + list(REMOVE_ITEM MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS + "${MPI_${LANG}_F77_HEADER_DIR}" + "${MPI_${LANG}_MODULE_DIR}" + ) + endif() + mark_as_advanced(MPI_${LANG}_F77_HEADER_DIR MPI_${LANG}_MODULE_DIR) + endif() + # Remove duplicates and default system directories from the list. + if(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) + list(REMOVE_DUPLICATES MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) + foreach(MPI_IMPLICIT_INC_DIR IN LISTS CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES) + list(REMOVE_ITEM MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS ${MPI_IMPLICIT_INC_DIR}) + endforeach() + endif() + set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} additional include directories" FORCE) +endfunction() + +macro(_MPI_create_imported_target LANG) + if(NOT TARGET MPI::MPI_${LANG}) + add_library(MPI::MPI_${LANG} INTERFACE IMPORTED) + endif() + + set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}") + set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_DEFINITIONS "${MPI_${LANG}_COMPILE_DEFINITIONS}") + + set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_LINK_LIBRARIES "") + if(MPI_${LANG}_LINK_FLAGS) + set_property(TARGET MPI::MPI_${LANG} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${MPI_${LANG}_LINK_FLAGS}") + endif() + # If the compiler links MPI implicitly, no libraries will be found as they're contained within + # CMAKE__IMPLICIT_LINK_LIBRARIES already. + if(MPI_${LANG}_LIBRARIES) + set_property(TARGET MPI::MPI_${LANG} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${MPI_${LANG}_LIBRARIES}") + endif() + # Given the new design of FindMPI, INCLUDE_DIRS will always be located, even under implicit linking. + set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MPI_${LANG}_INCLUDE_DIRS}") +endmacro() + +function(_MPI_try_staged_settings LANG MPI_TEST_FILE_NAME MODE RUN_BINARY) + set(WORK_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI") + set(SRC_DIR "${CMAKE_CURRENT_LIST_DIR}/FindMPI") + set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI/${MPI_TEST_FILE_NAME}_${LANG}.bin") + unset(MPI_TEST_COMPILE_DEFINITIONS) + if("${LANG}" STREQUAL "Fortran") + if("${MODE}" STREQUAL "F90_MODULE") + set(MPI_Fortran_INCLUDE_LINE "use mpi\n implicit none") + elseif("${MODE}" STREQUAL "F08_MODULE") + set(MPI_Fortran_INCLUDE_LINE "use mpi_f08\n implicit none") + else() # F77 header + set(MPI_Fortran_INCLUDE_LINE "implicit none\n include 'mpif.h'") + endif() + configure_file("${SRC_DIR}/${MPI_TEST_FILE_NAME}.f90.in" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90" @ONLY) + set(MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90") + elseif("${LANG}" STREQUAL "CXX") + configure_file("${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp" COPYONLY) + set(MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp") + if("${MODE}" STREQUAL "TEST_MPICXX") + set(MPI_TEST_COMPILE_DEFINITIONS TEST_MPI_MPICXX) + endif() + else() # C + set(MPI_TEST_SOURCE_FILE "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c") + endif() + if(RUN_BINARY) + try_run(MPI_RUN_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} + "${CMAKE_BINARY_DIR}" SOURCES "${MPI_TEST_SOURCE_FILE}" + COMPILE_DEFINITIONS ${MPI_TEST_COMPILE_DEFINITIONS} + LINK_LIBRARIES MPI::MPI_${LANG} + RUN_OUTPUT_VARIABLE MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}) + set(MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} "${MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}}" PARENT_SCOPE) + else() + try_compile(MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} + "${CMAKE_BINARY_DIR}" SOURCES "${MPI_TEST_SOURCE_FILE}" + COMPILE_DEFINITIONS ${MPI_TEST_COMPILE_DEFINITIONS} + LINK_LIBRARIES MPI::MPI_${LANG} + COPY_FILE "${BIN_FILE}") + endif() +endfunction() + +macro(_MPI_check_lang_works LANG) + # For Fortran we may have by the MPI-3 standard an implementation that provides: + # - the mpi_f08 module + # - *both*, the mpi module and 'mpif.h' + # Since older MPI standards (MPI-1) did not define anything but 'mpif.h', we need to check all three individually. + if( NOT MPI_${LANG}_WORKS ) + if("${LANG}" STREQUAL "Fortran") + set(MPI_Fortran_INTEGER_LINE "(kind=MPI_INTEGER_KIND)") + _MPI_try_staged_settings(${LANG} test_mpi F77_HEADER FALSE) + _MPI_try_staged_settings(${LANG} test_mpi F90_MODULE FALSE) + _MPI_try_staged_settings(${LANG} test_mpi F08_MODULE FALSE) + + set(MPI_${LANG}_WORKS FALSE) + + foreach(mpimethod IN ITEMS F77_HEADER F08_MODULE F90_MODULE) + if(MPI_RESULT_${LANG}_test_mpi_${mpimethod}) + set(MPI_${LANG}_WORKS TRUE) + set(MPI_${LANG}_HAVE_${mpimethod} TRUE) + else() + set(MPI_${LANG}_HAVE_${mpimethod} FALSE) + endif() + endforeach() + # MPI-1 versions had no MPI_INTGER_KIND defined, so we need to try without it. + # However, MPI-1 also did not define the Fortran 90 and 08 modules, so we only try the F77 header. + unset(MPI_Fortran_INTEGER_LINE) + if(NOT MPI_${LANG}_WORKS) + _MPI_try_staged_settings(${LANG} test_mpi F77_HEADER_NOKIND FALSE) + if(MPI_RESULT_${LANG}_test_mpi_F77_HEADER_NOKIND) + set(MPI_${LANG}_WORKS TRUE) + set(MPI_${LANG}_HAVE_F77_HEADER TRUE) + endif() + endif() + else() + _MPI_try_staged_settings(${LANG} test_mpi normal FALSE) + # If 'test_mpi' built correctly, we've found valid MPI settings. There might not be MPI-2 C++ support, but there can't + # be MPI-2 C++ support without the C bindings being present, so checking for them is sufficient. + set(MPI_${LANG}_WORKS "${MPI_RESULT_${LANG}_test_mpi_normal}") + endif() + endif() +endmacro() + +# Some systems install various MPI implementations in separate folders in some MPI prefix +# This macro enumerates all such subfolders and adds them to the list of hints that will be searched. +macro(MPI_search_mpi_prefix_folder PREFIX_FOLDER) + if(EXISTS "${PREFIX_FOLDER}") + file(GLOB _MPI_folder_children RELATIVE "${PREFIX_FOLDER}" "${PREFIX_FOLDER}/*") + foreach(_MPI_folder_child IN LISTS _MPI_folder_children) + if(IS_DIRECTORY "${PREFIX_FOLDER}/${_MPI_folder_child}") + list(APPEND MPI_HINT_DIRS "${PREFIX_FOLDER}/${_MPI_folder_child}") + endif() + endforeach() + endif() +endmacro() + +set(MPI_HINT_DIRS ${MPI_HOME} $ENV{MPI_ROOT} $ENV{MPI_HOME} $ENV{I_MPI_ROOT}) +if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux") + # SUSE Linux Enterprise Server stores its MPI implementations under /usr/lib64/mpi/gcc/ + # We enumerate the subfolders and append each as a prefix + MPI_search_mpi_prefix_folder("/usr/lib64/mpi/gcc") +elseif("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") + # MSMPI stores its runtime in a special folder, this adds the possible locations to the hints. + list(APPEND MPI_HINT_DIRS $ENV{MSMPI_BIN} "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPI;InstallRoot]") +elseif("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "FreeBSD") + # FreeBSD ships mpich under the normal system paths - but available openmpi implementations + # will be found in /usr/local/mpi/ + MPI_search_mpi_prefix_folder("/usr/local/mpi") +endif() + +# Most MPI distributions have some form of mpiexec or mpirun which gives us something we can look for. +# The MPI standard does not mandate the existence of either, but instead only makes requirements if a distribution +# ships an mpiexec program (mpirun executables are not regulated by the standard). +find_program(MPIEXEC_EXECUTABLE + NAMES ${_MPIEXEC_NAMES} + PATH_SUFFIXES bin sbin + HINTS ${MPI_HINT_DIRS} + DOC "Executable for running MPI programs.") + +# call get_filename_component twice to remove mpiexec and the directory it exists in (typically bin). +# This gives us a fairly reliable base directory to search for /bin /lib and /include from. +get_filename_component(_MPI_BASE_DIR "${MPIEXEC_EXECUTABLE}" PATH) +get_filename_component(_MPI_BASE_DIR "${_MPI_BASE_DIR}" PATH) + +# According to the MPI standard, section 8.8 -n is a guaranteed, and the only guaranteed way to +# launch an MPI process using mpiexec if such a program exists. +set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "Flag used by MPI to specify the number of processes for mpiexec; the next option will be the number of processes.") +set(MPIEXEC_PREFLAGS "" CACHE STRING "These flags will be directly before the executable that is being run by mpiexec.") +set(MPIEXEC_POSTFLAGS "" CACHE STRING "These flags will be placed after all flags passed to mpiexec.") + +# Set the number of processes to the physical processor count +cmake_host_system_information(RESULT _MPIEXEC_NUMPROCS QUERY NUMBER_OF_PHYSICAL_CORES) +set(MPIEXEC_MAX_NUMPROCS "${_MPIEXEC_NUMPROCS}" CACHE STRING "Maximum number of processors available to run MPI applications.") +unset(_MPIEXEC_NUMPROCS) +mark_as_advanced(MPIEXEC_EXECUTABLE MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS) + +#============================================================================= +# Backward compatibility input hacks. Propagate the FindMPI hints to C and +# CXX if the respective new versions are not defined. Translate the old +# MPI_LIBRARY and MPI_EXTRA_LIBRARY to respective MPI_${LANG}_LIBRARIES. +# +# Once we find the new variables, we translate them back into their old +# equivalents below. +if(NOT MPI_IGNORE_LEGACY_VARIABLES) + foreach (LANG IN ITEMS C CXX) + # Old input variables. + set(_MPI_OLD_INPUT_VARS COMPILER COMPILE_FLAGS INCLUDE_PATH LINK_FLAGS) + + # Set new vars based on their old equivalents, if the new versions are not already set. + foreach (var ${_MPI_OLD_INPUT_VARS}) + if (NOT MPI_${LANG}_${var} AND MPI_${var}) + set(MPI_${LANG}_${var} "${MPI_${var}}") + endif() + endforeach() + + # Chop the old compile flags into options and definitions + + unset(MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS) + unset(MPI_${LANG}_EXTRA_COMPILE_OPTIONS) + if(MPI_${LANG}_COMPILE_FLAGS) + separate_arguments(MPI_SEPARATE_FLAGS NATIVE_COMMAND "${MPI_${LANG}_COMPILE_FLAGS}") + foreach(_MPI_FLAG IN LISTS MPI_SEPARATE_FLAGS) + if("${_MPI_FLAG}" MATCHES "^ *[-/D]([^ ]+)") + list(APPEND MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS "${CMAKE_MATCH_1}") + else() + list(APPEND MPI_${LANG}_EXTRA_COMPILE_OPTIONS "${_MPI_FLAG}") + endif() + endforeach() + unset(MPI_SEPARATE_FLAGS) + endif() + + # If a list of libraries was given, we'll split it into new-style cache variables + unset(MPI_${LANG}_EXTRA_LIB_NAMES) + if(NOT MPI_${LANG}_LIB_NAMES) + foreach(_MPI_LIB IN LISTS MPI_${LANG}_LIBRARIES MPI_LIBRARY MPI_EXTRA_LIBRARY) + if(_MPI_LIB) + get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB}" NAME_WE) + get_filename_component(_MPI_LIB_NAME "${_MPI_LIB}" NAME) + get_filename_component(_MPI_LIB_DIR "${_MPI_LIB}" DIRECTORY) + list(APPEND MPI_${LANG}_EXTRA_LIB_NAMES "${_MPI_PLAIN_LIB_NAME}") + find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY + NAMES "${_MPI_LIB_NAME}" "lib${_MPI_LIB_NAME}" + HINTS ${_MPI_LIB_DIR} $ENV{MPI_LIB} + DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" + ) + mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) + endif() + endforeach() + endif() + endforeach() +endif() +#============================================================================= + +unset(MPI_VERSION) +unset(MPI_VERSION_MAJOR) +unset(MPI_VERSION_MINOR) + +unset(_MPI_MIN_VERSION) + +# If the user specified a library name we assume they prefer that library over a wrapper. If not, they can disable skipping manually. +if(NOT DEFINED MPI_SKIP_COMPILER_WRAPPER AND MPI_GUESS_LIBRARY_NAME) + set(MPI_SKIP_COMPILER_WRAPPER TRUE) +endif() + +# This loop finds the compilers and sends them off for interrogation. +foreach(LANG IN ITEMS C CXX Fortran) + if(CMAKE_${LANG}_COMPILER_LOADED) + if(NOT MPI_FIND_COMPONENTS) + set(_MPI_FIND_${LANG} TRUE) + elseif( ${LANG} IN_LIST MPI_FIND_COMPONENTS) + set(_MPI_FIND_${LANG} TRUE) + elseif( ${LANG} STREQUAL CXX AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS ) + set(_MPI_FIND_${LANG} TRUE) + else() + set(_MPI_FIND_${LANG} FALSE) + endif() + else() + set(_MPI_FIND_${LANG} FALSE) + endif() + if(_MPI_FIND_${LANG}) + if( ${LANG} STREQUAL CXX AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS ) + set(MPI_CXX_SKIP_MPICXX FALSE CACHE BOOL "If true, the MPI-2 C++ bindings are disabled using definitions.") + mark_as_advanced(MPI_CXX_SKIP_MPICXX) + endif() + if(NOT (MPI_${LANG}_LIB_NAMES AND (MPI_${LANG}_INCLUDE_PATH OR MPI_${LANG}_INCLUDE_DIRS OR MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS))) + set(MPI_${LANG}_TRIED_IMPLICIT FALSE) + set(MPI_${LANG}_WORKS_IMPLICIT FALSE) + if(NOT MPI_${LANG}_COMPILER AND NOT MPI_ASSUME_NO_BUILTIN_MPI) + # Should the imported targets be empty, we effectively try whether the compiler supports MPI on its own, which is the case on e.g. + # Cray PrgEnv. + _MPI_create_imported_target(${LANG}) + _MPI_check_lang_works(${LANG}) + + # If the compiler can build MPI code on its own, it functions as an MPI compiler and we'll set the variable to point to it. + if(MPI_${LANG}_WORKS) + set(MPI_${LANG}_COMPILER "${CMAKE_${LANG}_COMPILER}" CACHE FILEPATH "MPI compiler for ${LANG}" FORCE) + set(MPI_${LANG}_WORKS_IMPLICIT TRUE) + endif() + set(MPI_${LANG}_TRIED_IMPLICIT TRUE) + endif() + + if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_${LANG}_WORKS) + set(MPI_${LANG}_WRAPPER_FOUND FALSE) + set(MPI_PINNED_COMPILER FALSE) + + if(NOT MPI_SKIP_COMPILER_WRAPPER) + if(MPI_${LANG}_COMPILER) + # If the user supplies a compiler *name* instead of an absolute path, assume that we need to find THAT compiler. + if (NOT IS_ABSOLUTE "${MPI_${LANG}_COMPILER}") + # Get rid of our default list of names and just search for the name the user wants. + set(_MPI_${LANG}_COMPILER_NAMES "${MPI_${LANG}_COMPILER}") + unset(MPI_${LANG}_COMPILER CACHE) + endif() + # If the user specifies a compiler, we don't want to try to search libraries either. + set(MPI_PINNED_COMPILER TRUE) + endif() + + # If we have an MPI base directory, we'll try all compiler names in that one first. + # This should prevent mixing different MPI environments + if(_MPI_BASE_DIR) + find_program(MPI_${LANG}_COMPILER + NAMES ${_MPI_${LANG}_COMPILER_NAMES} + PATH_SUFFIXES bin sbin + HINTS ${_MPI_BASE_DIR} + NO_DEFAULT_PATH + DOC "MPI compiler for ${LANG}" + ) + endif() + + # If the base directory did not help (for example because the mpiexec isn't in the same directory as the compilers), + # we shall try searching in the default paths. + find_program(MPI_${LANG}_COMPILER + NAMES ${_MPI_${LANG}_COMPILER_NAMES} + PATH_SUFFIXES bin sbin + DOC "MPI compiler for ${LANG}" + ) + + if("${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") + set(MPI_PINNED_COMPILER TRUE) + + # If we haven't made the implicit compiler test yet, perform it now. + if(NOT MPI_${LANG}_TRIED_IMPLICIT) + _MPI_create_imported_target(${LANG}) + _MPI_check_lang_works(${LANG}) + endif() + + # Should the MPI compiler not work implicitly for MPI, still interrogate it. + # Otherwise, MPI compilers for which CMake has separate linking stages, e.g. Intel MPI on Windows where link.exe is being used + # directly during linkage instead of CMAKE__COMPILER will not work. + if(NOT MPI_${LANG}_WORKS) + set(MPI_${LANG}_WORKS_IMPLICIT FALSE) + _MPI_interrogate_compiler(${LANG}) + else() + set(MPI_${LANG}_WORKS_IMPLICIT TRUE) + endif() + elseif(MPI_${LANG}_COMPILER) + _MPI_interrogate_compiler(${LANG}) + endif() + endif() + + if(NOT MPI_SKIP_GUESSING AND NOT MPI_${LANG}_WRAPPER_FOUND AND NOT MPI_PINNED_COMPILER) + # For C++, we may use the settings for C. Should a given compiler wrapper for C++ not exist, but one for C does, we copy over the + # settings for C. An MPI distribution that is in this situation would be IBM Platform MPI. + if("${LANG}" STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND) + set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_C_COMPILE_OPTIONS} CACHE STRING "MPI ${LANG} compilation options" ) + set(MPI_${LANG}_COMPILE_DEFINITIONS ${MPI_C_COMPILE_DEFINITIONS} CACHE STRING "MPI ${LANG} compilation definitions" ) + set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS ${MPI_C_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} additional include directories") + set(MPI_${LANG}_LINK_FLAGS ${MPI_C_LINK_FLAGS} CACHE STRING "MPI ${LANG} linker flags" ) + set(MPI_${LANG}_LIB_NAMES ${MPI_C_LIB_NAMES} CACHE STRING "MPI ${LANG} libraries to link against" ) + else() + _MPI_guess_settings(${LANG}) + endif() + endif() + endif() + endif() + + _MPI_split_include_dirs(${LANG}) + _MPI_assemble_include_dirs(${LANG}) + _MPI_assemble_libraries(${LANG}) + + _MPI_adjust_compile_definitions(${LANG}) + # We always create imported targets even if they're empty + _MPI_create_imported_target(${LANG}) + + if(NOT MPI_${LANG}_WORKS) + _MPI_check_lang_works(${LANG}) + endif() + + # Next, we'll initialize the MPI variables that have not been previously set. + set(MPI_${LANG}_COMPILE_OPTIONS "" CACHE STRING "MPI ${LANG} compilation flags" ) + set(MPI_${LANG}_COMPILE_DEFINITIONS "" CACHE STRING "MPI ${LANG} compilation definitions" ) + set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "" CACHE STRING "MPI ${LANG} additional include directories") + set(MPI_${LANG}_LINK_FLAGS "" CACHE STRING "MPI ${LANG} linker flags" ) + if(NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER) + set(MPI_${LANG}_LIB_NAMES "" CACHE STRING "MPI ${LANG} libraries to link against" ) + endif() + mark_as_advanced(MPI_${LANG}_COMPILE_OPTIONS MPI_${LANG}_COMPILE_DEFINITIONS MPI_${LANG}_LINK_FLAGS + MPI_${LANG}_LIB_NAMES MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS MPI_${LANG}_COMPILER) + + # If we've found MPI, then we'll perform additional analysis: Determine the MPI version, MPI library version, supported + # MPI APIs (i.e. MPI-2 C++ bindings). For Fortran we also need to find specific parameters if we're under MPI-3. + if(MPI_${LANG}_WORKS) + if("${LANG}" STREQUAL "CXX" AND NOT DEFINED MPI_MPICXX_FOUND) + if(NOT MPI_CXX_SKIP_MPICXX AND NOT MPI_CXX_VALIDATE_SKIP_MPICXX) + _MPI_try_staged_settings(${LANG} test_mpi MPICXX FALSE) + if(MPI_RESULT_${LANG}_test_mpi_MPICXX) + set(MPI_MPICXX_FOUND TRUE) + else() + set(MPI_MPICXX_FOUND FALSE) + endif() + else() + set(MPI_MPICXX_FOUND FALSE) + endif() + endif() + + # At this point, we know the bindings present but not the MPI version or anything else. + if(NOT DEFINED MPI_${LANG}_VERSION) + unset(MPI_${LANG}_VERSION_MAJOR) + unset(MPI_${LANG}_VERSION_MINOR) + endif() + set(MPI_BIN_FOLDER ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI) + + # For Fortran, we'll want to use the most modern MPI binding to test capabilities other than the + # Fortran parameters, since those depend on the method of consumption. + # For C++, we can always use the C bindings, and should do so, since the C++ bindings do not exist in MPI-3 + # whereas the C bindings do, and the C++ bindings never offered any feature advantage over their C counterparts. + if("${LANG}" STREQUAL "Fortran") + if(MPI_${LANG}_HAVE_F08_MODULE) + set(MPI_${LANG}_HIGHEST_METHOD F08_MODULE) + elseif(MPI_${LANG}_HAVE_F90_MODULE) + set(MPI_${LANG}_HIGHEST_METHOD F90_MODULE) + else() + set(MPI_${LANG}_HIGHEST_METHOD F77_HEADER) + endif() + + # Another difference between C and Fortran is that we can't use the preprocessor to determine whether MPI_VERSION + # and MPI_SUBVERSION are provided. These defines did not exist in MPI 1.0 and 1.1 and therefore might not + # exist. For C/C++, test_mpi.c will handle the MPI_VERSION extraction, but for Fortran, we need mpiver.f90. + if(NOT DEFINED MPI_${LANG}_VERSION) + _MPI_try_staged_settings(${LANG} mpiver ${MPI_${LANG}_HIGHEST_METHOD} FALSE) + if(MPI_RESULT_${LANG}_mpiver_${MPI_${LANG}_HIGHEST_METHOD}) + file(STRINGS ${MPI_BIN_FOLDER}/mpiver_${LANG}.bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER") + if("${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*") + set(MPI_${LANG}_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(MPI_${LANG}_VERSION_MINOR "${CMAKE_MATCH_2}") + set(MPI_${LANG}_VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}") + endif() + endif() + endif() + + # Finally, we want to find out which capabilities a given interface supports, compare the MPI-3 standard. + # This is determined by interface specific parameters MPI_SUBARRAYS_SUPPORTED and MPI_ASYNC_PROTECTS_NONBLOCKING + # and might vary between the different methods of consumption. + if(MPI_DETERMINE_Fortran_CAPABILITIES AND NOT MPI_Fortran_CAPABILITIES_DETERMINED) + foreach(mpimethod IN ITEMS F08_MODULE F90_MODULE F77_HEADER) + if(MPI_${LANG}_HAVE_${mpimethod}) + set(MPI_${LANG}_${mpimethod}_SUBARRAYS FALSE) + set(MPI_${LANG}_${mpimethod}_ASYNCPROT FALSE) + _MPI_try_staged_settings(${LANG} fortranparam_mpi ${mpimethod} TRUE) + if(MPI_RESULT_${LANG}_fortranparam_mpi_${mpimethod} AND + NOT "${MPI_RUN_RESULT_${LANG}_fortranparam_mpi_${mpimethod}}" STREQUAL "FAILED_TO_RUN") + if("${MPI_RUN_OUTPUT_${LANG}_fortranparam_mpi_${mpimethod}}" MATCHES + ".*INFO:SUBARRAYS\\[ *([TF]) *\\]-ASYNCPROT\\[ *([TF]) *\\].*") + if("${CMAKE_MATCH_1}" STREQUAL "T") + set(MPI_${LANG}_${mpimethod}_SUBARRAYS TRUE) + endif() + if("${CMAKE_MATCH_2}" STREQUAL "T") + set(MPI_${LANG}_${mpimethod}_ASYNCPROT TRUE) + endif() + endif() + endif() + endif() + endforeach() + set(MPI_Fortran_CAPABILITIES_DETERMINED TRUE) + endif() + else() + set(MPI_${LANG}_HIGHEST_METHOD normal) + + # By the MPI-2 standard, MPI_VERSION and MPI_SUBVERSION are valid for both C and C++ bindings. + if(NOT DEFINED MPI_${LANG}_VERSION) + file(STRINGS ${MPI_BIN_FOLDER}/test_mpi_${LANG}.bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER") + if("${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*") + set(MPI_${LANG}_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(MPI_${LANG}_VERSION_MINOR "${CMAKE_MATCH_2}") + set(MPI_${LANG}_VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}") + endif() + endif() + endif() + + unset(MPI_BIN_FOLDER) + + # At this point, we have dealt with determining the MPI version and parameters for each Fortran method available. + # The one remaining issue is to determine which MPI library is installed. + # Determining the version and vendor of the MPI library is only possible via MPI_Get_library_version() at runtime, + # and therefore we cannot do this while cross-compiling (a user may still define MPI__LIBRARY_VERSION_STRING + # themselves and we'll attempt splitting it, which is equivalent to provide the try_run output). + # It's also worth noting that the installed version string can depend on the language, or on the system the binary + # runs on if MPI is not statically linked. + if(MPI_DETERMINE_LIBRARY_VERSION AND NOT MPI_${LANG}_LIBRARY_VERSION_STRING) + _MPI_try_staged_settings(${LANG} libver_mpi ${MPI_${LANG}_HIGHEST_METHOD} TRUE) + if(MPI_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD} AND + "${MPI_RUN_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}" EQUAL "0") + string(STRIP "${MPI_RUN_OUTPUT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}" + MPI_${LANG}_LIBRARY_VERSION_STRING) + else() + set(MPI_${LANG}_LIBRARY_VERSION_STRING "NOTFOUND") + endif() + endif() + endif() + + set(MPI_${LANG}_FIND_QUIETLY ${MPI_FIND_QUIETLY}) + set(MPI_${LANG}_FIND_VERSION ${MPI_FIND_VERSION}) + set(MPI_${LANG}_FIND_VERSION_EXACT ${MPI_FIND_VERSION_EXACT}) + + unset(MPI_${LANG}_REQUIRED_VARS) + if (NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") + foreach(mpilibname IN LISTS MPI_${LANG}_LIB_NAMES) + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${mpilibname}_LIBRARY") + endforeach() + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_LIB_NAMES") + if("${LANG}" STREQUAL "Fortran") + # For Fortran we only need one of the module or header directories to have *some* support for MPI. + if(NOT MPI_${LANG}_MODULE_DIR) + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_F77_HEADER_DIR") + endif() + if(NOT MPI_${LANG}_F77_HEADER_DIR) + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_MODULE_DIR") + endif() + else() + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_HEADER_DIR") + endif() + if(MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) + foreach(mpiincvar IN LISTS MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${mpiincvar}_INCLUDE_DIR") + endforeach() + endif() + # Append the works variable now. If the settings did not work, this will show up properly. + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_WORKS") + else() + # If the compiler worked implicitly, use its path as output. + # Should the compiler variable be set, we also require it to work. + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_COMPILER") + if(MPI_${LANG}_COMPILER) + list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_WORKS") + endif() + endif() + find_package_handle_standard_args(MPI_${LANG} REQUIRED_VARS ${MPI_${LANG}_REQUIRED_VARS} + VERSION_VAR MPI_${LANG}_VERSION) + + if(DEFINED MPI_${LANG}_VERSION) + if(NOT _MPI_MIN_VERSION OR _MPI_MIN_VERSION VERSION_GREATER MPI_${LANG}_VERSION) + set(_MPI_MIN_VERSION MPI_${LANG}_VERSION) + endif() + endif() + endif() +endforeach() + +unset(_MPI_REQ_VARS) +foreach(LANG IN ITEMS C CXX Fortran) + if((NOT MPI_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST MPI_FIND_COMPONENTS) + list(APPEND _MPI_REQ_VARS "MPI_${LANG}_FOUND") + endif() +endforeach() + +if(MPICXX IN_LIST MPI_FIND_COMPONENTS) + list(APPEND _MPI_REQ_VARS "MPI_MPICXX_FOUND") +endif() + +find_package_handle_standard_args(MPI + REQUIRED_VARS ${_MPI_REQ_VARS} + VERSION_VAR ${_MPI_MIN_VERSION} + HANDLE_COMPONENTS) + +#============================================================================= +# More backward compatibility stuff + +# For compatibility reasons, we also define MPIEXEC +set(MPIEXEC "${MPIEXEC_EXECUTABLE}") + +# Copy over MPI__INCLUDE_PATH from the assembled INCLUDE_DIRS. +foreach(LANG IN ITEMS C CXX Fortran) + if(MPI_${LANG}_FOUND) + set(MPI_${LANG}_INCLUDE_PATH "${MPI_${LANG}_INCLUDE_DIRS}") + unset(MPI_${LANG}_COMPILE_FLAGS) + if(MPI_${LANG}_COMPILE_OPTIONS) + set(MPI_${LANG}_COMPILE_FLAGS "${MPI_${LANG}_COMPILE_OPTIONS}") + endif() + if(MPI_${LANG}_COMPILE_DEFINITIONS) + foreach(_MPI_DEF IN LISTS MPI_${LANG}_COMPILE_DEFINITIONS) + string(APPEND MPI_${LANG}_COMPILE_FLAGS " -D${_MPI_DEF}") + endforeach() + endif() + endif() +endforeach() + +# Bare MPI sans ${LANG} vars are set to CXX then C, depending on what was found. +# This mimics the behavior of the old language-oblivious FindMPI. +set(_MPI_OLD_VARS COMPILER INCLUDE_PATH COMPILE_FLAGS LINK_FLAGS LIBRARIES) +if (MPI_CXX_FOUND) + foreach (var ${_MPI_OLD_VARS}) + set(MPI_${var} ${MPI_CXX_${var}}) + endforeach() +elseif (MPI_C_FOUND) + foreach (var ${_MPI_OLD_VARS}) + set(MPI_${var} ${MPI_C_${var}}) + endforeach() +endif() + +# Chop MPI_LIBRARIES into the old-style MPI_LIBRARY and MPI_EXTRA_LIBRARY, and set them in cache. +if (MPI_LIBRARIES) + list(GET MPI_LIBRARIES 0 MPI_LIBRARY_WORK) + set(MPI_LIBRARY "${MPI_LIBRARY_WORK}") + unset(MPI_LIBRARY_WORK) +else() + set(MPI_LIBRARY "MPI_LIBRARY-NOTFOUND") +endif() + +list(LENGTH MPI_LIBRARIES MPI_NUMLIBS) +if (MPI_NUMLIBS GREATER 1) + set(MPI_EXTRA_LIBRARY_WORK "${MPI_LIBRARIES}") + list(REMOVE_AT MPI_EXTRA_LIBRARY_WORK 0) + set(MPI_EXTRA_LIBRARY "${MPI_EXTRA_LIBRARY_WORK}") + unset(MPI_EXTRA_LIBRARY_WORK) +else() + set(MPI_EXTRA_LIBRARY "MPI_EXTRA_LIBRARY-NOTFOUND") +endif() +set(MPI_IGNORE_LEGACY_VARIABLES TRUE) +#============================================================================= + +# unset these vars to cleanup namespace +unset(_MPI_OLD_VARS) +unset(_MPI_PREFIX_PATH) +unset(_MPI_BASE_DIR) +foreach (lang C CXX Fortran) + unset(_MPI_${LANG}_COMPILER_NAMES) +endforeach() + +cmake_policy(POP) diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/fortranparam_mpi.f90.in b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/fortranparam_mpi.f90.in new file mode 100644 index 0000000000..30f912c627 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/fortranparam_mpi.f90.in @@ -0,0 +1,4 @@ + program mpi_ver + @MPI_Fortran_INCLUDE_LINE@ + print *, 'INFO:SUBARRAYS[', MPI_SUBARRAYS_SUPPORTED, ']-ASYNCPROT[', MPI_ASYNC_PROTECTS_NONBLOCKING, ']' + end program mpi_ver diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/libver_mpi.c b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/libver_mpi.c new file mode 100644 index 0000000000..be9d19d435 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/libver_mpi.c @@ -0,0 +1,19 @@ +#include + +#ifdef __cplusplus +#include +#else +#include +#endif + +int main(int argc, char* argv[]) +{ + char mpilibver_str[MPI_MAX_LIBRARY_VERSION_STRING]; + int mpilibver_len; + MPI_Get_library_version(mpilibver_str, &mpilibver_len); +#ifdef __cplusplus + std::puts(mpilibver_str); +#else + puts(mpilibver_str); +#endif +} diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/libver_mpi.f90.in b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/libver_mpi.f90.in new file mode 100644 index 0000000000..7938587168 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/libver_mpi.f90.in @@ -0,0 +1,7 @@ + program mpi_ver + @MPI_Fortran_INCLUDE_LINE@ + character(len=MPI_MAX_LIBRARY_VERSION_STRING) :: mpilibver_str + integer(kind=MPI_INTEGER_KIND) :: ierror, reslen + call MPI_GET_LIBRARY_VERSION(mpilibver_str, reslen, ierror) + print *, mpilibver_str + end program mpi_ver diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/mpiver.f90.in b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/mpiver.f90.in new file mode 100644 index 0000000000..a254523853 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/mpiver.f90.in @@ -0,0 +1,10 @@ + program mpi_ver + @MPI_Fortran_INCLUDE_LINE@ + integer(kind=kind(MPI_VERSION)), parameter :: zero = ichar('0') + character, dimension(17), parameter :: mpiver_str =& + (/ 'I', 'N', 'F', 'O', ':', 'M', 'P', 'I', '-', 'V', 'E', 'R', '[', & + char(zero + MPI_VERSION), & + '.', & + char(zero + MPI_SUBVERSION), ']' /) + print *, mpiver_str + end program mpi_ver diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/test_mpi.c b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/test_mpi.c new file mode 100644 index 0000000000..b8a308a4b0 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/test_mpi.c @@ -0,0 +1,37 @@ +#include + +#ifdef __cplusplus +#include +#else +#include +#endif + +#if defined(MPI_VERSION) && defined(MPI_SUBVERSION) +const char mpiver_str[] = { 'I', 'N', + 'F', 'O', + ':', 'M', + 'P', 'I', + '-', 'V', + 'E', 'R', + '[', ('0' + MPI_VERSION), + '.', ('0' + MPI_SUBVERSION), + ']', '\0' }; +#endif + +int main(int argc, char* argv[]) +{ +#if defined(MPI_VERSION) && defined(MPI_SUBVERSION) +#ifdef __cplusplus + std::puts(mpiver_str); +#else + puts(mpiver_str); +#endif +#endif +#ifdef TEST_MPI_MPICXX + MPI::MPI_Init(&argc, &argv); + MPI::MPI_Finalize(); +#else + MPI_Init(&argc, &argv); + MPI_Finalize(); +#endif +} diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/test_mpi.f90.in b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/test_mpi.f90.in new file mode 100644 index 0000000000..4d43a04d65 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindMPI/test_mpi.f90.in @@ -0,0 +1,6 @@ + program hello + @MPI_Fortran_INCLUDE_LINE@ + integer@MPI_Fortran_INTEGER_LINE@ ierror + call MPI_INIT(ierror) + call MPI_FINALIZE(ierror) + end program diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindPackageHandleStandardArgs.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindPackageHandleStandardArgs.cmake new file mode 100644 index 0000000000..67f6bd6f2b --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindPackageHandleStandardArgs.cmake @@ -0,0 +1,386 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindPackageHandleStandardArgs +----------------------------- + +This module provides a function intended to be used in :ref:`Find Modules` +implementing :command:`find_package()` calls. It handles the +``REQUIRED``, ``QUIET`` and version-related arguments of ``find_package``. +It also sets the ``_FOUND`` variable. The package is +considered found if all variables listed contain valid results, e.g. +valid filepaths. + +.. command:: find_package_handle_standard_args + + There are two signatures:: + + find_package_handle_standard_args( + (DEFAULT_MSG|) + ... + ) + + find_package_handle_standard_args( + [FOUND_VAR ] + [REQUIRED_VARS ...] + [VERSION_VAR ] + [HANDLE_COMPONENTS] + [CONFIG_MODE] + [FAIL_MESSAGE ] + ) + + The ``_FOUND`` variable will be set to ``TRUE`` if all + the variables ``...`` are valid and any optional + constraints are satisfied, and ``FALSE`` otherwise. A success or + failure message may be displayed based on the results and on + whether the ``REQUIRED`` and/or ``QUIET`` option was given to + the :command:`find_package` call. + + The options are: + + ``(DEFAULT_MSG|)`` + In the simple signature this specifies the failure message. + Use ``DEFAULT_MSG`` to ask for a default message to be computed + (recommended). Not valid in the full signature. + + ``FOUND_VAR `` + Obsolete. Specifies either ``_FOUND`` or + ``_FOUND`` as the result variable. This exists only + for compatibility with older versions of CMake and is now ignored. + Result variables of both names are always set for compatibility. + + ``REQUIRED_VARS ...`` + Specify the variables which are required for this package. + These may be named in the generated failure message asking the + user to set the missing variable values. Therefore these should + typically be cache entries such as ``FOO_LIBRARY`` and not output + variables like ``FOO_LIBRARIES``. + + ``VERSION_VAR `` + Specify the name of a variable that holds the version of the package + that has been found. This version will be checked against the + (potentially) specified required version given to the + :command:`find_package` call, including its ``EXACT`` option. + The default messages include information about the required + version and the version which has been actually found, both + if the version is ok or not. + + ``HANDLE_COMPONENTS`` + Enable handling of package components. In this case, the command + will report which components have been found and which are missing, + and the ``_FOUND`` variable will be set to ``FALSE`` + if any of the required components (i.e. not the ones listed after + the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are + missing. + + ``CONFIG_MODE`` + Specify that the calling find module is a wrapper around a + call to ``find_package( NO_MODULE)``. This implies + a ``VERSION_VAR`` value of ``_VERSION``. The command + will automatically check whether the package configuration file + was found. + + ``FAIL_MESSAGE `` + Specify a custom failure message instead of using the default + generated message. Not recommended. + +Example for the simple signature: + +.. code-block:: cmake + + find_package_handle_standard_args(LibXml2 DEFAULT_MSG + LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) + +The ``LibXml2`` package is considered to be found if both +``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid. +Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found +and ``REQUIRED`` was used, it fails with a +:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was +used or not. If it is found, success will be reported, including +the content of the first ````. On repeated CMake runs, +the same message will not be printed again. + +Example for the full signature: + +.. code-block:: cmake + + find_package_handle_standard_args(LibArchive + REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR + VERSION_VAR LibArchive_VERSION) + +In this case, the ``LibArchive`` package is considered to be found if +both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid. +Also the version of ``LibArchive`` will be checked by using the version +contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given, +the default messages will be printed. + +Another example for the full signature: + +.. code-block:: cmake + + find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) + find_package_handle_standard_args(Automoc4 CONFIG_MODE) + +In this case, a ``FindAutmoc4.cmake`` module wraps a call to +``find_package(Automoc4 NO_MODULE)`` and adds an additional search +directory for ``automoc4``. Then the call to +``find_package_handle_standard_args`` produces a proper success/failure +message. +#]=======================================================================] + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake) + +# internal helper macro +macro(_FPHSA_FAILURE_MESSAGE _msg) + if (${_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "${_msg}") + else () + if (NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "${_msg}") + endif () + endif () +endmacro() + + +# internal helper macro to generate the failure message when used in CONFIG_MODE: +macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: + if(${_NAME}_CONFIG) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + else() + # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. + # List them all in the error message: + if(${_NAME}_CONSIDERED_CONFIGS) + set(configsText "") + list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) + math(EXPR configsCount "${configsCount} - 1") + foreach(currentConfigIndex RANGE ${configsCount}) + list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) + list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) + string(APPEND configsText " ${filename} (version ${version})\n") + endforeach() + if (${_NAME}_NOT_FOUND_MESSAGE) + string(APPEND configsText " Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n") + endif() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") + + else() + # Simple case: No Config-file was found at all: + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + endif() + endif() +endmacro() + + +function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) + +# Set up the arguments for `cmake_parse_arguments`. + set(options CONFIG_MODE HANDLE_COMPONENTS) + set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR) + set(multiValueArgs REQUIRED_VARS) + +# Check whether we are in 'simple' or 'extended' mode: + set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) + list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + + if(${INDEX} EQUAL -1) + set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) + set(FPHSA_REQUIRED_VARS ${ARGN}) + set(FPHSA_VERSION_VAR) + else() + cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) + + if(FPHSA_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") + endif() + + if(NOT FPHSA_FAIL_MESSAGE) + set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") + endif() + + # In config-mode, we rely on the variable _CONFIG, which is set by find_package() + # when it successfully found the config-file, including version checking: + if(FPHSA_CONFIG_MODE) + list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) + list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) + set(FPHSA_VERSION_VAR ${_NAME}_VERSION) + endif() + + if(NOT FPHSA_REQUIRED_VARS) + message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") + endif() + endif() + +# now that we collected all arguments, process them + + if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG") + set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + endif() + + list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) + + string(TOUPPER ${_NAME} _NAME_UPPER) + string(TOLOWER ${_NAME} _NAME_LOWER) + + if(FPHSA_FOUND_VAR) + if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$") + set(_FOUND_VAR ${FPHSA_FOUND_VAR}) + else() + message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.") + endif() + else() + set(_FOUND_VAR ${_NAME_UPPER}_FOUND) + endif() + + # collect all variables which were not found, so they can be printed, so the + # user knows better what went wrong (#6375) + set(MISSING_VARS "") + set(DETAILS "") + # check if all passed variables are valid + set(FPHSA_FOUND_${_NAME} TRUE) + foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) + if(NOT ${_CURRENT_VAR}) + set(FPHSA_FOUND_${_NAME} FALSE) + string(APPEND MISSING_VARS " ${_CURRENT_VAR}") + else() + string(APPEND DETAILS "[${${_CURRENT_VAR}}]") + endif() + endforeach() + if(FPHSA_FOUND_${_NAME}) + set(${_NAME}_FOUND TRUE) + set(${_NAME_UPPER}_FOUND TRUE) + else() + set(${_NAME}_FOUND FALSE) + set(${_NAME_UPPER}_FOUND FALSE) + endif() + + # component handling + unset(FOUND_COMPONENTS_MSG) + unset(MISSING_COMPONENTS_MSG) + + if(FPHSA_HANDLE_COMPONENTS) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(${_NAME}_${comp}_FOUND) + + if(NOT DEFINED FOUND_COMPONENTS_MSG) + set(FOUND_COMPONENTS_MSG "found components: ") + endif() + string(APPEND FOUND_COMPONENTS_MSG " ${comp}") + + else() + + if(NOT DEFINED MISSING_COMPONENTS_MSG) + set(MISSING_COMPONENTS_MSG "missing components: ") + endif() + string(APPEND MISSING_COMPONENTS_MSG " ${comp}") + + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + string(APPEND MISSING_VARS " ${comp}") + endif() + + endif() + endforeach() + set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}") + string(APPEND DETAILS "[c${COMPONENT_MSG}]") + endif() + + # version handling: + set(VERSION_MSG "") + set(VERSION_OK TRUE) + + # check with DEFINED here as the requested or found version may be "0" + if (DEFINED ${_NAME}_FIND_VERSION) + if(DEFINED ${FPHSA_VERSION_VAR}) + set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}}) + + if(${_NAME}_FIND_VERSION_EXACT) # exact version required + # count the dots in the version string + string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${_FOUND_VERSION}") + # add one dot because there is one dot more than there are components + string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS) + if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT) + # Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT + # is at most 4 here. Therefore a simple lookup table is used. + if (${_NAME}_FIND_VERSION_COUNT EQUAL 1) + set(_VERSION_REGEX "[^.]*") + elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2) + set(_VERSION_REGEX "[^.]*\\.[^.]*") + elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3) + set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*") + else () + set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*") + endif () + string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${_FOUND_VERSION}") + unset(_VERSION_REGEX) + if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD) + set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")") + endif () + unset(_VERSION_HEAD) + else () + if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _FOUND_VERSION) + set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")") + endif () + endif () + unset(_VERSION_DOTS) + + else() # minimum version specified: + if (${_NAME}_FIND_VERSION VERSION_GREATER _FOUND_VERSION) + set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable version \"${_FOUND_VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")") + endif () + endif() + + else() + + # if the package was not found, but a version was given, add that to the output: + if(${_NAME}_FIND_VERSION_EXACT) + set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") + else() + set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") + endif() + + endif() + else () + # Check with DEFINED as the found version may be 0. + if(DEFINED ${FPHSA_VERSION_VAR}) + set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")") + endif() + endif () + + if(VERSION_OK) + string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]") + else() + set(${_NAME}_FOUND FALSE) + endif() + + + # print the result: + if (${_NAME}_FOUND) + FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}") + else () + + if(FPHSA_CONFIG_MODE) + _FPHSA_HANDLE_FAILURE_CONFIG_MODE() + else() + if(NOT VERSION_OK) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") + else() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}") + endif() + endif() + + endif () + + set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) + set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) +endfunction() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindPackageMessage.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindPackageMessage.cmake new file mode 100644 index 0000000000..6821cee4f7 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/FindPackageMessage.cmake @@ -0,0 +1,47 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindPackageMessage +# ------------------ +# +# +# +# FIND_PACKAGE_MESSAGE( "message for user" "find result details") +# +# This macro is intended to be used in FindXXX.cmake modules files. It +# will print a message once for each unique find result. This is useful +# for telling the user where a package was found. The first argument +# specifies the name (XXX) of the package. The second argument +# specifies the message to display. The third argument lists details +# about the find result so that if they change the message will be +# displayed again. The macro also obeys the QUIET argument to the +# find_package command. +# +# Example: +# +# :: +# +# if(X11_FOUND) +# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}" +# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]") +# else() +# ... +# endif() + +function(FIND_PACKAGE_MESSAGE pkg msg details) + # Avoid printing a message repeatedly for the same find result. + if(NOT ${pkg}_FIND_QUIETLY) + string(REPLACE "\n" "" details "${details}") + set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg}) + if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}") + # The message has not yet been printed. + message(STATUS "${msg}") + + # Save the find details in the cache to avoid printing the same + # message again. + set("${DETAILS_VAR}" "${details}" + CACHE INTERNAL "Details about finding ${pkg}") + endif() + endif() +endfunction() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/SelectLibraryConfigurations.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/SelectLibraryConfigurations.cmake new file mode 100644 index 0000000000..dce6f99262 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/NewCMake/SelectLibraryConfigurations.cmake @@ -0,0 +1,70 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# SelectLibraryConfigurations +# --------------------------- +# +# +# +# select_library_configurations( basename ) +# +# This macro takes a library base name as an argument, and will choose +# good values for basename_LIBRARY, basename_LIBRARIES, +# basename_LIBRARY_DEBUG, and basename_LIBRARY_RELEASE depending on what +# has been found and set. If only basename_LIBRARY_RELEASE is defined, +# basename_LIBRARY will be set to the release value, and +# basename_LIBRARY_DEBUG will be set to basename_LIBRARY_DEBUG-NOTFOUND. +# If only basename_LIBRARY_DEBUG is defined, then basename_LIBRARY will +# take the debug value, and basename_LIBRARY_RELEASE will be set to +# basename_LIBRARY_RELEASE-NOTFOUND. +# +# If the generator supports configuration types, then basename_LIBRARY +# and basename_LIBRARIES will be set with debug and optimized flags +# specifying the library to be used for the given configuration. If no +# build type has been set or the generator in use does not support +# configuration types, then basename_LIBRARY and basename_LIBRARIES will +# take only the release value, or the debug value if the release one is +# not set. + +# This macro was adapted from the FindQt4 CMake module and is maintained by Will +# Dicharry . + +macro( select_library_configurations basename ) + if(NOT ${basename}_LIBRARY_RELEASE) + set(${basename}_LIBRARY_RELEASE "${basename}_LIBRARY_RELEASE-NOTFOUND" CACHE FILEPATH "Path to a library.") + endif() + if(NOT ${basename}_LIBRARY_DEBUG) + set(${basename}_LIBRARY_DEBUG "${basename}_LIBRARY_DEBUG-NOTFOUND" CACHE FILEPATH "Path to a library.") + endif() + + if( ${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE AND + NOT ${basename}_LIBRARY_DEBUG STREQUAL ${basename}_LIBRARY_RELEASE AND + ( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) ) + # if the generator supports configuration types or CMAKE_BUILD_TYPE + # is set, then set optimized and debug options. + set( ${basename}_LIBRARY "" ) + foreach( _libname IN LISTS ${basename}_LIBRARY_RELEASE ) + list( APPEND ${basename}_LIBRARY optimized "${_libname}" ) + endforeach() + foreach( _libname IN LISTS ${basename}_LIBRARY_DEBUG ) + list( APPEND ${basename}_LIBRARY debug "${_libname}" ) + endforeach() + elseif( ${basename}_LIBRARY_RELEASE ) + set( ${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} ) + elseif( ${basename}_LIBRARY_DEBUG ) + set( ${basename}_LIBRARY ${${basename}_LIBRARY_DEBUG} ) + else() + set( ${basename}_LIBRARY "${basename}_LIBRARY-NOTFOUND") + endif() + + set( ${basename}_LIBRARIES "${${basename}_LIBRARY}" ) + + if( ${basename}_LIBRARY ) + set( ${basename}_FOUND TRUE ) + endif() + + mark_as_advanced( ${basename}_LIBRARY_RELEASE + ${basename}_LIBRARY_DEBUG + ) +endmacro() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/Testing/Temporary/CTestCostData.txt b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/Testing/Temporary/CTestCostData.txt new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/Testing/Temporary/CTestCostData.txt @@ -0,0 +1 @@ +--- diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/Testing/Temporary/LastTest.log b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/Testing/Temporary/LastTest.log new file mode 100644 index 0000000000..811fffbb04 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/Testing/Temporary/LastTest.log @@ -0,0 +1,3 @@ +Start testing: Apr 08 18:46 UTC +---------------------------------------------------------- +End testing: Apr 08 18:46 UTC diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/comp_src.pl b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/comp_src.pl new file mode 100755 index 0000000000..510be2504f --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/comp_src.pl @@ -0,0 +1,15 @@ +#!/usr/bin/perl + + @list = @ARGV; + foreach(@list) { + $file = $_; + $compfile = "../../../P2/cmake/Modules/".$file; + $diffs = `diff $file $compfile`; + if($diffs != '') { + print "------------------------------------\n"; + print "$file\n"; + print "$diffs\n"; + print "------------------------------------\n"; + } + } + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/findHelpers.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/findHelpers.cmake new file mode 100644 index 0000000000..028957a0a6 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/findHelpers.cmake @@ -0,0 +1,173 @@ +function (findSrc varName version varDir ) + if(EXISTS ${CMAKE_SOURCE_DIR}/libsrc/${varName}) + message("setting source for ${varName} to be in libsrc") + set( ${varDir} "${CMAKE_SOURCE_DIR}/libsrc/${varName}" PARENT_SCOPE) + set( ${varCacheName} "${CMAKE_SOURCE_DIR}/libsrc/${varName}" CACHE STRING "" FORCE ) + else() + set(searchName ${varName}_v${${version}}) + message("searching for source for ${searchName} in ${CRTM_BASE}") + string( TOLOWER ${varName} varNameLower ) + find_path( TMP_DIR + NAMES ${searchName} + HINTS + ${CMAKE_SOURCE_DIR}/../libs + ${CRTM_BASE}/${version} + ${CRTM_BASE}/${varName} + ${CRTM_BASE}/${varName}/${version} + ${CRTM_BASE}/${varNameLower} + ${CRTM_BASE}/${varNameLower}/${version} + ${COREPATH}/sorc + $ENV{${varDir}}/libsrc + $ENV{${varDir}}/lib/sorc + $ENV{CORPATH}/lib/sorc + ${CMAKE_SOURCE_DIR}/libsrc/${varName} + ) + if( NOT TMP_DIR ) + message("didn't find directory") + set(secondSearchName v${${version}}) + find_path( TMP2_DIR + NAMES ${secondSearchName} + HINTS + ${CRTM_BASE}/${varName} + ) + endif() + set( varCacheName "${varDir}_SRC" ) + file(GLOB f_FILES "${TMP_DIR}/${varName}_v${${version}}/*.f*" "${TMP_DIR}/${varName}_v${${version}}/*.F*") + if( f_FILES ) + set( ${varDir} "${TMP_DIR}/${varName}_v${${version}}" PARENT_SCOPE) + set( ${varCacheName} "${TMP_DIR}/${varName}_v${${version}}" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${TMP_DIR}/${varName}_v${${version}}/src/*.f*" "${TMP_DIR}/${varName}_v${${version}}/src/*.F*") + if( f_FILES ) + set( ${varDir} "${TMP_DIR}/${varName}_v${${version}}/src" PARENT_SCOPE) + set( ${varCacheName} "${TMP_DIR}/${varName}_v${${version}}/src" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${TMP_DIR}/${varName}_v${${version}}/libsrc/*.f*" "${TMP_DIR}/${varName}_v${${version}}/src/*.F*") + if( f_FILES ) + set( ${varDir} "${TMP_DIR}/${varName}_v${${version}}/libsrc" PARENT_SCOPE) + set( ${varCacheName} "${TMP_DIR}/${varName}_v${${version}}/libsrc" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${TMP_DIR}/${varName}_v${${version}}/sorc/*.f*" "${TMP_DIR}/${varName}_v${${version}}/sorc/*.F*") + if( f_FILES ) + set( ${varDir} "${TMP_DIR}/${varName}_v${${version}}/sorc" PARENT_SCOPE) + set( ${varCacheName} "${TMP_DIR}/${varName}_v${${version}}/sorc" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${TMP_DIR}/${varName}_v${${version}}/sorc/libsrc/*.f*" + "${TMP_DIR}/${varName}_v${${version}}/sorc/libsrc/*.F*") + if( f_FILES ) + set( ${varDir} "${TMP_DIR}/${varName}_v${${version}}/sorc/libsrc" PARENT_SCOPE) + set( ${varCacheName} "${TMP_DIR}/${varName}_v${${version}}/sorc/libsrc" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${TMP2_DIR}/v${${version}}/src/*.f*" + "${TMP_DIR}/v${${version}}/src/*.F*") + if( f_FILES ) + set( ${varDir} "${TMP2_DIR}/v${${version}}/src" PARENT_SCOPE) + set( ${varCacheName} "${TMP2_DIR}/v${${version}}/src" CACHE STRING "" FORCE ) + endif() + endif() + endif() + endif() + endif() + endif() + if( NOT f_FILES ) # look for source that is of a different version + message("WARNING: Did not find ${${version}} of ${varName}, looking for alternates") + findOtherVersion( TMP_DIR ${varName} srcPath ${version} ) + file(GLOB f_FILES "${srcPath}/*.f*" "${srcPath}/*.F*") + if( f_FILES ) + set( ${varDir} "${srcPath}" PARENT_SCOPE) + set( ${varCacheName} "${srcPath}" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${srcPath}/src/*.f*" "${srcPath}/src/*.F*") + if( f_FILES ) + set( ${varDir} "${srcPath}/src" PARENT_SCOPE) + set( ${varCacheName} "${srcPath}/src" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${srcPath}/libsrc/*.f*" "${srcPath}/src/*.F*") + if( f_FILES ) + set( ${varDir} "${srcPath}/libsrc" PARENT_SCOPE) + set( ${varCacheName} "${srcPath}/libsrc" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${srcPath}/sorc/*.f*" "${srcPath}/sorc/*.F*") + if( f_FILES ) + set( ${varDir} "${srcPath}/sorc" PARENT_SCOPE) + set( ${varCacheName} "${srcPath}/sorc" CACHE STRING "" FORCE ) + else() + file(GLOB f_FILES "${srcPath}/sorc/libsrc/*.f*" + "${srcPath}/sorc/libsrc/*.F*") + if( f_FILES ) + set( ${varDir} "${srcPath}/sorc/libsrc" PARENT_SCOPE) + set( ${varCacheName} "${srcPath}/sorc/libsrc" CACHE STRING "" FORCE ) + endif() + endif() + endif() + endif() + endif() + endif() + endif() +endfunction() + +function (findInc incName version incFile ) + cmake_policy(SET CMP0011 NEW) + cmake_policy(SET CMP0009 NEW) + STRING(COMPARE EQUAL ${incFile} "CRTMINC" USECRTMBASE ) + if(( USECRTMBASE ) AND ( CRTM_BASE )) + execute_process(COMMAND find ${CRTM_BASE} -iname ${incName}_module.mod RESULT_VARIABLE res OUTPUT_VARIABLE INCFILES) +# file(GLOB_RECURSE INCFILES ${CRTM_BASE}/*${CRTM_VER}*/*mod ) +# file(GLOB_RECURSE INCFILES2 ${CRTM_BASE}/crtm/*${CRTM_VER}*/*/*mod ) +# list(APPEND INCFILES ${INCFILES2} ) + else() + if(crayComp) + if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + execute_process(COMMAND find ${COREPATH}/${incName}/v${${version}}/intel -iname ${incName}_module.mod RESULT_VARIABLE res OUTPUT_VARIABLE INCFILES) + else() + execute_process(COMMAND find ${COREPATH}/${incName}/v${${version}}/cray -iname ${incName}_module.mod RESULT_VARIABLE res OUTPUT_VARIABLE INCFILES) + endif() + else() + execute_process(COMMAND find ${COREPATH}/${incName} -iname ${incName}_module.mod RESULT_VARIABLE res OUTPUT_VARIABLE INCFILES) + endif() + if( NOT (INCFILES) ) + execute_process(COMMAND find ${COREPATH}/sorc -iname ${incName}_module.mod RESULT_VARIABLE res OUTPUT_VARIABLE INCFILES) + endif() + endif() +# message("incfiles are ${INCFILES}") + if( INCFILES ) + string(REGEX REPLACE "\n" ";" INCFILES ${INCFILES} ) + endif() + foreach( INC_FILE in ${INCFILES} ) + string(REGEX MATCH ${${version}} MATCHFOUND ${INC_FILE} ) +# message("matchfound is ${MATCHFOUND}, version is ${${version}} for ${INC_FILE}") + if( MATCHFOUND ) + message("found ${INC_FILE}") + string(REGEX REPLACE "${incName}_module.mod" "" INCPATH ${INC_FILE} ) + set( ${incFile} ${INCPATH} PARENT_SCOPE ) + return() + endif() + endforeach() + file(GLOB_RECURSE INCFILES ${COREPATH}/${incName}_module.mod ) + list(LENGTH INCFILES numFiles) + if(numFiles EQUAL 1) + get_filename_component( INCPATH ${INCFILES} DIRECTORY ) + else() + foreach( INC_FILE in ${INCFILES} ) + get_filename_component( INCPATH ${INC_FILE} DIRECTORY ) +# message("WARNING: Did not find explicit version ${${version}} of ${incName} module, using un-versioned path") +# set( ${incFile} ${INCPATH} PARENT_SCOPE ) +# return() + endforeach() + endif() + set( ${incFile} ${INCPATH} PARENT_SCOPE ) +endfunction() + +function (findOtherVersion rootPath srcName srcPath newVer ) + file(GLOB SRCDIRS ${${rootPath}}/${srcName}* ) + foreach( SRC_DIR in ${SRCDIRS} ) + string(REGEX MATCH ${srcName} MATCHFOUND ${SRC_DIR} ) + if( MATCHFOUND ) + set( ${srcPath} ${SRC_DIR} PARENT_SCOPE ) + string(REGEX MATCH "[0-9].[0-9].[0-9]" ALTVER ${SRC_DIR} ) + message("Found ${ALTVER} of ${srcName}. Proceeding with Alternative") + set( ${newVer} ${ALTVER} PARENT_SCOPE ) + return() + endif() + endforeach() +endfunction() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Cheyenne.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Cheyenne.cmake new file mode 100644 index 0000000000..54477168e8 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Cheyenne.cmake @@ -0,0 +1,24 @@ +macro (setCheyenne) + message("Setting paths for Cheyenne") + option(FIND_HDF5 "Try to Find HDF5 libraries" OFF) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + + set(HOST_FLAG "-xHOST" CACHE INTERNAL "Host Flag") + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -O3 -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "GSI Fortran Flags") + set(ENKF_Platform_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert big_endian -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "ENKF Fortran Flags") + + set(BUILD_CORELIBS "ON" ) + set(BUILD_UTIL "OFF" CACHE INTERNAL "" ) + set(BUILD_BUFR "ON" CACHE INTERNAL "") + set(BUILD_SFCIO "ON" CACHE INTERNAL "") + set(BUILD_SIGIO "ON" CACHE INTERNAL "") + set(BUILD_W3EMC "ON" CACHE INTERNAL "") + set(BUILD_W3NCO "ON" CACHE INTERNAL "") + set(BUILD_BACIO "ON" CACHE INTERNAL "") + set(BUILD_CRTM "ON" CACHE INTERNAL "") + set(BUILD_SP "ON" CACHE INTERNAL "") + set(BUILD_NEMSIO "ON" CACHE INTERNAL "") + set(ENV{MPI_HOME} $ENV{MPI_ROOT} ) +endmacro() + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Discover.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Discover.cmake new file mode 100644 index 0000000000..fe8a2dfc0e --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Discover.cmake @@ -0,0 +1,55 @@ +macro (setDiscover) + message("Setting paths for Discover") +# option(FIND_HDF5 "Try to Find HDF5 libraries" OFF) +# option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + set(HDF5_USE_STATIC_LIBRARIES "OFF") + + set(HOST_FLAG "-xHOST" CACHE INTERNAL "Host Flag") + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -O3 -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "GSI Fortran Flags") + set(ENKF_Platform_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert big_endian -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "ENKF Fortran Flags") + set(host "Discover" CACHE INTERNAL "") + + set(COREPATH $ENV{COREPATH} ) + if( NOT DEFINED ENV{NETCDF_VER} ) + set(NETCDF_VER "3.6.3" ) + endif() + if( NOT DEFINED ENV{BACIO_VER} ) + set(BACIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{BUFR_VER} ) + set(BUFR_VER "10.2.5" ) + endif() + if( NOT DEFINED ENV{CRTM_VER} ) + set(CRTM_VER "2.2.3" ) + endif() + if( NOT DEFINED ENV{NEMSIO_VER} ) + set(NEMSIO_VER "2.2.1" ) + endif() + if( NOT DEFINED ENV{SFCIO_VER} ) + set(SFCIO_VER "1.1.0" ) + endif() + if( NOT DEFINED ENV{SIGIO_VER} ) + set(SIGIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{SP_VER} ) + set(SP_VER "2.0.2" ) + endif() + if( NOT DEFINED ENV{W3EMC_VER} ) + set(W3EMC_VER "2.2.0" ) + endif() + if( NOT DEFINED ENV{W3NCO_VER} ) + set(W3NCO_VER "2.0.6" ) + endif() + + if( ENV{BASEDIR} ) + set(BASEDIR $ENV{BASEDIR}/Linux CACHE INTERNAL "") + endif() + set(BUILD_CORELIBS "ON" CACHE INTERNAL "") + set(USE_WRF "OFF" CACHE INTERNAL "") + set(BUILD_GLOBAL "ON" CACHE INTERNAL "") + + set(ENV{MPI_HOME} $ENV{MPI_ROOT} ) + +endmacro() + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Gaea.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Gaea.cmake new file mode 100644 index 0000000000..d6929b8f03 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Gaea.cmake @@ -0,0 +1,14 @@ +macro (setGaea) + + message("Setting flags and paths for Cray") + option(FIND_HDF5 "Try to Find HDF5 libraries" OFF) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" ON) + set(HDF5_USE_STATIC_LIBRARIES "ON" CACHE INTERNAL "HDF5_Static" ) + + set(HOST_FLAG "-xCORE-AVX2" CACHE INTERNAL "Host Flag") # for Haswell (C4) + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag" ) + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -fp-model strict -assume byterecl -convert big_endian -implicitnone -D_REAL8_ -traceback ${HOST_FLAG} ${MKL_FLAG} ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS} -O3" CACHE INTERNAL "") + set(ENKF_Platform_FLAGS "-O3 -fp-model strict -convert big_endian -assume byterecl -implicitnone -DGFS -D_REAL8_ -traceback ${HOST_FLAG} ${MKL_FLAG} ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "") + set(GSI_LDFLAGS "${MKL_FLAG} ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "") + set(BUILD_CORELIBS "OFF" ) +endmacro() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Generic.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Generic.cmake new file mode 100644 index 0000000000..b584cf66cf --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Generic.cmake @@ -0,0 +1,24 @@ +macro (setGeneric) + message("Setting paths for Generic System") + option(FIND_HDF5 "Try to Find HDF5 libraries" OFF) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + if(EXISTS /jetmon) + set(HOST_FLAG "" CACHE INTERNAL "Host Flag") ## default, no host_flag required + else() + set(HOST_FLAG "" CACHE INTERNAL "Host Flag") ## default, no host_flag required + endif() + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -O3 -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "GSI Fortran Flags") + set(ENKF_Platform_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert big_endian -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "ENKF Fortran Flags") + + message("setting values for corelibs") + set(BUILD_BUFR "OFF" CACHE INTERNAL "Build the BUFR library" ) + set(BUILD_BACIO "OFF" CACHE INTERNAL "Build the BACIO library" ) + set(BUILD_SFCIO "OFF" CACHE INTERNAL "Build the SFCIO library" ) + set(BUILD_SIGIO "OFF" CACHE INTERNAL "Build the SIGIO library" ) + set(BUILD_NEMSIO "OFF" CACHE INTERNAL "Build the NEMSIO library" ) + set(BUILD_SP "OFF" CACHE INTERNAL "Build the SP library" ) + set(BUILD_CRTM "OFF" CACHE INTERNAL "Build the CRTM library" ) + set(BUILD_W3EMC "OFF" CACHE INTERNAL "Build the EMC library" ) + set(BUILD_NCO "OFF" CACHE INTERNAL "Build the NCO library" ) +endmacro() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Hera.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Hera.cmake new file mode 100644 index 0000000000..d8af27696c --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Hera.cmake @@ -0,0 +1,42 @@ +macro (setHERA) + message("Setting paths for HERA") + option(FIND_HDF5 "Try to Find HDF5 libraries" ON) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + set(HOST_FLAG "-xHOST" CACHE INTERNAL "Host Flag") + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -O3 -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "GSI Fortran Flags") + set(ENKF_Platform_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert big_endian -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "ENKF Fortran Flags") + set(HDF5_USE_STATIC_LIBRARIES "ON") + + if( NOT DEFINED ENV{NETCDF_VER} ) + set(NETCDF_VER "3.6.3" ) + endif() + if( NOT DEFINED ENV{BACIO_VER} ) + set(BACIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{BUFR_VER} ) + set(BUFR_VER "10.2.5" ) + endif() + if( NOT DEFINED ENV{CRTM_VER} ) + set(CRTM_VER "2.2.3" ) + endif() + if( NOT DEFINED ENV{NEMSIO_VER} ) + set(NEMSIO_VER "2.2.1" ) + endif() + if( NOT DEFINED ENV{SFCIO_VER} ) + set(SFCIO_VER "1.0.0" ) + endif() + if( NOT DEFINED ENV{SIGIO_VER} ) + set(SIGIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{SP_VER} ) + set(SP_VER "2.0.2" ) + endif() + if( NOT DEFINED ENV{W3EMC_VER} ) + set(W3EMC_VER "2.0.5" ) + endif() + if( NOT DEFINED ENV{W3NCO_VER} ) + set(W3NCO_VER "2.0.6" ) + endif() +endmacro() + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Jet.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Jet.cmake new file mode 100644 index 0000000000..8178526d40 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Jet.cmake @@ -0,0 +1,10 @@ +macro (setJet) + message("Setting paths for Jet") + option(FIND_HDF5 "Try to Find HDF5 libraries" OFF) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + set(HOST_FLAG "-axSSE4.2,AVX,CORE-AVX2" CACHE INTERNAL "Host Flag") + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "${HOST_FLAG} -DPOUND_FOR_STRINGIFY -O3 -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "GSI Fortran Flags") + set(ENKF_Platform_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert big_endian -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "ENKF Fortran Flags") +endmacro() + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Orion.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Orion.cmake new file mode 100644 index 0000000000..56ddd1f2c3 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/Orion.cmake @@ -0,0 +1,42 @@ +macro (setOrion) + message("Setting paths for Orion") + option(FIND_HDF5 "Try to Find HDF5 libraries" ON) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + set(HOST_FLAG "-xHOST" CACHE INTERNAL "Host Flag") + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -O3 -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "GSI Fortran Flags") + set(ENKF_Platform_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert big_endian -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "ENKF Fortran Flags") + set(HDF5_USE_STATIC_LIBRARIES "ON") + + if( NOT DEFINED ENV{NETCDF_VER} ) + set(NETCDF_VER "3.6.3" ) + endif() + if( NOT DEFINED ENV{BACIO_VER} ) + set(BACIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{BUFR_VER} ) + set(BUFR_VER "10.2.5" ) + endif() + if( NOT DEFINED ENV{CRTM_VER} ) + set(CRTM_VER "2.2.3" ) + endif() + if( NOT DEFINED ENV{NEMSIO_VER} ) + set(NEMSIO_VER "2.2.1" ) + endif() + if( NOT DEFINED ENV{SFCIO_VER} ) + set(SFCIO_VER "1.0.0" ) + endif() + if( NOT DEFINED ENV{SIGIO_VER} ) + set(SIGIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{SP_VER} ) + set(SP_VER "2.0.2" ) + endif() + if( NOT DEFINED ENV{W3EMC_VER} ) + set(W3EMC_VER "2.0.5" ) + endif() + if( NOT DEFINED ENV{W3NCO_VER} ) + set(W3NCO_VER "2.0.6" ) + endif() +endmacro() + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/S4.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/S4.cmake new file mode 100644 index 0000000000..c727765c16 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/S4.cmake @@ -0,0 +1,10 @@ +macro (setS4) + message("Setting paths for S4") + option(FIND_HDF5 "Try to Find HDF5 libraries" OFF) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + set(HOST_FLAG "-xHOST" CACHE INTERNAL "Host Flag") + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -O3 -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "GSI Fortran Flags") + set(ENKF_Platform_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert big_endian -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "ENKF Fortran Flags") + set(HDF5_USE_STATIC_LIBRARIES "OFF") +endmacro() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS-C.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS-C.cmake new file mode 100644 index 0000000000..1c9cf712cd --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS-C.cmake @@ -0,0 +1,60 @@ +macro (setWCOSS_C) + + message("Setting flags and paths for Cray") + option(FIND_HDF5 "Try to Find HDF5 libraries" OFF) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" ON) + set(HDF5_USE_STATIC_LIBRARIES "ON" CACHE INTERNAL "HDF5_Static" ) + + set(HOST_FLAG "-xHOST" CACHE INTERNAL "Host Flag") + set(MKL_FLAG "" CACHE INTERNAL "MKL flag" ) + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -fp-model strict -assume byterecl -convert big_endian -implicitnone -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS} -O3" CACHE INTERNAL "") + set(ENKF_Platform_FLAGS "-O3 -fp-model strict -convert big_endian -assume byterecl -implicitnone -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "") + set(GSI_LDFLAGS "${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "") + if( NOT DEFINED ENV{COREPATH} ) + set(COREPATH "/gpfs/hps/nco/ops/nwprod/lib" ) + else() + set(COREPATH $ENV{COREPATH} ) + endif() + if( NOT DEFINED ENV{CRTM_INC} ) + set(CRTM_BASE "/gpfs/hps/nco/ops/nwprod/lib/crtm" ) + endif() + if( NOT DEFINED ENV{WRFPATH} ) + if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + set(WRFPATH "/gpfs/hps/nco/ops/nwprod/wrf_shared.v1.1.0-intel" ) + else() + set(WRFPATH "/gpfs/hps/nco/ops/nwprod/wrf_shared.v1.1.0-cray" ) + endif() + else() + set(WRFPATH $ENV{WRFPATH} ) + endif() + if( NOT DEFINED ENV{NETCDF_VER} ) + set(NETCDF_VER "3.6.3" ) + endif() + if( NOT DEFINED ENV{BACIO_VER} ) + set(BACIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{BUFR_VER} ) + set(BUFR_VER "11.0.1" ) + endif() + if( NOT DEFINED ENV{CRTM_VER} ) + set(CRTM_VER "2.2.3" ) + endif() + if( NOT DEFINED ENV{NEMSIO_VER} ) + set(NEMSIO_VER "2.2.2" ) + endif() + if( NOT DEFINED ENV{SFCIO_VER} ) + set(SFCIO_VER "1.0.0" ) + endif() + if( NOT DEFINED ENV{SIGIO_VER} ) + set(SIGIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{SP_VER} ) + set(SP_VER "2.0.2" ) + endif() + if( NOT DEFINED ENV{W3EMC_VER} ) + set(W3EMC_VER "2.2.0" ) + endif() + if( NOT DEFINED ENV{W3NCO_VER} ) + set(W3NCO_VER "2.0.6" ) + endif() +endmacro() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS-D.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS-D.cmake new file mode 100644 index 0000000000..e0daffa593 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS-D.cmake @@ -0,0 +1,51 @@ +macro (setWCOSS_D) + message("Setting paths for Dell") + option(FIND_HDF5 "Try to Find HDF5 libraries" ON) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + + set(HOST_FLAG "-xHOST" CACHE INTERNAL "Host Flag") + set(MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -fp-model strict -assume byterecl -convert big_endian -implicitnone -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS} -O3" CACHE INTERNAL "GSI Fortran Flags") + set(GSI_LDFLAGS "${OpenMP_Fortran_FLAGS} ${MKL_FLAG}" CACHE INTERNAL "") + set(ENKF_Platform_FLAGS "-O3 -fp-model strict -convert big_endian -assume byterecl -implicitnone -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "ENKF Fortran Flags") + + set(HDF5_USE_STATIC_LIBRARIES "ON" CACHE INTERNAL "" ) + if( NOT DEFINED ENV{COREPATH} ) + set(COREPATH "/gpfs/dell1/nco/ops/nwprod/lib" ) + else() + set(COREPATH $ENV{COREPATH} ) + endif() + if( NOT DEFINED ENV{CRTM_INC} ) + set(CRTM_BASE "/gpfs/dell1/nco/ops/nwprod/lib/crtm" ) + endif() + if( NOT DEFINED ENV{NETCDF_VER} ) + set(NETCDF_VER "3.6.3" ) + endif() + if( NOT DEFINED ENV{BACIO_VER} ) + set(BACIO_VER "2.0.2" ) + endif() + if( NOT DEFINED ENV{BUFR_VER} ) + set(BUFR_VER "11.3.0" ) + endif() + if( NOT DEFINED ENV{CRTM_VER} ) + set(CRTM_VER "2.2.5" ) + endif() + if( NOT DEFINED ENV{NEMSIO_VER} ) + set(NEMSIO_VER "2.2.3" ) + endif() + if( NOT DEFINED ENV{SFCIO_VER} ) + set(SFCIO_VER "1.0.0" ) + endif() + if( NOT DEFINED ENV{SIGIO_VER} ) + set(SIGIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{SP_VER} ) + set(SP_VER "2.0.2" ) + endif() + if( NOT DEFINED ENV{W3EMC_VER} ) + set(W3EMC_VER "2.3.0" ) + endif() + if( NOT DEFINED ENV{W3NCO_VER} ) + set(W3NCO_VER "2.0.6" ) + endif() +endmacro() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS.cmake new file mode 100644 index 0000000000..81b1297392 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/platforms/WCOSS.cmake @@ -0,0 +1,61 @@ +macro (setWCOSS) + message("Setting paths for WCOSS") + option(FIND_HDF5 "Try to Find HDF5 libraries" OFF) + option(FIND_HDF5_HL "Try to Find HDF5 libraries" OFF) + set(HDF5_USE_STATIC_LIBRARIES "OFF") + + #if ibmpe module is not loaded last, CMake tries to use intel mpi. Force use of ibmhpc + set(HOST_FLAG "-xHOST" CACHE INTERNAL "Host Flag") + set( MKL_FLAG "-mkl" CACHE INTERNAL "MKL Flag") + set(GSI_Intel_Platform_FLAGS "-DPOUND_FOR_STRINGIFY -traceback -O3 -fp-model source -convert big_endian -assume byterecl -implicitnone -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "") + set(ENKF_Platform_FLAGS "-O3 -fp-model source -convert big_endian -assume byterecl -implicitnone -DGFS -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${HOST_FLAG} " CACHE INTERNAL "") + + set(MPI_Fortran_COMPILER /opt/ibmhpc/pe13010/base/bin/mpif90 CACHE FILEPATH "Forced use of ibm wrapper" FORCE ) + set(MPI_C_COMPILER /opt/ibmhpc/pe13010/base/bin/mpicc CACHE FILEPATH "Forced use of ibm wrapper" FORCE ) + set(MPI_CXX_COMPILER /opt/ibmhpc/pe13010/base/bin/mpicxx CACHE FILEPATH "Forced use of ibm wrapper" FORCE ) + + if( NOT DEFINED ENV{COREPATH} ) + set(COREPATH "/nwprod/lib" ) + else() + set(COREPATH $ENV{COREPATH} ) + endif() + if( NOT DEFINED ENV{CRTM_INC} ) + set(CRTM_BASE "/nwprod2/lib" ) + endif() + if( NOT DEFINED ENV{WRFPATH} ) + set(WRFPATH "/nwprod/sorc/wrf_shared.fd" ) + else() + set(WRFPATH $ENV{WRFPATH} ) + endif() + if( NOT DEFINED ENV{NETCDF_VER} ) + set(NETCDF_VER "3.6.3" ) + endif() + if( NOT DEFINED ENV{BACIO_VER} ) + set(BACIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{BUFR_VER} ) + set(BUFR_VER "10.2.5" ) + endif() + if( NOT DEFINED ENV{CRTM_VER} ) + set(CRTM_VER "2.2.3" ) + endif() + if( NOT DEFINED ENV{NEMSIO_VER} ) + set(NEMSIO_VER "2.2.1" ) + endif() + if( NOT DEFINED ENV{SFCIO_VER} ) + set(SFCIO_VER "1.0.0" ) + endif() + if( NOT DEFINED ENV{SIGIO_VER} ) + set(SIGIO_VER "2.0.1" ) + endif() + if( NOT DEFINED ENV{SP_VER} ) + set(SP_VER "2.0.2" ) + endif() + if( NOT DEFINED ENV{W3EMC_VER} ) + set(W3EMC_VER "2.0.5" ) + endif() + if( NOT DEFINED ENV{W3NCO_VER} ) + set(W3NCO_VER "2.0.6" ) + endif() + +endmacro() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setGNUFlags.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setGNUFlags.cmake new file mode 100644 index 0000000000..e4ef2d9ade --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setGNUFlags.cmake @@ -0,0 +1,66 @@ +function (setGNU) + set(COMPILER_TYPE "gnu" CACHE INTERNAL "Compiler brand") + message("Setting GNU Compiler Flags") + if( (BUILD_RELEASE) OR (BUILD_PRODUCTION) ) + set(GSI_Fortran_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -D_REAL8_ ${GSDCLOUDOPT} -fopenmp -ffree-line-length-0" CACHE INTERNAL "") + set(EXTRA_LINKER_FLAGS "-lgomp -lnetcdf -lnetcdff" CACHE INTERNAL "") + set(GSI_CFLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -g -Dfunder" CACHE INTERNAL "" ) + set(ENKF_Fortran_FLAGS " -O3 -fconvert=big-endian -ffree-line-length-0 -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -DGFS -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(UTIL_Fortran_FLAGS " -O3 -fconvert=big-endian -ffree-line-length-0 -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -DWRF -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(UTIL_COM_Fortran_FLAGS " -O3 -fconvert=big-endian -ffree-line-length-0 -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check" CACHE INTERNAL "") + set(BUFR_Fortran_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(BUFR_Fortran_PP_FLAGS " -P " CACHE INTERNAL "") + set(BUFR_C_FLAGS " -O3 -g -DUNDERSCORE -DDYNAMIC_ALLOCATION -DNFILES=32 -DMAXCD=250 -DMAXNC=600 -DMXNAF=3" CACHE INTERNAL "" ) + set(BACIO_Fortran_FLAGS " -O3 -fconvert=big-endian -ffree-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(CRTM_Fortran_FLAGS " -g -std=f2003 -fdollar-ok -O3 -fconvert=big-endian -ffree-form -fno-second-underscore -frecord-marker=4 -funroll-loops -static -Wall " CACHE INTERNAL "") + set(NEMSIO_Fortran_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(SIGIO_Fortran_FLAGS " -O3 -fconvert=big-endian -ffree-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(SFCIO_Fortran_FLAGS " -O3 -ffree-form -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(SP_Fortran_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ -fopenmp -DLINUX" CACHE INTERNAL "") + set(SP_Fortran_4_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -fopenmp -DLINUX" CACHE INTERNAL "") + set(SP_F77_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ -fopenmp -DLINUX" CACHE INTERNAL "") + set(SP_F77_4_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -fopenmp -DLINUX" CACHE INTERNAL "") + set(W3EMC_Fortran_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(W3EMC_4_Fortran_FLAGS " -O3 -fconvert=big-endian -ffixed-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check " CACHE INTERNAL "") + set(W3NCO_Fortran_FLAGS " -O3 -fconvert=big-endian -ffixed-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ " CACHE INTERNAL "") + set(W3NCO_4_Fortran_FLAGS " -O3 -fconvert=big-endian -ffixed-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check " CACHE INTERNAL "") + set(W3NCO_C_FLAGS " -DLINUX -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(WRFLIB_Fortran_FLAGS " -O3 -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp -ffree-line-length-0" CACHE INTERNAL "") + set( NCDIAG_Fortran_FLAGS "-ffree-line-length-none" CACHE INTERNAL "" ) + set( FV3GFS_NCIO_Fortran_FLAGS "-ffree-line-length-none" CACHE INTERNAL "" ) + set( NDATE_Fortran_FLAGS "-fconvert=big-endian -DCOMMCODE -DLINUX -DUPPLITTLEENDIAN -O3 -Wl,-noinhibit-exec" CACHE INTERNAL "") + set( COV_CALC_FLAGS "-c -O3 -fconvert=little-endian -ffast-math -ffree-form -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fopenmp" CACHE INTERNAL "") + set(GSDCLOUD_Fortran_FLAGS "-O3 -fconvert=big-endian" CACHE INTERNAL "") + else( ) #DEBUG + set(GSI_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -D_REAL8_ ${GSDCLOUDOPT} -fopenmp -ffree-line-length-0" CACHE INTERNAL "") + set(EXTRA_LINKER_FLAGS "-lgomp -lnetcdf -lnetcdff" CACHE INTERNAL "") + set(GSI_CFLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -g -fbacktrace -Dfunder" CACHE INTERNAL "" ) + set(ENKF_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffree-line-length-0 -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -DGFS -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(UTIL_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffree-line-length-0 -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -DWRF -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(UTIL_COM_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffree-line-length-0 -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check" CACHE INTERNAL "") + set(BUFR_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(BUFR_Fortran_PP_FLAGS " -P " CACHE INTERNAL "") + set(BUFR_C_FLAGS " -g -fbacktrace -g -fbacktrace -DUNDERSCORE -DDYNAMIC_ALLOCATION -DNFILES=32 -DMAXCD=250 -DMAXNC=600 -DMXNAF=3" CACHE INTERNAL "" ) + set(BACIO_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffree-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(CRTM_Fortran_FLAGS " -g -fbacktrace -std=f2003 -fdollar-ok -g -fbacktrace -fconvert=big-endian -ffree-form -fno-second-underscore -frecord-marker=4 -funroll-loops -static -Wall " CACHE INTERNAL "") + set(NEMSIO_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(SIGIO_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffree-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(SFCIO_Fortran_FLAGS " -g -fbacktrace -ffree-form -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(SP_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ -fopenmp -DLINUX" CACHE INTERNAL "") + set(SP_Fortran_4_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -fopenmp -DLINUX" CACHE INTERNAL "") + set(SP_F77_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ -fopenmp -DLINUX" CACHE INTERNAL "") + set(SP_F77_4_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -fopenmp -DLINUX" CACHE INTERNAL "") + set(W3EMC_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(W3EMC_4_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffixed-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check " CACHE INTERNAL "") + set(W3NCO_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffixed-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -fdefault-real-8 -D_REAL8_ " CACHE INTERNAL "") + set(W3NCO_4_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffixed-form -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check " CACHE INTERNAL "") + set(W3NCO_C_FLAGS " -DLINUX -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp" CACHE INTERNAL "") + set(WRFLIB_Fortran_FLAGS " -g -fbacktrace -fconvert=big-endian -ffast-math -fno-second-underscore -frecord-marker=4 -funroll-loops -g -ggdb -static -Wall -fno-range-check -D_REAL8_ -fopenmp -ffree-line-length-0" CACHE INTERNAL "") + set( NCDIAG_Fortran_FLAGS "-ffree-line-length-none" CACHE INTERNAL "" ) + set( FV3GFS_NCIO_Fortran_FLAGS "-ffree-line-length-none" CACHE INTERNAL "" ) + set( NDATE_Fortran_FLAGS "-fconvert=big-endian -DCOMMCODE -DLINUX -DUPPLITTLEENDIAN -g -fbacktrace -Wl,-noinhibit-exec" CACHE INTERNAL "") + set( COV_CALC_FLAGS "-c -O3 -fconvert=little-endian -ffast-math -ffree-form -fno-second-underscore -frecord-marker=4 -funroll-loops -ggdb -static -Wall -fopenmp" CACHE INTERNAL "") + set(GSDCLOUD_Fortran_FLAGS "-O3 -fconvert=big-endian" CACHE INTERNAL "") + endif( (BUILD_RELEASE) OR (BUILD_PRODUCTION) ) +endfunction() + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setHOST.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setHOST.cmake new file mode 100644 index 0000000000..1d0a3b5341 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setHOST.cmake @@ -0,0 +1,91 @@ +macro( setHOST ) + site_name(HOSTNAME) + message("The hostname is ${HOSTNAME}" ) + string(REGEX MATCH "s4-" HOST-S4 ${HOSTNAME} ) + string(REGEX MATCH "gaea" HOST-Gaea ${HOSTNAME} ) + string(REGEX MATCH "hfe[0-9]" HOST-Hera ${HOSTNAME} ) + string(REGEX MATCH "Orion" HOST-Orion ${HOSTNAME} ) + if(EXISTS /jetmon) + set(HOST-Jet "True" ) + endif() + string(REGEX MATCH "g[0-9][0-9]a" HOST-WCOSS ${HOSTNAME} ) + if( HOST-WCOSS ) + message("host is WCOSS") + endif() + string(REGEX MATCH "g[0-9][0-9]a" HOST-WCOSS ${HOSTNAME} ) + if( NOT HOST-WCOSS ) # don't overwrite if we are on gyre + string(REGEX MATCH "t[0-9][0-9]a" HOST-WCOSS ${HOSTNAME} ) + endif() + string(REGEX MATCH "v[0-9][0-9]a" HOST-WCOSS_D ${HOSTNAME} ) + if( NOT HOST-WCOSS_D )# don't overwrite if we are on venus + string(REGEX MATCH "m[0-9][0-9]a" HOST-WCOSS_D ${HOSTNAME} ) + endif() + string(REGEX MATCH "llogin" HOST-WCOSS_C ${HOSTNAME} ) + if( NOT HOST-WCOSS_C )# don't overwrite if we are on luna + string(REGEX MATCH "slogin" HOST-WCOSS_C ${HOSTNAME} ) + endif() + string(REGEX MATCH "discover" HOST-Discover ${HOSTNAME} ) + string(REGEX MATCH "cheyenne" HOST-Cheyenne ${HOSTNAME} ) + message("done figuring out host--${HOSTNAME}") + if ( BUILD_CORELIBS ) + MESSAGE(STATUS "BUILD_CORELIBS manually-specified as ON") + set( host "GENERIC" ) + set( HOST-Generic "TRUE" ) + setGeneric() + elseif(HOST-Jet) + option(BUILD_CORELIBS "Build the Core libraries " ON) + set( host "Jet" ) + set( HOST-Jet "TRUE" ) + setJet() + elseif( HOST-S4 ) + option(BUILD_CORELIBS "Build the Core libraries " ON) + set( host "S4" ) + set( HOST-S4 "TRUE" ) + setS4() + elseif( HOST-WCOSS ) + option(BUILD_CORELIBS "Build the Core libraries " OFF) + set( host "WCOSS" ) + set( HOST-WCOSS "TRUE" ) + setWCOSS() + elseif( HOST-Hera ) + set( host "Hera" ) + option(BUILD_CORELIBS "Build the Core libraries " OFF) + setHERA() + set( HOST-Hera "TRUE" ) + elseif( HOST-Orion ) + set( host "Orion" ) + option(BUILD_CORELIBS "Build the Core libraries " OFF) + setOrion() + set( HOST-Orion "TRUE" ) + elseif( HOST-Gaea ) + set( host "Gaea" ) + option(BUILD_CORELIBS "Build the Core libraries " On) + setGaea() + set( HOST-Gaea "TRUE" ) + elseif( HOST-Cheyenne ) + option(BUILD_CORELIBS "Build the Core libraries " ON) + set( host "Cheyenne" ) + setCheyenne() + set( HOST-Cheyenne "TRUE" ) + elseif( HOST-WCOSS_C ) + set( host "WCOSS_C" ) + option(BUILD_CORELIBS "Build the Core libraries " OFF) + setWCOSS_C() + set( HOST-WCOSS_C "TRUE" ) + elseif( HOST-WCOSS_D ) + set( host "WCOSS_D" ) + option(BUILD_CORELIBS "Build the Core libraries " OFF) + setWCOSS_D() + set( HOST-WCOSS_D "TRUE" ) + elseif( HOST-Discover ) + set(host "Discover" ) + setDiscover() + set( HOST-Discover "TRUE" ) + else( ) + set( host "GENERIC" ) + option(BUILD_CORELIBS "Build the Core libraries " ON) + setGeneric() + set( HOST-Generic "TRUE" ) + endif() + message("Host is set to ${host}") +endmacro() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setIntelFlags.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setIntelFlags.cmake new file mode 100644 index 0000000000..70544725a3 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setIntelFlags.cmake @@ -0,0 +1,94 @@ +set(intsize 4) +function(set_LIBRARY_UTIL_Intel) + set(BACIO_Fortran_FLAGS "-O3 -free -assume nocc_omp ${HOST_FLAG} " CACHE INTERNAL "" ) + set(BUFR_Fortran_FLAGS "-O2 -r8 -fp-model strict -traceback -O3 ${HOST_FLAG} ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(BUFR_C_FLAGS "-DSTATIC_ALLOCATION -DUNDERSCORE -DNFILES=32 -DMAXCD=250 -DMAXNC=600 -DMXNAF=3" CACHE INTERNAL "" ) + set(BUFR_Fortran_PP_FLAGS " -P -traditional-cpp -C " CACHE INTERNAL "" ) + set(WRFLIB_Fortran_FLAGS "-DPOUND_FOR_STRINGIFY -O3 -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "") + set(WRFLIB_C_FLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -O3 -Dfunder" CACHE INTERNAL "" ) + set (CRTM_Fortran_FLAGS " -O3 -convert big_endian -free -assume byterecl -fp-model source -traceback ${HOST_FLAG}" CACHE INTERNAL "" ) + set (NEMSIO_Fortran_FLAGS " -O2 -convert big_endian -free -assume byterecl -fp-model strict -traceback ${HOST_FLAG} -g ${MKL_FLAG} ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (SFCIO_Fortran_FLAGS " -O2 -convert big_endian -free -assume byterecl -fp-model strict -traceback ${HOST_FLAG} -g ${MKL_FLAG} ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (SIGIO_Fortran_FLAGS " -O2 -convert big_endian -free -assume byterecl -fp-model strict -traceback ${HOST_FLAG} -g ${MKL_FLAG} ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (SP_Fortran_FLAGS " -O2 -ip -fp-model strict -assume byterecl -convert big_endian -fpp -i${intsize} -r8 -convert big_endian -assume byterecl -DLINUX ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (SP_Fortran_4_FLAGS " -O2 -ip -fp-model strict -assume byterecl -convert big_endian -fpp -i${intsize} -convert big_endian -assume byterecl -DLINUX ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (SP_F77_FLAGS " -DLINUX -O2 -ip -fp-model strict -assume byterecl -convert big_endian -fpp -i${intsize} -r8 -convert big_endian -assume byterecl -DLINUX ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (W3EMC_Fortran_FLAGS " -O3 -auto -assume nocc_omp -i${intsize} -r8 -convert big_endian -assume byterecl -fp-model strict ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (W3EMC_4_Fortran_FLAGS " -O3 -auto -assume nocc_omp -i${intsize} -convert big_endian -assume byterecl -fp-model strict ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (W3NCO_Fortran_FLAGS " -O3 -auto -assume nocc_omp -i${intsize} -r8 -convert big_endian -assume byterecl -fp-model strict ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (W3NCO_4_Fortran_FLAGS " -O3 -auto -assume nocc_omp -i${intsize} -convert big_endian -assume byterecl -fp-model strict ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set (W3NCO_C_FLAGS "-O0 -DUNDERSCORE -DLINUX -D__linux__ " CACHE INTERNAL "" ) + set (NDATE_Fortran_FLAGS "${HOST_FLAG} -fp-model source -ftz -assume byterecl -convert big_endian -heap-arrays -DCOMMCODE -DLINUX -DUPPLITTLEENDIAN -O3 -Wl,-noinhibit-exec" CACHE INTERNAL "" ) + set(NCDIAG_Fortran_FLAGS "-free -assume byterecl -convert big_endian" CACHE INTERNAL "" ) + set(FV3GFS_NCIO_Fortran_FLAGS "-free" CACHE INTERNAL "" ) + set(UTIL_Fortran_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert big_endian -DWRF -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "") + set(UTIL_COM_Fortran_FLAGS "-O3 -fp-model source -convert big_endian -assume byterecl -implicitnone" CACHE INTERNAL "") +# set(COV_CALC_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert little_endian -D_REAL8_ -openmp -fpp -auto" CACHE INTERNAL "" ) + set(COV_CALC_FLAGS "-O3 ${HOST_FLAG} -warn all -implicitnone -traceback -fp-model strict -convert little_endian ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "") +# set(COV_CALC_FLAGS ${GSI_Intel_Platform_FLAGS} CACHE INTERNAL "Full GSI Fortran FLAGS" ) +endfunction(set_LIBRARY_UTIL_Intel) + +function(set_LIBRARY_UTIL_Debug_Intel) + set (BACIO_Fortran_FLAGS "-g -free -assume nocc_omp " CACHE INTERNAL "" ) + set(BUFR_Fortran_FLAGS " -c -g -traceback -O3 -axCORE-AVX2 -r8 " CACHE INTERNAL "" ) + set(BUFR_C_FLAGS "-g -traceback -DUNDERSCORE -O3 -axCORE-AVX2 -DDYNAMIC_ALLOCATION -DNFILES=32 -DMAXCD=250 -DMAXNC=600 -DMXNAF=3" CACHE INTERNAL "" ) + set(BUFR_Fortran_PP_FLAGS " -P -traditional-cpp -C " CACHE INTERNAL "" ) + set(CRTM_Fortran_FLAGS " -convert big_endian -free -assume byterecl -xHOST -fp-model strict -traceback -g ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(SFCIO_Fortran_FLAGS " -convert big_endian -free -assume byterecl -xHOST -fp-model strict -traceback -g ${MKL_FLAG} ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(SIGIO_Fortran_FLAGS " -convert big_endian -free -assume byterecl -xHOST -fp-model strict -traceback -g ${MKL_FLAG} ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(SP_Fortran_FLAGS " -g -ip -fp-model strict -assume byterecl -fpp -i${intsize} -r8 -convert big_endian -DLINUX ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(SP_Fortran_4_FLAGS " -g -ip -fp-model strict -assume byterecl -fpp -i${intsize} -convert big_endian -DLINUX ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(SP_F77_FLAGS " -g -ip -fp-model strict -assume byterecl -convert big_endian -fpp -i${intsize} -r8 -DLINUX ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(W3EMC_Fortran_FLAGS " -g -auto -assume nocc_omp -i${intsize} -r8 -convert big_endian -assume byterecl -fp-model strict ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(W3EMC_4_Fortran_FLAGS " -g -auto -assume nocc_omp -i${intsize} -convert big_endian -assume byterecl -fp-model strict ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(NEMSIO_Fortran_FLAGS " -convert big_endian -free -assume byterecl -xHOST -fp-model strict -traceback -g ${MKL_FLAG} ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(W3NCO_Fortran_FLAGS " -g -auto -assume nocc_omp -i${intsize} -r8 -convert big_endian -assume byterecl -fp-model strict ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(W3NCO_4_Fortran_FLAGS " -g -auto -assume nocc_omp -i${intsize} -convert big_endian -assume byterecl -fp-model strict ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) + set(W3NCO_C_FLAGS "-O0 -g -DUNDERSCORE -DLINUX -D__linux__ " CACHE INTERNAL "" ) + set(NCDIAG_Fortran_FLAGS "-free -assume byterecl -convert big_endian" CACHE INTERNAL "" ) + set(FV3GFS_NCIO_Fortran_FLAGS "-free" CACHE INTERNAL "" ) + set(WRFLIB_Fortran_FLAGS "-DPOUND_FOR_STRINGIFY -O1 -g -fp-model source -assume byterecl -convert big_endian -g -traceback -D_REAL8_ ${MPI_Fortran_COMPILE_FLAGS}" CACHE INTERNAL "") + set(NDATE_Fortran_FLAGS "${HOST_FLAG} -fp-model source -ftz -assume byterecl -convert big_endian -heap-arrays -DCOMMCODE -DLINUX -DUPPLITTLEENDIAN -g -Wl,-noinhibit-exec" CACHE INTERNAL "" ) + set(WRFLIB_C_FLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -g -Dfunder" CACHE INTERNAL "" ) + set(UTIL_Fortran_FLAGS "-O0 ${HOST_FLAG} -warn all -implicitnone -traceback -g -debug full -fp-model strict -convert big_endian -D_REAL8_ ${OpenMP_Fortran_FLAGS}" CACHE INTERNAL "") + set(UTIL_COM_Fortran_FLAGS "-O0 -warn all -implicitnone -traceback -g -debug full -fp-model strict -convert big_endian" CACHE INTERNAL "") + set(COV_CALC_FLAGS "-O3 ${HOST_FLAG} -implicitnone -traceback -fp-model strict -convert little_endian ${OpenMP_Fortran_FLAGS} " CACHE INTERNAL "" ) +endfunction(set_LIBRARY_UTIL_Debug_Intel) + +function(set_GSI_ENKF_Intel) + #Common release/production flags + set(GSI_CFLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -O3 -Dfunder" CACHE INTERNAL "" ) + set(GSI_Fortran_FLAGS "${GSI_Intel_Platform_FLAGS} ${GSDCLOUDOPT}" CACHE INTERNAL "Full GSI Fortran FLAGS" ) + set(ENKF_Fortran_FLAGS "${ENKF_Platform_FLAGS} ${GSDCLOUDOPT}" CACHE INTERNAL "Full ENKF Fortran FLAGS" ) + set(GSDCLOUD_Fortran_FLAGS "-O3 -convert big_endian" CACHE INTERNAL "") +endfunction(set_GSI_ENKF_Intel) + +function (set_GSI_ENKF_Debug_Intel) + set(GSI_Fortran_FLAGS "-DPOUND_FOR_STRINGIFY -O0 -fp-model source -convert big_endian -assume byterecl -implicitnone -mcmodel medium -shared-intel -g -traceback -debug -ftrapuv -check all,noarg_temp_created -fp-stack-check -fstack-protector -warn all,nointerfaces -convert big_endian -implicitnone -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${MPI_Fortran_COMPILE_FLAGS} ${GSDCLOUDOPT}" CACHE INTERNAL "") + set(ENKF_Fortran_FLAGS "-O0 ${HOST_FLAG} -warn all -implicitnone -traceback -g -debug all -check all,noarg_temp_created -fp-model strict -convert big_endian -assume byterecl -D_REAL8_ ${OpenMP_Fortran_FLAGS} ${GSDCLOUDOPT}" CACHE INTERNAL "") + set(GSDCLOUD_Fortran_FLAGS "-DPOUND_FOR_STRINGIFY -O3 -convert big_endian" CACHE INTERNAL "") + #Common debug flags + set(GSI_CFLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -g -Dfunder" CACHE INTERNAL "" ) +endfunction (set_GSI_ENKF_Debug_Intel) + +function (setIntel) + string(REPLACE "." ";" COMPILER_VERSION_LIST ${CMAKE_C_COMPILER_VERSION}) + list(GET COMPILER_VERSION_LIST 0 MAJOR_VERSION) + list(GET COMPILER_VERSION_LIST 1 MINOR_VERSION) + list(GET COMPILER_VERSION_LIST 2 PATCH_VERSION) + set(COMPILER_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}" CACHE INTERNAL "Compiler Version") + set(COMPILER_TYPE "intel" CACHE INTERNAL "Compiler brand") + STRING(COMPARE EQUAL ${CMAKE_BUILD_TYPE} "RELEASE" BUILD_RELEASE) + STRING(COMPARE EQUAL ${CMAKE_BUILD_TYPE} "PRODUCTION" BUILD_PRODUCTION) + set(EXTRA_LINKER_FLAGS ${MKL_FLAG} CACHE INTERNAL "Extra Linker flags") + if( (BUILD_RELEASE) OR (BUILD_PRODUCTION) ) + set_GSI_ENKF_Intel() + set_LIBRARY_UTIL_Intel() + else( ) #DEBUG flags + message("Building DEBUG version of GSI") + set( debug_suffix "_DBG" CACHE INTERNAL "" ) + set_GSI_ENKF_Debug_Intel() + set_LIBRARY_UTIL_Debug_Intel() + endif() +endfunction() + diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setPGIFlags.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setPGIFlags.cmake new file mode 100644 index 0000000000..2088a7416d --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setPGIFlags.cmake @@ -0,0 +1,78 @@ +function (setPGI) + message("Setting PGI Compiler Flags") + set(COMPILER_TYPE "pgi" CACHE INTERNAL "Compiler brand") + if( (BUILD_RELEASE) OR (BUILD_PRODUCTION) ) + set(CMAKE_Fortran_FLAGS_RELEASE "") + set(Fortran_FLAGS "" CACHE INTERNAL "") + set(GSI_Fortran_FLAGS "-Minform=inform -O1 -byteswapio -D_REAL8_ ${GSDCLOUDOPT} -mp -Mfree" CACHE INTERNAL "") + set(GSI_CFLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -g -Dfunder" CACHE INTERNAL "" ) + set(ENKF_Fortran_FLAGS " -O3 -byteswapio -fast -DGFS -D_REAL8_ -mp" CACHE INTERNAL "") + set(UTIL_Fortran_FLAGS " -O3 -byteswapio -fast -DWRF -D_REAL8_ -mp" CACHE INTERNAL "") + set(UTIL_COM_Fortran_FLAGS " -O3 -byteswapio -fast" CACHE INTERNAL "") + + set(BUFR_Fortran_FLAGS "-O1 -byteswapio -D_REAL8_ -mp -r8" CACHE INTERNAL "") + set(BUFR_Fortran_PP_FLAGS " -P " CACHE INTERNAL "") + set(BUFR_C_FLAGS " -g -DUNDERSCORE -DDYNAMIC_ALLOCATION -DNFILES=32 -DMAXCD=250 -DMAXNC=600 -DMXNAF=3" CACHE INTERNAL "" ) + + set(BACIO_C_INCLUDES " -I/usr/include/malloc" CACHE INTERNAL "") + set(BACIO_Fortran_FLAGS " -O3 -byteswapio -fast -D_REAL8_ -mp -Mfree" CACHE INTERNAL "") + set(CRTM_Fortran_FLAGS " -O1 -byteswapio -module ../../include -Mfree " CACHE INTERNAL "") + set(NEMSIO_Fortran_FLAGS " -O1 -byteswapio -D_REAL8_ -mp" CACHE INTERNAL "") + set(SIGIO_Fortran_FLAGS " -O3 -Mfree -byteswapio -fast -D_REAL8_ -mp" CACHE INTERNAL "") + set(SFCIO_Fortran_FLAGS " -O3 -byteswapio -Mfree -fast -D_REAL8_ -mp" CACHE INTERNAL "") + set(SP_Fortran_FLAGS " -O1 -byteswapio -DLINUX -mp -r8 " CACHE INTERNAL "") + set(SP_Fortran_4_FLAGS " -O1 -byteswapio -DLINUX -mp " CACHE INTERNAL "") + set(SP_F77_4_FLAGS "-DLINUX -O1 -byteswapio -DLINUX -mp " CACHE INTERNAL "") + set(SP_F77_FLAGS "-DLINUX -O1 -byteswapio -DLINUX -mp -r8 " CACHE INTERNAL "") + set(W3EMC_Fortran_FLAGS " -O1 -byteswapio -D_REAL8_ -r8 " CACHE INTERNAL "") + set(W3EMC_4_Fortran_FLAGS " -O1 -byteswapio " CACHE INTERNAL "") + set(W3NCO_Fortran_FLAGS " -O1 -byteswapio -D_REAL8_ -r8 " CACHE INTERNAL "") + set(W3NCO_4_Fortran_FLAGS " -DLINUX -O1 -byteswapio " CACHE INTERNAL "") + set(W3NCO_C_FLAGS " -O1 -D_REAL8_ -mp" CACHE INTERNAL "") + set(WRFLIB_Fortran_FLAGS "-Minform=inform -O1 -byteswapio -D_REAL8_ -mp -Mfree" CACHE INTERNAL "") + set(NDATE_Fortran_FLAGS "-DCOMMCODE -DLINUX -DUPPLITTLEENDIAN -O3 " CACHE INTERNAL "") + set(COV_CALC_FLAGS "-O3 -byteswapio -mp" CACHE INTERNAL "") + set(GSDCLOUD_Fortran_FLAGS "-O3 -byteswapio" CACHE INTERNAL "") + if ( ${CMAKE_C_COMPILER_VERSION} VERSION_LESS 18.5 ) + set( NCDIAG_Fortran_FLAGS "-Mfree -DOLDPGI" CACHE INTERNAL "" ) + else() + set( NCDIAG_Fortran_FLAGS "-Mfree" CACHE INTERNAL "" ) + endif() + else() + set(Fortran_FLAGS "" CACHE INTERNAL "") + set(GSI_Fortran_FLAGS "-Minform=inform -g -traceback -byteswapio -D_REAL8_ ${GSDCLOUDOPT} -mp -Mfree" CACHE INTERNAL "") + set(GSI_CFLAGS "-I. -DFortranByte=char -DFortranInt=int -DFortranLlong='long long' -g -traceback -Dfunder" CACHE INTERNAL "" ) + set(ENKF_Fortran_FLAGS " -g -traceback -byteswapio -fast -DGFS -D_REAL8_ -mp" CACHE INTERNAL "") + set(UTIL_Fortran_FLAGS " -g -traceback -byteswapio -fast -DWRF -D_REAL8_ -mp" CACHE INTERNAL "") + set(UTIL_COM_Fortran_FLAGS " -g -traceback -byteswapio -fast" CACHE INTERNAL "") + + set(BUFR_Fortran_FLAGS "-g -traceback -byteswapio -D_REAL8_ -mp -r8" CACHE INTERNAL "") + set(BUFR_Fortran_PP_FLAGS " -P " CACHE INTERNAL "") + set(BUFR_C_FLAGS " -g -traceback -DUNDERSCORE -DDYNAMIC_ALLOCATION -DNFILES=32 -DMAXCD=250 -DMAXNC=600 -DMXNAF=3" CACHE INTERNAL "" ) + + set(BACIO_C_INCLUDES " -I/usr/include/malloc" CACHE INTERNAL "") + set(BACIO_Fortran_FLAGS " -g -traceback -byteswapio -fast -D_REAL8_ -mp -Mfree" CACHE INTERNAL "") + set(CRTM_Fortran_FLAGS " -g -traceback -byteswapio -module ../../include -Mfree " CACHE INTERNAL "") + set(NEMSIO_Fortran_FLAGS " -g -traceback -byteswapio -D_REAL8_ -mp" CACHE INTERNAL "") + set(SIGIO_Fortran_FLAGS " -g -traceback -Mfree -byteswapio -fast -D_REAL8_ -mp" CACHE INTERNAL "") + set(SFCIO_Fortran_FLAGS " -g -traceback -byteswapio -Mfree -fast -D_REAL8_ -mp" CACHE INTERNAL "") + set(SP_Fortran_FLAGS " -g -traceback -byteswapio -DLINUX -mp -r8 " CACHE INTERNAL "") + set(SP_Fortran_4_FLAGS " -g -traceback -byteswapio -DLINUX -mp " CACHE INTERNAL "") + set(SP_F77_4_FLAGS "-DLINUX -g -traceback -byteswapio -DLINUX -mp " CACHE INTERNAL "") + set(SP_F77_FLAGS "-DLINUX -g -traceback -byteswapio -DLINUX -mp -r8 " CACHE INTERNAL "") + set(W3EMC_Fortran_FLAGS " -g -traceback -byteswapio -D_REAL8_ -r8 " CACHE INTERNAL "") + set(W3EMC_4_Fortran_FLAGS " -g -traceback -byteswapio " CACHE INTERNAL "") + set(W3NCO_Fortran_FLAGS " -g -traceback -byteswapio -D_REAL8_ -r8 " CACHE INTERNAL "") + set(W3NCO_4_Fortran_FLAGS " -g -traceback -byteswapio " CACHE INTERNAL "") + set(W3NCO_C_FLAGS " -DLINUX -g -traceback -D_REAL8_ -mp" CACHE INTERNAL "") + set(WRFLIB_Fortran_FLAGS "-Minform=inform -g -traceback -byteswapio -D_REAL8_ -mp -Mfree" CACHE INTERNAL "") + set(NDATE_Fortran_FLAGS "-DCOMMCODE -DLINUX -DUPPLITTLEENDIAN -g -traceback " CACHE INTERNAL "") + set(COV_CALC_FLAGS "-O3 -byteswapio -traceback -mp" CACHE INTERNAL "") + set(GSDCLOUD_Fortran_FLAGS "-O3 -byteswapio" CACHE INTERNAL "") + if ( ${CMAKE_C_COMPILER_VERSION} VERSION_LESS 18.5 ) + set( NCDIAG_Fortran_FLAGS "-Mfree -DOLDPGI" CACHE INTERNAL "" ) + else() + set( NCDIAG_Fortran_FLAGS "-Mfree" CACHE INTERNAL "" ) + endif() + endif( (BUILD_RELEASE) OR (BUILD_PRODUCTION) ) +endfunction() diff --git a/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setPlatformVariables.cmake b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setPlatformVariables.cmake new file mode 100644 index 0000000000..79408821a6 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/cmake/Modules/setPlatformVariables.cmake @@ -0,0 +1,11 @@ +include(${CMAKE_CURRENT_LIST_DIR}/platforms/Jet.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/WCOSS.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/WCOSS-C.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/S4.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/Hera.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/Orion.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/Gaea.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/Cheyenne.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/Discover.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/WCOSS-D.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/platforms/Generic.cmake) diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/.CMakeLists.txt.swp b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/.CMakeLists.txt.swp new file mode 100644 index 0000000000..10698790ec Binary files /dev/null and b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/.CMakeLists.txt.swp differ diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/CMakeLists.txt b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/CMakeLists.txt new file mode 100644 index 0000000000..337a5378c8 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8) +if(BUILD_FV3GFS_NCIO) + set(Fortran_MODULE_DIRECTORY "${PROJECT_BINARY_DIR}/include") + # NetCDF-4 library + include_directories( ${NETCDF_INCLUDES} ${FV3GFS_NCIO_INCS} ) + FILE(GLOB FV3GFS_NCIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/module_fv3gfs_ncio.f90 ) + set_source_files_properties( ${FV3GFS_NCIO_SRC} PROPERTIES COMPILE_FLAGS ${FV3GFS_NCIO_Fortran_FLAGS} ) + add_library(fv3gfs_ncio STATIC ${FV3GFS_NCIO_SRC}) +endif(BUILD_FV3GFS_NCIO) + diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/README.md b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/README.md new file mode 100644 index 0000000000..9535394fb8 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/README.md @@ -0,0 +1,92 @@ +# fv3gfs_ncio +module for reading/writing FV3 netcdf lat/lon data. + + +* open a Dataset. +```fortran +use module_fv3gfs_ncio +type(Dataset) :: ds +ds = open_dataset('gfs.t00z.atmf240.nc') +``` +* read an attribute. +```fortran +real(4), allocatable, dimension(:) :: ak,bk +character(len=32) charatt +! ak,bk are allocated and filled. +call read_attribute(ds, 'ak', ak) +call read_attribute(ds, 'bk', bk) +! read character variable attribute +call read_attribute(ds, 'long_name', charatt, 'vgrd') +``` +* read a variable. +```fortran +real(4), allocatable, dimension(:) :: lats,lons +real(4), allocatable, dimension(:,:,:) :: psfc +! arrays must be of correct rank (but not necessarily +! the same type). They are allocated and filled. +! The entire variable is read at once. +call read_vardata(ds,'latitudes',lats) +call read_vardata(ds,'latitudes',lons) +call read_vardata(ds,'pressfc',psfc) +``` +* create a new dataset from a template dataset. + +A template dataset can be created from a cdl file by running +`ncgen -7 -o `. +A [cdl](https://www.unidata.ucar.edu/software/netcdf/netcdf/CDL-Syntax.html) +file can be created from an existing dataset by running +`ncdump -cs > `. The cdl +text file can be edited with a text editor. +```fortran +type(Dataset) :: dso +! copy_vardata is optional, default .false. means just copy +! variables, dimensions and attributes and coordinate variable +! data (don't copy all variable data). +dso = create_dataset('gfs.t00z.atmf240_copy.nc', ds, copy_vardata=.true.) +``` +* write a variable. +```fortran +real(8), allocatable, dimension(:) :: times +call read_vardata(dso, 'time', times) +! times is now allocated and filled with values from template dataset. +! now overwrite with new values and write back. +times = times + 6 ! add six hours. +call write_vardata(dso, 'time', times) +``` +* quantize variable data before writing for better compression. +```fortran +! Lossy compression controlled by parameter nbits (1-31). +! The floating point data is quantized to improve compression +! See doi:10.5194/gmd-10-413-2017. The method employed +! here is identical to the 'scaled linear packing' method in +! that paper, except that the data are scaling into an arbitrary +! range (2**nbits-1 not just 2**16-1) and are stored as re-scaled floats +! instead of short integers. The zlib algorithm does almost as +! well packing the rescaled floats as it does the scaled +! integers, and this avoids the need for the client to apply the +! rescaling (plus it allows the ability to adjust the packing range). +data_save = data +nbits = 14 +call quantize_data(data_save, data, nbits, compress_err) +! compress_err is the max abs compression error (can be saved +! as a variable attribute). +``` +* write an attribute. +```fortran +charatt = 'hours since 2016-01-04 06:00:00' +call write_attribute(dso, 'units', charatt, 'time') +``` +* access Variable and Dimension derived data types. +```fortran +type(Variable) :: var +type(Dimension) :: dim +! see module_fv3gfs_ncio.f90 for type definitions. +! type members can be used to the call netcdf-fortran90 interface +! directly. +var = get_var(ds, 'ugrd') +dim = get_dim(ds, 'time') +``` +* close a dataset. +```fortran +call close_dataset(ds) +call close_dataset(dso) diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/example_fv3gfs_ncio.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/example_fv3gfs_ncio.f90 new file mode 100644 index 0000000000..7cba9f5051 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/example_fv3gfs_ncio.f90 @@ -0,0 +1,34 @@ +program example_fv3gfs_ncio + use module_fv3gfs_ncio + character(len=500) filename + type(Dataset) :: dsetin, dset + real(8), allocatable, dimension(:) :: values8_1d + real(4), allocatable, dimension(:,:,:) :: values_3d + integer ndim,nvar + ! template file created by running ncdump -cs on full file, then running + ! ncgen -7 -o + ! only coordinate variables have data + dsetin = open_dataset('test_data/dynf000_template.nc') + ! create a copy of the template file + dset = create_dataset('test_data/dynf000_copy.nc',dsetin) + print *,'ncid=',dset%ncid + print *,'nvars=',dset%nvars + print *,'ndims=',dset%ndims + print *,'natts=',dset%natts + do ndim=1,dset%ndims + print *,'dim',ndim,trim(dset%dimensions(ndim)%name),dset%dimensions(ndim)%len,dset%dimensions(ndim)%isunlimited + enddo + do nvar=1,dset%nvars + print *,'var',nvar,trim(dset%variables(nvar)%name),dset%variables(nvar)%ndims,dset%variables(nvar)%dimlens + enddo + ! read and print a coordinate variable. + call read_vardata(dset, 'grid_yt', values8_1d) + print *,'grid_yt=' + print *,values8_1d + ! other vars just filled with _FillValue + call read_vardata(dset, 'hgtsfc', values_3d) + print *,'min/max hgtsfc=',minval(values_3d),maxval(values_3d) + call close_dataset(dset) + call close_dataset(dsetin) + stop +end program example_fv3gfs_ncio diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/module_fv3gfs_ncio.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/module_fv3gfs_ncio.f90 new file mode 100644 index 0000000000..e7a38b63b0 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/module_fv3gfs_ncio.f90 @@ -0,0 +1,1338 @@ +module module_fv3gfs_ncio +! module for reading/writing netcdf global lat/lon grid files output by FV3GFS. +! assumes netcdf classic data model, nf90_format_netcdf4_classic format. +! handles 32 and 64 bit real variables, 8, 16 and 32 bit integer +! variables and char variables. Variables can have up to 5 dimensions. +! jeff whitaker 201910 + + use netcdf + use mpi + + implicit none + private + + type Variable + integer varid ! netCDF variable ID + integer ndims ! number of dimensions + integer dtype ! netCDF data type + integer natts ! number of attributes + integer deflate_level ! compression level (if > 0) + logical shuffle ! shuffle filter? + logical hasunlim ! has an unlimited dim? + character(len=nf90_max_name) :: name ! variable name + integer, allocatable, dimension(:) :: dimids ! netCDF dimension IDs + ! indices into Dataset%dimensions for associated dimensions. + integer, allocatable, dimension(:) :: dimindxs + ! names of associated dimensions. + character(len=nf90_max_name), allocatable, dimension(:) :: dimnames + ! current dimension lengths (updated after every write_vardata call) + integer, allocatable, dimension(:) :: dimlens + integer, allocatable, dimension(:) :: chunksizes + end type Variable + type Dimension + integer dimid ! netCDF dimension ID + integer len ! dimension length (updated after every write_vardata call) + logical isunlimited ! unlimited? + character(len=nf90_max_name) :: name ! name of dimension + end type Dimension + type Dataset + integer :: ncid ! netCDF ID. + integer :: nvars ! number of variables in dataset + integer :: ndims ! number of dimensions in dataset + integer :: natts ! number of dataset (global) attributes + integer :: nunlimdim ! dimension ID for unlimited dimension + logical :: ishdf5 ! is underlying disk format HDF5? + logical :: isparallel ! was file opened for parallel I/O? + character(len=500) filename ! netCDF filename + ! array of Variable instances + type(Variable), allocatable, dimension(:) :: variables + ! array of Dimension instances + type(Dimension), allocatable, dimension(:) :: dimensions + end type Dataset + + interface read_vardata + module procedure read_vardata_1d_r4, read_vardata_2d_r4, read_vardata_3d_r4,& + read_vardata_4d_r4, read_vardata_5d_r4, & + read_vardata_1d_r8, read_vardata_2d_r8, read_vardata_3d_r8,& + read_vardata_4d_r8, read_vardata_5d_r8, & + read_vardata_1d_int, read_vardata_2d_int, & + read_vardata_3d_int, read_vardata_4d_int, read_vardata_5d_int, & + read_vardata_1d_short, read_vardata_2d_short, & + read_vardata_3d_short, read_vardata_4d_short, read_vardata_5d_short , & + read_vardata_1d_byte, read_vardata_2d_byte, & + read_vardata_3d_byte, read_vardata_4d_byte, read_vardata_5d_byte, & + read_vardata_1d_char, read_vardata_2d_char, & + read_vardata_3d_char, read_vardata_4d_char, read_vardata_5d_char + end interface + + interface write_vardata + module procedure write_vardata_1d_r4, write_vardata_2d_r4, write_vardata_3d_r4,& + write_vardata_4d_r4, write_vardata_1d_r8, write_vardata_2d_r8, write_vardata_3d_r8,& + write_vardata_4d_r8, write_vardata_1d_int, write_vardata_2d_int, & + write_vardata_3d_int, write_vardata_4d_int, & + write_vardata_5d_int, write_vardata_5d_r4, write_vardata_5d_r8, & + write_vardata_1d_short, write_vardata_2d_short, write_vardata_3d_short, & + write_vardata_4d_short, write_vardata_5d_short, & + write_vardata_1d_byte, write_vardata_2d_byte, write_vardata_3d_byte, & + write_vardata_4d_byte, write_vardata_5d_byte, & + write_vardata_1d_char, write_vardata_2d_char, write_vardata_3d_char, & + write_vardata_4d_char, write_vardata_5d_char + end interface + + interface read_attribute + module procedure read_attribute_r4_scalar, read_attribute_int_scalar,& + read_attribute_r8_scalar, read_attribute_r4_1d,& + read_attribute_int_1d, read_attribute_r8_1d, read_attribute_char, & + read_attribute_short_scalar, read_attribute_short_1d, & + read_attribute_byte_scalar, read_attribute_byte_1d + end interface + + interface write_attribute + module procedure write_attribute_r4_scalar, write_attribute_int_scalar,& + write_attribute_r8_scalar, write_attribute_r4_1d,& + write_attribute_int_1d, write_attribute_r8_1d, write_attribute_char, & + write_attribute_short_scalar, write_attribute_short_1d, & + write_attribute_byte_scalar, write_attribute_byte_1d + end interface + + interface quantize_data + module procedure quantize_data_2d, quantize_data_3d, quantize_data_4d + end interface + + public :: open_dataset, create_dataset, close_dataset, Dataset, Variable, Dimension, & + read_vardata, read_attribute, write_vardata, write_attribute, get_ndim, & + get_nvar, get_var, get_dim, get_idate_from_time_units, & + get_time_units_from_idate, quantize_data, has_var, has_attr + + contains + + subroutine nccheck(status,halt,fname) + ! check return code, print error message + implicit none + integer, intent (in) :: status + logical, intent(in), optional :: halt + character(len=500), intent(in), optional :: fname + logical stopit + if (present(halt)) then + stopit = halt + else + stopit = .true. + endif + if (status /= nf90_noerr) then + write(0,*) status, trim(nf90_strerror(status)) + if (present(fname)) then + write(0,*) trim(fname) + end if + if (stopit) stop 99 + end if + end subroutine nccheck + + function get_dim(dset, dimname) result(dim) + type(Dataset) :: dset + type(Dimension) :: dim + character(len=*), intent(in) :: dimname + integer ndim + ndim = get_ndim(dset, dimname) + dim = dset%dimensions(ndim) + end function get_dim + + integer function get_ndim(dset, dimname) + ! get dimension index given name + type(Dataset), intent(in) :: dset + character(len=*), intent(in) :: dimname + integer ndim + get_ndim = -1 + do ndim=1,dset%ndims + if (trim(dset%dimensions(ndim)%name) == trim(dimname)) then + get_ndim = ndim + exit + endif + enddo + end function get_ndim + + function get_var(dset, varname) result (var) + type(Dataset) :: dset + type(Variable) :: var + character(len=*) :: varname + integer nvar + nvar = get_nvar(dset, varname) + var = dset%variables(nvar) + end function get_var + + logical function has_var(dset, varname) + ! returns .true. is varname exists in dset, otherwise .false. + type(Dataset) :: dset + character(len=*) :: varname + integer nvar + nvar = get_nvar(dset, varname) + if (nvar > 0) then + has_var=.true. + else + has_var=.false. + endif + end function has_var + + logical function has_attr(dset, attname, varname) + ! returns .true. if attribute exists in dset, otherwise .false. + ! use optional kwarg varname to check for a variable attribute. + type(Dataset) :: dset + character(len=*) :: attname + character(len=*), optional :: varname + integer nvar, varid, ncerr + nvar = get_nvar(dset, varname) + if(present(varname))then + nvar = get_nvar(dset,varname) + if (nvar < 0) then + has_attr = .false. + return + endif + varid = dset%variables(nvar)%varid + else + varid = NF90_GLOBAL + endif + ncerr = nf90_inquire_attribute(dset%ncid, varid, attname) + if (ncerr /= 0) then + has_attr=.false. + else + has_attr=.true. + endif + end function has_attr + + integer function get_nvar(dset,varname) + ! get variable index given name + type(Dataset), intent(in) :: dset + character(len=*), intent(in) :: varname + integer nvar + get_nvar = -1 + do nvar=1,dset%nvars + if (trim(dset%variables(nvar)%name) == trim(varname)) then + get_nvar = nvar + exit + endif + enddo + end function get_nvar + + subroutine set_varunlimdimlens_(dset,errcode) + ! reset dimension length (dimlens) for unlim dim for all variables + type(Dataset), intent(inout) :: dset + integer, intent(out), optional :: errcode + integer ndim,n,nvar,ncerr + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + ! loop over all vars + do nvar=1,dset%nvars + ! does var have unlim dimension? + if (dset%variables(nvar)%hasunlim) then + ! loop over all var dimensions + do ndim=1,dset%variables(nvar)%ndims + n = dset%variables(nvar)%dimindxs(ndim) + ! n is the dimension index for this variable dimension + ! if this dim is unlimited, update dimlens entry + if (dset%dimensions(n)%isunlimited) then + ncerr = nf90_inquire_dimension(dset%ncid,& + dset%dimensions(n)%dimid, & + len=dset%variables(nvar)%dimlens(ndim)) + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + return + else + call nccheck(ncerr) + endif + ! also update len attribute of Dimension object + dset%dimensions(n)%len = dset%variables(nvar)%dimlens(ndim) + endif + enddo + endif + enddo + end subroutine set_varunlimdimlens_ + + function open_dataset(filename,errcode,paropen, mpicomm) result(dset) + ! open existing dataset, create dataset object for reading netcdf file + ! if optional error return code errcode is not specified, + ! program will stop if a nonzero error code returned by the netcdf lib. + implicit none + character(len=*), intent(in) :: filename + type(Dataset) :: dset + integer, intent(out), optional :: errcode + logical, intent(in), optional :: paropen + integer, intent(in), optional :: mpicomm + integer ncerr,nunlimdim,ndim,nvar,n,formatnum + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if (present(paropen)) then + if (paropen) then + dset%isparallel = .true. + else + dset%isparallel = .false. + end if + else + dset%isparallel = .false. + end if + ! open netcdf file, get info, populate Dataset object. + if (dset%isparallel) then + if (present(mpicomm)) then + ncerr = nf90_open(trim(filename), ior(NF90_NOWRITE, NF90_MPIIO), & + comm=mpicomm, info = mpi_info_null, ncid=dset%ncid) + else + ncerr = nf90_open(trim(filename), ior(NF90_NOWRITE, NF90_MPIIO), & + comm=mpi_comm_world, info = mpi_info_null, ncid=dset%ncid) + end if + else + ncerr = nf90_open(trim(filename), NF90_NOWRITE, ncid=dset%ncid) + end if + if (return_errcode) then + call nccheck(ncerr,halt=.false.,fname=filename) + errcode=ncerr + if (ncerr /= 0) return + else + call nccheck(ncerr,fname=filename) + endif + ncerr = nf90_inquire(dset%ncid, dset%ndims, dset%nvars, dset%natts, nunlimdim, formatnum=formatnum) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.,fname=filename) + if (ncerr /= 0) return + else + call nccheck(ncerr,fname=filename) + endif + if (formatnum == nf90_format_netcdf4 .or. formatnum == nf90_format_netcdf4_classic) then + dset%ishdf5 = .true. + else + dset%ishdf5 = .false. + endif + dset%filename = trim(filename) + allocate(dset%variables(dset%nvars)) + allocate(dset%dimensions(dset%ndims)) + do ndim=1,dset%ndims + dset%dimensions(ndim)%dimid = ndim + ncerr = nf90_inquire_dimension(dset%ncid, ndim, name=dset%dimensions(ndim)%name, & + len=dset%dimensions(ndim)%len) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.,fname=filename) + if (ncerr /= 0) return + else + call nccheck(ncerr,fname=filename) + endif + if (ndim == nunlimdim) then + dset%dimensions(ndim)%isunlimited = .true. + else + dset%dimensions(ndim)%isunlimited = .false. + endif + enddo + do nvar=1,dset%nvars + dset%variables(nvar)%hasunlim = .false. + dset%variables(nvar)%varid = nvar + ncerr = nf90_inquire_variable(dset%ncid, nvar,& + name=dset%variables(nvar)%name,& + natts=dset%variables(nvar)%natts,& + xtype=dset%variables(nvar)%dtype,& + ndims=dset%variables(nvar)%ndims) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.,fname=filename) + if (ncerr /= 0) return + else + call nccheck(ncerr,fname=filename) + endif + allocate(dset%variables(nvar)%dimids(dset%variables(nvar)%ndims)) + allocate(dset%variables(nvar)%dimindxs(dset%variables(nvar)%ndims)) + allocate(dset%variables(nvar)%dimlens(dset%variables(nvar)%ndims)) + allocate(dset%variables(nvar)%chunksizes(dset%variables(nvar)%ndims)) + allocate(dset%variables(nvar)%dimnames(dset%variables(nvar)%ndims)) + if (dset%ishdf5) then + ncerr = nf90_inquire_variable(dset%ncid, nvar,& + dimids=dset%variables(nvar)%dimids,& + deflate_level=dset%variables(nvar)%deflate_level,& + chunksizes=dset%variables(nvar)%chunksizes,& + shuffle=dset%variables(nvar)%shuffle) + else + ncerr = nf90_inquire_variable(dset%ncid, nvar,& + dimids=dset%variables(nvar)%dimids) + endif + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.,fname=filename) + if (ncerr /= 0) return + else + call nccheck(ncerr,fname=filename) + endif + do ndim=1,dset%variables(nvar)%ndims + do n=1,dset%ndims + if (dset%variables(nvar)%dimids(ndim) == dset%dimensions(n)%dimid) then + exit + endif + enddo + dset%variables(nvar)%dimindxs(ndim) = n + dset%variables(nvar)%dimlens(ndim) = dset%dimensions(n)%len + dset%variables(nvar)%dimnames(ndim) = dset%dimensions(n)%name + if (dset%dimensions(n)%isunlimited) then + dset%variables(nvar)%hasunlim = .true. + endif + enddo + enddo + end function open_dataset + + function create_dataset(filename, dsetin, copy_vardata, paropen, nocompress, mpicomm, errcode) result(dset) + ! create new dataset, using an existing dataset object to define + ! variables, dimensions and attributes. + ! If copy_vardata=T, all variable data (not just coordinate + ! variable data) is copied. Default is F (only coord var data + ! copied). + ! if optional nocompress=.true., outputfile will not use compression even if input file does + ! if optional error return code errcode is not specified, + ! program will stop if a nonzero error code returned by the netcdf lib. + implicit none + character(len=*), intent(in) :: filename + character(len=nf90_max_name) :: attname, varname + logical, intent(in), optional :: copy_vardata + type(Dataset) :: dset + type(Dataset), intent(in) :: dsetin + logical, intent(in), optional :: paropen + integer, intent(in), optional :: mpicomm + logical, intent(in), optional :: nocompress + integer, intent(out), optional :: errcode + integer ncerr,ndim,nvar,n,ishuffle,natt + logical copyd, coordvar, compress + real(8), allocatable, dimension(:) :: values_1d + real(8), allocatable, dimension(:,:) :: values_2d + real(8), allocatable, dimension(:,:,:) :: values_3d + real(8), allocatable, dimension(:,:,:,:) :: values_4d + real(8), allocatable, dimension(:,:,:,:,:) :: values_5d + integer, allocatable, dimension(:) :: ivalues_1d + integer, allocatable, dimension(:,:) :: ivalues_2d + integer, allocatable, dimension(:,:,:) :: ivalues_3d + integer, allocatable, dimension(:,:,:,:) :: ivalues_4d + integer, allocatable, dimension(:,:,:,:,:) :: ivalues_5d + character, allocatable, dimension(:) :: cvalues_1d + character, allocatable, dimension(:,:) :: cvalues_2d + character, allocatable, dimension(:,:,:) :: cvalues_3d + character, allocatable, dimension(:,:,:,:) :: cvalues_4d + character, allocatable, dimension(:,:,:,:,:) :: cvalues_5d + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if (present(copy_vardata)) then + copyd = .true. ! copy all variable data + else + copyd = .false. ! only copy coordinate variable data + endif + if (present(paropen)) then + if (paropen) then + dset%isparallel = .true. + else + dset%isparallel = .false. + end if + else + dset%isparallel = .false. + end if + compress = .true. + if (present(nocompress)) then + if (nocompress) then + compress = .false. + end if + end if + ! create netcdf file + if (dsetin%ishdf5) then + if (dset%isparallel) then + if (present(mpicomm)) then + ncerr = nf90_create(trim(filename), & + cmode=IOR(NF90_CLOBBER,NF90_NETCDF4), ncid=dset%ncid, & + comm = mpicomm, info = mpi_info_null) + else + ncerr = nf90_create(trim(filename), & + cmode=IOR(NF90_CLOBBER,NF90_NETCDF4), ncid=dset%ncid, & + comm = mpi_comm_world, info = mpi_info_null) + end if + else + ncerr = nf90_create(trim(filename), & + cmode=IOR(IOR(NF90_CLOBBER,NF90_NETCDF4),NF90_CLASSIC_MODEL), & + !cmode=IOR(NF90_CLOBBER,NF90_NETCDF4), & + ncid=dset%ncid) + end if + dset%ishdf5 = .true. + else + ncerr = nf90_create(trim(filename), & + cmode=IOR(IOR(NF90_CLOBBER,NF90_64BIT_OFFSET),NF90_SHARE), & + ncid=dset%ncid) + dset%ishdf5 = .false. + endif + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.,fname=filename) + if (ncerr /= 0) return + else + call nccheck(ncerr,fname=filename) + endif + ! copy global attributes + do natt=1,dsetin%natts + ncerr = nf90_inq_attname(dsetin%ncid, NF90_GLOBAL, natt, attname) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + ncerr = nf90_copy_att(dsetin%ncid, NF90_GLOBAL, attname, dset%ncid, NF90_GLOBAL) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + enddo + dset%natts = dsetin%natts + dset%filename = trim(filename) + dset%ndims = dsetin%ndims + dset%nvars = dsetin%nvars + allocate(dset%variables(dsetin%nvars)) + allocate(dset%dimensions(dsetin%ndims)) + ! create dimensions + do ndim=1,dsetin%ndims + if (dsetin%dimensions(ndim)%isunlimited) then + ncerr = nf90_def_dim(dset%ncid, trim(dsetin%dimensions(ndim)%name), & + NF90_UNLIMITED, & + dset%dimensions(ndim)%dimid) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + dset%dimensions(ndim)%isunlimited = .true. + dset%nunlimdim = ndim + dset%dimensions(ndim)%len = 0 + dset%dimensions(ndim)%name = trim(dsetin%dimensions(ndim)%name) + else + ncerr = nf90_def_dim(dset%ncid, trim(dsetin%dimensions(ndim)%name),& + dsetin%dimensions(ndim)%len, & + dset%dimensions(ndim)%dimid) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + dset%dimensions(ndim)%len = dsetin%dimensions(ndim)%len + dset%dimensions(ndim)%isunlimited = .false. + dset%dimensions(ndim)%name = trim(dsetin%dimensions(ndim)%name) + endif + enddo + ! create variables + do nvar=1,dsetin%nvars + dset%variables(nvar)%hasunlim = .false. + dset%variables(nvar)%ndims = dsetin%variables(nvar)%ndims + allocate(dset%variables(nvar)%dimids(dset%variables(nvar)%ndims)) + allocate(dset%variables(nvar)%dimindxs(dset%variables(nvar)%ndims)) + allocate(dset%variables(nvar)%dimnames(dset%variables(nvar)%ndims)) + allocate(dset%variables(nvar)%dimlens(dset%variables(nvar)%ndims)) + allocate(dset%variables(nvar)%chunksizes(dset%variables(nvar)%ndims)) + dset%variables(nvar)%chunksizes = dsetin%variables(nvar)%chunksizes + do ndim=1,dset%variables(nvar)%ndims + do n=1,dset%ndims + if (trim(dsetin%variables(nvar)%dimnames(ndim)) == & + trim(dset%dimensions(n)%name)) then + exit + endif + enddo + dset%variables(nvar)%dimindxs(ndim) = n + dset%variables(nvar)%dimids(ndim) = dset%dimensions(n)%dimid + dset%variables(nvar)%dimlens(ndim) = dset%dimensions(n)%len + dset%variables(nvar)%dimnames(ndim) = dset%dimensions(n)%name + if (dset%dimensions(n)%isunlimited) then + dset%variables(nvar)%hasunlim = .true. + endif + enddo + dset%variables(nvar)%name = dsetin%variables(nvar)%name + dset%variables(nvar)%dtype = dsetin%variables(nvar)%dtype + if (maxval(dset%variables(nvar)%chunksizes) > 0 .and. dset%ishdf5) then + ! workaround for older versions of netcdf-fortran that don't + ! like zero chunksize to be specified. + ncerr = nf90_def_var(dset%ncid, & + trim(dset%variables(nvar)%name),& + dset%variables(nvar)%dtype, & + dset%variables(nvar)%dimids, & + dset%variables(nvar)%varid, & + chunksizes=dset%variables(nvar)%chunksizes) + else + ncerr = nf90_def_var(dset%ncid, & + trim(dset%variables(nvar)%name),& + dset%variables(nvar)%dtype, & + dset%variables(nvar)%dimids, & + dset%variables(nvar)%varid) + endif + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + if (dsetin%variables(nvar)%deflate_level > 0 .and. dset%ishdf5 .and. compress) then + if (dsetin%variables(nvar)%shuffle) then + ishuffle=1 + else + ishuffle=0 + endif + ncerr = nf90_def_var_deflate(dset%ncid, dset%variables(nvar)%varid,& + ishuffle,1,dsetin%variables(nvar)%deflate_level) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + dset%variables(nvar)%shuffle = dsetin%variables(nvar)%shuffle + dset%variables(nvar)%deflate_level = & + dsetin%variables(nvar)%deflate_level + endif + ! copy variable attributes + do natt=1,dsetin%variables(nvar)%natts + ncerr = nf90_inq_attname(dsetin%ncid, dsetin%variables(nvar)%varid, natt, attname) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + if (.not. compress) then + if (trim(attname) == 'max_abs_compression_error' & + .or. trim(attname) == 'nbits') then + cycle + end if + end if + ncerr = nf90_copy_att(dsetin%ncid, dsetin%variables(nvar)%varid, attname, dset%ncid, dset%variables(nvar)%varid) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + enddo + enddo + ncerr = nf90_enddef(dset%ncid) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + ! copy variable data + ! assumes data is real (32 or 64 bit), or integer (16 or 32 bit) and 1-4d. + do nvar=1,dsetin%nvars + varname = trim(dsetin%variables(nvar)%name) + ! is this variable a coordinate variable? + coordvar = .false. + if (trim(varname) == 'lats' .or. trim(varname) == 'lons' .or. & + trim(varname) == 'lat' .or. trim(varname) == 'lon') then + coordvar = .true. + else + do ndim=1,dset%ndims + if (trim(varname) == trim(dset%dimensions(ndim)%name)) then + coordvar = .true. + endif + enddo + endif + ! if copy_data flag not given, and not a coordinate var, + ! skip to next var. + if (.not. coordvar .and. .not. copyd) cycle + ! real variable + if (dsetin%variables(nvar)%dtype == NF90_FLOAT .or.& + dsetin%variables(nvar)%dtype == NF90_DOUBLE) then + if (dsetin%variables(nvar)%ndims == 1) then + call read_vardata(dsetin, varname, values_1d) + call write_vardata(dset, varname, values_1d) + else if (dsetin%variables(nvar)%ndims == 2) then + call read_vardata(dsetin, varname, values_2d) + call write_vardata(dset, varname, values_2d) + else if (dsetin%variables(nvar)%ndims == 3) then + call read_vardata(dsetin, varname, values_3d) + call write_vardata(dset, varname, values_3d) + else if (dsetin%variables(nvar)%ndims == 4) then + call read_vardata(dsetin, varname, values_4d) + call write_vardata(dset, varname, values_4d) + else if (dsetin%variables(nvar)%ndims == 5) then + call read_vardata(dsetin, varname, values_5d) + call write_vardata(dset, varname, values_5d) + endif + ! integer var + elseif (dsetin%variables(nvar)%dtype == NF90_INT .or.& + dsetin%variables(nvar)%dtype == NF90_BYTE .or.& + dsetin%variables(nvar)%dtype == NF90_SHORT) then + if (dsetin%variables(nvar)%ndims == 1) then + call read_vardata(dsetin, varname, ivalues_1d) + call write_vardata(dset, varname, ivalues_1d) + else if (dsetin%variables(nvar)%ndims == 2) then + call read_vardata(dsetin, varname, ivalues_2d) + call write_vardata(dset, varname, ivalues_2d) + else if (dsetin%variables(nvar)%ndims == 3) then + call read_vardata(dsetin, varname, ivalues_3d) + call write_vardata(dset, varname, ivalues_3d) + else if (dsetin%variables(nvar)%ndims == 4) then + call read_vardata(dsetin, varname, ivalues_4d) + call write_vardata(dset, varname, ivalues_4d) + else if (dsetin%variables(nvar)%ndims == 5) then + call read_vardata(dsetin, varname, ivalues_5d) + call write_vardata(dset, varname, ivalues_5d) + endif + elseif (dsetin%variables(nvar)%dtype == NF90_CHAR) then + if (dsetin%variables(nvar)%ndims == 1) then + call read_vardata(dsetin, varname, cvalues_1d) + call write_vardata(dset, varname, cvalues_1d) + else if (dsetin%variables(nvar)%ndims == 2) then + call read_vardata(dsetin, varname, cvalues_2d) + call write_vardata(dset, varname, cvalues_2d) + else if (dsetin%variables(nvar)%ndims == 3) then + call read_vardata(dsetin, varname, cvalues_3d) + call write_vardata(dset, varname, cvalues_3d) + else if (dsetin%variables(nvar)%ndims == 4) then + call read_vardata(dsetin, varname, cvalues_4d) + call write_vardata(dset, varname, cvalues_4d) + else if (dsetin%variables(nvar)%ndims == 5) then + call read_vardata(dsetin, varname, cvalues_5d) + call write_vardata(dset, varname, cvalues_5d) + endif + else + print *,'not copying variable ',trim(adjustl(varname)),& + ' (unsupported data type or rank)' + endif + enddo + end function create_dataset + + subroutine close_dataset(dset,errcode) + ! close netcdf file, deallocate members of dataset object. + ! if optional error return code errcode is not specified, + ! program will stop if a nonzero error code returned by the netcdf lib. + type(Dataset), intent(inout) :: dset + integer, intent(out), optional :: errcode + integer ncerr, nvar + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + ncerr = nf90_close(ncid=dset%ncid) + if (return_errcode) then + errcode=ncerr + call nccheck(ncerr,halt=.false.) + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + do nvar=1,dset%nvars + deallocate(dset%variables(nvar)%dimids) + deallocate(dset%variables(nvar)%dimindxs) + deallocate(dset%variables(nvar)%dimlens) + deallocate(dset%variables(nvar)%chunksizes) + deallocate(dset%variables(nvar)%dimnames) + enddo + deallocate(dset%variables,dset%dimensions) + end subroutine close_dataset + + !subroutine read_vardata(dset,varname,values,nslice,slicedim,errcode) + ! read data from variable varname in dataset dset, return in it array values. + ! dset: Input dataset instance returned by open_dataset/create_dataset. + ! varname: Input string name of variable. + ! values: Array to hold variable data. Must be + ! an allocatable array with same rank + ! as variable varname (or 1 dimension less). + ! nslice: optional index along dimension slicedim + ! slicedim: optional, if nslice is set, index of which dimension to slice with + ! nslice, default is ndims + ! ncstart: optional, if ncstart and nccount are set, manually specify the + ! start and count of netCDF read + ! nccount: optional, if ncstart and nccount are set, manually specify the + ! start and count of netCDF read + ! errcode: optional error return code. If not specified, + ! program will stop if a nonzero error code returned + ! from netcdf library. + + !subroutine write_vardata(dset,varname,values,nslice,slicedim,errcode) + ! write data (in array values) to variable varname in dataset dset. + ! dset: Input dataset instance returned by open_dataset/create_dataset. + ! varname: Input string name of variable. + ! values: Array with variable data. Must be + ! an allocatable array with same rank + ! as variable varname (or 1 dimension less). + ! nslice: optional index along dimension slicedim + ! slicedim: optional, if nslice is set, index of which dimension to slice with + ! nslice, default is ndims + ! ncstart: optional, if ncstart and nccount are set, manually specify the + ! start and count of netCDF write + ! nccount: optional, if ncstart and nccount are set, manually specify the + ! start and count of netCDF write + ! errcode: optional error return code. If not specified, + ! program will stop if a nonzero error code returned + ! from netcdf library. + + !subroutine read_attribute(dset, attname, values, varname, errcode) + ! read attribute 'attname' return in 'values'. If optional + ! argument 'varname' is given, a variable attribute is returned. + ! if the attribute is a 1d array, values should be an allocatable 1d + ! array of the correct type. + + !subroutine write_attribute(dset, attname, values, varname, errcode) + ! write attribute 'attname' with data in 'values'. If optional + ! argument 'varname' is given, a variable attribute is written. + ! values can be a real(4), real(8), integer, string or 1d array. + + subroutine read_vardata_1d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), allocatable, dimension(:), intent(inout) :: values + include "read_vardata_code_1d.f90" + end subroutine read_vardata_1d_r4 + + subroutine read_vardata_2d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), allocatable, dimension(:,:), intent(inout) :: values + include "read_vardata_code_2d.f90" + end subroutine read_vardata_2d_r4 + + subroutine read_vardata_3d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), allocatable, dimension(:,:,:), intent(inout) :: values + include "read_vardata_code_3d.f90" + end subroutine read_vardata_3d_r4 + + subroutine read_vardata_4d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), allocatable, dimension(:,:,:,:), intent(inout) :: values + include "read_vardata_code_4d.f90" + end subroutine read_vardata_4d_r4 + + subroutine read_vardata_5d_r4(dset, varname, values, errcode) + real(4), allocatable, dimension(:,:,:,:,:), intent(inout) :: values + include "read_vardata_code_5d.f90" + end subroutine read_vardata_5d_r4 + + subroutine read_vardata_1d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), allocatable, dimension(:), intent(inout) :: values + include "read_vardata_code_1d.f90" + end subroutine read_vardata_1d_r8 + + subroutine read_vardata_2d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), allocatable, dimension(:,:), intent(inout) :: values + include "read_vardata_code_2d.f90" + end subroutine read_vardata_2d_r8 + + subroutine read_vardata_3d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), allocatable, dimension(:,:,:), intent(inout) :: values + include "read_vardata_code_3d.f90" + end subroutine read_vardata_3d_r8 + + subroutine read_vardata_4d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), allocatable, dimension(:,:,:,:), intent(inout) :: values + include "read_vardata_code_4d.f90" + end subroutine read_vardata_4d_r8 + + subroutine read_vardata_5d_r8(dset, varname, values, errcode) + real(8), allocatable, dimension(:,:,:,:,:), intent(inout) :: values + include "read_vardata_code_5d.f90" + end subroutine read_vardata_5d_r8 + + subroutine read_vardata_1d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, allocatable, dimension(:), intent(inout) :: values + include "read_vardata_code_1d.f90" + end subroutine read_vardata_1d_int + + subroutine read_vardata_2d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, allocatable, dimension(:,:), intent(inout) :: values + include "read_vardata_code_2d.f90" + end subroutine read_vardata_2d_int + + subroutine read_vardata_3d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, allocatable, dimension(:,:,:), intent(inout) :: values + include "read_vardata_code_3d.f90" + end subroutine read_vardata_3d_int + + subroutine read_vardata_4d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, allocatable, dimension(:,:,:,:), intent(inout) :: values + include "read_vardata_code_4d.f90" + end subroutine read_vardata_4d_int + + subroutine read_vardata_5d_int(dset, varname, values, errcode) + integer, allocatable, dimension(:,:,:,:,:), intent(inout) :: values + include "read_vardata_code_5d.f90" + end subroutine read_vardata_5d_int + + subroutine read_vardata_1d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), allocatable, dimension(:), intent(inout) :: values + include "read_vardata_code_1d.f90" + end subroutine read_vardata_1d_short + + subroutine read_vardata_2d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), allocatable, dimension(:,:), intent(inout) :: values + include "read_vardata_code_2d.f90" + end subroutine read_vardata_2d_short + + subroutine read_vardata_3d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), allocatable, dimension(:,:,:), intent(inout) :: values + include "read_vardata_code_3d.f90" + end subroutine read_vardata_3d_short + + subroutine read_vardata_4d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), allocatable, dimension(:,:,:,:), intent(inout) :: values + include "read_vardata_code_4d.f90" + end subroutine read_vardata_4d_short + + subroutine read_vardata_5d_short(dset, varname, values, errcode) + integer(2), allocatable, dimension(:,:,:,:,:), intent(inout) :: values + include "read_vardata_code_5d.f90" + end subroutine read_vardata_5d_short + + subroutine read_vardata_1d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), allocatable, dimension(:), intent(inout) :: values + include "read_vardata_code_1d.f90" + end subroutine read_vardata_1d_byte + + subroutine read_vardata_2d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), allocatable, dimension(:,:), intent(inout) :: values + include "read_vardata_code_2d.f90" + end subroutine read_vardata_2d_byte + + subroutine read_vardata_3d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), allocatable, dimension(:,:,:), intent(inout) :: values + include "read_vardata_code_3d.f90" + end subroutine read_vardata_3d_byte + + subroutine read_vardata_4d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), allocatable, dimension(:,:,:,:), intent(inout) :: values + include "read_vardata_code_4d.f90" + end subroutine read_vardata_4d_byte + + subroutine read_vardata_5d_byte(dset, varname, values, errcode) + integer(1), allocatable, dimension(:,:,:,:,:), intent(inout) :: values + include "read_vardata_code_5d.f90" + end subroutine read_vardata_5d_byte + + subroutine read_vardata_1d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, allocatable, dimension(:), intent(inout) :: values + include "read_vardata_code_1d.f90" + end subroutine read_vardata_1d_char + + subroutine read_vardata_2d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, allocatable, dimension(:,:), intent(inout) :: values + include "read_vardata_code_2d.f90" + end subroutine read_vardata_2d_char + + subroutine read_vardata_3d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, allocatable, dimension(:,:,:), intent(inout) :: values + include "read_vardata_code_3d.f90" + end subroutine read_vardata_3d_char + + subroutine read_vardata_4d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, allocatable, dimension(:,:,:,:), intent(inout) :: values + include "read_vardata_code_4d.f90" + end subroutine read_vardata_4d_char + + subroutine read_vardata_5d_char(dset, varname, values, errcode) + character, allocatable, dimension(:,:,:,:,:), intent(inout) :: values + include "read_vardata_code_5d.f90" + end subroutine read_vardata_5d_char + + subroutine write_vardata_1d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), dimension(:), intent(in) :: values + integer, intent(in), optional :: ncstart(1) + integer, intent(in), optional :: nccount(1) + include "write_vardata_code.f90" + end subroutine write_vardata_1d_r4 + + subroutine write_vardata_2d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), dimension(:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(2) + integer, intent(in), optional :: nccount(2) + include "write_vardata_code.f90" + end subroutine write_vardata_2d_r4 + + subroutine write_vardata_3d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), dimension(:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(3) + integer, intent(in), optional :: nccount(3) + include "write_vardata_code.f90" + end subroutine write_vardata_3d_r4 + + subroutine write_vardata_4d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), dimension(:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(4) + integer, intent(in), optional :: nccount(4) + include "write_vardata_code.f90" + end subroutine write_vardata_4d_r4 + + subroutine write_vardata_5d_r4(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(4), dimension(:,:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(5) + integer, intent(in), optional :: nccount(5) + include "write_vardata_code.f90" + end subroutine write_vardata_5d_r4 + + subroutine write_vardata_1d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), dimension(:), intent(in) :: values + integer, intent(in), optional :: ncstart(1) + integer, intent(in), optional :: nccount(1) + include "write_vardata_code.f90" + end subroutine write_vardata_1d_r8 + + subroutine write_vardata_2d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), dimension(:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(2) + integer, intent(in), optional :: nccount(2) + include "write_vardata_code.f90" + end subroutine write_vardata_2d_r8 + + subroutine write_vardata_3d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), dimension(:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(3) + integer, intent(in), optional :: nccount(3) + include "write_vardata_code.f90" + end subroutine write_vardata_3d_r8 + + subroutine write_vardata_4d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), dimension(:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(4) + integer, intent(in), optional :: nccount(4) + include "write_vardata_code.f90" + end subroutine write_vardata_4d_r8 + + subroutine write_vardata_5d_r8(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + real(8), dimension(:,:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(5) + integer, intent(in), optional :: nccount(5) + include "write_vardata_code.f90" + end subroutine write_vardata_5d_r8 + + subroutine write_vardata_1d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, dimension(:), intent(in) :: values + integer, intent(in), optional :: ncstart(1) + integer, intent(in), optional :: nccount(1) + include "write_vardata_code.f90" + end subroutine write_vardata_1d_int + + subroutine write_vardata_2d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, dimension(:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(2) + integer, intent(in), optional :: nccount(2) + include "write_vardata_code.f90" + end subroutine write_vardata_2d_int + + subroutine write_vardata_3d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, dimension(:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(3) + integer, intent(in), optional :: nccount(3) + include "write_vardata_code.f90" + end subroutine write_vardata_3d_int + + subroutine write_vardata_4d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, dimension(:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(4) + integer, intent(in), optional :: nccount(4) + include "write_vardata_code.f90" + end subroutine write_vardata_4d_int + + subroutine write_vardata_5d_int(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer, dimension(:,:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(5) + integer, intent(in), optional :: nccount(5) + include "write_vardata_code.f90" + end subroutine write_vardata_5d_int + + subroutine write_vardata_1d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), dimension(:), intent(in) :: values + integer, intent(in), optional :: ncstart(1) + integer, intent(in), optional :: nccount(1) + include "write_vardata_code.f90" + end subroutine write_vardata_1d_short + + subroutine write_vardata_2d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), dimension(:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(2) + integer, intent(in), optional :: nccount(2) + include "write_vardata_code.f90" + end subroutine write_vardata_2d_short + + subroutine write_vardata_3d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), dimension(:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(3) + integer, intent(in), optional :: nccount(3) + include "write_vardata_code.f90" + end subroutine write_vardata_3d_short + + subroutine write_vardata_4d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), dimension(:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(4) + integer, intent(in), optional :: nccount(4) + include "write_vardata_code.f90" + end subroutine write_vardata_4d_short + + subroutine write_vardata_5d_short(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(2), dimension(:,:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(5) + integer, intent(in), optional :: nccount(5) + include "write_vardata_code.f90" + end subroutine write_vardata_5d_short + + subroutine write_vardata_1d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), dimension(:), intent(in) :: values + integer, intent(in), optional :: ncstart(1) + integer, intent(in), optional :: nccount(1) + include "write_vardata_code.f90" + end subroutine write_vardata_1d_byte + + subroutine write_vardata_2d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), dimension(:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(2) + integer, intent(in), optional :: nccount(2) + include "write_vardata_code.f90" + end subroutine write_vardata_2d_byte + + subroutine write_vardata_3d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), dimension(:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(3) + integer, intent(in), optional :: nccount(3) + include "write_vardata_code.f90" + end subroutine write_vardata_3d_byte + + subroutine write_vardata_4d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), dimension(:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(4) + integer, intent(in), optional :: nccount(4) + include "write_vardata_code.f90" + end subroutine write_vardata_4d_byte + + subroutine write_vardata_5d_byte(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + integer(1), dimension(:,:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(5) + integer, intent(in), optional :: nccount(5) + include "write_vardata_code.f90" + end subroutine write_vardata_5d_byte + + subroutine write_vardata_1d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, dimension(:), intent(in) :: values + integer, intent(in), optional :: ncstart(1) + integer, intent(in), optional :: nccount(1) + include "write_vardata_code.f90" + end subroutine write_vardata_1d_char + + subroutine write_vardata_2d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, dimension(:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(2) + integer, intent(in), optional :: nccount(2) + include "write_vardata_code.f90" + end subroutine write_vardata_2d_char + + subroutine write_vardata_3d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, dimension(:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(3) + integer, intent(in), optional :: nccount(3) + include "write_vardata_code.f90" + end subroutine write_vardata_3d_char + + subroutine write_vardata_4d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, dimension(:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(4) + integer, intent(in), optional :: nccount(4) + include "write_vardata_code.f90" + end subroutine write_vardata_4d_char + + subroutine write_vardata_5d_char(dset, varname, values, nslice, slicedim, ncstart, nccount, errcode) + character, dimension(:,:,:,:,:), intent(in) :: values + integer, intent(in), optional :: ncstart(5) + integer, intent(in), optional :: nccount(5) + include "write_vardata_code.f90" + end subroutine write_vardata_5d_char + + subroutine read_attribute_int_scalar(dset, attname, values, varname, errcode) + integer, intent(inout) :: values + include "read_scalar_attribute_code.f90" + end subroutine read_attribute_int_scalar + + subroutine read_attribute_short_scalar(dset, attname, values, varname, errcode) + integer(2), intent(inout) :: values + include "read_scalar_attribute_code.f90" + end subroutine read_attribute_short_scalar + + subroutine read_attribute_byte_scalar(dset, attname, values, varname, errcode) + integer(1), intent(inout) :: values + include "read_scalar_attribute_code.f90" + end subroutine read_attribute_byte_scalar + + subroutine read_attribute_r4_scalar(dset, attname, values, varname, errcode) + real(4), intent(inout) :: values + include "read_scalar_attribute_code.f90" + end subroutine read_attribute_r4_scalar + + subroutine read_attribute_r8_scalar(dset, attname, values, varname, errcode) + real(8), intent(inout) :: values + include "read_scalar_attribute_code.f90" + end subroutine read_attribute_r8_scalar + + subroutine read_attribute_r4_1d(dset, attname, values, varname, errcode) + real(4), intent(inout), allocatable, dimension(:) :: values + include "read_attribute_code.f90" + end subroutine read_attribute_r4_1d + + subroutine read_attribute_r8_1d(dset, attname, values, varname, errcode) + real(8), intent(inout), allocatable, dimension(:) :: values + include "read_attribute_code.f90" + end subroutine read_attribute_r8_1d + + subroutine read_attribute_int_1d(dset, attname, values, varname, errcode) + integer, intent(inout), allocatable, dimension(:) :: values + include "read_attribute_code.f90" + end subroutine read_attribute_int_1d + + subroutine read_attribute_short_1d(dset, attname, values, varname, errcode) + integer(2), intent(inout), allocatable, dimension(:) :: values + include "read_attribute_code.f90" + end subroutine read_attribute_short_1d + + subroutine read_attribute_byte_1d(dset, attname, values, varname, errcode) + integer(1), intent(inout), allocatable, dimension(:) :: values + include "read_attribute_code.f90" + end subroutine read_attribute_byte_1d + + subroutine read_attribute_char(dset, attname, values, varname, errcode) + character(len=*), intent(inout) :: values + include "read_scalar_attribute_code.f90" + end subroutine read_attribute_char + + subroutine write_attribute_int_scalar(dset, attname, values, varname, errcode) + integer, intent(in) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_int_scalar + + subroutine write_attribute_short_scalar(dset, attname, values, varname, errcode) + integer(2), intent(in) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_short_scalar + + subroutine write_attribute_byte_scalar(dset, attname, values, varname, errcode) + integer(1), intent(in) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_byte_scalar + + subroutine write_attribute_r4_scalar(dset, attname, values, varname, errcode) + real(4), intent(in) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_r4_scalar + + subroutine write_attribute_r8_scalar(dset, attname, values, varname, errcode) + real(8), intent(in) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_r8_scalar + + subroutine write_attribute_r4_1d(dset, attname, values, varname, errcode) + real(4), intent(in), allocatable, dimension(:) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_r4_1d + + subroutine write_attribute_r8_1d(dset, attname, values, varname, errcode) + real(8), intent(in), allocatable, dimension(:) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_r8_1d + + subroutine write_attribute_int_1d(dset, attname, values, varname, errcode) + integer, intent(in), allocatable, dimension(:) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_int_1d + + subroutine write_attribute_short_1d(dset, attname, values, varname, errcode) + integer(2), intent(in), allocatable, dimension(:) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_short_1d + + subroutine write_attribute_byte_1d(dset, attname, values, varname, errcode) + integer(1), intent(in), allocatable, dimension(:) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_byte_1d + + subroutine write_attribute_char(dset, attname, values, varname, errcode) + character(len=*), intent(in) :: values + include "write_attribute_code.f90" + end subroutine write_attribute_char + + function get_idate_from_time_units(dset) result(idate) + ! return integer array with year,month,day,hour,minute,second + ! parsed from time units attribute. + type(Dataset), intent(in) :: dset + integer idate(6) + character(len=nf90_max_name) :: time_units + integer ipos1,ipos2 + call read_attribute(dset, 'units', time_units, 'time') + ipos1 = scan(time_units,"since",back=.true.)+1 + ipos2 = scan(time_units,"-",back=.false.)-1 + read(time_units(ipos1:ipos2),*) idate(1) + ipos1 = ipos2+2; ipos2=ipos1+1 + read(time_units(ipos1:ipos2),*) idate(2) + ipos1 = ipos2+2; ipos2=ipos1+1 + read(time_units(ipos1:ipos2),*) idate(3) + ipos1 = scan(time_units,":")-2 + ipos2 = ipos1+1 + read(time_units(ipos1:ipos2),*) idate(4) + ipos1 = ipos2+2 + ipos2 = ipos1+1 + read(time_units(ipos1:ipos2),*) idate(5) + ipos1 = ipos2+2 + ipos2 = ipos1+1 + read(time_units(ipos1:ipos2),*) idate(6) + end function get_idate_from_time_units + + function get_time_units_from_idate(idate, time_measure) result(time_units) + ! create time units attribute of form 'hours since YYYY-MM-DD HH:MM:SS' + ! from integer array with year,month,day,hour,minute,second + ! optional argument 'time_measure' can be used to change 'hours' to + ! 'days', 'minutes', 'seconds' etc. + character(len=*), intent(in), optional :: time_measure + integer, intent(in) :: idate(6) + character(len=12) :: timechar + character(len=nf90_max_name) :: time_units + if (present(time_measure)) then + timechar = trim(time_measure) + else + timechar = 'hours' + endif + write(time_units,101) idate +101 format(' since ',i4.4,'-',i2.2,'-',i2.2,' ',& + i2.2,':',i2.2,':',i2.2) + time_units = trim(adjustl(timechar))//time_units + end function get_time_units_from_idate + + subroutine quantize_data_2d(dataIn, dataOut, nbits, compress_err) + real(4), intent(in) :: dataIn(:,:) + real(4), intent(out) :: dataOut(:,:) + include "quantize_data_code.f90" + end subroutine quantize_data_2d + + subroutine quantize_data_3d(dataIn, dataOut, nbits, compress_err) + real(4), intent(in) :: dataIn(:,:,:) + real(4), intent(out) :: dataOut(:,:,:) + include "quantize_data_code.f90" + end subroutine quantize_data_3d + + subroutine quantize_data_4d(dataIn, dataOut, nbits, compress_err) + real(4), intent(in) :: dataIn(:,:,:,:) + real(4), intent(out) :: dataOut(:,:,:,:) + include "quantize_data_code.f90" + end subroutine quantize_data_4d + +end module module_fv3gfs_ncio diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/quantize_data_code.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/quantize_data_code.f90 new file mode 100644 index 0000000000..ece0f77463 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/quantize_data_code.f90 @@ -0,0 +1,17 @@ + integer, intent(in) :: nbits + real(4), intent(out) :: compress_err + real(4) dataMin, dataMax, scale_fact, offset + ! if nbits not between 1 and 31, don't do anything + if (nbits <= 0 .or. nbits > 31) then + dataOut = dataIn + compress_err = 0.0 + return + endif + dataMax = maxval(dataIn); dataMin = minval(dataIn) + ! convert data to 32 bit integers in range 0 to 2**nbits-1, then cast + ! cast back to 32 bit floats (data is then quantized in steps + ! proportional to 2**nbits so last 32-nbits in floating + ! point representation should be zero for efficient zlib compression). + scale_fact = (dataMax - dataMin) / (2**nbits-1); offset = dataMin + dataOut = scale_fact*(nint((dataIn - offset) / scale_fact)) + offset + compress_err = maxval(abs(dataIn-dataOut)) diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_attribute_code.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_attribute_code.f90 new file mode 100644 index 0000000000..6a0bcffcd5 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_attribute_code.f90 @@ -0,0 +1,35 @@ + type(Dataset), intent(in) :: dset + character(len=*), intent(in), optional :: varname + character(len=*), intent(in) :: attname + integer, intent(out), optional :: errcode + integer ncerr, varid, nvar, nlen + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if(present(varname))then + nvar = get_nvar(dset,varname) + varid = dset%variables(nvar)%varid + else + varid = NF90_GLOBAL + endif + ncerr = nf90_inquire_attribute(dset%ncid, varid, attname, len=nlen) + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + if (allocated(values)) deallocate(values) + allocate(values(nlen)) + ncerr = nf90_get_att(dset%ncid, varid, trim(attname), values) + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + else + call nccheck(ncerr) + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_scalar_attribute_code.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_scalar_attribute_code.f90 new file mode 100644 index 0000000000..2b8c6ce046 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_scalar_attribute_code.f90 @@ -0,0 +1,31 @@ + ! read attribute 'attname' return in 'values'. If optional + ! argument 'varname' is given, an variable attribute is returned. + ! if the attribute is an 1d array, values should be an allocatable 1d + ! array of the correct type. if values is allocated, it be deallocated + ! and reallocated. + type(Dataset), intent(in) :: dset + character(len=*), intent(in), optional :: varname + integer, intent(out), optional :: errcode + character(len=*), intent(in) :: attname + integer ncerr, varid, nvar + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if(present(varname))then + nvar = get_nvar(dset,varname) + varid = dset%variables(nvar)%varid + else + varid = NF90_GLOBAL + endif + ncerr = nf90_get_att(dset%ncid, varid, trim(attname), values) + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + return + else + call nccheck(ncerr) + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_1d.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_1d.f90 new file mode 100644 index 0000000000..1a92b7fc16 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_1d.f90 @@ -0,0 +1,75 @@ + type(Dataset), intent(in) :: dset + character(len=*), intent(in) :: varname + integer, intent(in), optional :: nslice + integer, intent(in), optional :: slicedim + integer, intent(in), optional :: ncstart(1) + integer, intent(in), optional :: nccount(1) + integer, intent(out), optional :: errcode + integer ncerr, nvar, n, nd, dimlen, ncount + integer, allocatable, dimension(:) :: start, count + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if (present(nslice)) then + ncount = nslice + else + ncount = 1 + endif + nvar = get_nvar(dset,varname) + allocate(start(dset%variables(nvar)%ndims),count(dset%variables(nvar)%ndims)) + start(:) = 1 + count(:) = 1 + if (present(slicedim)) then + nd = slicedim + else + nd = dset%variables(nvar)%ndims + end if + do n=1,dset%variables(nvar)%ndims + if (n == nd) then + start(n) = ncount + count(n) = 1 + else + start(n) = 1 + count(n) = dset%variables(nvar)%dimlens(n) + dimlen = dset%variables(nvar)%dimlens(n) + end if + end do + if (dset%variables(nvar)%ndims /= 1 .and. dset%variables(nvar)%ndims /= 2) then + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=nf90_ebaddim + return + else + print *,'rank of data array != variable ndims (or ndims-1)' + stop 99 + endif + endif + if (allocated(values)) deallocate(values) + if (present(ncstart) .and. present(nccount)) then + allocate(values(nccount(1))) + start(1)=ncstart(1); count(1)=nccount(1) + if (dset%variables(nvar)%ndims == 2) then + start(2)=1; count(2)=1 + end if + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values,& + start=start, count=count) + else + if (dset%variables(nvar)%ndims == 2) then + allocate(values(dimlen)) + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values,& + start=start, count=count) + else + allocate(values(dset%variables(nvar)%dimlens(1))) + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values) + end if + end if + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + else + call nccheck(ncerr) + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_2d.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_2d.f90 new file mode 100644 index 0000000000..c0e62a6abb --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_2d.f90 @@ -0,0 +1,81 @@ + type(Dataset), intent(in) :: dset + character(len=*), intent(in) :: varname + integer, intent(in), optional :: nslice + integer, intent(in), optional :: slicedim + integer, intent(in), optional :: ncstart(2) + integer, intent(in), optional :: nccount(2) + integer, intent(out), optional :: errcode + integer ncerr, nvar, n, nd, ndim, ncount + integer, allocatable, dimension(:) :: start, count + integer :: dimlens(2) + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if (present(nslice)) then + ncount = nslice + else + ncount = 1 + endif + nvar = get_nvar(dset,varname) + allocate(start(dset%variables(nvar)%ndims),count(dset%variables(nvar)%ndims)) + start(:) = 1 + count(:) = 1 + dimlens(:) = 1 + if (present(slicedim)) then + nd = slicedim + else + nd = dset%variables(nvar)%ndims + end if + ndim = 1 + do n=1,dset%variables(nvar)%ndims + if (n == nd) then + start(n) = ncount + count(n) = 1 + else + start(n) = 1 + count(n) = dset%variables(nvar)%dimlens(n) + dimlens(ndim) = dset%variables(nvar)%dimlens(n) + ndim = ndim + 1 + end if + end do + + if (dset%variables(nvar)%ndims /= 2 .and. dset%variables(nvar)%ndims /= 3) then + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=nf90_ebaddim + return + else + print *,'rank of data array != variable ndims (or ndims-1)' + stop 99 + endif + endif + if (allocated(values)) deallocate(values) + if (present(ncstart) .and. present(nccount)) then + allocate(values(nccount(1),nccount(2))) + start(1)=ncstart(1); count(1)=nccount(1) + start(2)=ncstart(2); count(2)=nccount(2) + if (dset%variables(nvar)%ndims == 3) then + start(3)=1; count(3)=1 + end if + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values,& + start=start, count=count) + else + if (dset%variables(nvar)%ndims == 3) then + allocate(values(dimlens(1),dimlens(2))) + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values,& + start=start, count=count) + else + allocate(values(dset%variables(nvar)%dimlens(1),dset%variables(nvar)%dimlens(2))) + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values) + end if + end if + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + else + call nccheck(ncerr) + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_3d.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_3d.f90 new file mode 100644 index 0000000000..cc426b2361 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_3d.f90 @@ -0,0 +1,85 @@ + type(Dataset), intent(in) :: dset + character(len=*), intent(in) :: varname + integer, intent(in), optional :: nslice + integer, intent(in), optional :: slicedim + integer, intent(in), optional :: ncstart(3) + integer, intent(in), optional :: nccount(3) + integer, intent(out), optional :: errcode + integer ncerr, nvar, n, nd, ndim, ncount + integer, allocatable, dimension(:) :: start, count + integer :: dimlens(3) + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if (present(nslice)) then + ncount = nslice + else + ncount = 1 + endif + nvar = get_nvar(dset,varname) + allocate(start(dset%variables(nvar)%ndims),count(dset%variables(nvar)%ndims)) + start(:) = 1 + count(:) = 1 + dimlens(:) = 1 + if (present(slicedim)) then + nd = slicedim + else + nd = dset%variables(nvar)%ndims + end if + ndim = 1 + do n=1,dset%variables(nvar)%ndims + if (n == nd) then + start(n) = ncount + count(n) = 1 + else + start(n) = 1 + count(n) = dset%variables(nvar)%dimlens(n) + dimlens(ndim) = dset%variables(nvar)%dimlens(n) + ndim = ndim + 1 + end if + end do + + if (dset%variables(nvar)%ndims /= 3 .and. dset%variables(nvar)%ndims /= 4) then + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=nf90_ebaddim + return + else + print *,'rank of data array != variable ndims (or ndims-1)' + stop 99 + endif + endif + + if (allocated(values)) deallocate(values) + if (present(ncstart) .and. present(nccount)) then + allocate(values(nccount(1),nccount(2),nccount(3))) + start(1)=ncstart(1); count(1)=nccount(1) + start(2)=ncstart(2); count(2)=nccount(2) + start(3)=ncstart(3); count(3)=nccount(3) + if (dset%variables(nvar)%ndims == 4) then + start(4)=1; count(4)=1 + end if + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values,& + start=start, count=count) + else + if (dset%variables(nvar)%ndims == 4) then + allocate(values(dimlens(1),dimlens(2),dimlens(3))) + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values,& + start=start, count=count) + else + allocate(values(dset%variables(nvar)%dimlens(1),& + dset%variables(nvar)%dimlens(2),& + dset%variables(nvar)%dimlens(3))) + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values) + end if + end if + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + else + call nccheck(ncerr) + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_4d.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_4d.f90 new file mode 100644 index 0000000000..fd3dd42153 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_4d.f90 @@ -0,0 +1,83 @@ + type(Dataset), intent(in) :: dset + character(len=*), intent(in) :: varname + integer, intent(in), optional :: nslice + integer, intent(in), optional :: slicedim + integer, intent(in), optional :: ncstart(4) + integer, intent(in), optional :: nccount(4) + integer, intent(out), optional :: errcode + integer ncerr, nvar, n, nd, ndim, ncount + integer, allocatable, dimension(:) :: start, count + integer :: dimlens(4) + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if (present(nslice)) then + ncount = nslice + else + ncount = 1 + endif + nvar = get_nvar(dset,varname) + allocate(start(dset%variables(nvar)%ndims),count(dset%variables(nvar)%ndims)) + start(:) = 1 + count(:) = 1 + dimlens(:) = 1 + if (present(slicedim)) then + nd = slicedim + else + nd = dset%variables(nvar)%ndims + end if + ndim = 1 + do n=1,dset%variables(nvar)%ndims + if (n == nd) then + start(n) = ncount + count(n) = 1 + else + start(n) = 1 + count(n) = dset%variables(nvar)%dimlens(n) + dimlens(ndim) = dset%variables(nvar)%dimlens(n) + ndim = ndim + 1 + end if + end do + + if (dset%variables(nvar)%ndims /= 4 .and. dset%variables(nvar)%ndims /= 5) then + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=nf90_ebaddim + return + else + print *,'rank of data array != variable ndims (or ndims-1)' + stop 99 + endif + endif + + if (allocated(values)) deallocate(values) + if (present(ncstart) .and. present(nccount)) then + allocate(values(nccount(1),nccount(2),nccount(3),nccount(4))) + start(1)=ncstart(1); count(1)=nccount(1) + start(2)=ncstart(2); count(2)=nccount(2) + start(3)=ncstart(3); count(3)=nccount(3) + start(4)=ncstart(4); count(4)=nccount(4) + if (dset%variables(nvar)%ndims == 5) then + start(5)=1; count(5)=1 + end if + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values,& + start=start, count=count) + else + allocate(values(dimlens(1),dimlens(2),dimlens(3),dimlens(4))) + if (dset%variables(nvar)%ndims == 5) then + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values,& + start=start, count=count) + else + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values) + end if + end if + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + else + call nccheck(ncerr) + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_5d.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_5d.f90 new file mode 100644 index 0000000000..ea9bd2e2cf --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/read_vardata_code_5d.f90 @@ -0,0 +1,35 @@ + type(Dataset), intent(in) :: dset + character(len=*), intent(in) :: varname + integer, intent(out), optional :: errcode + integer ncerr, nvar, n1,n2,n3,n4,n5 + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + nvar = get_nvar(dset,varname) + if (dset%variables(nvar)%ndims /= 5) then + if (return_errcode) then + errcode=nf90_ebaddim + return + else + print *,'rank of data array != variable ndims (or ndims-1)' + stop 99 + endif + endif + n1 = dset%variables(nvar)%dimlens(1) + n2 = dset%variables(nvar)%dimlens(2) + n3 = dset%variables(nvar)%dimlens(3) + n4 = dset%variables(nvar)%dimlens(4) + n5 = dset%variables(nvar)%dimlens(5) + if (allocated(values)) deallocate(values) + allocate(values(n1,n2,n3,n4,n5)) + ncerr = nf90_get_var(dset%ncid, dset%variables(nvar)%varid, values) + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + else + call nccheck(ncerr) + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/test_fv3gfs_ncio.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/test_fv3gfs_ncio.f90 new file mode 100644 index 0000000000..2f7a5270bf --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/test_fv3gfs_ncio.f90 @@ -0,0 +1,97 @@ +program test_fv3gfs_ncio + use netcdf + use module_fv3gfs_ncio + implicit none + character(len=500) filename + character(len=72) charatt, time_units + type(Dataset) :: dset, dsetout + type(Variable) :: var + real(4), allocatable, dimension(:) :: values_1d + real(8), allocatable, dimension(:) :: values8_1d + real(4), allocatable, dimension(:,:) :: values_2d + real(4), allocatable, dimension(:,:,:) :: values_3d + real(4), allocatable, dimension(:,:,:,:) :: values_4d + real(4) mval,r4val + integer ndim,nvar,ndims,ival,idate(6),ierr,n + logical hasit + filename='test_data/dynf000.nc' + dset = open_dataset(filename) + print *,'ncid=',dset%ncid + print *,'nvars=',dset%nvars + print *,'ndims=',dset%ndims + print *,'natts=',dset%natts + do ndim=1,dset%ndims + print *,'dim',ndim,trim(dset%dimensions(ndim)%name),dset%dimensions(ndim)%len,dset%dimensions(ndim)%isunlimited + enddo + do nvar=1,dset%nvars + print *,'var',nvar,trim(dset%variables(nvar)%name),dset%variables(nvar)%ndims,dset%variables(nvar)%dimlens + enddo + var = get_var(dset,'vgrd') + print *,'vgrd has ',var%ndims,' dims' + call read_vardata(dset, 'vgrd', values_4d) + print *,'min/max vgrd (4d)' + print *,minval(values_4d),maxval(values_4d) + ! this should work also, since time dim is singleton + call read_vardata(dset, 'vgrd', values_3d) + print *,'min/max vgrd (3d)' + print *,minval(values_3d),maxval(values_3d) + print *,'min/max diff=',minval(values_4d(:,:,:,1)-values_3d),maxval(values_4d(:,:,:,1)-values_3d) + ! this should work also, since time dim is singleton + print *,'min/max hgtsfc (3d)' + call read_vardata(dset, 'hgtsfc', values_3d) + print *,minval(values_3d),maxval(values_3d) + print *,'min/max pressfc (3d)' + call read_vardata(dset, 'pressfc', values_3d) + print *,minval(values_3d),maxval(values_3d) + print *,'min/max pressfc (2d)' + call read_vardata(dset, 'pressfc', values_2d) + print *,minval(values_2d),maxval(values_2d) + print *,'min/max diff=',minval(values_3d(:,:,1)-values_2d),maxval(values_3d(:,:,1)-values_2d) + print *,'min/max pfull (1d_r8)' + call read_vardata(dset, 'pfull', values8_1d) + print *,minval(values8_1d),maxval(values8_1d) + hasit = has_var(dset,'pressfc') + print *,'has var pressfc',hasit + hasit = has_attr(dset,'max_abs_compression_error','pressfc') + print *,'pressfc has max_abs_compression_error attribute',hasit + call read_attribute(dset,'ncnsto',ival) + print *,'ncnsto =',ival + call read_attribute(dset,'ak',values_1d) + print *,'ak =',values_1d +! create a copy of the dataset + filename='test_data/dynf000_copy.nc' + dsetout = create_dataset(filename, dset, copy_vardata=.true.) + call write_attribute(dsetout,'foo',1,'ugrd') + if (allocated(values_1d)) deallocate(values_1d) + allocate(values_1d(5)) + values_1d = (/1,2,3,4,5/) + call write_attribute(dsetout,'bar',values_1d,'ugrd') + call write_attribute(dsetout,'hello','world') + call read_attribute(dsetout,'hello',charatt) + print *,trim(charatt) + call read_attribute(dsetout,'missing_value',mval,'pressfc') + print *,'missing_value=',mval + call read_vardata(dsetout, 'pressfc', values_3d) + print *,'min/max pressfc',minval(values_3d),maxval(values_3d) + print *,shape(values_3d) + values_3d(:,:,:) = mval + call write_vardata(dsetout,'pressfc', values_3d) + call read_vardata(dsetout, 'pressfc', values_3d) + print *,'min/max pressfc',minval(values_3d),maxval(values_3d) + print *,shape(values_3d) + nvar = get_nvar(dsetout, 'vgrd') + print *,trim(dsetout%variables(nvar)%name) + do n=1,dsetout%variables(nvar)%ndims + print *,trim(adjustl(dsetout%variables(nvar)%dimnames(n))),& + dsetout%variables(nvar)%dimlens(n),& + dsetout%dimensions(dsetout%variables(nvar)%dimindxs(n))%len + enddo + idate = get_idate_from_time_units(dset) + print *,'idate=',idate + time_units = get_time_units_from_idate(idate, time_measure='minutes') + print *,'time_units=',trim(time_units) + call read_attribute(dset,'foo',time_units,errcode=ierr) + print *,'error code = ',ierr,'should be',NF90_ENOTATT + call close_dataset(dset) + call close_dataset(dsetout) +end program test_fv3gfs_ncio diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/write_attribute_code.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/write_attribute_code.f90 new file mode 100644 index 0000000000..c700a90dc2 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/write_attribute_code.f90 @@ -0,0 +1,37 @@ + type(Dataset), intent(in) :: dset + character(len=*), intent(in), optional :: varname + character(len=*), intent(in) :: attname + integer, intent(out), optional :: errcode + integer ncerr, varid, nvar + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if(present(varname))then + nvar = get_nvar(dset,varname) + varid = dset%variables(nvar)%varid + else + varid = NF90_GLOBAL + endif + ncerr = nf90_redef(dset%ncid) + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + ncerr = nf90_put_att(dset%ncid, varid, trim(attname), values) + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + ncerr = nf90_enddef(dset%ncid) + return + else + call nccheck(ncerr) + ncerr = nf90_enddef(dset%ncid) + call nccheck(ncerr) + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/write_vardata_code.f90 b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/write_vardata_code.f90 new file mode 100644 index 0000000000..a6f8d4ffb8 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/fv3gfs_ncio/write_vardata_code.f90 @@ -0,0 +1,97 @@ + type(Dataset), intent(inout) :: dset + character(len=*), intent(in) :: varname + integer, intent(in), optional :: nslice + integer, intent(in), optional :: slicedim + integer, intent(out), optional :: errcode + integer ncerr, nvar, ncount, ndim, nd, n + integer, allocatable, dimension(:) :: start, count, dimlens + logical is_slice + logical return_errcode + if(present(errcode)) then + return_errcode=.true. + errcode = 0 + else + return_errcode=.false. + endif + if (present(nslice)) then + ncount = nslice + is_slice = .true. + else + ncount = 1 + is_slice = .false. + endif + nvar = get_nvar(dset,varname) + allocate(start(dset%variables(nvar)%ndims),count(dset%variables(nvar)%ndims)) + allocate(dimlens(dset%variables(nvar)%ndims)) + start(:) = 1 + count(:) = 1 + dimlens(:) = 1 + if (present(slicedim)) then + nd = slicedim + else + nd = dset%variables(nvar)%ndims + end if + ndim = 1 + do n=1,dset%variables(nvar)%ndims + if (n == nd) then + start(n) = ncount + count(n) = 1 + else + start(n) = 1 + count(n) = dset%variables(nvar)%dimlens(n) + dimlens(ndim) = dset%variables(nvar)%dimlens(n) + ndim = ndim + 1 + end if + end do + + + + ncerr = nf90_var_par_access(dset%ncid, dset%variables(nvar)%varid, nf90_collective) + if (is_slice) then + if (dset%variables(nvar)%ndims == 4) then + ncerr = nf90_put_var(dset%ncid, dset%variables(nvar)%varid,values, & + start=start,count=count) + else if (dset%variables(nvar)%ndims == 3) then + ncerr = nf90_put_var(dset%ncid, dset%variables(nvar)%varid,values, & + start=start,count=count) + else if (dset%variables(nvar)%ndims == 2) then + ncerr = nf90_put_var(dset%ncid, dset%variables(nvar)%varid,values, & + start=start,count=count) + else if (dset%variables(nvar)%ndims == 1) then + if (return_errcode) then + errcode = -1 + return + else + print *,'cannot write a slice to a 1d variable' + stop 99 + endif + else if (dset%variables(nvar)%ndims > 4) then + if (return_errcode) then + errcode = -1 + return + else + print *,'only variables up to 4d supported' + stop 99 + endif + endif + else if (present(ncstart) .and. present(nccount)) then + ncerr = nf90_put_var(dset%ncid, dset%variables(nvar)%varid,values, & + start=ncstart, count=nccount) + else + ncerr = nf90_put_var(dset%ncid, dset%variables(nvar)%varid, values) + endif + if (return_errcode) then + call nccheck(ncerr,halt=.false.) + errcode=ncerr + if (ncerr /= 0) return + else + call nccheck(ncerr) + endif + ! reset unlim dim size for all variables + if (dset%variables(nvar)%hasunlim) then + if (return_errcode) then + call set_varunlimdimlens_(dset,errcode) + else + call set_varunlimdimlens_(dset) + endif + endif diff --git a/sorc/enkf_chgres_recenter_nc.fd/src/CMakeLists.txt b/sorc/enkf_chgres_recenter_nc.fd/src/CMakeLists.txt new file mode 100644 index 0000000000..f842e53aea --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/src/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.6) + file(GLOB LOCAL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.f90) + + set(Util_MODULE_DIRECTORY "${PROJECT_BINARY_DIR}/include/chgres_ncio") + set_source_files_properties( ${LOCAL_SRC} PROPERTIES COMPILE_FLAGS ${UTIL_Fortran_FLAGS} ) + add_executable( chgres_recenter_ncio.exe ${LOCAL_SRC} ) + set_target_properties( chgres_recenter_ncio.exe PROPERTIES COMPILE_FLAGS ${UTIL_Fortran_FLAGS} ) + set_target_properties( chgres_recenter_ncio.exe PROPERTIES Fortran_MODULE_DIRECTORY ${Util_MODULE_DIRECTORY} ) + SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_Fortran_FLAGS} ${UTIL_Fortran_FLAGS}" ) + include_directories( ${UTIL_INC} ${NETCDF_INCLUDES} ${MPI_Fortran_INCLUDE_PATH} ${FV3GFS_NCIO_INCS}) + target_link_libraries( chgres_recenter_ncio.exe ${FV3GFS_NCIO_LIBRARIES} ${BACIO_4_LIBRARY} ${W3NCO_4_LIBRARY} ${IP_4_LIBRARY} ${SP_4_LIBRARY} ${NETCDF_LIBRARIES} ${MPI_Fortran_LIBRARIES} ${HDF5_HL_LIBRARIES} ${HDF5_LIBRARIES} ${ZLIB_LIBRARIES} ${CURL_LIBRARIES}) diff --git a/sorc/enkf_chgres_recenter_nc.fd/src/driver.f90 b/sorc/enkf_chgres_recenter_nc.fd/src/driver.f90 new file mode 100644 index 0000000000..1ec7c70f03 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/src/driver.f90 @@ -0,0 +1,67 @@ +!!! based on chgres_recenter +!!! cory.r.martin@noaa.gov 2019-09-27 + program regrid + + use setup, only : program_setup + use interp, only : gaus_to_gaus, adjust_for_terrain + use input_data, only : read_input_data, & + read_vcoord_info + use output_data, only : set_output_grid, write_output_data + + implicit none + + call w3tagb('ENKF_CHGRES_RECENTER_NCIO',2019,0270,0085,'NP20') + + print*,"STARTING PROGRAM" + +!-------------------------------------------------------- +! Read configuration namelist. +!-------------------------------------------------------- + + call program_setup + +!-------------------------------------------------------- +! Read input grid data +!-------------------------------------------------------- + + call read_input_data + +!-------------------------------------------------------- +! Read vertical coordinate info +!-------------------------------------------------------- + + call read_vcoord_info + +!-------------------------------------------------------- +! Get output grid specs +!-------------------------------------------------------- + + call set_output_grid + +!-------------------------------------------------------- +! Interpolate data to output grid +!-------------------------------------------------------- + + call gaus_to_gaus + +!-------------------------------------------------------- +! Adjust output fields for differences between +! interpolated and external terrain. +!-------------------------------------------------------- + + call adjust_for_terrain + +!-------------------------------------------------------- +! Write output data to file. +!-------------------------------------------------------- + + call write_output_data + + print* + print*,"PROGRAM FINISHED NORMALLY!" + + call w3tage('ENKF_CHGRES_RECENTER_NCIO') + + stop + + end program regrid diff --git a/sorc/enkf_chgres_recenter_nc.fd/src/input_data.f90 b/sorc/enkf_chgres_recenter_nc.fd/src/input_data.f90 new file mode 100644 index 0000000000..609aed05a6 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/src/input_data.f90 @@ -0,0 +1,345 @@ + module input_data + + use utils + use setup + use module_fv3gfs_ncio + + implicit none + + private + + integer, public :: idvc, idsl, idvm, nvcoord + integer, public :: nvcoord_input, ntrac, ncldt + integer, public :: ij_input, kgds_input(200) + integer, public :: i_input, j_input, lev, lev_output + integer, public :: idate(6) + integer, public :: icldamt, iicmr, & + idelz,idpres,idzdt, & + irwmr,isnmr,igrle + + + real, allocatable, public :: vcoord(:,:) + real, allocatable, public :: vcoord_input(:,:) + real, allocatable, public :: clwmr_input(:,:) + real, allocatable, public :: dzdt_input(:,:) + real, allocatable, public :: grle_input(:,:) + real, allocatable, public :: cldamt_input(:,:) + real, allocatable, public :: hgt_input(:) + real, allocatable, public :: icmr_input(:,:) + real, allocatable, public :: o3mr_input(:,:) + real, allocatable, public :: rwmr_input(:,:) + real, allocatable, public :: sfcp_input(:) + real, allocatable, public :: snmr_input(:,:) + real, allocatable, public :: spfh_input(:,:) + real, allocatable, public :: tmp_input(:,:) + real, allocatable, public :: ugrd_input(:,:) + real, allocatable, public :: vgrd_input(:,:) + real :: missing_value=1.e30 + + public :: read_input_data + public :: read_vcoord_info + + contains + + subroutine read_input_data + +!------------------------------------------------------------------------------------- +! Read input grid data from a netcdf file. +!------------------------------------------------------------------------------------- + + implicit none + + integer :: vlev,rvlev + type(Dataset) :: indset + type(Dimension) :: ncdim + real, allocatable :: work2d(:,:),work3d(:,:,:) + integer iret, k, kk + real, allocatable :: ak(:), bk(:) + + ! hard code these values that are the same for GFS + idvc=2 + idsl=1 + idvm=1 + ntrac = 8 + ncldt = 5 + + print* + print*,"OPEN INPUT FILE: ",trim(input_file) + indset = open_dataset(input_file) + + print*,"GET INPUT FILE HEADER" + ncdim = get_dim(indset, 'grid_xt'); i_input = ncdim%len + ncdim = get_dim(indset, 'grid_yt'); j_input = ncdim%len + ncdim = get_dim(indset, 'pfull'); lev = ncdim%len + idate = get_idate_from_time_units(indset) + + print*,'DIMENSIONS OF DATA ARE: ', i_input, j_input, lev + print*,'DATE OF DATA IS: ', idate + + ij_input = i_input * j_input + + call read_attribute(indset, 'ak', ak) + call read_attribute(indset, 'bk', bk) + + nvcoord_input = 2 + allocate(vcoord_input(lev+1,nvcoord_input)) + do k = 1, lev+1 + kk = lev+2-k + vcoord_input(k,1) = ak(kk) + vcoord_input(k,2) = bk(kk) + print*,'VCOORD OF INPUT DATA ',k,vcoord_input(k,:) + enddo + + deallocate(ak, bk) + + print* + print*,"READ SURFACE PRESSURE" + call read_vardata(indset, 'pressfc', work2d) + + allocate(sfcp_input(ij_input)) + sfcp_input = reshape(work2d,(/ij_input/)) + print*,'MAX/MIN SURFACE PRESSURE: ',maxval(sfcp_input), minval(sfcp_input) + + print* + print*,"READ SURFACE HEIGHT" + call read_vardata(indset, 'hgtsfc', work2d) + + allocate(hgt_input(ij_input)) + hgt_input = reshape(work2d,(/ij_input/)) + print*,'MAX/MIN SURFACE HEIGHT: ',maxval(hgt_input), minval(hgt_input) + + print* + print*,"READ U WIND" + allocate(ugrd_input(ij_input,lev)) + call read_vardata(indset, 'ugrd', work3d) + do vlev = 1, lev + rvlev = lev+1-vlev + ugrd_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN U WIND AT LEVEL ',vlev, "IS: ", maxval(ugrd_input(:,vlev)), minval(ugrd_input(:,vlev)) + enddo + + print* + print*,"READ V WIND" + allocate(vgrd_input(ij_input,lev)) + call read_vardata(indset, 'vgrd', work3d) + do vlev = 1, lev + rvlev = lev+1-vlev + vgrd_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN V WIND AT LEVEL ', vlev, "IS: ", maxval(vgrd_input(:,vlev)), minval(vgrd_input(:,vlev)) + enddo + + print* + print*,"READ TEMPERATURE" + allocate(tmp_input(ij_input,lev)) + call read_vardata(indset, 'tmp', work3d) + do vlev = 1, lev + rvlev = lev+1-vlev + tmp_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN TEMPERATURE AT LEVEL ', vlev, 'IS: ', maxval(tmp_input(:,vlev)), minval(tmp_input(:,vlev)) + enddo + + print* + print*,"READ SPECIFIC HUMIDITY" + allocate(spfh_input(ij_input,lev)) + call read_vardata(indset, 'spfh', work3d) + do vlev = 1, lev + rvlev = lev+1-vlev + spfh_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN SPECIFIC HUMIDITY AT LEVEL ', vlev, 'IS: ', maxval(spfh_input(:,vlev)), minval(spfh_input(:,vlev)) + enddo + + print* + print*,"READ CLOUD LIQUID WATER" + allocate(clwmr_input(ij_input,lev)) + call read_vardata(indset, 'clwmr', work3d) + do vlev = 1, lev + rvlev = lev+1-vlev + clwmr_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN CLOUD LIQUID WATER AT LEVEL ', vlev, 'IS: ', maxval(clwmr_input(:,vlev)), minval(clwmr_input(:,vlev)) + enddo + + print* + print*,"READ OZONE" + allocate(o3mr_input(ij_input,lev)) + call read_vardata(indset, 'o3mr', work3d) + do vlev = 1, lev + rvlev = lev+1-vlev + o3mr_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN OZONE AT LEVEL ', vlev, 'IS: ', maxval(o3mr_input(:,vlev)), minval(o3mr_input(:,vlev)) + enddo + + print* + print*,"READ DZDT" + allocate(dzdt_input(ij_input,lev)) + call read_vardata(indset, 'dzdt', work3d, errcode=iret) + if (iret == 0) then + do vlev = 1, lev + rvlev = lev+1-vlev + dzdt_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN DZDT AT LEVEL ', vlev, 'IS: ', maxval(dzdt_input(:,vlev)), minval(dzdt_input(:,vlev)) + enddo + idzdt = 1 + else + dzdt_input = missing_value + print*,'DZDT NOT IN INPUT FILE' + idzdt = 0 + endif + + + print* + print*,"READ RWMR" + allocate(rwmr_input(ij_input,lev)) + call read_vardata(indset, 'rwmr', work3d, errcode=iret) + if (iret == 0) then + do vlev = 1, lev + rvlev = lev+1-vlev + rwmr_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN RWMR AT LEVEL ', vlev, 'IS: ', maxval(rwmr_input(:,vlev)), minval(rwmr_input(:,vlev)) + enddo + irwmr = 1 + else + rwmr_input = missing_value + print*,'RWMR NOT IN INPUT FILE' + irwmr = 0 + endif + + print* + print*,"READ ICMR" + allocate(icmr_input(ij_input,lev)) + call read_vardata(indset, 'icmr', work3d, errcode=iret) + if (iret == 0) then + do vlev = 1, lev + rvlev = lev+1-vlev + icmr_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN ICMR AT LEVEL ', vlev, 'IS: ', maxval(icmr_input(:,vlev)), minval(icmr_input(:,vlev)) + enddo + iicmr = 1 + else + icmr_input = missing_value + print*,'ICMR NOT IN INPUT FILE' + iicmr = 0 + endif + + print* + print*,"READ SNMR" + allocate(snmr_input(ij_input,lev)) + call read_vardata(indset, 'snmr', work3d, errcode=iret) + if (iret == 0) then + do vlev = 1, lev + rvlev = lev+1-vlev + snmr_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN SNMR AT LEVEL ', vlev, 'IS: ', maxval(snmr_input(:,vlev)), minval(snmr_input(:,vlev)) + enddo + isnmr = 1 + else + snmr_input = missing_value + print*,'SNMR NOT IN INPUT FILE' + isnmr = 0 + endif + + print* + print*,"READ GRLE" + allocate(grle_input(ij_input,lev)) + call read_vardata(indset, 'grle', work3d, errcode=iret) + if (iret == 0) then + do vlev = 1, lev + rvlev = lev+1-vlev + grle_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN GRLE AT LEVEL ', vlev, 'IS: ', maxval(grle_input(:,vlev)), minval(grle_input(:,vlev)) + enddo + igrle = 1 + else + grle_input = missing_value + print*,'GRLE NOT IN INPUT FILE' + igrle = 0 + endif + + print* + print*,"READ CLD_AMT" + allocate(cldamt_input(ij_input,lev)) + if (cld_amt) then + call read_vardata(indset, 'cld_amt', work3d, errcode=iret) + if (iret == 0) then + do vlev = 1, lev + rvlev = lev+1-vlev + cldamt_input(:,vlev) = reshape(work3d(:,:,rvlev),(/ij_input/)) + print*,'MAX/MIN CLD_AMT AT LEVEL ', vlev, 'IS: ', maxval(cldamt_input(:,vlev)), minval(cldamt_input(:,vlev)) + enddo + icldamt = 1 + else + cldamt_input = missing_value + print*,'CLDAMT NOT IN INPUT FILE' + icldamt = 0 + endif + else + cldamt_input = missing_value + print*,'CLDAMT NOT READ - CLD_AMT NAMELIST OPTION NOT SET TO TRUE' + icldamt = 0 + end if + + call read_vardata(indset, 'dpres', work3d, errcode=iret) + if (iret == 0) then + idpres = 1 + else + idpres = 0 + endif + call read_vardata(indset, 'delz', work3d, errcode=iret) + if (iret == 0) then + idelz = 1 + else + idelz = 0 + endif + + print*,"CLOSE FILE" + call close_dataset(indset) + deallocate(work2d,work3d) + +!--------------------------------------------------------------------------------------- +! Set the grib 1 grid description array need by the NCEP IPOLATES library. +!--------------------------------------------------------------------------------------- + + call calc_kgds(i_input, j_input, kgds_input) + + return + + end subroutine read_input_data + + subroutine read_vcoord_info + +!--------------------------------------------------------------------------------- +! Read vertical coordinate information. +!--------------------------------------------------------------------------------- + + implicit none + + integer :: istat, n, k, k2 + + real, allocatable :: ak(:), bk(:) + + type(Dataset) :: refdset + + print* + print*,"READ OUTPUT VERT COORDINATE INFO FROM REFERENCE FILE: ",trim(ref_file) + + refdset = open_dataset(ref_file) + call read_attribute(refdset, 'ak', ak) + call read_attribute(refdset, 'bk', bk) + call close_dataset(refdset) + + lev_output = size(bk) - 1 + + nvcoord=2 + allocate(vcoord(lev_output+1, nvcoord)) + + do k = 1, (lev_output+1) + k2 = lev_output+2 - k + vcoord(k,1) = ak(k2) + vcoord(k,2) = bk(k2) + print*,'VCOORD OF OUTPUT GRID ',k,vcoord(k,:) + enddo + + deallocate (ak, bk) + + end subroutine read_vcoord_info + + end module input_data diff --git a/sorc/enkf_chgres_recenter_nc.fd/src/interp.f90 b/sorc/enkf_chgres_recenter_nc.fd/src/interp.f90 new file mode 100644 index 0000000000..291e8ef0d3 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/src/interp.f90 @@ -0,0 +1,582 @@ + module interp + + implicit none + + private + + real, allocatable :: sfcp_b4_adj_output(:) + real, allocatable :: clwmr_b4_adj_output(:,:) + real, allocatable :: dzdt_b4_adj_output(:,:) + real, allocatable :: grle_b4_adj_output(:,:) + real, allocatable :: cldamt_b4_adj_output(:,:) + real, allocatable :: icmr_b4_adj_output(:,:) + real, allocatable :: o3mr_b4_adj_output(:,:) + real, allocatable :: rwmr_b4_adj_output(:,:) + real, allocatable :: snmr_b4_adj_output(:,:) + real, allocatable :: spfh_b4_adj_output(:,:) + real, allocatable :: tmp_b4_adj_output(:,:) + real, allocatable :: ugrd_b4_adj_output(:,:) + real, allocatable :: vgrd_b4_adj_output(:,:) + + public :: adjust_for_terrain + public :: gaus_to_gaus + + contains + + subroutine adjust_for_terrain + +!--------------------------------------------------------------------------------- +! Adjust fields based on differences between the interpolated and external +! terrain. +!--------------------------------------------------------------------------------- + + use input_data + use output_data + use utils + use setup + + implicit none + + integer :: k + + real, allocatable :: pres_b4_adj_output(:,:) + real, allocatable :: pres_output(:,:) + real, allocatable :: q_b4_adj_output(:,:,:), q_output(:,:,:) + +!--------------------------------------------------------------------------------- +! First, compute the mid-layer pressure using the interpolated surface pressure. +!--------------------------------------------------------------------------------- + + allocate(pres_b4_adj_output(ij_output,lev)) + pres_b4_adj_output = 0.0 + + print*,'before newpr1, sfcp b4 adj: ', sfcp_b4_adj_output(ij_output/2) + + print* + print*,"COMPUTE MID-LAYER PRESSURE FROM INTERPOLATED SURFACE PRESSURE." + call newpr1(ij_output, lev, idvc, idsl, nvcoord_input, vcoord_input, & + sfcp_b4_adj_output, pres_b4_adj_output) + + print*,'after newpr1, pres b4 adj: ', pres_b4_adj_output(ij_output/2,:) + +!--------------------------------------------------------------------------------- +! Adjust surface pressure based on differences between interpolated and +! grid terrain. +!--------------------------------------------------------------------------------- + + allocate(sfcp_output(ij_output)) + sfcp_output = 0.0 + + print*,"ADJUST SURFACE PRESSURE BASED ON TERRAIN DIFFERENCES" + call newps(hgt_output, sfcp_b4_adj_output, ij_output, & + lev, pres_b4_adj_output, tmp_b4_adj_output, & + spfh_b4_adj_output, hgt_external_output, sfcp_output) + + print*,'after newps ',sfcp_b4_adj_output(ij_output/2),sfcp_output(ij_output/2) + + deallocate(sfcp_b4_adj_output) + +!--------------------------------------------------------------------------------- +! Recompute mid-layer pressure based on the adjusted surface pressure. +!--------------------------------------------------------------------------------- + + allocate(pres_output(ij_output, lev_output)) + pres_output = 0.0 + + allocate(dpres_output(ij_output, lev_output)) + dpres_output = 0.0 + + print*,'before newpr1 ',sfcp_output(ij_output/2) + print*,'before newpr1 ',idvc,idsl,nvcoord,vcoord + + print*,"RECOMPUTE MID-LAYER PRESSURE." + call newpr1(ij_output, lev_output, idvc, idsl, nvcoord, vcoord, & + sfcp_output, pres_output, dpres_output) + + do k = 1, lev_output + print*,'after newpr1 ',pres_output(ij_output/2,k), dpres_output(ij_output/2,k) + enddo + +!--------------------------------------------------------------------------------- +! Vertically interpolate from the pre-adjusted to the adjusted mid-layer +! pressures. +!--------------------------------------------------------------------------------- + + allocate(q_b4_adj_output(ij_output,lev,ntrac)) + q_b4_adj_output(:,:,1) = spfh_b4_adj_output(:,:) + q_b4_adj_output(:,:,2) = o3mr_b4_adj_output(:,:) + q_b4_adj_output(:,:,3) = clwmr_b4_adj_output(:,:) + q_b4_adj_output(:,:,4) = rwmr_b4_adj_output(:,:) + q_b4_adj_output(:,:,5) = icmr_b4_adj_output(:,:) + q_b4_adj_output(:,:,6) = snmr_b4_adj_output(:,:) + q_b4_adj_output(:,:,7) = grle_b4_adj_output(:,:) + q_b4_adj_output(:,:,8) = cldamt_b4_adj_output(:,:) + + allocate(q_output(ij_output,lev_output,ntrac)) + q_output = 0.0 + + allocate(dzdt_output(ij_output,lev_output)) + dzdt_output = 0.0 + + allocate(ugrd_output(ij_output,lev_output)) + ugrd_output=0.0 + + allocate(vgrd_output(ij_output,lev_output)) + vgrd_output=0.0 + + allocate(tmp_output(ij_output,lev_output)) + tmp_output=0.0 + + print*,"VERTICALLY INTERPOLATE TO NEW PRESSURE LEVELS" + call vintg(ij_output, lev, lev_output, ntrac, pres_b4_adj_output, & + ugrd_b4_adj_output, vgrd_b4_adj_output, tmp_b4_adj_output, q_b4_adj_output, & + dzdt_b4_adj_output, pres_output, ugrd_output, vgrd_output, tmp_output, & + q_output, dzdt_output) + + deallocate (dzdt_b4_adj_output, q_b4_adj_output) +!deallocate (pres_b4_adj_output, pres_output) + + allocate(spfh_output(ij_output,lev_output)) + spfh_output = q_output(:,:,1) + allocate(o3mr_output(ij_output,lev_output)) + o3mr_output = q_output(:,:,2) + allocate(clwmr_output(ij_output,lev_output)) + clwmr_output = q_output(:,:,3) + allocate(rwmr_output(ij_output,lev_output)) + rwmr_output = q_output(:,:,4) + allocate(icmr_output(ij_output,lev_output)) + icmr_output = q_output(:,:,5) + allocate(snmr_output(ij_output,lev_output)) + snmr_output = q_output(:,:,6) + allocate(grle_output(ij_output,lev_output)) + grle_output = q_output(:,:,7) + allocate(cldamt_output(ij_output,lev_output)) + cldamt_output = q_output(:,:,8) + + deallocate(q_output) + + do k = 1, lev + print*,'after vintg tmp b4 ',tmp_b4_adj_output(ij_output/2,k), pres_b4_adj_output(ij_output/2,k) + enddo + do k = 1, lev_output + print*,'after vintg tmp ',tmp_output(ij_output/2,k),pres_output(ij_output/2,k) + enddo + + deallocate(tmp_b4_adj_output) + + deallocate(ugrd_b4_adj_output) + + deallocate(vgrd_b4_adj_output) + + deallocate(spfh_b4_adj_output) + + deallocate(o3mr_b4_adj_output) + + deallocate(clwmr_b4_adj_output) + + deallocate(rwmr_b4_adj_output) + + deallocate(icmr_b4_adj_output) + + deallocate(snmr_b4_adj_output) + + deallocate(grle_b4_adj_output) + + deallocate(cldamt_b4_adj_output) + + allocate(delz_output(ij_output, lev_output)) + delz_output = 0.0 + + call compute_delz(ij_output, lev_output, vcoord(:,1), vcoord(:,2), sfcp_output, hgt_output, & + tmp_output, spfh_output, delz_output) + + do k = 1, lev_output + print*,'after compute_delz ',delz_output(ij_output/2,k) + enddo + + deallocate(hgt_output) + + end subroutine adjust_for_terrain + + subroutine gaus_to_gaus + +!---------------------------------------------------------------------------------- +! Interpolate data from the input to output grid using IPOLATES library. +!---------------------------------------------------------------------------------- + + use output_data + use input_data + use setup + + implicit none + + integer :: ip, ipopt(20), i + integer :: num_fields + integer :: iret, numpts + integer, allocatable :: ibi(:), ibo(:) + + logical*1, allocatable :: bitmap_input(:,:), bitmap_output(:,:) + logical :: same_grid + + real, allocatable :: data_input(:,:) + real, allocatable :: data_output(:,:), crot(:), srot(:) + + same_grid=.true. + do i = 1, 11 + if (kgds_input(i) /= kgds_output(i)) then + same_grid=.false. + exit + endif + enddo + + if (same_grid) then + + print* + print*,'INPUT AND OUTPUT GRIDS ARE THE SAME.' + print*,'NO HORIZ INTERPOLATION REQUIRED.' + + allocate(hgt_output(ij_output)) + hgt_output = hgt_input + deallocate(hgt_input) + + allocate(sfcp_b4_adj_output(ij_output)) + sfcp_b4_adj_output = sfcp_input + deallocate(sfcp_input) + + allocate(tmp_b4_adj_output(ij_output,lev)) + tmp_b4_adj_output = tmp_input + deallocate(tmp_input) + + allocate(clwmr_b4_adj_output(ij_output,lev)) + clwmr_b4_adj_output = clwmr_input + deallocate(clwmr_input) + + allocate(spfh_b4_adj_output(ij_output,lev)) + spfh_b4_adj_output = spfh_input + deallocate(spfh_input) + + allocate(o3mr_b4_adj_output(ij_output,lev)) + o3mr_b4_adj_output = o3mr_input + deallocate(o3mr_input) + + allocate(dzdt_b4_adj_output(ij_output,lev)) + dzdt_b4_adj_output = dzdt_input + deallocate(dzdt_input) + + allocate(rwmr_b4_adj_output(ij_output,lev)) + rwmr_b4_adj_output = rwmr_input + deallocate(rwmr_input) + + allocate(snmr_b4_adj_output(ij_output,lev)) + snmr_b4_adj_output = snmr_input + deallocate(snmr_input) + + allocate(icmr_b4_adj_output(ij_output,lev)) + icmr_b4_adj_output = icmr_input + deallocate(icmr_input) + + allocate(grle_b4_adj_output(ij_output,lev)) + grle_b4_adj_output = grle_input + deallocate(grle_input) + + allocate(cldamt_b4_adj_output(ij_output,lev)) + cldamt_b4_adj_output = cldamt_input + deallocate(cldamt_input) + + allocate(ugrd_b4_adj_output(ij_output,lev)) + ugrd_b4_adj_output = ugrd_input + deallocate(ugrd_input) + + allocate(vgrd_b4_adj_output(ij_output,lev)) + vgrd_b4_adj_output = vgrd_input + deallocate(vgrd_input) + + else + + print* + print*,'INTERPOLATE DATA TO OUTPUT GRID' + + + ip = 0 ! bilinear + ipopt = 0 + +!---------------------------------------------------------------------------------- +! Do 2-D fields first +!---------------------------------------------------------------------------------- + + num_fields = 1 + + allocate(ibi(num_fields)) + ibi = 0 ! no bitmap + allocate(ibo(num_fields)) + ibo = 0 ! no bitmap + + allocate(bitmap_input(ij_input,num_fields)) + bitmap_input = .true. + allocate(bitmap_output(ij_output,num_fields)) + bitmap_output = .true. + + allocate(rlat_output(ij_output)) + rlat_output = 0.0 + allocate(rlon_output(ij_output)) + rlon_output = 0.0 + +!---------------- +! Surface height +!---------------- + + allocate(data_input(ij_input,num_fields)) + data_input(:,num_fields) = hgt_input(:) + deallocate(hgt_input) + + allocate(data_output(ij_output,num_fields)) + data_output = 0 + + print*,"INTERPOLATE SURFACE HEIGHT" + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, data_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + data_output, iret) + if (iret /= 0) goto 89 + + allocate(hgt_output(ij_output)) + hgt_output = data_output(:,num_fields) + +!------------------ +! surface pressure +!------------------ + + data_input(:,num_fields) = sfcp_input(:) + deallocate(sfcp_input) + + print*,"INTERPOLATE SURFACE PRESSURE" + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, data_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + data_output, iret) + if (iret /= 0) goto 89 + + allocate(sfcp_b4_adj_output(ij_output)) + sfcp_b4_adj_output = data_output(:,num_fields) + + deallocate(ibi, ibo, bitmap_input, bitmap_output, data_input, data_output) + +!---------------------------------------------------------------------------------- +! 3d scalars +!---------------------------------------------------------------------------------- + + num_fields = lev + + allocate(ibi(num_fields)) + ibi = 0 ! no bitmap + allocate(ibo(num_fields)) + ibo = 0 ! no bitmap + + allocate(bitmap_input(ij_input,num_fields)) + bitmap_input = .true. + allocate(bitmap_output(ij_output,num_fields)) + bitmap_output = .true. + +!------------- +! Temperature +!------------- + + allocate(tmp_b4_adj_output(ij_output,num_fields)) + tmp_b4_adj_output = 0 + + print*,'INTERPOLATE TEMPERATURE' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, tmp_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + tmp_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(tmp_input) + +!-------------------- +! Cloud liquid water +!-------------------- + + allocate(clwmr_b4_adj_output(ij_output,num_fields)) + clwmr_b4_adj_output = 0 + + print*,'INTERPOLATE CLOUD LIQUID WATER' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, clwmr_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + clwmr_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(clwmr_input) + +!-------------------- +! Specific humidity +!-------------------- + + allocate(spfh_b4_adj_output(ij_output,num_fields)) + spfh_b4_adj_output = 0 + + print*,'INTERPOLATE SPECIFIC HUMIDITY' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, spfh_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + spfh_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(spfh_input) + +!----------- +! Ozone +!----------- + + allocate(o3mr_b4_adj_output(ij_output,num_fields)) + o3mr_b4_adj_output = 0 + + print*,'INTERPOLATE OZONE' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, o3mr_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + o3mr_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(o3mr_input) + +!----------- +! DZDT +!----------- + + allocate(dzdt_b4_adj_output(ij_output,num_fields)) + dzdt_b4_adj_output = 0 + + print*,'INTERPOLATE DZDT' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, dzdt_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + dzdt_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(dzdt_input) + +!---------------------------------------------------------------------------------- +! Interpolate additional 3-d scalars for GFDL microphysics. +!---------------------------------------------------------------------------------- + + +!------------- +! Rain water +!------------- + + allocate(rwmr_b4_adj_output(ij_output,num_fields)) + rwmr_b4_adj_output = 0 + + print*,'INTERPOLATE RWMR' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, rwmr_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + rwmr_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(rwmr_input) + +!------------- +! Snow water +!------------- + + allocate(snmr_b4_adj_output(ij_output,num_fields)) + snmr_b4_adj_output = 0 + + print*,'INTERPOLATE SNMR' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, snmr_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + snmr_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(snmr_input) + +!------------- +! Ice water +!------------- + + allocate(icmr_b4_adj_output(ij_output,num_fields)) + icmr_b4_adj_output = 0 + + print*,'INTERPOLATE ICMR' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, icmr_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + icmr_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(icmr_input) + +!------------- +! Graupel +!------------- + + allocate(grle_b4_adj_output(ij_output,num_fields)) + grle_b4_adj_output = 0 + + print*,'INTERPOLATE GRLE' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, grle_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + grle_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(grle_input) + + +!--------------------------- +! Cloud amount +!--------------------------- + + allocate(cldamt_b4_adj_output(ij_output,num_fields)) + cldamt_b4_adj_output = 0 + + print*,'INTERPOLATE CLD_AMT' + call ipolates(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, cldamt_input, & + numpts, rlat_output, rlon_output, ibo, bitmap_output, & + cldamt_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate(cldamt_input) + + + +!---------------------------------------------------------------------------------- +! 3d u/v winds +!---------------------------------------------------------------------------------- + + allocate(crot(ij_output), srot(ij_output)) + crot = 0. + srot = 0. + + allocate(ugrd_b4_adj_output(ij_output,num_fields)) + ugrd_b4_adj_output = 0 + allocate(vgrd_b4_adj_output(ij_output,num_fields)) + vgrd_b4_adj_output = 0 + + print*,'INTERPOLATE WINDS' + call ipolatev(ip, ipopt, kgds_input, kgds_output, ij_input, ij_output,& + num_fields, ibi, bitmap_input, ugrd_input, vgrd_input, & + numpts, rlat_output, rlon_output, crot, srot, ibo, bitmap_output, & + ugrd_b4_adj_output, vgrd_b4_adj_output, iret) + if (iret /= 0) goto 89 + + deallocate (ugrd_input, vgrd_input) + deallocate (crot, srot) + deallocate (ibi, ibo, bitmap_input, bitmap_output) + + endif + + return + + 89 continue + print*,"FATAL ERROR IN IPOLATES. IRET IS: ", iret + call errexit(23) + + end subroutine gaus_to_gaus + + end module interp diff --git a/sorc/enkf_chgres_recenter_nc.fd/src/makefile b/sorc/enkf_chgres_recenter_nc.fd/src/makefile new file mode 100644 index 0000000000..a622d92fc2 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/src/makefile @@ -0,0 +1,28 @@ +SHELL= /bin/sh + +LIBS= $(FV3GFS_NCIO_LIB) $(BACIO_LIB4) $(W3NCO_LIB4) $(IP_LIB4) $(SP_LIB4) -L$(NETCDF)/lib -lnetcdff -lnetcdf -lhdf5_hl -lhdf5 -lz + +CMD= chgres_recenter_ncio.exe + +OBJS = driver.o input_data.o interp.o output_data.o utils.o setup.o + +$(CMD): $(OBJS) + $(FC) $(FFLAGS) -o $(CMD) $(OBJS) $(LIBS) + +driver.o: setup.o output_data.o interp.o input_data.o driver.f90 + $(FC) $(FFLAGS) -I$(FV3GFS_NCIO_INC) -I$(NETCDF)/include -c driver.f90 +interp.o: setup.o utils.o output_data.o input_data.o interp.f90 + $(FC) $(FFLAGS) -I$(FV3GFS_NCIO_INC) -I$(NETCDF)/include -c interp.f90 +input_data.o: setup.o utils.o input_data.f90 + $(FC) $(FFLAGS) -I$(FV3GFS_NCIO_INC) -I$(NETCDF)/include -c input_data.f90 +output_data.o: setup.o utils.o input_data.o output_data.f90 + $(FC) $(FFLAGS) -I$(FV3GFS_NCIO_INC) -I$(NETCDF)/include -c output_data.f90 +setup.o: setup.f90 + $(FC) $(FFLAGS) -I$(FV3GFS_NCIO_INC) -I$(NETCDF)/include -c setup.f90 +utils.o: utils.f90 + $(FC) $(FFLAGS) -I$(FV3GFS_NCIO_INC) -I$(NETCDF)/include -c utils.f90 +clean: + rm -f *.o *.mod ${CMD} +install: + -cp $(CMD) ../../../exec/. + diff --git a/sorc/enkf_chgres_recenter_nc.fd/src/output_data.f90 b/sorc/enkf_chgres_recenter_nc.fd/src/output_data.f90 new file mode 100644 index 0000000000..17766d23c0 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/src/output_data.f90 @@ -0,0 +1,288 @@ + module output_data + + use module_fv3gfs_ncio + + implicit none + + private + + integer, public :: kgds_output(200) + +! data on the output grid. + real, allocatable, public :: hgt_output(:) ! interpolated from input grid + real, allocatable, public :: hgt_external_output(:) + real, allocatable, public :: sfcp_output(:) + real, allocatable, public :: tmp_output(:,:) + real, allocatable, public :: clwmr_output(:,:) + real, allocatable, public :: delz_output(:,:) + real, allocatable, public :: dpres_output(:,:) + real, allocatable, public :: dzdt_output(:,:) + real, allocatable, public :: o3mr_output(:,:) + real, allocatable, public :: spfh_output(:,:) + real, allocatable, public :: ugrd_output(:,:) + real, allocatable, public :: vgrd_output(:,:) + real, allocatable, public :: rwmr_output(:,:) + real, allocatable, public :: icmr_output(:,:) + real, allocatable, public :: snmr_output(:,:) + real, allocatable, public :: grle_output(:,:) + real, allocatable, public :: cldamt_output(:,:) + real, allocatable, public :: rlat_output(:) + real, allocatable, public :: rlon_output(:) + + public :: set_output_grid + public :: write_output_data + type(Dataset) :: indset, outdset + + + contains + + subroutine set_output_grid + +!------------------------------------------------------------------- +! Set grid specs on the output grid. +!------------------------------------------------------------------- + + use setup + use input_data + use utils + + implicit none + + + type(Dataset) :: indset + real, allocatable :: work2d(:,:) + + + + print* + print*,"OUTPUT GRID I/J DIMENSIONS: ", i_output, j_output + +!------------------------------------------------------------------- +! Set the grib 1 grid description section, which is needed +! by the IPOLATES library. +!------------------------------------------------------------------- + + kgds_output = 0 + + call calc_kgds(i_output, j_output, kgds_output) + +!------------------------------------------------------------------- +! Read the terrain on the output grid. To ensure exact match, +! read it from an existing netcdf file. +!------------------------------------------------------------------- + + print* + print*,"OPEN OUTPUT GRID TERRAIN FILE: ", trim(terrain_file) + indset = open_dataset(terrain_file) + + allocate(hgt_external_output(ij_output)) + + print* + print*,"READ SURFACE HEIGHT" + call read_vardata(indset, 'hgtsfc', work2d) + + hgt_external_output = reshape(work2d,(/ij_output/)) + + call close_dataset(indset) + + end subroutine set_output_grid + + subroutine write_output_data + +!------------------------------------------------------------------- +! Write output grid data to a netcdf file. +!------------------------------------------------------------------- + + use input_data + use setup + + implicit none + + integer :: n,nrev + real, allocatable, dimension (:,:) :: out2d + real, allocatable, dimension (:,:,:) :: out3d + +!------------------------------------------------------------------- +! Set up some header info. +!------------------------------------------------------------------- + + call header_set + +!------------------------------------------------------------------- +! Open and write file. +!------------------------------------------------------------------- +! TODO: note there can be compression applied to this output file if necessary +! see how it's done in the GSI EnKF for example + + + print* + print*,'OPEN OUTPUT FILE: ',trim(output_file) + allocate(out2d(i_output,j_output)) + allocate(out3d(i_output,j_output,lev_output)) + + print*,"WRITE SURFACE HEIGHT" + out2d = reshape(hgt_external_output, (/i_output,j_output/)) + call write_vardata(outdset, 'hgtsfc', out2d) + deallocate(hgt_external_output) + + print*,"WRITE SURFACE PRESSURE" + out2d = reshape(sfcp_output, (/i_output,j_output/)) + call write_vardata(outdset, 'pressfc', out2d) + deallocate(sfcp_output) + + print*,"WRITE TEMPERATURE" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(tmp_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'tmp', out3d) + deallocate(tmp_output) + + print*,"WRITE CLOUD LIQUID WATER" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(clwmr_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'clwmr', out3d) + deallocate(clwmr_output) + + print*,"WRITE SPECIFIC HUMIDITY" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(spfh_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'spfh', out3d) + deallocate(spfh_output) + + print*,"WRITE OZONE" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(o3mr_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'o3mr', out3d) + deallocate(o3mr_output) + + print*,"WRITE U-WINDS" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(ugrd_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'ugrd', out3d) + deallocate(ugrd_output) + + print*,"WRITE V-WINDS" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(vgrd_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'vgrd', out3d) + deallocate(vgrd_output) + + if (idzdt == 1) then + print*,"WRITE DZDT" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(dzdt_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'dzdt', out3d) + deallocate(dzdt_output) + endif + + if (idpres == 1) then + print*,"WRITE DPRES" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(dpres_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'dpres', out3d) + endif + deallocate(dpres_output) + + if (idelz == 1) then + print*,"WRITE DELZ" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(delz_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'delz', out3d) + endif + deallocate(delz_output) + + if (irwmr == 1) then + print*,"WRITE RAIN WATER" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(rwmr_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'rwmr', out3d) + deallocate(rwmr_output) + endif + + if (isnmr == 1) then + print*,"WRITE SNOW WATER" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(snmr_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'snmr', out3d) + deallocate(snmr_output) + endif + + if (iicmr == 1) then + print*,"WRITE ICE WATER" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(icmr_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'icmr', out3d) + deallocate(icmr_output) + endif + + if (igrle == 1) then + print*,"WRITE GRAUPEL" + do n=1,lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(grle_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'grle', out3d) + deallocate(grle_output) + endif + + if (icldamt == 1) then + print*,"WRITE CLD_AMT" + do n = 1, lev_output + nrev = lev_output+1-n + out3d(:,:,n) = reshape(cldamt_output(:,nrev), (/i_output,j_output/)) + end do + call write_vardata(outdset, 'cld_amt', out3d) + deallocate(cldamt_output) + endif + + + deallocate(out2d,out3d) + + return + + end subroutine write_output_data + + subroutine header_set + +!------------------------------------------------------------------- +! copy dimensions and metadata to the output file from the +! input terrain (output res) file +!------------------------------------------------------------------- + + use input_data + use setup + + implicit none + + print* + print*,"SET HEADER INFO FOR OUTPUT FILE." + + indset = open_dataset(ref_file) + outdset = create_dataset(output_file, indset, nocompress=.true.) + + end subroutine header_set + + end module output_data diff --git a/sorc/enkf_chgres_recenter_nc.fd/src/setup.f90 b/sorc/enkf_chgres_recenter_nc.fd/src/setup.f90 new file mode 100644 index 0000000000..ee9956ae03 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/src/setup.f90 @@ -0,0 +1,55 @@ + module setup + + implicit none + + private + + character(len=300), public :: input_file + character(len=300), public :: output_file + character(len=300), public :: terrain_file + character(len=300), public :: ref_file + + integer, public :: i_output + integer, public :: j_output + integer , public :: ij_output + logical, public :: cld_amt + + public :: program_setup + + contains + + subroutine program_setup + + implicit none + + integer :: istat + character(len=500) :: filenamelist + + namelist /chgres_setup/ i_output, j_output, input_file, output_file, & + terrain_file, cld_amt, ref_file + + cld_amt = .false. ! default option + + print* + call getarg(1,filenamelist) + print*,"OPEN SETUP NAMELIST ",trim(filenamelist) + open(43, file=filenamelist, iostat=istat) + if (istat /= 0) then + print*,"FATAL ERROR OPENING NAMELIST FILE. ISTAT IS: ",istat + stop + endif + + print*,"READ SETUP NAMELIST." + read(43, nml=chgres_setup, iostat=istat) + if (istat /= 0) then + print*,"FATAL ERROR READING NAMELIST FILE. ISTAT IS: ",istat + stop + endif + + ij_output = i_output * j_output + + close(43) + + end subroutine program_setup + + end module setup diff --git a/sorc/enkf_chgres_recenter_nc.fd/src/utils.f90 b/sorc/enkf_chgres_recenter_nc.fd/src/utils.f90 new file mode 100644 index 0000000000..786c3644b5 --- /dev/null +++ b/sorc/enkf_chgres_recenter_nc.fd/src/utils.f90 @@ -0,0 +1,776 @@ + module utils + + private + + public :: calc_kgds + public :: newps + public :: newpr1 + public :: vintg + public :: compute_delz + + contains + + subroutine compute_delz(ijm, levp, ak_in, bk_in, ps, zs, t, sphum, delz) + + implicit none + integer, intent(in):: levp, ijm + real, intent(in), dimension(levp+1):: ak_in, bk_in + real, intent(in), dimension(ijm):: ps, zs + real, intent(in), dimension(ijm,levp):: t + real, intent(in), dimension(ijm,levp):: sphum + real, intent(out), dimension(ijm,levp):: delz +! Local: + real, dimension(ijm,levp+1):: zh + real, dimension(ijm,levp+1):: pe0, pn0 + real, dimension(levp+1) :: ak, bk + integer i,k + real, parameter :: GRAV = 9.80665 + real, parameter :: RDGAS = 287.05 + real, parameter :: RVGAS = 461.50 + real :: zvir + real:: grd + + print*,"COMPUTE LAYER THICKNESS." + + grd = grav/rdgas + zvir = rvgas/rdgas - 1. + ak = ak_in + bk = bk_in + ak(levp+1) = max(1.e-9, ak(levp+1)) + + do i=1, ijm + pe0(i,levp+1) = ak(levp+1) + pn0(i,levp+1) = log(pe0(i,levp+1)) + enddo + + do k=levp,1, -1 + do i=1,ijm + pe0(i,k) = ak(k) + bk(k)*ps(i) + pn0(i,k) = log(pe0(i,k)) + enddo + enddo + + do i = 1, ijm + zh(i,1) = zs(i) + enddo + + do k = 2, levp+1 + do i = 1, ijm + zh(i,k) = zh(i,k-1)+t(i,k-1)*(1.+zvir*sphum(i,k-1))* & + (pn0(i,k-1)-pn0(i,k))/grd + enddo + enddo + + do k = 1, levp + do i = 1, ijm + delz(i,k) = zh(i,k) - zh(i,k+1) + enddo + enddo + + end subroutine compute_delz + + subroutine calc_kgds(idim, jdim, kgds) + + implicit none + + integer, intent(in) :: idim, jdim + + integer, intent(out) :: kgds(200) + + kgds = 0 + kgds(1) = 4 ! OCT 6 - TYPE OF GRID (GAUSSIAN) + kgds(2) = idim ! OCT 7-8 - # PTS ON LATITUDE CIRCLE + kgds(3) = jdim ! OCT 9-10 - # PTS ON LONGITUDE CIRCLE + kgds(4) = 90000 ! OCT 11-13 - LAT OF ORIGIN + kgds(5) = 0 ! OCT 14-16 - LON OF ORIGIN + kgds(6) = 128 ! OCT 17 - RESOLUTION FLAG + kgds(7) = -90000 ! OCT 18-20 - LAT OF EXTREME POINT + kgds(8) = nint(-360000./idim) ! OCT 21-23 - LON OF EXTREME POINT + kgds(9) = nint((360.0 / float(idim))*1000.0) + ! OCT 24-25 - LONGITUDE DIRECTION INCR. + kgds(10) = jdim/2 ! OCT 26-27 - NUMBER OF CIRCLES POLE TO EQUATOR + kgds(12) = 255 ! OCT 29 - RESERVED + kgds(20) = 255 ! OCT 5 - NOT USED, SET TO 255 + + end subroutine calc_kgds + + SUBROUTINE NEWPS(ZS,PS,IM,KM,P,T,Q,ZSNEW,PSNEW) +!$$$ SUBPROGRAM DOCUMENTATION BLOCK +! +! SUBPROGRAM: NEWPS COMPUTE NEW SURFACE PRESSURE +! PRGMMR: IREDELL ORG: W/NMC23 DATE: 92-10-31 +! +! ABSTRACT: COMPUTES A NEW SURFACE PRESSURE GIVEN A NEW OROGRAPHY. +! THE NEW PRESSURE IS COMPUTED ASSUMING A HYDROSTATIC BALANCE +! AND A CONSTANT TEMPERATURE LAPSE RATE. BELOW GROUND, THE +! LAPSE RATE IS ASSUMED TO BE -6.5 K/KM. +! +! PROGRAM HISTORY LOG: +! 91-10-31 MARK IREDELL +! +! USAGE: CALL NEWPS(ZS,PS,IM,KM,P,T,Q,ZSNEW,PSNEW) +! INPUT ARGUMENT LIST: +! IM INTEGER NUMBER OF POINTS TO COMPUTE +! ZS REAL (IM) OLD OROGRAPHY (M) +! PS REAL (IM) OLD SURFACE PRESSURE (PA) +! KM INTEGER NUMBER OF LEVELS +! P REAL (IM,KM) PRESSURES (PA) +! T REAL (IM,KM) TEMPERATURES (K) +! Q REAL (IM,KM) SPECIFIC HUMIDITIES (KG/KG) +! ZSNEW REAL (IM) NEW OROGRAPHY (M) +! OUTPUT ARGUMENT LIST: +! PSNEW REAL (IM) NEW SURFACE PRESSURE (PA) +! +! ATTRIBUTES: +! LANGUAGE: FORTRAN +! +!C$$$ + REAL ZS(IM),PS(IM),P(IM,KM),T(IM,KM),Q(IM,KM) + REAL ZSNEW(IM),PSNEW(IM) + PARAMETER(BETA=-6.5E-3,EPSILON=1.E-9) + PARAMETER(G=9.80665,RD=287.05,RV=461.50) + PARAMETER(GOR=G/RD,FV=RV/RD-1.) + REAL ZU(IM) + FTV(AT,AQ)=AT*(1+FV*AQ) + FGAM(APU,ATVU,APD,ATVD)=-GOR*LOG(ATVD/ATVU)/LOG(APD/APU) + FZ0(AP,ATV,AZD,APD)=AZD+ATV/GOR*LOG(APD/AP) + FZ1(AP,ATV,AZD,APD,AGAM)=AZD-ATV/AGAM*((APD/AP)**(-AGAM/GOR)-1) + FP0(AZ,AZU,APU,ATVU)=APU*EXP(-GOR/ATVU*(AZ-AZU)) + FP1(AZ,AZU,APU,ATVU,AGAM)=APU*(1+AGAM/ATVU*(AZ-AZU))**(-GOR/AGAM) +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! COMPUTE SURFACE PRESSURE BELOW THE ORIGINAL GROUND + LS=0 + K=1 + GAMMA=BETA + DO I=1,IM + PU=P(I,K) + TVU=FTV(T(I,K),Q(I,K)) + ZU(I)=FZ1(PU,TVU,ZS(I),PS(I),GAMMA) + IF(ZSNEW(I).LE.ZU(I)) THEN + PU=P(I,K) + TVU=FTV(T(I,K),Q(I,K)) + IF(ABS(GAMMA).GT.EPSILON) THEN + PSNEW(I)=FP1(ZSNEW(I),ZU(I),PU,TVU,GAMMA) + ELSE + PSNEW(I)=FP0(ZSNEW(I),ZU(I),PU,TVU) + ENDIF + ELSE + PSNEW(I)=0 + LS=LS+1 + ENDIF +! endif + ENDDO +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! COMPUTE SURFACE PRESSURE ABOVE THE ORIGINAL GROUND + DO K=2,KM + IF(LS.GT.0) THEN + DO I=1,IM + IF(PSNEW(I).EQ.0) THEN + PU=P(I,K) + TVU=FTV(T(I,K),Q(I,K)) + PD=P(I,K-1) + TVD=FTV(T(I,K-1),Q(I,K-1)) + GAMMA=FGAM(PU,TVU,PD,TVD) + IF(ABS(GAMMA).GT.EPSILON) THEN + ZU(I)=FZ1(PU,TVU,ZU(I),PD,GAMMA) + ELSE + ZU(I)=FZ0(PU,TVU,ZU(I),PD) + ENDIF + IF(ZSNEW(I).LE.ZU(I)) THEN + IF(ABS(GAMMA).GT.EPSILON) THEN + PSNEW(I)=FP1(ZSNEW(I),ZU(I),PU,TVU,GAMMA) + ELSE + PSNEW(I)=FP0(ZSNEW(I),ZU(I),PU,TVU) + ENDIF + LS=LS-1 + ENDIF + ENDIF + ENDDO + ENDIF + ENDDO +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! COMPUTE SURFACE PRESSURE OVER THE TOP + IF(LS.GT.0) THEN + K=KM + GAMMA=0 + DO I=1,IM + IF(PSNEW(I).EQ.0) THEN + PU=P(I,K) + TVU=FTV(T(I,K),Q(I,K)) + PSNEW(I)=FP0(ZSNEW(I),ZU(I),PU,TVU) + ENDIF + ENDDO + ENDIF + END SUBROUTINE NEWPS + + SUBROUTINE NEWPR1(IM,KM,IDVC,IDSL,NVCOORD,VCOORD, & + PS,PM,DP) +!$$$ SUBPROGRAM DOCUMENTATION BLOCK +! +! SUBPROGRAM: NEWPR1 COMPUTE MODEL PRESSURES +! PRGMMR: JUANG ORG: W/NMC23 DATE: 2005-04-11 +! PRGMMR: Fanglin Yang ORG: W/NMC23 DATE: 2006-11-28 +! PRGMMR: S. Moorthi ORG: NCEP/EMC DATE: 2006-12-12 +! PRGMMR: S. Moorthi ORG: NCEP/EMC DATE: 2007-01-02 +! +! ABSTRACT: COMPUTE MODEL PRESSURES. +! +! PROGRAM HISTORY LOG: +! 2005-04-11 HANN_MING HENRY JUANG hybrid sigma, sigma-p, and sigma- +! +! USAGE: CALL NEWPR1(IM,IX,KM,KMP,IDVC,IDSL,NVCOORD,VCOORD,PP,TP,QP,P +! INPUT ARGUMENT LIST: +! IM INTEGER NUMBER OF POINTS TO COMPUTE +! KM INTEGER NUMBER OF LEVELS +! IDVC INTEGER VERTICAL COORDINATE ID +! (1 FOR SIGMA AND 2 FOR HYBRID) +! IDSL INTEGER TYPE OF SIGMA STRUCTURE +! (1 FOR PHILLIPS OR 2 FOR MEAN) +! NVCOORD INTEGER NUMBER OF VERTICAL COORDINATES +! VCOORD REAL (KM+1,NVCOORD) VERTICAL COORDINATE VALUES +! FOR IDVC=1, NVCOORD=1: SIGMA INTERFACE +! FOR IDVC=2, NVCOORD=2: HYBRID INTERFACE A AND B +! FOR IDVC=3, NVCOORD=3: JUANG GENERAL HYBRID INTERFACE +! AK REAL (KM+1) HYBRID INTERFACE A +! BK REAL (KM+1) HYBRID INTERFACE B +! PS REAL (IX) SURFACE PRESSURE (PA) +! OUTPUT ARGUMENT LIST: +! PM REAL (IX,KM) MID-LAYER PRESSURE (PA) +! DP REAL (IX,KM) LAYER DELTA PRESSURE (PA) +! +! ATTRIBUTES: +! LANGUAGE: FORTRAN +! +!C$$$ + IMPLICIT NONE + + INTEGER, INTENT(IN) :: IM, KM, NVCOORD, IDVC, IDSL + + REAL, INTENT(IN) :: VCOORD(KM+1,NVCOORD) + REAL, INTENT(IN) :: PS(IM) + + REAL, INTENT(OUT) :: PM(IM,KM) + REAL, OPTIONAL, INTENT(OUT) :: DP(IM,KM) + + REAL, PARAMETER :: RD=287.05, RV=461.50, CP=1004.6, & + ROCP=RD/CP, ROCP1=ROCP+1, ROCPR=1/ROCP, & + FV=RV/RD-1. + + INTEGER :: I, K + + REAL :: AK(KM+1), BK(KM+1), PI(IM,KM+1) + + IF(IDVC.EQ.2) THEN + DO K=1,KM+1 + AK(K) = VCOORD(K,1) + BK(K) = VCOORD(K,2) + PI(:,K) = AK(K) + BK(K)*PS(:) + ENDDO + ELSE + print*,'routine only works for idvc 2' + stop + ENDIF + + IF(IDSL.EQ.2) THEN + DO K=1,KM + PM(1:IM,K) = (PI(1:IM,K)+PI(1:IM,K+1))/2 + ENDDO + ELSE + DO K=1,KM + PM(1:IM,K) = ((PI(1:IM,K)**ROCP1-PI(1:IM,K+1)**ROCP1)/ & + (ROCP1*(PI(1:IM,K)-PI(1:IM,K+1))))**ROCPR + ENDDO + ENDIF + + IF(PRESENT(DP))THEN + DO K=1,KM + DO I=1,IM + DP(I,K) = PI(I,K) - PI(I,K+1) + ENDDO + ENDDO + ENDIF + + END SUBROUTINE NEWPR1 + + SUBROUTINE TERP3(IM,IXZ1,IXQ1,IXZ2,IXQ2,NM,NXQ1,NXQ2, & + KM1,KXZ1,KXQ1,Z1,Q1,KM2,KXZ2,KXQ2,Z2,Q2,J2) +!$$$ SUBPROGRAM DOCUMENTATION BLOCK +! +! SUBPROGRAM: TERP3 CUBICALLY INTERPOLATE IN ONE DIMENSION +! PRGMMR: IREDELL ORG: W/NMC23 DATE: 98-05-01 +! +! ABSTRACT: INTERPOLATE FIELD(S) IN ONE DIMENSION ALONG THE COLUMN(S). +! THE INTERPOLATION IS CUBIC LAGRANGIAN WITH A MONOTONIC CONSTRAINT +! IN THE CENTER OF THE DOMAIN. IN THE OUTER INTERVALS IT IS LINEAR. +! OUTSIDE THE DOMAIN, FIELDS ARE HELD CONSTANT. +! +! PROGRAM HISTORY LOG: +! 98-05-01 MARK IREDELL +! 1999-01-04 IREDELL USE ESSL SEARCH +! +! USAGE: CALL TERP3(IM,IXZ1,IXQ1,IXZ2,IXQ2,NM,NXQ1,NXQ2, +! & KM1,KXZ1,KXQ1,Z1,Q1,KM2,KXZ2,KXQ2,Z2,Q2,J2) +! INPUT ARGUMENT LIST: +! IM INTEGER NUMBER OF COLUMNS +! IXZ1 INTEGER COLUMN SKIP NUMBER FOR Z1 +! IXQ1 INTEGER COLUMN SKIP NUMBER FOR Q1 +! IXZ2 INTEGER COLUMN SKIP NUMBER FOR Z2 +! IXQ2 INTEGER COLUMN SKIP NUMBER FOR Q2 +! NM INTEGER NUMBER OF FIELDS PER COLUMN +! NXQ1 INTEGER FIELD SKIP NUMBER FOR Q1 +! NXQ2 INTEGER FIELD SKIP NUMBER FOR Q2 +! KM1 INTEGER NUMBER OF INPUT POINTS +! KXZ1 INTEGER POINT SKIP NUMBER FOR Z1 +! KXQ1 INTEGER POINT SKIP NUMBER FOR Q1 +! Z1 REAL (1+(IM-1)*IXZ1+(KM1-1)*KXZ1) +! INPUT COORDINATE VALUES IN WHICH TO INTERPOLATE +! (Z1 MUST BE STRICTLY MONOTONIC IN EITHER DIRECTION) +! Q1 REAL (1+(IM-1)*IXQ1+(KM1-1)*KXQ1+(NM-1)*NXQ1) +! INPUT FIELDS TO INTERPOLATE +! KM2 INTEGER NUMBER OF OUTPUT POINTS +! KXZ2 INTEGER POINT SKIP NUMBER FOR Z2 +! KXQ2 INTEGER POINT SKIP NUMBER FOR Q2 +! Z2 REAL (1+(IM-1)*IXZ2+(KM2-1)*KXZ2) +! OUTPUT COORDINATE VALUES TO WHICH TO INTERPOLATE +! (Z2 NEED NOT BE MONOTONIC) +! +! OUTPUT ARGUMENT LIST: +! Q2 REAL (1+(IM-1)*IXQ2+(KM2-1)*KXQ2+(NM-1)*NXQ2) +! OUTPUT INTERPOLATED FIELDS +! J2 REAL (1+(IM-1)*IXQ2+(KM2-1)*KXQ2+(NM-1)*NXQ2) +! OUTPUT INTERPOLATED FIELDS CHANGE WRT Z2 +! +! SUBPROGRAMS CALLED: +! RSEARCH SEARCH FOR A SURROUNDING REAL INTERVAL +! +! ATTRIBUTES: +! LANGUAGE: FORTRAN +! +!C$$$ + IMPLICIT NONE + INTEGER IM,IXZ1,IXQ1,IXZ2,IXQ2,NM,NXQ1,NXQ2 + INTEGER KM1,KXZ1,KXQ1,KM2,KXZ2,KXQ2 + INTEGER I,K1,K2,N + REAL Z1(1+(IM-1)*IXZ1+(KM1-1)*KXZ1) + REAL Q1(1+(IM-1)*IXQ1+(KM1-1)*KXQ1+(NM-1)*NXQ1) + REAL Z2(1+(IM-1)*IXZ2+(KM2-1)*KXZ2) + REAL Q2(1+(IM-1)*IXQ2+(KM2-1)*KXQ2+(NM-1)*NXQ2) + REAL J2(1+(IM-1)*IXQ2+(KM2-1)*KXQ2+(NM-1)*NXQ2) + REAL FFA(IM),FFB(IM),FFC(IM),FFD(IM) + REAL GGA(IM),GGB(IM),GGC(IM),GGD(IM) + INTEGER K1S(IM,KM2) + REAL Z1A,Z1B,Z1C,Z1D,Q1A,Q1B,Q1C,Q1D,Z2S,Q2S,J2S +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! FIND THE SURROUNDING INPUT INTERVAL FOR EACH OUTPUT POINT. + CALL RSEARCH(IM,KM1,IXZ1,KXZ1,Z1,KM2,IXZ2,KXZ2,Z2,1,IM,K1S) +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! GENERALLY INTERPOLATE CUBICALLY WITH MONOTONIC CONSTRAINT +! FROM TWO NEAREST INPUT POINTS ON EITHER SIDE OF THE OUTPUT POINT, +! BUT WITHIN THE TWO EDGE INTERVALS INTERPOLATE LINEARLY. +! KEEP THE OUTPUT FIELDS CONSTANT OUTSIDE THE INPUT DOMAIN. + +!!$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(IM,IXZ1,IXQ1,IXZ2), & +!!$OMP& SHARED(IXQ2,NM,NXQ1,NXQ2,KM1,KXZ1,KXQ1,Z1,Q1,KM2,KXZ2), & +!!$OMP& SHARED(KXQ2,Z2,Q2,J2,K1S) + + DO K2=1,KM2 + DO I=1,IM + K1=K1S(I,K2) + IF(K1.EQ.1.OR.K1.EQ.KM1-1) THEN + Z2S=Z2(1+(I-1)*IXZ2+(K2-1)*KXZ2) + Z1A=Z1(1+(I-1)*IXZ1+(K1-1)*KXZ1) + Z1B=Z1(1+(I-1)*IXZ1+(K1+0)*KXZ1) + FFA(I)=(Z2S-Z1B)/(Z1A-Z1B) + FFB(I)=(Z2S-Z1A)/(Z1B-Z1A) + GGA(I)=1/(Z1A-Z1B) + GGB(I)=1/(Z1B-Z1A) + ELSEIF(K1.GT.1.AND.K1.LT.KM1-1) THEN + Z2S=Z2(1+(I-1)*IXZ2+(K2-1)*KXZ2) + Z1A=Z1(1+(I-1)*IXZ1+(K1-2)*KXZ1) + Z1B=Z1(1+(I-1)*IXZ1+(K1-1)*KXZ1) + Z1C=Z1(1+(I-1)*IXZ1+(K1+0)*KXZ1) + Z1D=Z1(1+(I-1)*IXZ1+(K1+1)*KXZ1) + FFA(I)=(Z2S-Z1B)/(Z1A-Z1B)* & + (Z2S-Z1C)/(Z1A-Z1C)* & + (Z2S-Z1D)/(Z1A-Z1D) + FFB(I)=(Z2S-Z1A)/(Z1B-Z1A)* & + (Z2S-Z1C)/(Z1B-Z1C)* & + (Z2S-Z1D)/(Z1B-Z1D) + FFC(I)=(Z2S-Z1A)/(Z1C-Z1A)* & + (Z2S-Z1B)/(Z1C-Z1B)* & + (Z2S-Z1D)/(Z1C-Z1D) + FFD(I)=(Z2S-Z1A)/(Z1D-Z1A)* & + (Z2S-Z1B)/(Z1D-Z1B)* & + (Z2S-Z1C)/(Z1D-Z1C) + GGA(I)= 1/(Z1A-Z1B)* & + (Z2S-Z1C)/(Z1A-Z1C)* & + (Z2S-Z1D)/(Z1A-Z1D)+ & + (Z2S-Z1B)/(Z1A-Z1B)* & + 1/(Z1A-Z1C)* & + (Z2S-Z1D)/(Z1A-Z1D)+ & + (Z2S-Z1B)/(Z1A-Z1B)* & + (Z2S-Z1C)/(Z1A-Z1C)* & + 1/(Z1A-Z1D) + GGB(I)= 1/(Z1B-Z1A)* & + (Z2S-Z1C)/(Z1B-Z1C)* & + (Z2S-Z1D)/(Z1B-Z1D)+ & + (Z2S-Z1A)/(Z1B-Z1A)* & + 1/(Z1B-Z1C)* & + (Z2S-Z1D)/(Z1B-Z1D)+ & + (Z2S-Z1A)/(Z1B-Z1A)* & + (Z2S-Z1C)/(Z1B-Z1C)* & + 1/(Z1B-Z1D) + GGC(I)= 1/(Z1C-Z1A)* & + (Z2S-Z1B)/(Z1C-Z1B)* & + (Z2S-Z1D)/(Z1C-Z1D)+ & + (Z2S-Z1A)/(Z1C-Z1A)* & + 1/(Z1C-Z1B)* & + (Z2S-Z1D)/(Z1C-Z1D)+ & + (Z2S-Z1A)/(Z1C-Z1A)* & + (Z2S-Z1B)/(Z1C-Z1B)* & + 1/(Z1C-Z1D) + GGD(I)= 1/(Z1D-Z1A)* & + (Z2S-Z1B)/(Z1D-Z1B)* & + (Z2S-Z1C)/(Z1D-Z1C)+ & + (Z2S-Z1A)/(Z1D-Z1A)* & + 1/(Z1D-Z1B)* & + (Z2S-Z1C)/(Z1D-Z1C)+ & + (Z2S-Z1A)/(Z1D-Z1A)* & + (Z2S-Z1B)/(Z1D-Z1B)* & + 1/(Z1D-Z1C) + ENDIF + ENDDO +! INTERPOLATE. + DO N=1,NM + DO I=1,IM + K1=K1S(I,K2) + IF(K1.EQ.0) THEN + Q2S=Q1(1+(I-1)*IXQ1+(N-1)*NXQ1) + J2S=0 + ELSEIF(K1.EQ.KM1) THEN + Q2S=Q1(1+(I-1)*IXQ1+(KM1-1)*KXQ1+(N-1)*NXQ1) + J2S=0 + ELSEIF(K1.EQ.1.OR.K1.EQ.KM1-1) THEN + Q1A=Q1(1+(I-1)*IXQ1+(K1-1)*KXQ1+(N-1)*NXQ1) + Q1B=Q1(1+(I-1)*IXQ1+(K1+0)*KXQ1+(N-1)*NXQ1) + Q2S=FFA(I)*Q1A+FFB(I)*Q1B + J2S=GGA(I)*Q1A+GGB(I)*Q1B + ELSE + Q1A=Q1(1+(I-1)*IXQ1+(K1-2)*KXQ1+(N-1)*NXQ1) + Q1B=Q1(1+(I-1)*IXQ1+(K1-1)*KXQ1+(N-1)*NXQ1) + Q1C=Q1(1+(I-1)*IXQ1+(K1+0)*KXQ1+(N-1)*NXQ1) + Q1D=Q1(1+(I-1)*IXQ1+(K1+1)*KXQ1+(N-1)*NXQ1) + Q2S=FFA(I)*Q1A+FFB(I)*Q1B+FFC(I)*Q1C+FFD(I)*Q1D + J2S=GGA(I)*Q1A+GGB(I)*Q1B+GGC(I)*Q1C+GGD(I)*Q1D + IF(Q2S.LT.MIN(Q1B,Q1C)) THEN + Q2S=MIN(Q1B,Q1C) + J2S=0 + ELSEIF(Q2S.GT.MAX(Q1B,Q1C)) THEN + Q2S=MAX(Q1B,Q1C) + J2S=0 + ENDIF + ENDIF + Q2(1+(I-1)*IXQ2+(K2-1)*KXQ2+(N-1)*NXQ2)=Q2S + J2(1+(I-1)*IXQ2+(K2-1)*KXQ2+(N-1)*NXQ2)=J2S + ENDDO + ENDDO + ENDDO +!!$OMP END PARALLEL DO + + END SUBROUTINE TERP3 + + SUBROUTINE RSEARCH(IM,KM1,IXZ1,KXZ1,Z1,KM2,IXZ2,KXZ2,Z2,IXL2,KXL2,& + L2) +!$$$ SUBPROGRAM DOCUMENTATION BLOCK +! +! SUBPROGRAM: RSEARCH SEARCH FOR A SURROUNDING REAL INTERVAL +! PRGMMR: IREDELL ORG: W/NMC23 DATE: 98-05-01 +! +! ABSTRACT: THIS SUBPROGRAM SEARCHES MONOTONIC SEQUENCES OF REAL NUMBERS +! FOR INTERVALS THAT SURROUND A GIVEN SEARCH SET OF REAL NUMBERS. +! THE SEQUENCES MAY BE MONOTONIC IN EITHER DIRECTION; THE REAL NUMBERS +! MAY BE SINGLE OR DOUBLE PRECISION; THE INPUT SEQUENCES AND SETS +! AND THE OUTPUT LOCATIONS MAY BE ARBITRARILY DIMENSIONED. +! +! PROGRAM HISTORY LOG: +! 1999-01-05 MARK IREDELL +! +! USAGE: CALL RSEARCH(IM,KM1,IXZ1,KXZ1,Z1,KM2,IXZ2,KXZ2,Z2,IXL2,KXL2, +! & L2) +! INPUT ARGUMENT LIST: +! IM INTEGER NUMBER OF SEQUENCES TO SEARCH +! KM1 INTEGER NUMBER OF POINTS IN EACH SEQUENCE +! IXZ1 INTEGER SEQUENCE SKIP NUMBER FOR Z1 +! KXZ1 INTEGER POINT SKIP NUMBER FOR Z1 +! Z1 REAL (1+(IM-1)*IXZ1+(KM1-1)*KXZ1) +! SEQUENCE VALUES TO SEARCH +! (Z1 MUST BE MONOTONIC IN EITHER DIRECTION) +! KM2 INTEGER NUMBER OF POINTS TO SEARCH FOR +! IN EACH RESPECTIVE SEQUENCE +! IXZ2 INTEGER SEQUENCE SKIP NUMBER FOR Z2 +! KXZ2 INTEGER POINT SKIP NUMBER FOR Z2 +! Z2 REAL (1+(IM-1)*IXZ2+(KM2-1)*KXZ2) +! SET OF VALUES TO SEARCH FOR +! (Z2 NEED NOT BE MONOTONIC) +! IXL2 INTEGER SEQUENCE SKIP NUMBER FOR L2 +! KXL2 INTEGER POINT SKIP NUMBER FOR L2 +! +! OUTPUT ARGUMENT LIST: +! L2 INTEGER (1+(IM-1)*IXL2+(KM2-1)*KXL2) +! INTERVAL LOCATIONS HAVING VALUES FROM 0 TO KM1 +! (Z2 WILL BE BETWEEN Z1(L2) AND Z1(L2+1)) +! +! SUBPROGRAMS CALLED: +! SBSRCH ESSL BINARY SEARCH +! DBSRCH ESSL BINARY SEARCH +! +! REMARKS: +! IF THE ARRAY Z1 IS DIMENSIONED (IM,KM1), THEN THE SKIP NUMBERS ARE +! IXZ1=1 AND KXZ1=IM; IF IT IS DIMENSIONED (KM1,IM), THEN THE SKIP +! NUMBERS ARE IXZ1=KM1 AND KXZ1=1; IF IT IS DIMENSIONED (IM,JM,KM1), +! THEN THE SKIP NUMBERS ARE IXZ1=1 AND KXZ1=IM*JM; ETCETERA. +! SIMILAR EXAMPLES APPLY TO THE SKIP NUMBERS FOR Z2 AND L2. +! +! RETURNED VALUES OF 0 OR KM1 INDICATE THAT THE GIVEN SEARCH VALUE +! IS OUTSIDE THE RANGE OF THE SEQUENCE. +! +! IF A SEARCH VALUE IS IDENTICAL TO ONE OF THE SEQUENCE VALUES +! THEN THE LOCATION RETURNED POINTS TO THE IDENTICAL VALUE. +! IF THE SEQUENCE IS NOT STRICTLY MONOTONIC AND A SEARCH VALUE IS +! IDENTICAL TO MORE THAN ONE OF THE SEQUENCE VALUES, THEN THE +! LOCATION RETURNED MAY POINT TO ANY OF THE IDENTICAL VALUES. +! +! TO BE EXACT, FOR EACH I FROM 1 TO IM AND FOR EACH K FROM 1 TO KM2, +! Z=Z2(1+(I-1)*IXZ2+(K-1)*KXZ2) IS THE SEARCH VALUE AND +! L=L2(1+(I-1)*IXL2+(K-1)*KXL2) IS THE LOCATION RETURNED. +! IF L=0, THEN Z IS LESS THAN THE START POINT Z1(1+(I-1)*IXZ1) +! FOR ASCENDING SEQUENCES (OR GREATER THAN FOR DESCENDING SEQUENCES). +! IF L=KM1, THEN Z IS GREATER THAN OR EQUAL TO THE END POINT +! Z1(1+(I-1)*IXZ1+(KM1-1)*KXZ1) FOR ASCENDING SEQUENCES +! (OR LESS THAN OR EQUAL TO FOR DESCENDING SEQUENCES). +! OTHERWISE Z IS BETWEEN THE VALUES Z1(1+(I-1)*IXZ1+(L-1)*KXZ1) AND +! Z1(1+(I-1)*IXZ1+(L-0)*KXZ1) AND MAY EQUAL THE FORMER. +! +! ATTRIBUTES: +! LANGUAGE: FORTRAN +! +!C$$$ +! IMPLICIT NONE +! INTEGER,INTENT(IN):: IM,KM1,IXZ1,KXZ1,KM2,IXZ2,KXZ2,IXL2,KXL2 +! REAL,INTENT(IN):: Z1(1+(IM-1)*IXZ1+(KM1-1)*KXZ1) +! REAL,INTENT(IN):: Z2(1+(IM-1)*IXZ2+(KM2-1)*KXZ2) +! INTEGER,INTENT(OUT):: L2(1+(IM-1)*IXL2+(KM2-1)*KXL2) +! INTEGER(4) INCX,N,INCY,M,INDX(KM2),RC(KM2),IOPT +! INTEGER I,K2 +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! FIND THE SURROUNDING INPUT INTERVAL FOR EACH OUTPUT POINT. +! DO I=1,IM +! IF(Z1(1+(I-1)*IXZ1).LE.Z1(1+(I-1)*IXZ1+(KM1-1)*KXZ1)) THEN +! INPUT COORDINATE IS MONOTONICALLY ASCENDING. +! INCX=KXZ2 +! N=KM2 +! INCY=KXZ1 +! M=KM1 +! IOPT=1 +! IF(DIGITS(1.).LT.DIGITS(1._8)) THEN +! CALL SBSRCH(Z2(1+(I-1)*IXZ2),INCX,N, +! & Z1(1+(I-1)*IXZ1),INCY,M,INDX,RC,IOPT) +! ELSE +! CALL DBSRCH(Z2(1+(I-1)*IXZ2),INCX,N, +! & Z1(1+(I-1)*IXZ1),INCY,M,INDX,RC,IOPT) +! ENDIF +! DO K2=1,KM2 +! L2(1+(I-1)*IXL2+(K2-1)*KXL2)=INDX(K2)-RC(K2) +! ENDDO +! ELSE +! INPUT COORDINATE IS MONOTONICALLY DESCENDING. +! INCX=KXZ2 +! N=KM2 +! INCY=-KXZ1 +! M=KM1 +! IOPT=0 +! IF(DIGITS(1.).LT.DIGITS(1._8)) THEN +! CALL SBSRCH(Z2(1+(I-1)*IXZ2),INCX,N, +! & Z1(1+(I-1)*IXZ1),INCY,M,INDX,RC,IOPT) +! ELSE +! CALL DBSRCH(Z2(1+(I-1)*IXZ2),INCX,N, +! & Z1(1+(I-1)*IXZ1),INCY,M,INDX,RC,IOPT) +! ENDIF +! DO K2=1,KM2 +! L2(1+(I-1)*IXL2+(K2-1)*KXL2)=KM1+1-INDX(K2) +! ENDDO +! ENDIF +! ENDDO +! + IMPLICIT NONE + INTEGER,INTENT(IN):: IM,KM1,IXZ1,KXZ1,KM2,IXZ2,KXZ2,IXL2,KXL2 + REAL,INTENT(IN):: Z1(1+(IM-1)*IXZ1+(KM1-1)*KXZ1) + REAL,INTENT(IN):: Z2(1+(IM-1)*IXZ2+(KM2-1)*KXZ2) + INTEGER,INTENT(OUT):: L2(1+(IM-1)*IXL2+(KM2-1)*KXL2) + INTEGER I,K2,L + REAL Z +!C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +!C FIND THE SURROUNDING INPUT INTERVAL FOR EACH OUTPUT POINT. + DO I=1,IM + IF(Z1(1+(I-1)*IXZ1).LE.Z1(1+(I-1)*IXZ1+(KM1-1)*KXZ1)) THEN +!C INPUT COORDINATE IS MONOTONICALLY ASCENDING. + DO K2=1,KM2 + Z=Z2(1+(I-1)*IXZ2+(K2-1)*KXZ2) + L=0 + DO + IF(Z.LT.Z1(1+(I-1)*IXZ1+L*KXZ1)) EXIT + L=L+1 + IF(L.EQ.KM1) EXIT + ENDDO + L2(1+(I-1)*IXL2+(K2-1)*KXL2)=L + ENDDO + ELSE +!C INPUT COORDINATE IS MONOTONICALLY DESCENDING. + DO K2=1,KM2 + Z=Z2(1+(I-1)*IXZ2+(K2-1)*KXZ2) + L=0 + DO + IF(Z.GT.Z1(1+(I-1)*IXZ1+L*KXZ1)) EXIT + L=L+1 + IF(L.EQ.KM1) EXIT + ENDDO + L2(1+(I-1)*IXL2+(K2-1)*KXL2)=L + ENDDO + ENDIF + ENDDO + + END SUBROUTINE RSEARCH + + SUBROUTINE VINTG(IM,KM1,KM2,NT,P1,U1,V1,T1,Q1,W1,P2, & + U2,V2,T2,Q2,W2) +!$$$ SUBPROGRAM DOCUMENTATION BLOCK +! +! SUBPROGRAM: VINTG VERTICALLY INTERPOLATE UPPER-AIR FIELDS +! PRGMMR: IREDELL ORG: W/NMC23 DATE: 92-10-31 +! +! ABSTRACT: VERTICALLY INTERPOLATE UPPER-AIR FIELDS. +! WIND, TEMPERATURE, HUMIDITY AND OTHER TRACERS ARE INTERPOLATED. +! THE INTERPOLATION IS CUBIC LAGRANGIAN IN LOG PRESSURE +! WITH A MONOTONIC CONSTRAINT IN THE CENTER OF THE DOMAIN. +! IN THE OUTER INTERVALS IT IS LINEAR IN LOG PRESSURE. +! OUTSIDE THE DOMAIN, FIELDS ARE GENERALLY HELD CONSTANT, +! EXCEPT FOR TEMPERATURE AND HUMIDITY BELOW THE INPUT DOMAIN, +! WHERE THE TEMPERATURE LAPSE RATE IS HELD FIXED AT -6.5 K/KM AND +! THE RELATIVE HUMIDITY IS HELD CONSTANT. +! +! PROGRAM HISTORY LOG: +! 91-10-31 MARK IREDELL +! +! USAGE: CALL VINTG(IM,KM1,KM2,NT,P1,U1,V1,T1,Q1,P2, +! & U2,V2,T2,Q2) +! INPUT ARGUMENT LIST: +! IM INTEGER NUMBER OF POINTS TO COMPUTE +! KM1 INTEGER NUMBER OF INPUT LEVELS +! KM2 INTEGER NUMBER OF OUTPUT LEVELS +! NT INTEGER NUMBER OF TRACERS +! P1 REAL (IM,KM1) INPUT PRESSURES +! ORDERED FROM BOTTOM TO TOP OF ATMOSPHERE +! U1 REAL (IM,KM1) INPUT ZONAL WIND +! V1 REAL (IM,KM1) INPUT MERIDIONAL WIND +! T1 REAL (IM,KM1) INPUT TEMPERATURE (K) +! Q1 REAL (IM,KM1,NT) INPUT TRACERS (HUMIDITY FIRST) +! P2 REAL (IM,KM2) OUTPUT PRESSURES +! OUTPUT ARGUMENT LIST: +! U2 REAL (IM,KM2) OUTPUT ZONAL WIND +! V2 REAL (IM,KM2) OUTPUT MERIDIONAL WIND +! T2 REAL (IM,KM2) OUTPUT TEMPERATURE (K) +! Q2 REAL (IM,KM2,NT) OUTPUT TRACERS (HUMIDITY FIRST) +! +! SUBPROGRAMS CALLED: +! TERP3 CUBICALLY INTERPOLATE IN ONE DIMENSION +! +! ATTRIBUTES: +! LANGUAGE: FORTRAN +! +!C$$$ + IMPLICIT NONE + + INTEGER, INTENT(IN) :: IM, KM1, KM2, NT + + REAL, INTENT(IN) :: P1(IM,KM1),U1(IM,KM1),V1(IM,KM1) + REAL, INTENT(IN) :: T1(IM,KM1),Q1(IM,KM1,NT) + REAL, INTENT(IN) :: W1(IM,KM1),P2(IM,KM2) + REAL, INTENT(OUT) :: U2(IM,KM2),V2(IM,KM2) + REAL, INTENT(OUT) :: T2(IM,KM2),Q2(IM,KM2,NT) + REAL, INTENT(OUT) :: W2(IM,KM2) + + REAL, PARAMETER :: DLTDZ=-6.5E-3*287.05/9.80665 + REAL, PARAMETER :: DLPVDRT=-2.5E6/461.50 + + INTEGER :: I, K, N + + REAL :: DZ + REAL,ALLOCATABLE :: Z1(:,:),Z2(:,:) + REAL,ALLOCATABLE :: C1(:,:,:),C2(:,:,:),J2(:,:,:) + + ALLOCATE (Z1(IM+1,KM1),Z2(IM+1,KM2)) + ALLOCATE (C1(IM+1,KM1,4+NT),C2(IM+1,KM2,4+NT),J2(IM+1,KM2,4+NT)) +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! COMPUTE LOG PRESSURE INTERPOLATING COORDINATE +! AND COPY INPUT WIND, TEMPERATURE, HUMIDITY AND OTHER TRACERS +!$OMP PARALLEL DO PRIVATE(K,I) + DO K=1,KM1 + DO I=1,IM + Z1(I,K) = -LOG(P1(I,K)) + C1(I,K,1) = U1(I,K) + C1(I,K,2) = V1(I,K) + C1(I,K,3) = W1(I,K) + C1(I,K,4) = T1(I,K) + C1(I,K,5) = Q1(I,K,1) + ENDDO + ENDDO +!$OMP END PARALLEL DO + DO N=2,NT + DO K=1,KM1 + DO I=1,IM + C1(I,K,4+N) = Q1(I,K,N) + ENDDO + ENDDO + ENDDO +!$OMP PARALLEL DO PRIVATE(K,I) + DO K=1,KM2 + DO I=1,IM + Z2(I,K) = -LOG(P2(I,K)) + ENDDO + ENDDO +!$OMP END PARALLEL DO +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! PERFORM LAGRANGIAN ONE-DIMENSIONAL INTERPOLATION +! THAT IS 4TH-ORDER IN INTERIOR, 2ND-ORDER IN OUTSIDE INTERVALS +! AND 1ST-ORDER FOR EXTRAPOLATION. + CALL TERP3(IM,1,1,1,1,4+NT,(IM+1)*KM1,(IM+1)*KM2, & + KM1,IM+1,IM+1,Z1,C1,KM2,IM+1,IM+1,Z2,C2,J2) +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! COPY OUTPUT WIND, TEMPERATURE, HUMIDITY AND OTHER TRACERS +! EXCEPT BELOW THE INPUT DOMAIN, LET TEMPERATURE INCREASE WITH A FIXED +! LAPSE RATE AND LET THE RELATIVE HUMIDITY REMAIN CONSTANT. + DO K=1,KM2 + DO I=1,IM + U2(I,K)=C2(I,K,1) + V2(I,K)=C2(I,K,2) + W2(I,K)=C2(I,K,3) + DZ=Z2(I,K)-Z1(I,1) + IF(DZ.GE.0) THEN + T2(I,K)=C2(I,K,4) + Q2(I,K,1)=C2(I,K,5) + ELSE + T2(I,K)=T1(I,1)*EXP(DLTDZ*DZ) + Q2(I,K,1)=Q1(I,1,1)*EXP(DLPVDRT*(1/T2(I,K)-1/T1(I,1))-DZ) + ENDIF + ENDDO + ENDDO + DO N=2,NT + DO K=1,KM2 + DO I=1,IM + Q2(I,K,N)=C2(I,K,4+N) + ENDDO + ENDDO + ENDDO + DEALLOCATE (Z1,Z2,C1,C2,J2) + END SUBROUTINE VINTG + end module utils diff --git a/sorc/fv3gfs_build.cfg b/sorc/fv3gfs_build.cfg index 190ff0e994..9dc2d3a90c 100644 --- a/sorc/fv3gfs_build.cfg +++ b/sorc/fv3gfs_build.cfg @@ -1,26 +1,27 @@ # # ***** configuration of fv3gfs build ***** - Building libraries (libs) ............................. no - Building fv3gfs (fv3gfs) .............................. yes - Building gsi (gsi) .................................... yes - Building gdas (gdas) .................................. yes - Building ncep_post (ncep_post) ........................ yes - Building ufs_utils (ufs_utils) ........................ yes - Building gfs_wafs (gfs_wafs) .......................... yes - Building sfcanl_nsttfchg (sfcanl_nsttfchg)............. yes - Building enkf_chgres_recenter (enkf_chgres_recenter) .. yes - Building tropcy_NEMS (tropcy) ......................... yes - Building gfs_fbwndgfs (gfs_fbwndgfs) .................. yes - Building gfs_overpdtg2 (gfs_overpdtg2) ................ yes - Building gfs_wintemv (gfs_wintemv) .................... yes - Building gfs_bufrsnd (gfs_bufrsnd) .................... yes - Building fv3nc2nemsio (fv3nc2nemsio) .................. yes - Building regrid_nemsio (regrid_nemsio) ................ yes - Building gsd_prep_chem (gsd_prep_chem) ................ yes - Building gfs_util (gfs_util) .......................... yes - Building prod_util (prod_util) ........................ no - Building grib_util (grib_util) ........................ no + Building libraries (libs) .................................... no + Building fv3gfs (fv3gfs) ..................................... yes + Building gsi (gsi) ........................................... yes + Building gdas (gdas) ......................................... no + Building ncep_post (ncep_post) ............................... yes + Building ufs_utils (ufs_utils) ............................... yes + Building gfs_wafs (gfs_wafs) ................................. no + Building sfcanl_nsttfchg (sfcanl_nsttfchg).................... no + Building enkf_chgres_recenter (enkf_chgres_recenter) ......... no + Building enkf_chgres_recenter_nc (enkf_chgres_recenter_nc) ... yes + Building tropcy_NEMS (tropcy) ................................ no + Building gfs_fbwndgfs (gfs_fbwndgfs) ......................... no + Building gfs_overpdtg2 (gfs_overpdtg2) ....................... no + Building gfs_wintemv (gfs_wintemv) ........................... no + Building gfs_bufrsnd (gfs_bufrsnd) ........................... yes + Building fv3nc2nemsio (fv3nc2nemsio) ......................... no + Building regrid_nemsio (regrid_nemsio) ....................... no + Building gsd_prep_chem (gsd_prep_chem) ....................... yes + Building gfs_util (gfs_util) ................................. no + Building prod_util (prod_util) ............................... no + Building grib_util (grib_util) ............................... no # -- END -- diff --git a/sorc/link_fv3gfs.sh b/sorc/link_fv3gfs.sh index d32a637622..4175406514 100755 --- a/sorc/link_fv3gfs.sh +++ b/sorc/link_fv3gfs.sh @@ -45,10 +45,10 @@ for dir in fix_am fix_chem fix_fv3 fix_orog fix_fv3_gmted2010 fix_verif; do done $LINK $FIX_DIR/* . -if [ -d ${pwd}/ufs_utils.fd ]; then - cd ${pwd}/ufs_utils.fd/sorc - ./link_fixdirs.sh $RUN_ENVIR $machine -fi +# if [ -d ${pwd}/ufs_utils.fd ]; then +# cd ${pwd}/ufs_utils.fd/sorc +# ./link_fixdirs.sh $RUN_ENVIR $machine +# fi #--------------------------------------- #--add files from external repositories @@ -71,7 +71,7 @@ cd ${pwd}/../ush ||exit 8 done for file in emcsfc_ice_blend.sh fv3gfs_driver_grid.sh fv3gfs_make_orog.sh global_cycle_driver.sh \ emcsfc_snow.sh fv3gfs_filter_topo.sh global_chgres_driver.sh global_cycle.sh \ - fv3gfs_chgres.sh fv3gfs_make_grid.sh global_chgres.sh ; do + fv3gfs_chgres.sh fv3gfs_make_grid.sh global_chgres.sh chgres_cube.sh; do $LINK ../sorc/ufs_utils.fd/ush/$file . done cd ${pwd}/../util ||exit 8 @@ -83,41 +83,29 @@ cd ${pwd}/../util ||exit 8 #------------------------------ #--add gfs_wafs link if on Dell -if [ $machine = dell -o $machine = hera ]; then -#------------------------------ - cd ${pwd}/../jobs ||exit 8 - $LINK ../sorc/gfs_wafs.fd/jobs/* . - cd ${pwd}/../parm ||exit 8 - [[ -d wafs ]] && rm -rf wafs - $LINK ../sorc/gfs_wafs.fd/parm/wafs wafs - cd ${pwd}/../scripts ||exit 8 - $LINK ../sorc/gfs_wafs.fd/scripts/* . - cd ${pwd}/../ush ||exit 8 - $LINK ../sorc/gfs_wafs.fd/ush/* . - cd ${pwd}/../fix ||exit 8 - $LINK ../sorc/gfs_wafs.fd/fix/* . -fi +# if [ $machine = dell -o $machine = hera ]; then +# #------------------------------ +# cd ${pwd}/../jobs ||exit 8 +# $LINK ../sorc/gfs_wafs.fd/jobs/* . +# cd ${pwd}/../parm ||exit 8 +# [[ -d wafs ]] && rm -rf wafs +# $LINK ../sorc/gfs_wafs.fd/parm/wafs wafs +# cd ${pwd}/../scripts ||exit 8 +# $LINK ../sorc/gfs_wafs.fd/scripts/* . +# cd ${pwd}/../ush ||exit 8 +# $LINK ../sorc/gfs_wafs.fd/ush/* . +# cd ${pwd}/../fix ||exit 8 +# $LINK ../sorc/gfs_wafs.fd/fix/* . +# fi #------------------------------ #--add GSI/EnKF file #------------------------------ cd ${pwd}/../jobs ||exit 8 - $LINK ../sorc/gsi.fd/jobs/JGLOBAL_ANALYSIS . - $LINK ../sorc/gsi.fd/jobs/JGLOBAL_ENKF_SELECT_OBS . - $LINK ../sorc/gsi.fd/jobs/JGLOBAL_ENKF_INNOVATE_OBS . - $LINK ../sorc/gsi.fd/jobs/JGLOBAL_ENKF_UPDATE . - $LINK ../sorc/gsi.fd/jobs/JGDAS_ENKF_RECENTER . $LINK ../sorc/gsi.fd/jobs/JGDAS_ENKF_FCST . $LINK ../sorc/gsi.fd/jobs/JGDAS_ENKF_POST . cd ${pwd}/../scripts ||exit 8 - $LINK ../sorc/gsi.fd/scripts/exglobal_analysis_fv3gfs.sh.ecf . - $LINK ../sorc/gsi.fd/scripts/exglobal_innovate_obs_fv3gfs.sh.ecf . - $LINK ../sorc/gsi.fd/scripts/exglobal_enkf_innovate_obs_fv3gfs.sh.ecf . - $LINK ../sorc/gsi.fd/scripts/exglobal_enkf_update_fv3gfs.sh.ecf . - $LINK ../sorc/gsi.fd/scripts/exglobal_enkf_recenter_fv3gfs.sh.ecf . - $LINK ../sorc/gsi.fd/scripts/exglobal_enkf_fcst_fv3gfs.sh.ecf . - $LINK ../sorc/gsi.fd/scripts/exglobal_enkf_post_fv3gfs.sh.ecf . cd ${pwd}/../fix ||exit 8 [[ -d fix_gsi ]] && rm -rf fix_gsi $LINK ../sorc/gsi.fd/fix fix_gsi @@ -138,10 +126,6 @@ cd ${pwd}/../fix ||exit 8 $LINK ../../sorc/gsi.fd/util/Radiance_Monitor/nwprod/gdas_radmon.v3.0.0/fix/gdas_radmon_satype.txt . $LINK ../../sorc/gsi.fd/util/Radiance_Monitor/nwprod/gdas_radmon.v3.0.0/fix/gdas_radmon_scaninfo.txt . cd ${pwd}/../jobs ||exit 8 - $LINK ../sorc/gsi.fd/util/Minimization_Monitor/nwprod/gdas.v1.0.0/jobs/JGDAS_VMINMON . - $LINK ../sorc/gsi.fd/util/Minimization_Monitor/nwprod/gfs.v1.0.0/jobs/JGFS_VMINMON . - $LINK ../sorc/gsi.fd/util/Ozone_Monitor/nwprod/gdas_oznmon.v2.0.0/jobs/JGDAS_VERFOZN . - $LINK ../sorc/gsi.fd/util/Radiance_Monitor/nwprod/gdas_radmon.v3.0.0/jobs/JGDAS_VERFRAD . cd ${pwd}/../parm ||exit 8 [[ -d mon ]] && rm -rf mon mkdir -p mon @@ -152,10 +136,6 @@ cd ${pwd}/../parm ||exit 8 $LINK ../../sorc/gsi.fd/util/Ozone_Monitor/nwprod/gdas_oznmon.v2.0.0/parm/gdas_oznmon.parm . # $LINK ../../sorc/gsi.fd/util/Radiance_Monitor/nwprod/gdas_radmon.v3.0.0/parm/gdas_radmon.parm . cd ${pwd}/../scripts ||exit 8 - $LINK ../sorc/gsi.fd/util/Minimization_Monitor/nwprod/gdas.v1.0.0/scripts/exgdas_vrfminmon.sh.ecf . - $LINK ../sorc/gsi.fd/util/Minimization_Monitor/nwprod/gfs.v1.0.0/scripts/exgfs_vrfminmon.sh.ecf . - $LINK ../sorc/gsi.fd/util/Ozone_Monitor/nwprod/gdas_oznmon.v2.0.0/scripts/exgdas_vrfyozn.sh.ecf . - $LINK ../sorc/gsi.fd/util/Radiance_Monitor/nwprod/gdas_radmon.v3.0.0/scripts/exgdas_vrfyrad.sh.ecf . cd ${pwd}/../ush ||exit 8 $LINK ../sorc/gsi.fd/util/Minimization_Monitor/nwprod/minmon_shared.v1.0.1/ush/minmon_xtrct_costs.pl . $LINK ../sorc/gsi.fd/util/Minimization_Monitor/nwprod/minmon_shared.v1.0.1/ush/minmon_xtrct_gnorms.pl . @@ -174,7 +154,7 @@ cd ${pwd}/../ush ||exit 8 cd ${pwd}/../jobs ||exit 8 $LINK ../sorc/gsd_prep_chem.fd/workflow/emc-global/jobs/JGLOBAL_PREP_CHEM . cd ${pwd}/../scripts ||exit 8 - $LINK ../sorc/gsd_prep_chem.fd/workflow/emc-global/scripts/exglobal_prep_chem.bash . + $LINK ../sorc/gsd_prep_chem.fd/workflow/emc-global/scripts/exglobal_prep_chem.sh . #------------------------------ #--link executables @@ -200,17 +180,13 @@ if [ $machine = dell -o $machine = hera ]; then done fi -for ufs_utilsexe in \ - chgres_cube.exe fregrid make_hgrid nemsio_get shave.x \ - emcsfc_ice_blend fregrid_parallel make_hgrid_parallel nemsio_read \ - emcsfc_snow2mdl global_chgres make_solo_mosaic nst_tf_chg.x \ - filter_topo global_cycle mkgfsnemsioctl orog.x ; do +for ufs_utilsexe in chgres_cube nemsio_get nemsio_read global_chgres ; do [[ -s $ufs_utilsexe ]] && rm -f $ufs_utilsexe $LINK ../sorc/ufs_utils.fd/exec/$ufs_utilsexe . done -for gsiexe in global_gsi.x global_enkf.x calc_increment_ens.x calc_increment_ens_gsdchem.x getsfcensmeanp.x \ - getsigensmeanp_smooth.x getsigensstatp.x nc_diag_cat_serial.x nc_diag_cat.x recentersigp.x oznmon_horiz.x \ +for gsiexe in global_gsi.x global_enkf.x calc_increment_ens.x getsfcensmeanp.x \ + getsigensmeanp_smooth.x getsigensstatp.x recentersigp.x oznmon_horiz.x \ oznmon_time.x radmon_angle.x radmon_bcoef.x radmon_bcor.x radmon_time.x ;do [[ -s $gsiexe ]] && rm -f $gsiexe $LINK ../sorc/gsi.fd/exec/$gsiexe . @@ -246,8 +222,8 @@ cd ${pwd}/../sorc || exit 8 $SLINK ufs_utils.fd/sorc/fre-nctools.fd/tools/$prog ${prog}.fd done for prog in chgres_cube.fd global_cycle.fd nemsio_read.fd \ - emcsfc_ice_blend.fd mkgfsnemsioctl.fd nst_tf_chg.fd \ - emcsfc_snow2mdl.fd global_chgres.fd nemsio_get.fd orog.fd ;do + mkgfsnemsioctl.fd nst_tf_chg.fd \ + global_chgres.fd nemsio_get.fd orog.fd ;do $SLINK ufs_utils.fd/sorc/$prog $prog done diff --git a/sorc/partial_build.sh b/sorc/partial_build.sh index acde105dea..e5c2d216a2 100755 --- a/sorc/partial_build.sh +++ b/sorc/partial_build.sh @@ -9,6 +9,7 @@ "Build_sfcanl_nsttfchg" \ "Build_tropcy" \ "Build_enkf_chgres_recenter" \ + "Build_enkf_chgres_recenter_nc" \ "Build_gfs_fbwndgfs" "Build_gfs_overpdtg2" \ "Build_gfs_wintemv" \ "Build_gfs_bufrsnd" \ diff --git a/util/modulefiles/gfs_util.wcoss_dell_p3 b/util/modulefiles/gfs_util.wcoss_dell_p3 index 1390c1fe7c..d6fbd11082 100755 --- a/util/modulefiles/gfs_util.wcoss_dell_p3 +++ b/util/modulefiles/gfs_util.wcoss_dell_p3 @@ -19,6 +19,6 @@ module load ip/3.0.1 module load sp/2.0.2 module load g2/3.1.0 - module load bufr/11.2.0 + module load bufr/11.3.1 module load graphics/2.0.0