From 6c6ccda4cafa0a85fe081061dd039a341f007bcc Mon Sep 17 00:00:00 2001 From: Liam Bindle Date: Fri, 31 Jul 2020 09:45:29 -0600 Subject: [PATCH 1/2] Moved (and slightly updated) the old script lines that configured GEOS-Chem Classic to the new geos-chem-classic wrapper --- CMakeLists.txt | 245 +++++++++++++++++++- CMakeScripts/FindNetCDF.cmake | 182 +++++++++++++++ CMakeScripts/GC-ConfigureClassic.cmake | 307 +++++++++++++++++++++++++ CMakeScripts/GC-Helpers.cmake | 185 +++++++++++++++ CMakeScripts/try_compile.F90 | 57 +++++ src/CMakeLists.txt | 2 +- 6 files changed, 965 insertions(+), 13 deletions(-) create mode 100755 CMakeScripts/FindNetCDF.cmake create mode 100755 CMakeScripts/GC-ConfigureClassic.cmake create mode 100755 CMakeScripts/GC-Helpers.cmake create mode 100644 CMakeScripts/try_compile.F90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 3593971..2f37864 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,21 +19,61 @@ if(POLICY CMP0079) endif() #--------------------------------------------------------------------- -# Set high-level logicals for using this repository +# Add CMakeScripts/ to the module path and import helper functions #--------------------------------------------------------------------- -set(GCCLASSIC_WRAPPER TRUE) -set(GC_EXTERNAL_CONFIG FALSE) -set(HEMCO_EXTERNAL_CONFIG TRUE) +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/CMakeScripts) +include(GC-Helpers) + +add_library(GEOSChemBuildProperties INTERFACE) #--------------------------------------------------------------------- -# Set install to run directory +# Set default compiler options #--------------------------------------------------------------------- -set(RUNDIR ${CMAKE_BINARY_DIR}/.. CACHE PATH "Path to GEOS-Chem run directory") -if(RUNDIR) - set(CMAKE_INSTALL_PREFIX ${RUNDIR} CACHE PATH "Install prefix for GEOS-Chem" FORCE) - set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE) +if("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "Intel") + target_compile_options(GEOSChemBuildProperties INTERFACE + -cpp -w -auto -noalign -convert big_endian -fp-model source -mcmodel=medium + -shared-intel -traceback -DLINUX_IFORT + # $<$:-O2> + # $<$:-O2> + # $<$:-g -O0 -check arg_temp_created -debug all -DDEBUG> + ) +elseif("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "GNU") + target_compile_options(GEOSChemBuildProperties INTERFACE + -cpp -w -std=legacy -fautomatic -fno-align-commons -fconvert=big-endian + -fno-range-check -mcmodel=medium -fbacktrace -g -DLINUX_GFORTRAN + # $<$:-O3 -funroll-loops> + # $<$:-O3 -funroll-loops> + # $<$:-g -gdwarf-2 -gstrict-dwarf -O0 -Wall -Wextra -Wconversion -Warray-temporaries -fcheck-array-temporaries> + -ffree-line-length-none + ) +else() + message(FATAL_ERROR "Unknown Fortran compiler: ${CMAKE_Fortran_COMPILER_ID}") endif() +#--------------------------------------------------------------------- +# Put all of GEOS-Chem's mod files in build subdir called mod +#--------------------------------------------------------------------- +set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mod) +target_include_directories(GEOSChemBuildProperties + INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/mod +) + +#--------------------------------------------------------------------- +# Append GEOS-Chem's environment variables to CMAKE_PREFIX_PATH +#--------------------------------------------------------------------- +list(APPEND CMAKE_PREFIX_PATH + # Possible NetCDF environment variables + $ENV{NetCDF_F_ROOT} $ENV{NetCDF_C_ROOT} $ENV{NetCDF_ROOT} + $ENV{NETCDF_F_ROOT} $ENV{NETCDF_C_ROOT} $ENV{NETCDF_ROOT} + $ENV{NetCDF_Fortran_ROOT} + $ENV{NETCDF_FORTRAN_ROOT} + + # Possible GEOS-Chem's environmnet variables + $ENV{GC_F_BIN} $ENV{GC_BIN} + $ENV{GC_F_INCLUDE} $ENV{GC_INCLUDE} + $ENV{GC_F_LIB} $ENV{GC_LIB} +) + #--------------------------------------------------------------------- # Find nc-config and nf-config and add to CMAKE_PREFIX_PATH #--------------------------------------------------------------------- @@ -58,13 +98,194 @@ inspect_netcdf_config(CMAKE_PREFIX_PATH "${NC_CONFIG}" "--prefix") inspect_netcdf_config(CMAKE_PREFIX_PATH "${NF_CONFIG}" "--prefix") #--------------------------------------------------------------------- -# Set gfortran-specific compile flags +# Link NetCDF-F to GEOSChemBuildProperties +#--------------------------------------------------------------------- +find_package(NetCDF REQUIRED) +target_include_directories(GEOSChemBuildProperties INTERFACE + ${NETCDF_INCLUDE_DIRS} +) +# Not sure if HCOI should be here... +target_link_libraries(GEOSChemBuildProperties INTERFACE + ${NETCDF_LIBRARIES} +) + +#--------------------------------------------------------------------- +# Use the NC_HAS_COMPRESSION def if nf_def_var_deflate is in netcdf.inc +#--------------------------------------------------------------------- +if(EXISTS ${NETCDF_F77_INCLUDE_DIR}/netcdf.inc) + file(READ ${NETCDF_F77_INCLUDE_DIR}/netcdf.inc NCINC) + if("${NCINC}" MATCHES ".*nf_def_var_deflate.*") + target_compile_definitions(GEOSChemBuildProperties + INTERFACE "NC_HAS_COMPRESSION" + ) + endif() +endif() + +#--------------------------------------------------------------------- +# Set high-level logicals for using this repository +#--------------------------------------------------------------------- +set(GCCLASSIC_WRAPPER TRUE) +set(GC_EXTERNAL_CONFIG FALSE) +set(HEMCO_EXTERNAL_CONFIG TRUE) + +#--------------------------------------------------------------------- +# Print a description of the source code repo's version +#--------------------------------------------------------------------- +get_repo_version(GC_REPO_VERSION ${CMAKE_CURRENT_SOURCE_DIR}) +message(STATUS "GEOS-Chem @ ${GC_REPO_VERSION}") + +#--------------------------------------------------------------------- +# For GEOS-Chem Classic only #--------------------------------------------------------------------- -if("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "GNU") - list(APPEND CMAKE_Fortran_FLAGS "-ffree-line-length-none") +if(NOT GC_EXTERNAL_CONFIG) + + # This conditional block configures the GEOS-Chem build + # for GEOS-Chem Classic. As mentioned above, it sets + # GCCLASSIC_EXE_TARGETS, RRTMG, GTMM, TOMAS, MECH, and + # GCHP, and it configures the GEOSChemBuildProperties. + + # Set CMAKE_BUILD_TYPE to Release by default + if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" + CACHE STRING + "Set the build type" + FORCE + ) + endif() + + # Display CMAKE_PREFIX_PATH and CMAKE_BUILD_TYPE + gc_pretty_print(SECTION "Useful CMake variables") + gc_pretty_print(VARIABLE CMAKE_PREFIX_PATH) + gc_pretty_print(VARIABLE CMAKE_BUILD_TYPE) + + # Get the run directory + gc_pretty_print(SECTION "Run directory setup") + set(RUNDIR ".." CACHE PATH "Path to your run directory") + gc_pretty_print(VARIABLE RUNDIR) + message(STATUS "Bootstrapping ${RUNDIR}") + # Make RUNDIR an absolute path + get_filename_component(RUNDIR "${RUNDIR}" + ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}" + ) + + # Configure the GEOS-Chem build for GCHP or GC-Classic + set(BUILD_WITHOUT_RUNDIR FALSE) + if(EXISTS ${RUNDIR}/input.geos) + file(STRINGS ${RUNDIR}/input.geos GCHP REGEX ": *gchp_*") + elseif(EXISTS ${RUNDIR}/getRunInfo) + # getRunInfo is only in GC-Classic run directories + set(GCHP FALSE) + elseif((NOT EXISTS RUNDIR) AND (DEFINED RUNDIR_SIM)) + # special case for building without a run directory + set(GCHP FALSE) + set(RUNDIR ${CMAKE_BINARY_DIR}) + set(BUILD_WITHOUT_RUNDIR TRUE) + else() + message(FATAL_ERROR "Your run directory doesn't + have an input.geos or getRunInfo! Set + RUNDIR to a valid run directory." + ) + endif() + + # Configure for GCClassic + include(GC-ConfigureClassic) + configureGCClassic() + endif() #--------------------------------------------------------------------- # Add the directory with source code #--------------------------------------------------------------------- add_subdirectory(src) + +#--------------------------------------------------------------------- +# Write GEOSChemBuildProperties's configuration to a file +#--------------------------------------------------------------------- +get_target_property(BT_DEFINITIONS GEOSChemBuildProperties + INTERFACE_COMPILE_DEFINITIONS +) +get_target_property(BT_OPTIONS GEOSChemBuildProperties + INTERFACE_COMPILE_OPTIONS +) +get_target_property(BT_LIBRARIES GEOSChemBuildProperties + INTERFACE_LINK_LIBRARIES +) +get_target_property(BT_INCLUDES GEOSChemBuildProperties + INTERFACE_INCLUDE_DIRECTORIES +) +file(WRITE ${CMAKE_BINARY_DIR}/GEOSChemBuildProperties.txt + "# This file shows the GEOSChemBuildProperties's configuration.\n" + "\n" + "GEOSChemBuildProperties::INTERFACE_COMPILE_DEFINITIONS:${BT_DEFINITIONS}\n" + "GEOSChemBuildProperties::INTERFACE_COMPILE_OPTIONS:${BT_OPTIONS}\n" + "GEOSChemBuildProperties::INTERFACE_LINK_LIBRARIES:${BT_LIBRARIES}\n" + "GEOSChemBuildProperties::INTERFACE_INCLUDE_DIRECTORIES:${BT_INCLUDES}\n" + "CMAKE_Fortran_FLAGS_RELEASE:${CMAKE_Fortran_FLAGS_RELEASE}\n" + "CMAKE_Fortran_FLAGS_DEBUG:${CMAKE_Fortran_FLAGS_DEBUG}\n" + "CMAKE_Fortran_FLAGS:${CMAKE_Fortran_FLAGS}\n\n" +) + + +#--------------------------------------------------------------------- +# Try to compile a simple program that uses NetCDF-Fortran and OpenMP +#--------------------------------------------------------------------- +if(NOT GC_EXTERNAL_CONFIG AND NOT GC_TRY_RUN_PASSED) + + # Format definitions with -D prefix + set(TRY_RUN_DEFINITIONS "") + foreach(DEF ${BT_DEFINITIONS}) + list(APPEND TRY_RUN_DEFINITIONS "-D${DEF}") + endforeach() + + # Try to compile and run try_compile.F90 + try_run(RUN_FAILED COMPILED_OK + ${CMAKE_CURRENT_BINARY_DIR}/try_compile # binary dir + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeScripts/try_compile.F90 # test src file + COMPILE_DEFINITIONS ${TRY_RUN_DEFINITIONS} ${BT_OPTIONS} # compile flags + LINK_LIBRARIES ${BT_LIBRARIES} # link flags + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${BT_INCLUDES}" # include dirs + COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT + RUN_OUTPUT_VARIABLE RUN_OUTPUT + ) + + # Display a warning if its compilation failed + if(NOT COMPILED_OK) + if(OMP) + set(CONDITIONAL_AND_OMP " and OpenMP") + endif() + message(WARNING + "Failed to compile a simple program that uses " + "NetCDF-Fortran ${CONDITIONAL_AND_OMP}! Could " + "your NetCDF installation be broken?\nSee " + "\"FailedCompile.txt\" for more info." + ) + file(WRITE ${CMAKE_BINARY_DIR}/FailedCompile.txt + "${COMPILE_OUTPUT}" + ) + else() + file(REMOVE ${CMAKE_BINARY_DIR}/FailedCompile.txt) + endif() + + # Display a warning if its execution failed + if(RUN_FAILED) + if(OMP) + set(CONDITIONAL_AND_OMP "and OpenMP ") + endif() + message(WARNING + "A simple program that uses NetCDF-Fortran " + "${CONDITIONAL_AND_OMP}compiled successfully, " + "but its execution failed!\n\nSee " + "\"FailedExecution.txt\" for more info." + ) + file(WRITE ${CMAKE_BINARY_DIR}/FailedEasyRun.txt + "${COMPILE_OUTPUT}\n${RUN_OUTPUT}" + ) + else() + file(REMOVE ${CMAKE_BINARY_DIR}/FailedEasyRun.txt + ${CMAKE_BINARY_DIR}/simple_xy.nc + ) + set(GC_TRY_RUN_PASSED TRUE CACHE INTERNAL + "try_run passed" FORCE + ) + endif() +endif() \ No newline at end of file diff --git a/CMakeScripts/FindNetCDF.cmake b/CMakeScripts/FindNetCDF.cmake new file mode 100755 index 0000000..7db8b54 --- /dev/null +++ b/CMakeScripts/FindNetCDF.cmake @@ -0,0 +1,182 @@ +#[[ FindNetCDF.cmake + +This module finds NetCDF-C and NetCDF-F. It uses nc-config and nf-config to +get HINTS for the find_xxxx's that are used to find the files/directories +listed below. + +If a file or directory cannot be found, the user should add the appropriate +directories to CMAKE_PREFIX_PATH. + +Resulting variables: + NETCDF_F_LIBRARY: Path to libnetcdff.so + NETCDF_C_LIBRARY: Path to libnetcdf.so + NETCDF_C_INCLUDE_DIR: Path to the directory containing netcdf.h + NETCDF_F90_INCLUDE_DIR: Path to the directory containing netcdf.mod + NETCDF_F77_INCLUDE_DIR: Path to the directory containing netcdf.inc + + NETCDF_LIBRARIES: Paths to all of NetCDF's libraries + NETCDF_INCLUDE_DIRS: Paths to all of NetCDF's include directories. + +]] + + +# Find the nc-config and nf-config programs +find_program(NC_CONFIG NAMES "nc-config" DOC "Location of nc-config utility") +find_program(NF_CONFIG NAMES "nf-config" DOC "Location of nf-config utility") + + +# A function to call nx-config with an argument, and append the resulting path to a list +function(inspect_netcdf_config VAR NX_CONFIG ARG) + execute_process( + COMMAND ${NX_CONFIG} ${ARG} + RESULT_VARIABLE NX_CONFIG_RET + OUTPUT_VARIABLE NX_CONFIG_OUTPUT + ERROR_VARIABLE NX_CONFIG_STDERR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(EXISTS "${NX_CONFIG_OUTPUT}") + list(APPEND ${VAR} ${NX_CONFIG_OUTPUT}) + set(${VAR} ${${VAR}} PARENT_SCOPE) + endif() +endfunction() + +# Determine HINTS for netcdf.h +set(NC_INC_HINTS "") +inspect_netcdf_config(NC_INC_HINTS "${NC_CONFIG}" --includedir) +inspect_netcdf_config(NC_INC_HINTS "${NC_CONFIG}" --prefix) +# Find netcdf.h +find_path(NETCDF_C_INCLUDE_DIR + netcdf.h + DOC "Directory containing \"netcdf.h\"" + HINTS + ${NC_INC_HINTS} + PATH_SUFFIXES + "include" +) + +# Determine HINTS for netcdf.mod +set(NF_INC_HINTS "") +inspect_netcdf_config(NF_INC_HINTS "${NF_CONFIG}" --includedir) +inspect_netcdf_config(NF_INC_HINTS "${NF_CONFIG}" --prefix) +# Find netcdf.mod +find_path(NETCDF_F90_INCLUDE_DIR + netcdf.mod + DOC "Directory containing \"netcdf.mod\"" + HINTS + ${NF_INC_HINTS} + PATH_SUFFIXES + "include" + "mod" + "module" +) +# Find netcdf.inc +find_path(NETCDF_F77_INCLUDE_DIR + netcdf.inc + DOC "Directory containing \"netcdf.inc\"" + HINTS + ${NF_INC_HINTS} + PATH_SUFFIXES + "include" + "mod" + "module" +) + +# Determine HINTS for NetCDF-C's library +set(NC_LIBDIR_HINTS "") +inspect_netcdf_config(NC_LIBDIR_HINTS "${NC_CONFIG}" --libdir) +inspect_netcdf_config(NC_LIBDIR_HINTS "${NC_CONFIG}" --prefix) +# Find libnetcdf.so +find_library(NETCDF_C_LIBRARY + netcdf + DOC "Path to \"libnetcdf\"" + HINTS + ${NC_LIBDIR_HINTS} + PATH_SUFFIXES + "lib" +) + +# Determine HINTS for NetCDF-F's library +set(NF_LIBDIR_HINTS "") +inspect_netcdf_config(NF_LIBDIR_HINTS "${NF_CONFIG}" --libdir) +inspect_netcdf_config(NF_LIBDIR_HINTS "${NF_CONFIG}" --prefix) +# Find libnetcdff.so +find_library(NETCDF_F_LIBRARY + netcdff + DOC "Path to \"libnetcdff\"" + HINTS + ${NF_LIBDIR_HINTS} + PATH_SUFFIXES + "lib" +) + +# Make a readable error message +set(NetCDF_ERRMSG "\nCounldn't find one or more of NetCDF's files! The following files/directories weren't found:") +if(NOT NETCDF_F_LIBRARY) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_F_LIBRARY: Path to \"libnetcdff.so\"") +endif() +if(NOT NETCDF_C_LIBRARY) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_C_LIBRARY: Path to \"libnetcdf.so\"") +endif() +if(NOT NETCDF_C_INCLUDE_DIR) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_C_INCLUDE_DIR: Directory containing \"netcdf.h\"") +endif() +if(NOT NETCDF_F90_INCLUDE_DIR) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_F90_INCLUDE_DIR: Directory containing \"netcdf.mod\"") +endif() +if(NOT NETCDF_F77_INCLUDE_DIR) + set(NetCDF_ERRMSG "${NetCDF_ERRMSG} + NETCDF_F77_INCLUDE_DIR: Directory containing \"netcdf.inc\"") +endif() +set(NetCDF_ERRMSG "${NetCDF_ERRMSG}\nFind the directories/files that are listed above. Specify the directories you want CMake to search with the CMAKE_PREFIX_PATH variable (or the NetCDF_ROOT environment variable).\n") + +# Conform to the find_package standards +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args(NetCDF + REQUIRED_VARS + NETCDF_F_LIBRARY + NETCDF_C_LIBRARY + NETCDF_C_INCLUDE_DIR + NETCDF_F90_INCLUDE_DIR + NETCDF_F77_INCLUDE_DIR + FAIL_MESSAGE "${NetCDF_ERRMSG}" +) +mark_as_advanced( + NC_CONFIG + NF_CONFIG + NETCDF_F_LIBRARY + NETCDF_C_LIBRARY + NETCDF_C_INCLUDE_DIR + NETCDF_F90_INCLUDE_DIR + NETCDF_F77_INCLUDE_DIR +) + +# Set NETCDF_LIBRARIES NETCDF_INCLUDE_DIRS +set(NETCDF_LIBRARIES ${NETCDF_F_LIBRARY} ${NETCDF_C_LIBRARY}) +set(NETCDF_INCLUDE_DIRS ${NETCDF_F90_INCLUDE_DIR} ${NETCDF_F77_INCLUDE_DIR} ${NETCDF_C_INCLUDE_DIR}) + +if(NOT TARGET NetCDF-C) + add_library(NetCDF-C SHARED IMPORTED) + set_property(TARGET NetCDF-C + PROPERTY IMPORTED_LOCATION ${NETCDF_C_LIBRARY} + ) + set_property(TARGET NetCDF-C + PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${NETCDF_C_INCLUDE_DIR} + ) +endif() + +if(NOT TARGET NetCDF-F) + add_library(NetCDF-F SHARED IMPORTED) + set_property(TARGET NetCDF-F + PROPERTY IMPORTED_LOCATION ${NETCDF_F_LIBRARY} + ) + set_property(TARGET NetCDF-F + PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${NETCDF_F90_INCLUDE_DIR} ${NETCDF_F77_INCLUDE_DIR} + ) + set_property(TARGET NetCDF-F + PROPERTY INTERFACE_LINK_LIBRARIES NetCDF-C + ) +endif() diff --git a/CMakeScripts/GC-ConfigureClassic.cmake b/CMakeScripts/GC-ConfigureClassic.cmake new file mode 100755 index 0000000..3ffa141 --- /dev/null +++ b/CMakeScripts/GC-ConfigureClassic.cmake @@ -0,0 +1,307 @@ +function(configureGCClassic) + + #---------------------------------------------------------------- + # Find OpenMP if we're building a multithreaded executable + #---------------------------------------------------------------- + gc_pretty_print(SECTION "Threading") + set(OMP ON CACHE STRING + "Switch to enable/disable OpenMP threading in GEOS-Chem" + ) + gc_pretty_print(VARIABLE OMP IS_BOOLEAN) + if("${OMP}") + find_package(OpenMP REQUIRED) + target_compile_options(GEOSChemBuildProperties + INTERFACE ${OpenMP_Fortran_FLAGS} + ) + target_link_libraries(GEOSChemBuildProperties + INTERFACE ${OpenMP_Fortran_FLAGS} + ) + else() + target_compile_definitions(GEOSChemBuildProperties + INTERFACE NO_OMP + ) + endif() + + #---------------------------------------------------------------- + # Check that GEOS-Chem's version number matches the run directory's version + #---------------------------------------------------------------- + if(NOT GCCLASSIC_WRAPPER) + if(EXISTS ${RUNDIR}/Makefile AND NOT "${BUILD_WITHOUT_RUNDIR}") + # Read ${RUNDIR}/Makefile which has the version number + file(READ ${RUNDIR}/Makefile RUNDIR_MAKEFILE) + + # Pull out the major.minor version + if(RUNDIR_MAKEFILE MATCHES + "VERSION[ \t]*:=[ \t]*([0-9]+\\.[0-9]+)\\.[0-9]+") + set(RUNDIR_VERSION ${CMAKE_MATCH_1}) + else() + message(FATAL_ERROR "Failed to determine your run directory's " + "version from ${RUNDIR}/Makefile" + ) + endif() + + # Get the major.minor version of GEOS-Chem + if(PROJECT_VERSION MATCHES "([0-9]+\\.[0-9]+)\\.[0-9]+") + set(GC_VERSION ${CMAKE_MATCH_1}) + else() + message(FATAL_ERROR "Internal error. Bad GEOS-Chem version number.") + endif() + + # Throw error if major.minor versions don't match + if(NOT "${GC_VERSION}" VERSION_EQUAL "${RUNDIR_VERSION}") + message(FATAL_ERROR + "Mismatched version numbers. Your run directory's version " + "number is ${RUNDIR_VERSION} but the GEOS-Chem source's " + "version number is ${PROJECT_VERSION}" + ) + endif() + endif() + endif() + + #---------------------------------------------------------------- + # Configure the build based on the run directory. + #---------------------------------------------------------------- + # Propagate the configuration variables. + # Define a macro for inspecting the run directory. Inspecting the run + # directory is how we determine which compiler definitions need to be set. + macro(inspect_rundir VAR ID) + if(EXISTS ${RUNDIR}/getRunInfo) + execute_process(COMMAND perl ${RUNDIR}/getRunInfo ${RUNDIR} ${ID} + OUTPUT_VARIABLE ${VAR} + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + endmacro() + + #---------------------------------------------------------------- + # Inspect the run directory to get simulation type + #---------------------------------------------------------------- + inspect_rundir(RUNDIR_SIM 5) + + #---------------------------------------------------------------- + # Determine the appropriate chemistry mechanism base on the simulation + #---------------------------------------------------------------- + set(STANDARD_MECHS + standard benchmark aciduptake marinePOA + masscons TransportTracers POPs CH4 + tagCH4 tagO3 tagCO + tagHg CO2 aerosol + Hg + HEMCO # doesn't matter for the HEMCO standalone + ) + set(TROPCHEM_MECHS + tropchem RRTMG TOMAS15 + TOMAS40 APM complexSOA + ) + set(SOA_SVPOA_MECHS + complexSOA_SVPOA + ) + set(CUSTOM_MECHS + custom + ) + if("${RUNDIR_SIM}" IN_LIST STANDARD_MECHS) + set(RUNDIR_MECH Standard) + elseif("${RUNDIR_SIM}" IN_LIST TROPCHEM_MECHS) + set(RUNDIR_MECH Tropchem) + elseif("${RUNDIR_SIM}" IN_LIST SOA_SVPOA_MECHS) + set(RUNDIR_MECH SOA_SVPOA) + elseif("${RUNDIR_SIM}" IN_LIST CUSTOM_MECHS) + set(RUNDIR_MECH custom) + else() + message(FATAL_ERROR "Unknown simulation type \"${RUNDIR_SIM}\". " + "Cannot determine MECH.") + endif() + + #---------------------------------------------------------------- + # Definitions for specific run directories + #---------------------------------------------------------------- + set(TOMAS FALSE) + if("${RUNDIR_SIM}" STREQUAL masscons) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE MASSCONS + ) + elseif("${RUNDIR_SIM}" MATCHES TOMAS15) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE TOMAS TOMAS15 + ) + set(TOMAS TRUE) + elseif("${RUNDIR_SIM}" MATCHES TOMAS40) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE TOMAS TOMAS40 + ) + set(TOMAS TRUE) + endif() + + gc_pretty_print(SECTION "General settings") + + #---------------------------------------------------------------- + # Make MECH an option. This controls which KPP directory is used. + #---------------------------------------------------------------- + set(MECH "${RUNDIR_MECH}" CACHE STRING "GEOS-Chem's chemistry mechanism") + # Check that MECH is a valid + set(VALID_MECHS Standard Tropchem SOA_SVPOA) + # print MECH to console + gc_pretty_print(VARIABLE MECH OPTIONS ${VALID_MECHS}) + if(NOT "${MECH}" IN_LIST VALID_MECHS) + message(FATAL_ERROR "The value of MECH, \"${MECH}\", is an " + "invalid chemistry mechanism! Select one " + "of: ${VALID_MECHS}." + ) + endif() + + #---------------------------------------------------------------- + # Turn on bpch diagnostics? + #---------------------------------------------------------------- + # Define simulations that need bpch diagnostics on + set(BPCH_ON_SIM RRTMG TOMAS12 TOMAS15 TOMAS30 TOMAS40 Hg tagHg POPs) + if("${RUNDIR_SIM}" IN_LIST BPCH_ON_SIM) + set(BPCH_DIAG_DEFAULT ON) + else() + set(BPCH_DIAG_DEFAULT OFF) + endif() + set(BPCH_DIAG "${BPCH_DIAG_DEFAULT}" CACHE BOOL + "Switch to enable GEOS-Chem's bpch diagnostics" + ) + gc_pretty_print(VARIABLE BPCH_DIAG IS_BOOLEAN) + if(${BPCH_DIAG}) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE BPCH_DIAG + ) + endif() + + #---------------------------------------------------------------- + # Always set MODEL_CLASSIC when building GEOS-Chem Classic + #---------------------------------------------------------------- + target_compile_definitions(GEOSChemBuildProperties + INTERFACE MODEL_CLASSIC + ) + + #---------------------------------------------------------------- + # Always set USE_REAL8. See https://github.com/geoschem/geos-chem/issues/43. + #---------------------------------------------------------------- + target_compile_definitions(GEOSChemBuildProperties + INTERFACE USE_REAL8 + ) + + #---------------------------------------------------------------- + # Build with timers? + #---------------------------------------------------------------- + if("${RUNDIR_SIM}" STREQUAL benchmark) + set(TIMERS_DEFAULT ON) + else() + set(TIMERS_DEFAULT OFF) + endif() + set(TIMERS "${TIMERS_DEFAULT}" CACHE BOOL + "Switch to enable GEOS-Chem's timers" + ) + gc_pretty_print(VARIABLE TIMERS IS_BOOLEAN) + # Set USE_TIMERS + if(${TIMERS}) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE USE_TIMERS + ) + endif() + + gc_pretty_print(SECTION "Components") + + #---------------------------------------------------------------- + # Build APM? + #---------------------------------------------------------------- + if("${RUNDIR_SIM}" STREQUAL APM) + set(APM_DEFAULT ON) + else() + set(APM_DEFAULT OFF) + endif() + set(APM "${APM_DEFAULT}" CACHE BOOL + "Switch to build APM as a component of GEOS-Chem" + ) + gc_pretty_print(VARIABLE APM IS_BOOLEAN) + if(${APM}) + target_compile_definitions(GEOSChemBuildProperties INTERFACE APM) + endif() + + #---------------------------------------------------------------- + # Build RRTMG? + #---------------------------------------------------------------- + if("${RUNDIR_SIM}" STREQUAL RRTMG) + set(RRTMG_DEFAULT TRUE) + else() + set(RRTMG_DEFAULT FALSE) + endif() + set(RRTMG "${RRTMG_DEFAULT}" CACHE BOOL + "Switch to build RRTMG as a component of GEOS-Chem" + ) + gc_pretty_print(VARIABLE RRTMG IS_BOOLEAN) + if(${RRTMG}) + target_compile_definitions(GEOSChemBuildProperties INTERFACE RRTMG) + endif() + + #---------------------------------------------------------------- + # Build GTMM? + #---------------------------------------------------------------- + set(GTMM OFF CACHE BOOL + "Switch to build GTMM as a component of GEOS-Chem" + ) + gc_pretty_print(VARIABLE GTMM IS_BOOLEAN) + if(${GTMM}) + target_compile_definitions(GEOSChemBuildProperties INTERFACE GTMM_Hg) + endif() + + #---------------------------------------------------------------- + # Build HEMCO standalone? + #---------------------------------------------------------------- + if(NOT GCCLASSIC_WRAPPER) + if("${RUNDIR_SIM}" STREQUAL HEMCO) + set(HCOSA_DEFAULT TRUE) + else() + set(HCOSA_DEFAULT FALSE) + endif() + set(HCOSA "${HCOSA_DEFAULT}" CACHE BOOL + "Switch to build the hemco-standalone (HCOSA) executable" + ) + gc_pretty_print(VARIABLE HCOSA IS_BOOLEAN) + endif() + + #---------------------------------------------------------------- + # Build Luo et al wetdep scheme? + #---------------------------------------------------------------- + set(LUO_WETDEP OFF CACHE BOOL + "Switch to build the Luo et al (2019) wetdep scheme into GEOS-Chem" + ) + gc_pretty_print(VARIABLE LUO_WETDEP IS_BOOLEAN) + if(${LUO_WETDEP}) + target_compile_definitions(GEOSChemBuildProperties + INTERFACE LUO_WETDEP + ) + endif() + + #---------------------------------------------------------------- + # Determine which executables should be built + #---------------------------------------------------------------- + if(NOT GCCLASSIC_WRAPPER) + set(GCCLASSIC_EXE_TARGETS geos CACHE STRING + "Executable targets that get built as a part of \"all\"" + ) + if(${HCOSA}) + list(APPEND GCCLASSIC_EXE_TARGETS hemco_standalone) + endif() + if(GTMM) + list(APPEND GCCLASSIC_EXE_TARGETS gtmm) + endif() + endif() + + #---------------------------------------------------------------- + # Export the following variables to GEOS-Chem directory's scope + #---------------------------------------------------------------- + if(NOT GCCLASSIC_WRAPPER) + set(GCCLASSIC_EXE_TARGETS ${GCCLASSIC_EXE_TARGETS} PARENT_SCOPE) + endif() + set(GCHP FALSE PARENT_SCOPE) + set(MECH ${MECH} PARENT_SCOPE) + set(TOMAS ${TOMAS} PARENT_SCOPE) + set(APM ${APM} PARENT_SCOPE) + set(RRTMG ${RRTMG} PARENT_SCOPE) + set(GTMM ${GTMM} PARENT_SCOPE) + set(LUO_WETDEP ${LUO_WETDEP} PARENT_SCOPE) + set(RUNDIR ${RUNDIR} PARENT_SCOPE) +endfunction() diff --git a/CMakeScripts/GC-Helpers.cmake b/CMakeScripts/GC-Helpers.cmake new file mode 100755 index 0000000..142417a --- /dev/null +++ b/CMakeScripts/GC-Helpers.cmake @@ -0,0 +1,185 @@ + +#[[ stringify_list + +Stringify a list of strings. + +Usage: + stringify_list( + [PRINT] + [LINE_LENGTH ] + [HIGHLIGHT ...] + [JOIN ...] + [AFTER] + ) + +Options: + PRINT Print the stringified list to console. Highlighted text + will also be colorized. + + LINE_LENGTH When JOINing a list of string, the resulting lines will + be limited to characters. The resulting + will be a list of lines that can then be JOINed with + newlines. + + HIGHLIGHT A list of keywords to highlight. + + JOIN A list of tokens that will be used sequentially to join + list items. The last token will be used to join all + remaining items. + + AFTER Place the JOIN tokens after the item, rather than before. + +]] +function(stringify_list LIST) + cmake_parse_arguments(BETTER + "PRINT;AFTER" + "LINE_LENGTH" + "HIGHLIGHT;JOIN" + ${ARGN} + ) + + if(NOT DEFINED BETTER_LINE_LENGTH) + set(BETTER_LINE_LENGTH 1000) # Arbitrary big number + endif() + + set(STR ${${LIST}}) + + # Limit joined line length + if(DEFINED BETTER_JOIN) + set(TEMP "") + set(CUR_LEN "0") + + set(JOIN_IDX "0 - 1") + list(LENGTH BETTER_JOIN JOIN_LEN) + + foreach(ITEM ${STR}) + # Get the join token + math(EXPR JOIN_IDX "${JOIN_IDX} + 1") + if(${JOIN_IDX} LESS ${JOIN_LEN}) + list(GET BETTER_JOIN "${JOIN_IDX}" JOIN_TOKEN) + endif() + string(LENGTH "${JOIN_TOKEN}" SEP_LEN) + + # If a line length was + string(LENGTH "${ITEM}" WORD_LEN) + math(EXPR POST_LEN "${WORD_LEN} + ${CUR_LEN} + ${SEP_LEN}") + if("${POST_LEN}" LESS "${BETTER_LINE_LENGTH}") + if(${BETTER_AFTER}) + set(TEMP "${TEMP}${ITEM}${JOIN_TOKEN}") + else() + set(TEMP "${TEMP}${JOIN_TOKEN}${ITEM}") + endif() + set(CUR_LEN "${POST_LEN}") + else() + if(${BETTER_AFTER}) + set(TEMP "${TEMP};${ITEM}${JOIN_TOKEN}") + else() + set(TEMP "${TEMP};${JOIN_TOKEN}${ITEM}") + endif() + set(CUR_LEN "0") + math(EXPR CUR_LEN "${SEP_LEN} + ${WORD_LEN}") + endif() + endforeach() + + set(STR "${TEMP}") + endif() + + # Highlight selected words + if(DEFINED BETTER_HIGHLIGHT) + foreach(KEYWORD ${BETTER_HIGHLIGHT}) + string(REPLACE "${KEYWORD}" "[${KEYWORD}]" STR "${STR}") + endforeach() + endif() + + if(${BETTER_PRINT}) + string(ASCII 27 Esc) + if(${CMAKE_COLOR_MAKEFILE}) + string(REGEX REPLACE "\\[([a-zA-Z0-9_\\.]+)\\]" "${Esc}[32m\\1${Esc}[m" COLORIZED "${STR}") + else() + set(COLORIZED "${STR}") + endif() + string(REGEX REPLACE "\n$" "" COLORIZED "${COLORIZED}") + message("${COLORIZED}") + endif() + + + # Export the new string + set(${LIST} "${STR}" PARENT_SCOPE) +endfunction() + +#[[ get_repo_version + +Variable with name ${VARNAME} gets set to first 7 characters of the hash +of the last commit to the repo at ${DIR}. + +Usage: + get_repo_version(VARNAME DIR) + +]] +macro(get_repo_version VARNAME DIR) + execute_process( + COMMAND git describe --tags --dirty=.dirty + WORKING_DIRECTORY ${DIR} + OUTPUT_VARIABLE ${VARNAME} + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endmacro() + +function(gc_pretty_print) + cmake_parse_arguments(ARGS + "IS_BOOLEAN" + "VARIABLE;SECTION" + "OPTIONS" + ${ARGN} + ) + + if(DEFINED ARGS_VARIABLE) + if(ARGS_IS_BOOLEAN) + set(LOGLINE "ON" "OFF") + # Split list with " " + stringify_list(LOGLINE + JOIN " " + LINE_LENGTH 60 + ) + # Wrap lines + stringify_list(LOGLINE + JOIN " * ${ARGS_VARIABLE}:\t" "\n ... \t" + ) + if("${${ARGS_VARIABLE}}") + stringify_list(LOGLINE PRINT HIGHLIGHT "ON") + else() + stringify_list(LOGLINE PRINT HIGHLIGHT "OFF") + endif() + elseif(DEFINED ARGS_OPTIONS) + set(LOGLINE ${ARGS_OPTIONS}) + # Split list with " " + stringify_list(LOGLINE + JOIN " " + LINE_LENGTH 60 + ) + # Wrap lines + stringify_list(LOGLINE + JOIN " * ${ARGS_VARIABLE}:\t" "\n ... \t" + ) + stringify_list(LOGLINE PRINT HIGHLIGHT ${${ARGS_VARIABLE}}) + else() + if(NOT DEFINED ${ARGS_VARIABLE}) + set(LOGLINE " ") # special case for empty variable + else() + set(LOGLINE ${${ARGS_VARIABLE}}) + endif() + # Split list with " " + stringify_list(LOGLINE + JOIN " " + LINE_LENGTH 60 + ) + # Wrap lines + stringify_list(LOGLINE + JOIN " + ${ARGS_VARIABLE}:\t" "\n ... \t" + ) + stringify_list(LOGLINE PRINT) + endif() + elseif(DEFINED ARGS_SECTION) + message(STATUS "${ARGS_SECTION}:") + endif() +endfunction() \ No newline at end of file diff --git a/CMakeScripts/try_compile.F90 b/CMakeScripts/try_compile.F90 new file mode 100644 index 0000000..40eaef3 --- /dev/null +++ b/CMakeScripts/try_compile.F90 @@ -0,0 +1,57 @@ +program try_compile + use netcdf + + implicit none + + character (len = *), parameter :: FILE_NAME = "simple_xy.nc" + integer, parameter :: NDIMS = 2 + integer, parameter :: NX = 6, NY = 12 + integer :: ncid, varid, dimids(NDIMS) + integer :: x_dimid, y_dimid + integer :: data_out(NY, NX) + integer :: x, y +#ifndef NO_OMP + integer nthreads, tid, OMP_GET_THREAD_NUM + + write(*,*) 'About to start multiple threads' + ! Try OpenMP + !$OMP PARALLEL PRIVATE(nthreads, tid) + TID = OMP_GET_THREAD_NUM() + write(*,*) 'Hello from thread ', tid + !$OMP END PARALLEL +#endif + + ! Try NetCDF-F + do x = 1, NX + do y = 1, NY + data_out(y, x) = (x - 1) * NY + (y - 1) + end do + end do + write(*,*) 'Creating NetCDF file' + call check( nf90_create(FILE_NAME, NF90_CLOBBER, ncid) ) + call check( nf90_def_dim(ncid, "x", NX, x_dimid) ) + call check( nf90_def_dim(ncid, "y", NY, y_dimid) ) + + ! The dimids array is used to pass the IDs of the dimensions of + ! the variables. Note that in fortran arrays are stored in + ! column-major format. + dimids = (/ y_dimid, x_dimid /) + + call check( nf90_def_var(ncid, "data", NF90_INT, dimids, varid) ) + + call check( nf90_enddef(ncid) ) + call check( nf90_put_var(ncid, varid, data_out) ) + call check( nf90_close(ncid) ) + write(*,*) 'Finished creating the NetCDF file' + + contains + subroutine check(status) + integer, intent ( in) :: status + + if(status /= nf90_noerr) then + print *, trim(nf90_strerror(status)) + stop "Stopped" + end if + end subroutine check + +end program diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6abb405..7c081a0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,5 +22,5 @@ target_link_libraries(geos set_target_properties(geos PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) install(TARGETS geos - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION ${RUNDIR} ) From 22c2dcbc99aeec2dca89235af27e570fcf466bb3 Mon Sep 17 00:00:00 2001 From: Liam Bindle Date: Fri, 31 Jul 2020 09:57:25 -0600 Subject: [PATCH 2/2] updated GEOS-Chem submodule --- src/GEOS-Chem | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GEOS-Chem b/src/GEOS-Chem index 22c503b..96cb767 160000 --- a/src/GEOS-Chem +++ b/src/GEOS-Chem @@ -1 +1 @@ -Subproject commit 22c503be96fa2dd848eb2fba142beb6d92a09889 +Subproject commit 96cb76797c81f850a584e8a4dd9a7f65ef7e19b1