From 841d06b5051b361d61d2aa1a44602f47fc9bb4ff Mon Sep 17 00:00:00 2001 From: Carlisle Wishard Date: Thu, 13 Oct 2022 10:32:58 -0400 Subject: [PATCH] added the cmake infrastructure --- CMakeLists.txt | 95 ++++++ cmake/Modules/FindOpenMP_Fortran.cmake | 104 ++++++ cmake/Modules/SetCompileFlag.cmake | 112 +++++++ cmake/Modules/SetFortranFlags.cmake | 313 ++++++++++++++++++ cmake/Modules/SetParallelizationLibrary.cmake | 39 +++ cmake/Modules/SetUpLAPACK.cmake | 11 + distclean.cmake | 68 ++++ lib/CMakeLists.txt | 3 + src/CMakeLists.txt | 134 ++++++++ 9 files changed, 879 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 cmake/Modules/FindOpenMP_Fortran.cmake create mode 100644 cmake/Modules/SetCompileFlag.cmake create mode 100644 cmake/Modules/SetFortranFlags.cmake create mode 100644 cmake/Modules/SetParallelizationLibrary.cmake create mode 100644 cmake/Modules/SetUpLAPACK.cmake create mode 100644 distclean.cmake create mode 100644 lib/CMakeLists.txt create mode 100644 src/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..4699a11ba --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,95 @@ +# CMake project file for FOO + +################################################## +# Define the project and the depencies that it has +################################################## + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5...3.20.1) +PROJECT(Swiftest) + +# Set the Swiftest version +SET(VERSION 1.0.0) + +# Add our local modlues to the module path +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/") + +# Uncomment if it is required that Fortran 90 is supported +IF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90) + MESSAGE(FATAL_ERROR "Fortran compiler does not support F90") +ENDIF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90) + +# Set some options the user may choose +# Uncomment the below if you want the user to choose a parallelization library +#OPTION(USE_MPI "Use the MPI library for parallelization" OFF) +#OPTION(USE_OPENMP "Use OpenMP for parallelization" OFF) + +# This INCLUDE statement executes code that sets the compile flags for DEBUG, +# RELEASE, and TESTING. You should review this file and make sure the flags +# are to your liking. +INCLUDE(${CMAKE_MODULE_PATH}/SetFortranFlags.cmake) +# Locate and set parallelization libraries. There are some CMake peculiarities +# taken care of here, such as the fact that the FindOpenMP routine doesn't know +# about Fortran. +INCLUDE(${CMAKE_MODULE_PATH}/SetParallelizationLibrary.cmake) +# Setup the LAPACK libraries. This also takes care of peculiarities, such as +# the fact the searching for MKL requires a C compiler, and that the results +# are not stored in the cache. +INCLUDE(${CMAKE_MODULE_PATH}/SetUpLAPACK.cmake) + +# There is an error in CMAKE with this flag for pgf90. Unset it +GET_FILENAME_COMPONENT(FCNAME ${CMAKE_Fortran_COMPILER} NAME) +IF(FCNAME STREQUAL "pgf90") + UNSET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS) +ENDIF(FCNAME STREQUAL "pgf90") + +############################################################ +# Define the actual files and folders that make up the build +############################################################ + +# Define the executable name +SET(FOOEXE swiftest_driver) + +# Define the library name +SET(BARLIB libswiftest) + +# Define some directories +SET(SRC ${CMAKE_SOURCE_DIR}/src) +SET(LIB ${CMAKE_SOURCE_DIR}/lib) +SET(BIN ${CMAKE_SOURCE_DIR}/bin) +SET(DISCARD ${SRC}/discard) +SET(DRIFT ${SRC}/drift) +SET(ENCOUNTER ${SRC}/encounter) +SET(FRAGGLE ${SRC}/fraggle) +SET(GR ${SRC}/gr) +SET(HELIO ${SRC}/helio) +SET(IO ${SRC}/io) +SET(KICK ${SRC}/kick) +SET(MAIN ${SRC}/main) +SET(MODULES ${SRC}/modules) +SET(NETCDF ${SRC}/netcdf) +SET(OBL ${SRC}/obl) +SET(OPERATORS ${SRC}/operators) +SET(ORBEL ${SRC}/orbel) +SET(PYTHONBINDINGS ${SRC}/python_bindings) +SET(RMVS ${SRC}/rmvs) +SET(SETUP ${SRC}/setup) +SET(SYMBA ${SRC}/SYMBA) +#SET(TIDES ${SRC}/tides) +SET(USER ${SRC}/user) +SET(UTIL ${SRC}/util) +SET(WALLTIME ${SRC}/walltime) +SET(WHM ${SRC}/whm) + +# Have the .mod files placed in the lib folder +SET(CMAKE_Fortran_MODULE_DIRECTORY ${LIB}) + +# The source for the Swiftest library and have it placed in the lib folder +ADD_SUBDIRECTORY(${BARLIB} ${LIB}) + +# The source for the EXE binary and have it placed in the bin folder +ADD_SUBDIRECTORY(${FOOEXE} ${BIN}) + +# Add a distclean target to the Makefile +ADD_CUSTOM_TARGET(distclean + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/distclean.cmake +) diff --git a/cmake/Modules/FindOpenMP_Fortran.cmake b/cmake/Modules/FindOpenMP_Fortran.cmake new file mode 100644 index 000000000..bc440ae10 --- /dev/null +++ b/cmake/Modules/FindOpenMP_Fortran.cmake @@ -0,0 +1,104 @@ +# - Finds OpenMP support +# This module can be used to detect OpenMP support in a compiler. +# If the compiler supports OpenMP, the flags required to compile with +# openmp support are set. +# +# This module was modified from the standard FindOpenMP module to find Fortran +# flags. +# +# The following variables are set: +# OpenMP_Fortran_FLAGS - flags to add to the Fortran compiler for OpenMP +# support. In general, you must use these at both +# compile- and link-time. +# OMP_NUM_PROCS - the max number of processors available to OpenMP + +#============================================================================= +# Copyright 2009 Kitware, Inc. +# Copyright 2008-2009 André Rigland Brodtkorb +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +INCLUDE (${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) + +SET (OpenMP_Fortran_FLAG_CANDIDATES + #Microsoft Visual Studio + "/openmp" + #Intel windows + "/Qopenmp" + #Intel + "-qopenmp" + #Gnu + "-fopenmp" + #Empty, if compiler automatically accepts openmp + " " + #Sun + "-xopenmp" + #HP + "+Oopenmp" + #IBM XL C/c++ + "-qsmp" + #Portland Group + "-mp" +) + +IF (DEFINED OpenMP_Fortran_FLAGS) + SET (OpenMP_Fortran_FLAG_CANDIDATES) +ENDIF (DEFINED OpenMP_Fortran_FLAGS) + +# check fortran compiler. also determine number of processors +FOREACH (FLAG ${OpenMP_Fortran_FLAG_CANDIDATES}) + SET (SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + SET (CMAKE_REQUIRED_FLAGS "${FLAG}") + UNSET (OpenMP_FLAG_DETECTED CACHE) + MESSAGE (STATUS "Try OpenMP Fortran flag = [${FLAG}]") + FILE (WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranOpenMP.f90" +" +program TestOpenMP + use omp_lib + write(*,'(I2)',ADVANCE='NO') omp_get_num_procs() +end program TestOpenMP +") + SET (MACRO_CHECK_FUNCTION_DEFINITIONS + "-DOpenMP_FLAG_DETECTED ${CMAKE_REQUIRED_FLAGS}") + TRY_RUN (OpenMP_RUN_FAILED OpenMP_FLAG_DETECTED ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranOpenMP.f90 + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + COMPILE_OUTPUT_VARIABLE OUTPUT + RUN_OUTPUT_VARIABLE OMP_NUM_PROCS_INTERNAL) + IF (OpenMP_FLAG_DETECTED) + FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the Fortran compiler supports OpenMP passed with " + "the following output:\n${OUTPUT}\n\n") + SET (OpenMP_FLAG_DETECTED 1) + IF (OpenMP_RUN_FAILED) + MESSAGE (FATAL_ERROR "OpenMP found, but test code did not run") + ENDIF (OpenMP_RUN_FAILED) + SET (OMP_NUM_PROCS ${OMP_NUM_PROCS_INTERNAL} CACHE + STRING "Number of processors OpenMP may use" FORCE) + SET (OpenMP_Fortran_FLAGS_INTERNAL "${FLAG}") + BREAK () + ELSE () + FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the Fortran compiler supports OpenMP failed with " + "the following output:\n${OUTPUT}\n\n") + SET (OpenMP_FLAG_DETECTED 0) + ENDIF (OpenMP_FLAG_DETECTED) +ENDFOREACH (FLAG ${OpenMP_Fortran_FLAG_CANDIDATES}) + +SET (OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_INTERNAL}" + CACHE STRING "Fortran compiler flags for OpenMP parallization") + +# handle the standard arguments for FIND_PACKAGE +FIND_PACKAGE_HANDLE_STANDARD_ARGS (OpenMP_Fortran DEFAULT_MSG + OpenMP_Fortran_FLAGS) + +MARK_AS_ADVANCED(OpenMP_Fortran_FLAGS) diff --git a/cmake/Modules/SetCompileFlag.cmake b/cmake/Modules/SetCompileFlag.cmake new file mode 100644 index 000000000..04ff3ffbd --- /dev/null +++ b/cmake/Modules/SetCompileFlag.cmake @@ -0,0 +1,112 @@ +############################################################################# +# Given a list of flags, this function will try each, one at a time, +# and choose the first flag that works. If no flags work, then nothing +# will be set, unless the REQUIRED key is given, in which case an error +# will be given. +# +# Call is: +# SET_COMPILE_FLAG(FLAGVAR FLAGVAL (Fortran|C|CXX) flag1 flag2...) +# +# For example, if you have the flag CMAKE_C_FLAGS and you want to add +# warnings and want to fail if this is not possible, you might call this +# function in this manner: +# SET_COMPILE_FLAGS(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" C REQUIRED +# "-Wall" # GNU +# "-warn all" # Intel +# ) +# The optin "-Wall" will be checked first, and if it works, will be +# appended to the CMAKE_C_FLAGS variable. If it doesn't work, then +# "-warn all" will be tried. If this doesn't work then checking will +# terminate because REQUIRED was given. +# +# The reasong that the variable must be given twice (first as the name then +# as the value in quotes) is because of the way CMAKE handles the passing +# of variables in functions; it is difficult to extract a variable's +# contents and assign new values to it from within a function. +############################################################################# + +INCLUDE(${CMAKE_ROOT}/Modules/CheckCCompilerFlag.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CheckCXXCompilerFlag.cmake) + +FUNCTION(SET_COMPILE_FLAG FLAGVAR FLAGVAL LANG) + + # Do some up front setup if Fortran + IF(LANG STREQUAL "Fortran") + # Create a list of error messages from compilers + SET(FAIL_REGEX + "ignoring unknown option" # Intel + "invalid argument" # Intel + "unrecognized .*option" # GNU + "[Uu]nknown switch" # Portland Group + "ignoring unknown option" # MSVC + "warning D9002" # MSVC, any lang + "[Uu]nknown option" # HP + "[Ww]arning: [Oo]ption" # SunPro + "command option .* is not recognized" # XL + ) + ENDIF(LANG STREQUAL "Fortran") + + # Make a variable holding the flags. Filter out REQUIRED if it is there + SET(FLAG_REQUIRED FALSE) + SET(FLAG_FOUND FALSE) + UNSET(FLAGLIST) + FOREACH (var ${ARGN}) + STRING(TOUPPER "${var}" UP) + IF(UP STREQUAL "REQUIRED") + SET(FLAG_REQUIRED TRUE) + ELSE() + SET(FLAGLIST ${FLAGLIST} "${var}") + ENDIF(UP STREQUAL "REQUIRED") + ENDFOREACH (var ${ARGN}) + + # Now, loop over each flag + FOREACH(flag ${FLAGLIST}) + + UNSET(FLAG_WORKS) + # Check the flag for the given language + IF(LANG STREQUAL "C") + CHECK_C_COMPILER_FLAG("${flag}" FLAG_WORKS) + ELSEIF(LANG STREQUAL "CXX") + CHECK_CXX_COMPILER_FLAG("${flag}" FLAG_WORKS) + ELSEIF(LANG STREQUAL "Fortran") + # There is no nice function to do this for FORTRAN, so we must manually + # create a test program and check if it compiles with a given flag. + SET(TESTFILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}") + SET(TESTFILE "${TESTFILE}/CMakeTmp/testFortranFlags.f90") + FILE(WRITE "${TESTFILE}" +" +program dummyprog + i = 5 +end program dummyprog +") + TRY_COMPILE(FLAG_WORKS ${CMAKE_BINARY_DIR} ${TESTFILE} + COMPILE_DEFINITIONS "${flag}" OUTPUT_VARIABLE OUTPUT) + + # Check that the output message doesn't match any errors + FOREACH(rx ${FAIL_REGEX}) + IF("${OUTPUT}" MATCHES "${rx}") + SET(FLAG_WORKS FALSE) + ENDIF("${OUTPUT}" MATCHES "${rx}") + ENDFOREACH(rx ${FAIL_REGEX}) + + ELSE() + MESSAGE(FATAL_ERROR "Unknown language in SET_COMPILE_FLAGS: ${LANG}") + ENDIF(LANG STREQUAL "C") + + # If this worked, use these flags, otherwise use other flags + IF(FLAG_WORKS) + # Append this flag to the end of the list that already exists + SET(${FLAGVAR} "${FLAGVAL} ${flag}" CACHE STRING + "Set the ${FLAGVAR} flags" FORCE) + SET(FLAG_FOUND TRUE) + BREAK() # We found something that works, so exit + ENDIF(FLAG_WORKS) + + ENDFOREACH(flag ${FLAGLIST}) + + # Raise an error if no flag was found + IF(FLAG_REQUIRED AND NOT FLAG_FOUND) + MESSAGE(FATAL_ERROR "No compile flags were found") + ENDIF(FLAG_REQUIRED AND NOT FLAG_FOUND) + +ENDFUNCTION() diff --git a/cmake/Modules/SetFortranFlags.cmake b/cmake/Modules/SetFortranFlags.cmake new file mode 100644 index 000000000..a8c1121e7 --- /dev/null +++ b/cmake/Modules/SetFortranFlags.cmake @@ -0,0 +1,313 @@ +###################################################### +# Determine and set the Fortran compiler flags we want +###################################################### + +#################################################################### +# Make sure that the default build type is RELEASE if not specified. +#################################################################### +INCLUDE(${CMAKE_MODULE_PATH}/SetCompileFlag.cmake) + +# Make sure the build type is uppercase +STRING(TOUPPER "${CMAKE_BUILD_TYPE}" BT) + +IF(BT STREQUAL "RELEASE") + SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING + "Choose the type of build, options are DEBUG, RELEASE, or TESTING." + FORCE) +ELSEIF(BT STREQUAL "DEBUG") + SET (CMAKE_BUILD_TYPE DEBUG CACHE STRING + "Choose the type of build, options are DEBUG, RELEASE, or TESTING." + FORCE) +ELSEIF(BT STREQUAL "TESTING") + SET (CMAKE_BUILD_TYPE TESTING CACHE STRING + "Choose the type of build, options are DEBUG, RELEASE, or TESTING." + FORCE) +ELSEIF(NOT BT) + SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING + "Choose the type of build, options are DEBUG, RELEASE, or TESTING." + FORCE) + MESSAGE(STATUS "CMAKE_BUILD_TYPE not given, defaulting to RELEASE") +ELSE() + MESSAGE(FATAL_ERROR "CMAKE_BUILD_TYPE not valid, choices are DEBUG, RELEASE, or TESTING") +ENDIF(BT STREQUAL "RELEASE") + +######################################################### +# If the compiler flags have already been set, return now +######################################################### + +IF(CMAKE_Fortran_FLAGS_RELEASE AND CMAKE_Fortran_FLAGS_TESTING AND CMAKE_Fortran_FLAGS_DEBUG) + RETURN () +ENDIF(CMAKE_Fortran_FLAGS_RELEASE AND CMAKE_Fortran_FLAGS_TESTING AND CMAKE_Fortran_FLAGS_DEBUG) + +######################################################################## +# Determine the appropriate flags for this compiler for each build type. +# For each option type, a list of possible flags is given that work +# for various compilers. The first flag that works is chosen. +# If none of the flags work, nothing is added (unless the REQUIRED +# flag is given in the call). This way unknown compiles are supported. +####################################################################### + +##################### +### GENERAL FLAGS ### +##################### + +# Don't add underscores in symbols for C-compatability +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-fno-underscoring") + +# There is some bug where -march=native doesn't work on Mac +IF(APPLE) + SET(GNUNATIVE "-mtune=native") +ELSE() + SET(GNUNATIVE "-march=native") +ENDIF() +# Optimize for the host's architecture +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-xHost" # Intel + "/QxHost" # Intel Windows + ${GNUNATIVE} # GNU + "-ta=host" # Portland Group + ) + +################### +### DEBUG FLAGS ### +################### + +# NOTE: debugging symbols (-g or /debug:full) are already on by default + +# Disable optimizations +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran REQUIRED "-O0" # All compilers not on Windows + "/Od" # Intel Windows + "-Og" # GNU (gfortran) + ) + +# Turn on all warnings +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-warn all" # Intel + "/warn:all" # Intel Windows + "-Wall" # GNU + # Portland Group (on by default) + ) + +# Traceback +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-traceback" # Intel/Portland Group + "/traceback" # Intel Windows + "-fbacktrace" # GNU (gfortran) + "-ftrace=full" # GNU (g95) + ) + +# Check array bounds +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-check bounds" # Intel + "/check:bounds" # Intel Windows + "-fcheck=bounds" # GNU (New style) + "-fbounds-check" # GNU (Old style) + "-Mbounds" # Portland Group + ) + +# Initializes matrices/arrays with NaN values +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-init=snan,arrays" # Intel + ) + +# Does not generate an interface block for each routine in a source file +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-nogen-interfaces" # Intel + ) + +# Does not generate aposition independent executable +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-no-pie" # Intel + ) + +# Does not set denormal results from floating-point calculations to zero +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-no-ftz" # Intel + ) + +# Enables floating-point invalid, divide-by-zero, and overflow exceptions +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fpe-all=0" # Intel + ) + +# Improves floating-point precision and consistency +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-mp1" # Intel + ) + +# Calls the Matrix Multiply library +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-qopt-matmul" # Intel + ) + +# Strict model for floating-point calculations (precise and except) +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fp-model strict" # Intel + ) + +# Enables floating-point invalid, divide-by-zero, and overflow exceptions +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fpe0" # Intel + ) + +# Enables debug info +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-debug all" # Intel + ) + +# Aligns a variable to a specified boundary and offset +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-align all" # Intel + ) + +# Enables changing the variable and array memory layout +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-pad" # Intel + ) + +# Enables additional interprocedural optimizations for a single file cimpilation +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-ip" # Intel + ) + +# Improves precision when dividing floating-points +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-prec-div" # Intel + ) + +# Improves precision when taking the square root of floating-points +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-prec-sqrt" # Intel + ) + +# Treat parentheses in accordance with the Fortran standard (ifort 10 only) +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-assume protect-parens" # Intel + ) + +# Checks the bounds of arrays at run-time +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-CB" # Intel + ) + +# Allows for lines longer than 80 characters without truncation +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-no-wrap-margin" # Intel + "-ffree-line-length-none" # GNU (gfortran) + ) + +##################### +### TESTING FLAGS ### +##################### + +# Optimizations +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_TESTING "${CMAKE_Fortran_FLAGS_TESTING}" + Fortran REQUIRED "-O2" # All compilers not on Windows + "/O2" # Intel Windows + ) + +##################### +### RELEASE FLAGS ### +##################### + +# NOTE: agressive optimizations (-O3) are already turned on by default + +# Unroll loops +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-funroll-loops" # GNU + "-unroll" # Intel + "/unroll" # Intel Windows + "-Munroll" # Portland Group + ) + +# Inline functions +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-inline" # Intel + "/Qinline" # Intel Windows + "-finline-functions" # GNU + "-Minline" # Portland Group + ) + +# Interprocedural (link-time) optimizations +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-ipo" # Intel + "/Qipo" # Intel Windows + "-flto" # GNU + "-Mipa" # Portland Group + ) + +# Single-file optimizations +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-ip" # Intel + "/Qip" # Intel Windows + ) + +# Vectorize code +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-vec-report0" # Intel + "/Qvec-report0" # Intel Windows + "-Mvect" # Portland Group + ) + +# Allows for lines longer than 80 characters without truncation +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-no-wrap-margin" # Intel + "-ffree-line-length-none" # GNU (gfortran) + ) + +# Disables prefetch insertion optimization +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-qopt-prefetch=0" # Intel + ) + +# Calls the Matrix Multiply library +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-qopt-matmul" # Intel + ) + +# Saves the compiler options and version number to the executable +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-sox" # Intel + ) + +# Enforces vectorization of loops +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-simd" # Intel + ) + +# Generate instructions for the highest instruction set available +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-xhost" # Intel + ) + +# Aligns a variable to a specified boundary and offset +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-align all" # Intel + ) + +# Assume all objects are contiguous in memory +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-assume contiguous_assumed_shape" # Intel + ) + +# Generate an extended set of vector functions +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-vecabi=cmdtarget" # Intel + ) + +# No floating-point exceptions +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-fp-model no-except" # Intel + ) + +# Generate fused multiply-add instructions +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-fma" # Intel + ) + +# Enables agressive optimixation on floating-points +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-fp-model=fast" # Intel + ) diff --git a/cmake/Modules/SetParallelizationLibrary.cmake b/cmake/Modules/SetParallelizationLibrary.cmake new file mode 100644 index 000000000..603d4299c --- /dev/null +++ b/cmake/Modules/SetParallelizationLibrary.cmake @@ -0,0 +1,39 @@ +# Turns on either OpenMP or MPI +# If both are requested, the other is disabled +# When one is turned on, the other is turned off +# If both are off, we explicitly disable them just in case + +IF (USE_OPENMP AND USE_MPI) + MESSAGE (FATAL_ERROR "Cannot use both OpenMP and MPI") +ELSEIF (USE_OPENMP) + # Find OpenMP + IF (NOT OpenMP_Fortran_FLAGS) + FIND_PACKAGE (OpenMP_Fortran) + IF (NOT OpenMP_Fortran_FLAGS) + MESSAGE (FATAL_ERROR "Fortran compiler does not support OpenMP") + ENDIF (NOT OpenMP_Fortran_FLAGS) + ENDIF (NOT OpenMP_Fortran_FLAGS) + # Turn of MPI + UNSET (MPI_FOUND CACHE) + UNSET (MPI_COMPILER CACHE) + UNSET (MPI_LIBRARY CACHE) +ELSEIF (USE_MPI) + # Find MPI + IF (NOT MPI_Fortran_FOUND) + FIND_PACKAGE (MPI REQUIRED) + ENDIF (NOT MPI_Fortran_FOUND) + # Turn off OpenMP + SET (OMP_NUM_PROCS 0 CACHE + STRING "Number of processors OpenMP may use" FORCE) + UNSET (OpenMP_C_FLAGS CACHE) + UNSET (GOMP_Fortran_LINK_FLAGS CACHE) +ELSE () + # Turn off both OpenMP and MPI + SET (OMP_NUM_PROCS 0 CACHE + STRING "Number of processors OpenMP may use" FORCE) + UNSET (OpenMP_Fortran_FLAGS CACHE) + UNSET (GOMP_Fortran_LINK_FLAGS CACHE) + UNSET (MPI_FOUND CACHE) + UNSET (MPI_COMPILER CACHE) + UNSET (MPI_LIBRARY CACHE) +ENDIF (USE_OPENMP AND USE_MPI) diff --git a/cmake/Modules/SetUpLAPACK.cmake b/cmake/Modules/SetUpLAPACK.cmake new file mode 100644 index 000000000..ae5bdea52 --- /dev/null +++ b/cmake/Modules/SetUpLAPACK.cmake @@ -0,0 +1,11 @@ +# Find LAPACK (finds BLAS also) if not already found +IF(NOT LAPACK_FOUND) + ENABLE_LANGUAGE(C) # Some libraries need a C compiler to find + FIND_PACKAGE(LAPACK REQUIRED) + # Remember that LAPACK (and BLAS) was found. For some reason the + # FindLAPACK routine doesn't place these into the CACHE. + SET(BLAS_FOUND TRUE CACHE INTERNAL "BLAS was found" FORCE) + SET(LAPACK_FOUND TRUE CACHE INTERNAL "LAPACK was found" FORCE) + SET(BLAS_LIBRARIES ${BLAS_LIBRARIES} CACHE INTERNAL "BLAS LIBS" FORCE) + SET(LAPACK_LIBRARIES ${LAPACK_LIBRARIES} CACHE INTERNAL "LAPACK LIBS" FORCE) +ENDIF(NOT LAPACK_FOUND) diff --git a/distclean.cmake b/distclean.cmake new file mode 100644 index 000000000..8e24f9e49 --- /dev/null +++ b/distclean.cmake @@ -0,0 +1,68 @@ +# This CMake script will delete build directories and files to bring the +# package back to it's distribution state + +# We want to start from the top of the source dir, so if we are in build +# we want to start one directory up +GET_FILENAME_COMPONENT(BASEDIR ${CMAKE_SOURCE_DIR} NAME) +IF(${BASEDIR} STREQUAL "build") + SET(TOPDIR "${CMAKE_SOURCE_DIR}/..") +ELSE() + SET(TOPDIR "${CMAKE_SOURCE_DIR}") +ENDIF() + +MACRO(GET_PARENT_DIRECTORIES search_string return_list grandparents) + FILE(GLOB_RECURSE new_list ${search_string}) + SET(dir_list "") + FOREACH(file_path ${new_list}) + GET_FILENAME_COMPONENT(dir_path ${file_path} PATH) + # Remove an extra directory component to return grandparent + IF(${grandparents}) + # Tack on a fake extension to trick CMake into removing a second + # path component + SET(dir_path "${dir_path}.tmp") + GET_FILENAME_COMPONENT(dir_path ${dir_path} PATH) + ENDIF(${grandparents}) + SET(dir_list ${dir_list} ${dir_path}) + ENDFOREACH() + LIST(REMOVE_DUPLICATES dir_list) + SET(${return_list} ${dir_list}) +ENDMACRO() + +# Find directories and files that we will want to remove +FILE(GLOB_RECURSE CMAKECACHE "${TOPDIR}/*CMakeCache.txt") +FILE(GLOB_RECURSE CMAKEINSTALL "${TOPDIR}/*cmake_install.cmake" + "${TOPDIR}/*install_manifest.txt") +FILE(GLOB_RECURSE MAKEFILE "${TOPDIR}/*Makefile") +FILE(GLOB_RECURSE CMAKETESTFILES "${TOPDIR}/*CTestTestfile.cmake") +SET(TOPDIRECTORIES "${TOPDIR}/lib" + "${TOPDIR}/test" + "${TOPDIR}/bin" +) + +# CMake has trouble finding directories recursively, so locate these +# files and then save the parent directory of the files +GET_PARENT_DIRECTORIES(Makefile.cmake CMAKEFILES 0) +GET_PARENT_DIRECTORIES(LastTest.log CMAKETESTING 1) + +# Place these files and directories into a list +SET(DEL ${TOPDIRECTORIES} + ${CMAKECACHE} + ${CMAKEINSTALL} + ${MAKEFILE} + ${CMAKEFILES} + ${CMAKETESTING} + ${CMAKETESTFILES} +) + +# If we are not in the build dir, delete that as well +IF(NOT (${BASEDIR} STREQUAL "build")) + FILE(GLOB BUILD "${TOPDIR}/build") + SET(DEL ${DEL} ${BUILD}) +ENDIF() + +# Loop over the directories and delete each one +FOREACH(D ${DEL}) + IF(EXISTS ${D}) + FILE(REMOVE_RECURSE ${D}) + ENDIF() +ENDFOREACH() diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 000000000..b621d3204 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,3 @@ +# bar library +SET(BAR_src ${SRCBAR}/libswiftest.a) +ADD_LIBRARY(${BARLIB} STATIC ${BAR_src}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 000000000..021eb0e89 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,134 @@ +######################################## +# Set up how to compile the source files +######################################## + +# Add the source files +SET(FOO_src ${DISCARD}/discard.f90 + ${DRIFT}/drift.f90 + ${ENCOUNTER}/encounter_check.f90 + ${ENCOUNTER}/encounter_io.f90 + ${ENCOUNTER}/encounter_setup.f90 + ${ENCOUNTER}/encounter_util.f90 + ${FRAGGLE}/fraggle_generate.f90 + ${FRAGGLE}/fraggle_io.f90 + ${FRAGGLE}/fraggle_placeholder.f90 + ${FRAGGLE}/fraggle_regime.f90 + ${FRAGGLE}/fraggle_set.f90 + ${FRAGGLE}/fraggle_setup.f90 + ${FRAGGLE}/fraggle_util.f90 + ${GR}/gr.f90 + ${HELIO}/helio_drift.f90 + ${HELIO}/helio_gr.f90 + ${HELIO}/helio_kick.f90 + ${HELIO}/helio_setup.f90 + ${HELIO}/helio_step.f90 + ${HELIO}/helio_util.f90 + ${IO}/io.f90 + ${KICK}/kick.f90 + ${MAIN}/swiftest_driver.f90 + ${MODULES}/encounter_classes.f90 + ${MODULES}/fraggle_classes.f90 + ${MODULES}/helio_classes.f90 + ${MODULES}/lambda_function.f90 + ${MODULES}/rmvs_classes.f90 + ${MODULES}/swiftest_classes.f90 + ${MODULES}/swiftest_globals.f90 + ${MODULES}/swiftest_operators.f90 + ${MODULES}/swiftest.f90 + ${MODULES}/symba_classes.f90 + ${MODULES}/walltime_classes.f90 + ${MODULES}/whm_classes.f90 + ${NETCDF}/netcdf.f90 + ${OBL}/obl.f90 + ${OPERATORS}/operator_cross.f90 + ${OPERATORS}/operator_mag.f90 + ${ORBEL}/orbel.f90 + ${PYTHONBINDINGS}/orbel.f90 + ${RMVS}/rmvs_discard.f90 + ${RMVS}/rmvs_encounter_check.f90 + ${RMVS}/rmvs_io.f90 + ${RMVS}/rmvs_kick.f90 + ${RMVS}/rmvs_setup.f90 + ${RMVS}/rmvs_step.f90 + ${RMVS}/rmvs_util.f90 + ${SETUP}/setup.f90 + ${SYMBA}/symba_collision.f90 + ${SYMBA}/symba_discard.f90 + ${SYMBA}/symba_drift.f90 + ${SYMBA}/symba_encounter_check.f90 + ${SYMBA}/symba_gr.f90 + ${SYMBA}/symba_io.f90 + ${SYMBA}/symba_kick.f90 + ${SYMBA}/symba_setup.f90 + ${SYMBA}/symba_step.f90 + ${SYMBA}/symba_util.f90 +# ${TIDES}/tides_getacch_pl.f90 +# ${TIDES}/tides_spin_step.f90 + ${USER}/user_getacch.f90 + ${UTIL}/util_append.f90 + ${UTIL}/util_coord.f90 + ${UTIL}/util_copy.f90 + ${UTIL}/util_dealloc.f90 + ${UTIL}/util_exit.f90 + ${UTIL}/util_fill.f90 + ${UTIL}/util_flatten.f90 + ${UTIL}/util_get_energy_momentum.f90 + ${UTIL}/util_index_array.f90 + ${UTIL}/util_minimize_bfgs.f90 + ${UTIL}/util_peri.f90 + ${UTIL}/util_rescale.f90 + ${UTIL}/util_resize.f90 + ${UTIL}/util_set.f90 + ${UTIL}/util_solve.f90 + ${UTIL}/util_sort.f90 + ${UTIL}/util_spill.f90 + ${UTIL}/util_valid.f90 + ${UTIL}/util_version.f90 + ${WALLTIME}/walltime.f90 + ${WHM}/whm_coord.f90 + ${WHM}/whm_drift.f90 + ${WHM}/whm_gr.f90 + ${WHM}/whm_kick.f90 + ${WHM}/whm_setup.f90 + ${WHM}/whm_step.f90 + ${WHM}/whm_util.f90 +) + +# Define the executable in terms of the source files +ADD_EXECUTABLE(${FOOEXE} ${FOO_src}) + +##################################################### +# Add the needed libraries and special compiler flags +##################################################### + +# This links foo to the bar library +TARGET_LINK_LIBRARIES(${FOOEXE} ${BARLIB}) + +# Uncomment if you need to link to BLAS and LAPACK +#TARGET_LINK_LIBRARIES(${FOOEXE} ${BLAS_LIBRARIES} +# ${LAPACK_LIBRARIES} +# ${CMAKE_THREAD_LIBS_INIT}) + +# Uncomment if you have parallization +IF(USE_OPENMP) + SET_TARGET_PROPERTIES(${FOOEXE} PROPERTIES + COMPILE_FLAGS "${OpenMP_Fortran_FLAGS}" + LINK_FLAGS "${OpenMP_Fortran_FLAGS}") +ELSEIF(USE_MPI) + SET_TARGET_PROPERTIES(${FOOEXE} PROPERTIES + COMPILE_FLAGS "${MPI_Fortran_COMPILE_FLAGS}" + LINK_FLAGS "${MPI_Fortran_LINK_FLAGS}") + INCLUDE_DIRECTORIES(${MPI_Fortran_INCLUDE_PATH}) + TARGET_LINK_LIBRARIES(${FOOEXE} ${MPI_Fortran_LIBRARIES}) +ENDIF(USE_OPENMP) + +##################################### +# Tell how to install this executable +##################################### + +IF(WIN32) + SET(CMAKE_INSTALL_PREFIX "C:\\Program Files") +ELSE() + SET(CMAKE_INSTALL_PREFIX /usr/local) +ENDIF(WIN32) +INSTALL(TARGETS ${FOOEXE} RUNTIME DESTINATION bin)