-
Notifications
You must be signed in to change notification settings - Fork 304
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce CMake build for init_atmosphere and atmosphere cores
This commit introduces a CMake build capability for the MPAS init_atmosphere and atmosphere cores, with support for the GNU, Intel, and NVHPC compilers. The following must be defined: * MPAS_CORE : Either 'init_atmosphere' or 'atmophere' * MPAS_COMPILER : One of 'gnu', 'intel', or 'nvhpc' Optionally, MPAS_PRECISION can be specified as 'single' or 'double', with builds defaulting to double-precision reals. Acknowledgements: Miles Curry and Maryam Abdi-Oskouei both contributed to the development of this capability.
- Loading branch information
Showing
22 changed files
with
843 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
cmake_minimum_required(VERSION 3.13) | ||
cmake_policy(SET CMP0076 NEW) | ||
project(reg C Fortran) | ||
|
||
|
||
# | ||
# Define build options | ||
# | ||
set(MPAS_CORE "None" CACHE STRING "The MPAS core to build. Possible options: atmosphere init_atmosphere") | ||
set(MPAS_COMPILER "None" CACHE STRING "The MPAS core to build. Possible options: gnu intel nvhpc") | ||
set(MPAS_PRECISION "double" CACHE STRING "The default precision for real values. Possible options: single double") | ||
|
||
# | ||
# Set core to build and associated preprocessing definitions | ||
# | ||
if(MPAS_CORE STREQUAL "atmosphere") | ||
set(MPAS_EXE_NAME "atmosphere_model") | ||
set(MPAS_CORE_DEF "CORE_ATMOSPHERE") | ||
elseif(MPAS_CORE STREQUAL "init_atmosphere") | ||
set(MPAS_EXE_NAME "init_atmosphere_model") | ||
set(MPAS_CORE_DEF "CORE_INIT_ATMOSPHERE") | ||
else() | ||
message(FATAL_ERROR "Please define MPAS_CORE as one of: atmosphere init_atmosphere") | ||
endif() | ||
|
||
add_executable(${MPAS_EXE_NAME}) | ||
target_compile_definitions(${MPAS_EXE_NAME} PUBLIC ${MPAS_CORE_DEF}) | ||
|
||
|
||
# | ||
# Set compilation macros that are invariant | ||
# | ||
target_compile_definitions(${MPAS_EXE_NAME} PUBLIC _MPI) | ||
|
||
|
||
# | ||
# Set compiler and compiler options | ||
# | ||
if(MPAS_COMPILER STREQUAL gnu) | ||
set(CMAKE_C_COMPILER mpicc) | ||
set(CMAKE_Fortran_COMPILER mpif90) | ||
set(CMAKE_Fortran_FLAGS "-ffree-line-length-none") | ||
set(PROMOTION_FLAGS "-fdefault-real-8 -fdefault-double-8") | ||
set(BYTESWAP_FLAGS "-fconvert=big-endian") | ||
elseif(MPAS_COMPILER STREQUAL intel) | ||
set(CMAKE_C_COMPILER mpicc) | ||
set(CMAKE_Fortran_COMPILER mpif90) | ||
set(PROMOTION_FLAGS "-real-size 64") | ||
set(BYTESWAP_FLAGS "-convert big_endian") | ||
elseif(MPAS_COMPILER STREQUAL nvhpc) | ||
set(CMAKE_C_COMPILER mpicc) | ||
set(CMAKE_Fortran_COMPILER mpifort) | ||
set(PROMOTION_FLAGS "-r8") | ||
set(BYTESWAP_FLAGS "-byteswapio") | ||
else() | ||
message(FATAL_ERROR "Please define MPAS_COMPILER as one of: gnu intel nvhpc") | ||
endif() | ||
|
||
set_property(TARGET ${MPAS_EXE_NAME} PROPERTY Fortran_FORMAT FREE) | ||
set_property(TARGET ${MPAS_EXE_NAME} PROPERTY Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/mod) | ||
|
||
|
||
# | ||
# Set precision for real values | ||
# | ||
if(MPAS_PRECISION STREQUAL "single") | ||
target_compile_definitions(${MPAS_EXE_NAME} PUBLIC SINGLE_PRECISION) | ||
else() | ||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${PROMOTION_FLAGS}") | ||
endif() | ||
|
||
|
||
# | ||
# Set flags to handle endianness of binary files | ||
# | ||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${BYTESWAP_FLAGS}") | ||
|
||
|
||
# | ||
# Locate external libraries: netCDF, parallel-netCDF, PIO | ||
# | ||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) | ||
|
||
|
||
find_package(NetCDF REQUIRED) | ||
find_package(HDF5 REQUIRED) | ||
find_package(PNETCDF REQUIRED) | ||
find_package(PIO) | ||
|
||
|
||
# | ||
# If the PIO library was found, use PIO; otherwise use SMIOL | ||
# | ||
get_property(PIO_VERSION GLOBAL PROPERTY PIO_VERSION) | ||
if(PIO_VERSION GREATER_EQUAL 1) | ||
target_compile_definitions(${MPAS_EXE_NAME} PUBLIC MPAS_PIO_SUPPORT) | ||
|
||
# | ||
# Set compilation macros to select appropriate PIO API | ||
# | ||
if(PIO_VERSION STREQUAL "2") | ||
target_compile_definitions(${MPAS_EXE_NAME} PUBLIC USE_PIO2) | ||
endif() | ||
set(IO_LIBRARIES ${PIO_LIBRARIES}) | ||
set(IO_INCLUDES_DIRS ${PIO_INCLUDE_DIRS}) | ||
else() | ||
target_compile_definitions(${MPAS_EXE_NAME} PUBLIC MPAS_SMIOL_SUPPORT) | ||
endif() | ||
|
||
|
||
# | ||
# Process everything in the src/ subdirectory | ||
# | ||
add_subdirectory(src) | ||
|
||
|
||
# | ||
# Add include paths and libraries from packages that are internally built by MPAS | ||
# | ||
get_property(MPAS_INTERNAL_INCLUDE_DIRS GLOBAL PROPERTY MPAS_INTERNAL_INCLUDE_DIRS) | ||
get_property(MPAS_INTERNAL_LIBRARIES GLOBAL PROPERTY MPAS_INTERNAL_LIBRARIES) | ||
target_include_directories(${MPAS_EXE_NAME} PRIVATE ${MPAS_INTERNAL_INCLUDE_DIRS}) | ||
target_link_libraries(${MPAS_EXE_NAME} PRIVATE ${MPAS_INTERNAL_LIBRARIES}) | ||
|
||
# | ||
# Add external include paths and libraries | ||
# | ||
target_include_directories(${MPAS_EXE_NAME} | ||
PUBLIC | ||
${IO_INCLUDE_DIRS} | ||
${PNETCDF_INCLUDE_DIRS} | ||
${HDF5_INCLUDE_DIRS} | ||
${NETCDF_INCLUDE_DIRS} | ||
) | ||
|
||
target_link_libraries(${MPAS_EXE_NAME} | ||
PUBLIC | ||
${IO_LIBRARIES} | ||
${NetCDF_LIBRARIES} | ||
${HDF5_LIBRARIES} | ||
${PNETCDF_LIBRARIES} | ||
${CMAKE_DL_LIBS} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
# (C) Copyright 2011- ECMWF. | ||
# | ||
# This software is licensed under the terms of the Apache Licence Version 2.0 | ||
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
# In applying this licence, ECMWF does not waive the privileges and immunities | ||
# granted to it by virtue of its status as an intergovernmental organisation nor | ||
# does it submit to any jurisdiction. | ||
|
||
# Try to find NetCDF includes and library, only shared libraries are supported! | ||
# | ||
# This module defines | ||
# | ||
# - NetCDF_FOUND - System has NetCDF | ||
# - NetCDF_INCLUDE_DIRS - the NetCDF include directories | ||
# - NetCDF_LIBRARIES - the libraries needed to use NetCDF | ||
# - NetCDF_VERSION - the version of NetCDF | ||
# | ||
# Following components are available: | ||
# | ||
# - C - C interface to NetCDF (netcdf) | ||
# - CXX - CXX4 interface to NetCDF (netcdf_c++4) | ||
# - Fortran - Fortran interface to NetCDF (netcdff) | ||
# - CXX_LEGACY - Legacy C++ interface to NetCDF (netcdf_c++) | ||
# | ||
# For each component the following are defined: | ||
# | ||
# - NetCDF_<comp>_FOUND - whether the component is found | ||
# - NetCDF_<comp>_LIBRARIES - the libraries for the component | ||
# - NetCDF_<comp>_INCLUDE_DIRS - the include directories for specfied component | ||
# - NetCDF::NetCDF_<comp> - target of component to be used with target_link_libraries() | ||
# | ||
# The following paths will be searched in order if set in CMake (first priority) or environment (second priority) | ||
# | ||
# - NETCDF_ROOT - root of NetCDF installation | ||
# - NETCDF_DIR - root of NetCDF installation | ||
# - NETCDF_PATH - root of NetCDF installation | ||
# - NETCDF4_DIR - root of NetCDF installation | ||
# - NetCDF_ROOT - root of NetCDF installation | ||
# - NetCDF_DIR - root of NetCDF installation | ||
# - NetCDF_PATH - root of NetCDF installation | ||
# - NetCDF4_DIR - root of NetCDF installation | ||
# | ||
# Notes: | ||
# | ||
# - Each variable is also available in fully uppercased version | ||
# - In each variable (not in targets), the "NetCDF" prefix may be interchanged with | ||
# * NetCDF4 | ||
# * NETCDF | ||
# * NETCDF4 | ||
# * The part "<xxx>" in current filename Find<xxx>.cmake | ||
# - Capitalisation of COMPONENT arguments does not matter: The <comp> part of variables will be defined with | ||
# * capitalisation as defined above | ||
# * Uppercase capitalisation | ||
# * capitalisation as used in find_package() arguments | ||
# - If no components are defined, all components will be searched without guarantee that the required component is available. | ||
# | ||
|
||
list( APPEND _possible_components C CXX Fortran CXX_LEGACY ) | ||
|
||
## Library names for each component | ||
set( NetCDF_C_LIBRARY_NAME netcdf ) | ||
set( NetCDF_CXX_LIBRARY_NAME netcdf_c++4 ) | ||
set( NetCDF_CXX_LEGACY_LIBRARY_NAME netcdf_c++ ) | ||
set( NetCDF_Fortran_LIBRARY_NAME netcdff ) | ||
|
||
foreach( _comp ${_possible_components} ) | ||
string( TOUPPER "${_comp}" _COMP ) | ||
set( _arg_${_COMP} ${_comp} ) | ||
set( _name_${_COMP} ${_comp} ) | ||
endforeach() | ||
|
||
unset( _search_components ) | ||
foreach( _comp ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS} ) | ||
string( TOUPPER "${_comp}" _COMP ) | ||
set( _arg_${_COMP} ${_comp} ) | ||
list( APPEND _search_components ${_name_${_COMP}} ) | ||
if( NOT _name_${_COMP} ) | ||
ecbuild_error( "Find${CMAKE_FIND_PACKAGE_NAME}: COMPONENT ${_comp} is not a valid component. Valid components: ${_possible_components}" ) | ||
endif() | ||
endforeach() | ||
if( NOT _search_components ) | ||
set( _search_components C ) | ||
endif() | ||
|
||
## Search hints for finding include directories and libraries | ||
set( _search_hints | ||
${NETCDF_ROOT} ${NETCDF_DIR} ${NETCDF_PATH} ${NETCDF4_DIR} | ||
${NetCDF_ROOT} ${NetCDF_DIR} ${NetCDF_PATH} ${NetCDF4_DIR} | ||
ENV NETCDF_ROOT ENV NETCDF_DIR ENV NETCDF_PATH ENV NETCDF4_DIR | ||
ENV NetCDF_ROOT ENV NetCDF_DIR ENV NetCDF_PATH ENV NetCDF4_DIR | ||
) | ||
|
||
## Find include directories | ||
find_path(NetCDF_INCLUDE_DIRS | ||
NAMES netcdf.h | ||
DOC "netcdf include directories" | ||
HINTS ${_search_hints} | ||
PATH_SUFFIXES include ../../include | ||
) | ||
mark_as_advanced(NetCDF_INCLUDE_DIRS) | ||
|
||
## Find libraries for each component | ||
foreach( _comp ${_search_components} ) | ||
string( TOUPPER "${_comp}" _COMP ) | ||
|
||
find_library(NetCDF_${_comp}_LIBRARY | ||
NAMES ${NetCDF_${_comp}_LIBRARY_NAME} | ||
DOC "netcdf ${_comp} library" | ||
HINTS ${_search_hints} | ||
PATH_SUFFIXES lib ../../lib | ||
) | ||
mark_as_advanced(NetCDF_${_comp}_LIBRARY) | ||
if( NetCDF_${_comp}_LIBRARY AND NOT (NetCDF_${_comp}_LIBRARY MATCHES ".a$") ) | ||
set( NetCDF_${_comp}_LIBRARY_SHARED TRUE ) | ||
endif() | ||
if( NetCDF_${_comp}_LIBRARY_SHARED AND NetCDF_INCLUDE_DIRS ) | ||
set( ${CMAKE_FIND_PACKAGE_NAME}_${_arg_${_COMP}}_FOUND TRUE ) | ||
list( APPEND NetCDF_LIBRARIES ${NetCDF_${_comp}_LIBRARY} ) | ||
list( APPEND NetCDF_${_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARY} ) | ||
|
||
if (NOT TARGET NetCDF::NetCDF_${_comp}) | ||
add_library(NetCDF::NetCDF_${_comp} UNKNOWN IMPORTED) | ||
set_target_properties(NetCDF::NetCDF_${_comp} PROPERTIES | ||
IMPORTED_LOCATION "${NetCDF_${_comp}_LIBRARY}" | ||
INTERFACE_INCLUDE_DIRECTORIES "${NetCDF_INCLUDE_DIRS}") | ||
endif() | ||
endif() | ||
endforeach() | ||
|
||
## Find version | ||
if (NetCDF_INCLUDE_DIRS) | ||
find_program( NETCDF_CONFIG_EXECUTABLE | ||
NAMES nc-config | ||
HINTS ${_search_hints} | ||
PATH_SUFFIXES bin Bin ../../bin | ||
DOC "NetCDF nc-config helper" ) | ||
mark_as_advanced( NETCDF_CONFIG_EXECUTABLE ) | ||
|
||
if( NETCDF_CONFIG_EXECUTABLE ) | ||
execute_process( COMMAND ${NETCDF_CONFIG_EXECUTABLE} --version | ||
RESULT_VARIABLE _netcdf_config_result | ||
OUTPUT_VARIABLE _netcdf_config_version) | ||
|
||
if( _netcdf_config_result EQUAL 0 ) | ||
string(REGEX REPLACE ".* ((([0-9]+)\\.)+([0-9]+)).*" "\\1" NetCDF_VERSION "${_netcdf_config_version}" ) | ||
endif() | ||
|
||
elseif( EXISTS "${NetCDF_INCLUDE_DIRS}/netcdf_meta.h" ) | ||
|
||
file(STRINGS "${NetCDF_INCLUDE_DIRS}/netcdf_meta.h" _netcdf_version_lines | ||
REGEX "#define[ \t]+NC_VERSION_(MAJOR|MINOR|PATCH|NOTE)") | ||
string(REGEX REPLACE ".*NC_VERSION_MAJOR *\([0-9]*\).*" "\\1" _netcdf_version_major "${_netcdf_version_lines}") | ||
string(REGEX REPLACE ".*NC_VERSION_MINOR *\([0-9]*\).*" "\\1" _netcdf_version_minor "${_netcdf_version_lines}") | ||
string(REGEX REPLACE ".*NC_VERSION_PATCH *\([0-9]*\).*" "\\1" _netcdf_version_patch "${_netcdf_version_lines}") | ||
string(REGEX REPLACE ".*NC_VERSION_NOTE *\"\([^\"]*\)\".*" "\\1" _netcdf_version_note "${_netcdf_version_lines}") | ||
set(NetCDF_VERSION "${_netcdf_version_major}.${_netcdf_version_minor}.${_netcdf_version_patch}${_netcdf_version_note}") | ||
unset(_netcdf_version_major) | ||
unset(_netcdf_version_minor) | ||
unset(_netcdf_version_patch) | ||
unset(_netcdf_version_note) | ||
unset(_netcdf_version_lines) | ||
endif() | ||
endif () | ||
|
||
## Finalize find_package | ||
include(FindPackageHandleStandardArgs) | ||
|
||
find_package_handle_standard_args( ${CMAKE_FIND_PACKAGE_NAME} | ||
REQUIRED_VARS NetCDF_INCLUDE_DIRS NetCDF_LIBRARIES | ||
VERSION_VAR NetCDF_VERSION | ||
HANDLE_COMPONENTS ) | ||
|
||
if( ${CMAKE_FIND_PACKAGE_NAME}_FOUND AND NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY ) | ||
message( STATUS "Find${CMAKE_FIND_PACKAGE_NAME} defines targets:" ) | ||
foreach( _comp ${_search_components} ) | ||
string( TOUPPER "${_comp}" _COMP ) | ||
|
||
if( ${CMAKE_FIND_PACKAGE_NAME}_${_arg_${_COMP}}_FOUND ) | ||
message( STATUS " - NetCDF::NetCDF_${_comp} [${NetCDF_${_comp}_LIBRARY}]") | ||
endif() | ||
endforeach() | ||
endif() | ||
|
||
foreach( _prefix NetCDF NetCDF4 NETCDF NETCDF4 ${CMAKE_FIND_PACKAGE_NAME} ) | ||
set( ${_prefix}_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} ) | ||
set( ${_prefix}_LIBRARIES ${NetCDF_LIBRARIES}) | ||
set( ${_prefix}_VERSION ${NetCDF_VERSION} ) | ||
set( ${_prefix}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_FOUND} ) | ||
|
||
foreach( _comp ${_search_components} ) | ||
string( TOUPPER "${_comp}" _COMP ) | ||
set( _arg_comp ${_arg_${_COMP}} ) | ||
set( ${_prefix}_${_comp}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) | ||
set( ${_prefix}_${_COMP}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) | ||
set( ${_prefix}_${_arg_comp}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) | ||
|
||
set( ${_prefix}_${_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) | ||
set( ${_prefix}_${_COMP}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) | ||
set( ${_prefix}_${_arg_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) | ||
|
||
set( ${_prefix}_${_comp}_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} ) | ||
set( ${_prefix}_${_COMP}_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} ) | ||
set( ${_prefix}_${_arg_comp}_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} ) | ||
endforeach() | ||
endforeach() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# - Try to find PIO | ||
# Once done this will define | ||
# PIO_FOUND - System has PIO | ||
# PIO_INCLUDE_DIRS - The PIO include directories | ||
# PIO_LIBRARIES - The libraries needed to use PIO | ||
# PIO_VERSION - A global property indicating the PIO API: either 1 or 2 if PIO was found, and 0 otherwise | ||
|
||
find_path(PIO_INCLUDE_DIR pio.mod PIO.mod HINTS ENV PIO ENV PIO_PATH PATH_SUFFIXES include) | ||
find_library(PIO1_C_LIBRARY libpio.a HINTS ENV PIO ENV PIO_PATH PATH_SUFFIXES lib) | ||
find_library(PIO2_C_LIBRARY libpioc.a libpioc.so HINTS ENV PIO ENV PIO_PATH PATH_SUFFIXES lib) | ||
find_library(PIO_F_LIBRARY libpiof.a libpiof.so HINTS ENV PIO ENV PIO_PATH PATH_SUFFIXES lib) | ||
|
||
if(PIO1_C_LIBRARY) | ||
set(PIO_C_LIBRARY ${PIO1_C_LIBRARY}) | ||
set_property(GLOBAL PROPERTY PIO_VERSION 1) | ||
|
||
# | ||
# PIO 1.x may not have a separate Fortran and C library, in which case, we can just | ||
# use libpio.a as the only PIO library | ||
# | ||
if (${PIO_F_LIBRARY} STREQUAL "PIO_F_LIBRARY-NOTFOUND") | ||
set(PIO_LIBRARIES ${PIO_C_LIBRARY}) | ||
else() | ||
set(PIO_LIBRARIES ${PIO_F_LIBRARY} ${PIO_C_LIBRARY}) | ||
endif() | ||
set(PIO_INCLUDE_DIRS ${PIO_INCLUDE_DIR}) | ||
elseif(PIO2_C_LIBRARY) | ||
set(PIO_C_LIBRARY ${PIO2_C_LIBRARY}) | ||
set_property(GLOBAL PROPERTY PIO_VERSION 2) | ||
set(PIO_LIBRARIES ${PIO_F_LIBRARY} ${PIO_C_LIBRARY}) | ||
set(PIO_INCLUDE_DIRS ${PIO_INCLUDE_DIR}) | ||
else() | ||
message("No PIO library found...") | ||
set_property(GLOBAL PROPERTY PIO_VERSION 0) | ||
set(PIO_LIBRARIES "") | ||
set(PIO_INCLUDE_DIRS "") | ||
endif() | ||
|
||
|
||
include(FindPackageHandleStandardArgs) | ||
# handle the QUIETLY and REQUIRED arguments and set PIO_FOUND to TRUE | ||
# if all listed variables are TRUE | ||
find_package_handle_standard_args(PIO DEFAULT_MSG PIO_LIBRARIES PIO_INCLUDE_DIRS) |
Oops, something went wrong.