diff --git a/.gitignore b/.gitignore index a8fb113c9021c24bc975dd3981dfcfa7dc25da35..ada040779c74a9ee956bb9a47588ca600280a9d6 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ autom4te.cache autogen* INSTALL configure -config.h.in +/config.h.in build-aux build-stamp semantic.cache @@ -234,3 +234,93 @@ src/.fortran_dependencies/ # /testsuite/photo_electron/ /testsuite/photo_electron/.log + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### CMake template +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + + +### Custom development +/.idea/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..89c3b98c8c19ca24ee0c473576be089201d41144 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "third_party/Libxc"] + path = third_party/Libxc + url = https://gitlab.com/libxc/libxc.git +[submodule "third_party/Spglib"] + path = third_party/Spglib + url = https://github.com/spglib/spglib.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..de96aaeb3624a75b16f66f1ecd1ca1dbf773bda3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,291 @@ +cmake_minimum_required(VERSION 3.13) +# CMake version compatibility + +#[==============================================================================================[ +# Basic project defintion # +]==============================================================================================] + +project(Octopus VERSION 12.1 + HOMEPAGE_URL https://www.octopus-code.org + DESCRIPTION "real-space, real-time, TDDFT code" + LANGUAGES C Fortran CXX) + +# Define language standards +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) +# Upstream issue: Fortran standards are not defined in cmake yet + +#[==============================================================================================[ +# Options # +]==============================================================================================] + +set(OCTOPUS_MAX_DIM "3" CACHE STRING + "Octopus: Maximum number of dimensions Octopus can use; [default=3;must be>=3]") +option(OCTOPUS_MPI "Octopus: Build with MPI support" OFF) +option(OCTOPUS_OpenMP "Octopus: Build with OpenMP support" OFF) +option(OCTOPUS_ELPA "Octopus: Build with ELPA support" OFF) +option(OCTOPUS_netCDF "Octopus: Build with netCDF support" OFF) +option(OCTOPUS_INSTALL "Octopus: Install project" ${PROJECT_IS_TOP_LEVEL}) +option(OCTOPUS_TESTS "Octopus: Build with unit-tests" ${PROJECT_IS_TOP_LEVEL}) +option(OCTOPUS_TESTS_FULL "Octopus: Build with full test-suite" ${PROJECT_IS_TOP_LEVEL}) +option(OCTOPUS_FFTW "Octopus: Build with FFTW support" OFF) +option(OCTOPUS_MKL "Octopus: Build with MKL support" OFF) +option(OCTOPUS_ScaLAPACK "Octopus: Build with ScaLAPACK support" OFF) + +if (OCTOPUS_TESTS_FULL AND NOT OCTOPUS_TESTS) + message(WARNING "OCTOPUS_TESTS will be set to ON because OCTOPUS_TESTS_FULL=ON") + set(OCTOPUS_TESTS ON) +endif () + +#[==============================================================================================[ +# Project configuration # +]==============================================================================================] + +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +include(FetchContent) + +## Include other cmake modules +include(Octopus) +include(GNUInstallDirs) + +## Configure project variables +# Default to Release build if not specified +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () +# Add custom/third-party cmake modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") +# Build all fortran modules in a common module directory for simpler loading +if (NOT CMAKE_Fortran_MODULE_DIRECTORY) + set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fortran_mods) +endif () +include_directories(${CMAKE_Fortran_MODULE_DIRECTORY}) +if (OCTOPUS_FFTW AND OCTOPUS_MKL) + message(FATAL_ERROR + "Octopus: Cannot configure for both FFTW and MKL. MKL is more recommended.") +endif () +# Configure the find_package(MKL) arguments +set(MKL_ARGS) +if (OCTOPUS_MKL) + list(APPEND MKL_ARGS REQUIRED) + # Set BLAS/LAPACK to MKL as well + # Note the user has to set MKL_THREADING_LAYER and MKL_INTERFACE_LAYER accordingly + set(BLA_VENDOR Intel10_64_dyn CACHE STRING "Octopus: Overload") + # if (OCTOPUS_OpenMP OR OCTOPUS_MPI) + # set(BLA_VENDOR Intel10_64ilp CACHE STRING "Octopus: Overload") + # else () + # set(BLA_VENDOR Intel10_64ilp_seq CACHE STRING "Octopus: Overload") + # endif () + set(MKL_INTERFACE lp64 CACHE STRING "Octopus: Overload") + set(MKL_LINK dynamic CACHE STRING "Octopus: Overload") + set(MKL_ARCH intel64 CACHE STRING "Octopus: Overload") + if (OCTOPUS_ScaLAPACK) + set(ENABLE_SCALAPACK ON CACHE BOOL "Octopus: Overloaded") + endif () + set(MKL_DPCPP_INTERFACE_FULL intel_ilp64 CACHE STRING "Octopus: Overload") +endif () +# Add the default MKL arguments +list(APPEND MKL_ARGS CONFIG) +# Configure the find_package(FFTW) arguments +set(FFTW_ARGS) +if (OCTOPUS_FFTW) + list(APPEND FFTW_ARGS REQUIRED) +endif () + +#[==============================================================================================[ +# External packages # +]==============================================================================================] + +set(Octopus_ext_libs) + +## Build flags for cmake projects +# Libxc +# TODO: Remove non-namespaced options when upstream accepts it +set(ENABLE_FORTRAN ON CACHE BOOL "Octopus: Overloaded" FORCE) +set(BUILD_TESTING OFF CACHE BOOL "Octopus: Overloaded" FORCE) +set(LIBXC_ENABLE_FORTRAN ON CACHE BOOL "Octopus: Overloaded" FORCE) +set(LIBXC_BUILD_TESTING OFF CACHE BOOL "Octopus: Overloaded" FORCE) +set(LIBXC_IGNORE_DEPRECATED ON CACHE BOOL "Octopus: Overloaded" FORCE) +# Spglib +set(SPGLIB_WITH_Fortran ON CACHE BOOL "Octopus: Overloaded" FORCE) + +## Add external packages +# Required libraries +find_package(GSL REQUIRED) +if (OCTOPUS_MPI) + find_package(MPI REQUIRED) + # Further set MKL variables + # First detect what mpi environment is used + try_run(_run_result + _compile_result + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/find_mpi_vendor.cpp + LINK_LIBRARIES MPI::MPI_CXX + RUN_OUTPUT_VARIABLE _run_output + ) + if (NOT _run_result EQUAL 0 OR NOT _compile_result) + message(FATAL_ERROR "Could not detect MPI vendor") + endif () + if (_run_output MATCHES Intel) + set(MKL_THREADING intel_thread CACHE STRING "Octopus: Overloaded") + set(MKL_MPI intelmpi CACHE STRING "Octopus: Overloaded") + elseif (_run_output MATCHES "Open MPI") + set(MKL_THREADING gnu_thread CACHE STRING "Octopus: Overloaded") + set(MKL_MPI openmpi CACHE STRING "Octopus: Overloaded") + else () + message(FATAL_ERROR + "Octopus: Could not detect mpi type from string:\n${MPIRUN_version}") + endif () +endif () +if (OCTOPUS_OpenMP) + find_package(OpenMP REQUIRED) +endif () +# find_package(MKL) must not be run if FFTW is requested +if (NOT OCTOPUS_FFTW) + find_package(MKL ${MKL_ARGS}) + # if MKL is not found, make FFTW a required package + if (NOT MKL_FOUND) + list(APPEND FFTW_ARGS REQUIRED) + endif () +endif () +# Avoid duplicating targets +if (NOT MKL_FOUND) + find_package(BLAS REQUIRED) + find_package(LAPACK REQUIRED) +endif () +# find_package(FFTW) can be run if FFTW requested or if no MKL package was found +if (OCTOPUS_FFTW OR NOT MKL_FOUND) + find_package(FFTW ${FFTW_ARGS}) +endif () + +Octopus_FetchContent_Declare(Libxc + GIT_REPOSITORY https://gitlab.com/LecrisUT/libxc + GIT_TAG cmake/external-project-6.x + FIND_PACKAGE_ARGS MODULE REQUIRED COMPONENTS Fortran + ) +Octopus_FetchContent_Declare(Spglib + GIT_REPOSITORY https://github.com/spglib/spglib + GIT_TAG v2.1.0-rc2 + FIND_PACKAGE_ARGS MODULE REQUIRED COMPONENTS Fortran + ) +if (OCTOPUS_ELPA) + find_package(ELPA REQUIRED MODULE OPTIONAL_COMPONENTS OpenMP) + set(HAVE_ELPA 1) +endif () +if (OCTOPUS_netCDF) + find_package(netCDF-Fortran REQUIRED MODULE) + set(HAVE_NETCDF 1) +endif () +# TODO: Missing various other supported libraries +#find_package(BerkleyGW) +# Add all remaining packages +FetchContent_MakeAvailable(${Octopus_ext_libs}) + +# Fix target aliases +if (NOT TARGET Spglib::fortran) + add_library(Spglib::fortran ALIAS spglib_f08_static) +endif () +if (NOT TARGET Libxc::xcf03) + add_library(Libxc::xcf03 ALIAS xcf03) +endif () + +# Fix missing version exports +# Assuming the bundled version is used +if (NOT DEFINED Libxc_VERSION) + set(Libxc_VERSION 5.2.3) +endif () + +if (Libxc_VERSION VERSION_GREATER_EQUAL 5) + set(HAVE_LIBXC5 1) +endif () +if (Libxc_VERSION VERSION_GREATER 6) + message(WARNING "Libxc version ${Libxc_VERSION} is not officially supported. Use it at your own risk.\n + Please report any issues in the build and execution to the official repository so we can support it as quickly as possible.") +endif () + +#[==============================================================================================[ +# Boilerplate # +]==============================================================================================] + +## Boilerplate because of custom octopus things +# TODO: Move away from header re-generation of mk_varinfo.pl. Use static lists and dictionaries instead +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/tmp_generated) +add_custom_target(VarInfo + COMMAND ${PROJECT_SOURCE_DIR}/scripts/mk_varinfo.pl + -s ${PROJECT_SOURCE_DIR} + -b ${PROJECT_BINARY_DIR}/tmp_generated + COMMENT "Generating variable information") +# Define target ChecksumCopy that copies from ${PROJECT_BINARY_DIR}/tmp_generated to ${PROJECT_BINARY_DIR} only if +# contents changed. This guarantees VarInfo is always called, but dependent targets do not rebuild unnecessarily if +# src/include/options.h and src/include/defaults.h is not *really* changed. +if (CMAKE_VERSION VERSION_LESS 3.26) + add_custom_target(ChecksumCopy + COMMAND ${CMAKE_COMMAND} + -Dchecksum_src=${PROJECT_BINARY_DIR}/tmp_generated + -Dchecksum_dest=${PROJECT_BINARY_DIR} + -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ChecksumCopy.cmake + COMMENT "Checking and copying files") +else () + add_custom_target(ChecksumCopy + COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${PROJECT_BINARY_DIR}/tmp_generated ${PROJECT_BINARY_DIR} + COMMENT "Checking and copying files") +endif () +add_dependencies(ChecksumCopy VarInfo) +add_library(Octopus_base INTERFACE) +add_dependencies(Octopus_base ChecksumCopy) + +#[==============================================================================================[ +# Main definition # +]==============================================================================================] + +# Mimic autotools +include(mock_autotools) + +## Main targets +add_library(Octopus_lib) +target_link_libraries(Octopus_lib PRIVATE Octopus_base) +add_executable(Octopus_octopus) + +# Setup octopus library +set_target_properties(Octopus_lib PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + EXPORT_NAME octopus + OUTPUT_NAME octopus + ) +# Add alias target so that project is compatible with FetchContent +add_library(Octopus::octopus ALIAS Octopus_lib) +# Setup octopus executable +set_target_properties(Octopus_octopus PROPERTIES + OUTPUT_NAME octopus + ) + +# Include necessary non-cmake bundled libs +add_subdirectory(external_libs) + +# Main project definition in src folder +add_subdirectory(src) + +# Auxiliary files +add_subdirectory(share) + +# Unit testing and testsuite +if (OCTOPUS_TESTS) + enable_testing() + add_subdirectory(test) +endif() +if (OCTOPUS_TESTS_FULL) + add_subdirectory(testsuite) + file(COPY testsuite DESTINATION ${PROJECT_BINARY_DIR}/share + REGEX ".*\\.(am|in)\$" EXCLUDE) + # file(CREATE_LINK ${PROJECT_BINARY_DIR}/share/testsuite/oct-run_regression_test.pl ${PROJECT_BINARY_DIR}/bin/oct-run_regression_test.pl SYMBOLIC) +endif() + +#[==============================================================================================[ +# Install or Export # +]==============================================================================================] +# Defined in subdirectories diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000000000000000000000000000000000000..8ed2f280ce0c15f7e31d2817ebcfde672f6cdf02 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,7 @@ +{ + "version": 6, + "include": [ + "cmake/CMakePresets-defaults.json", + "cmake/CMakePresets-buildbot.json" + ] +} diff --git a/cmake/CMakePresets-buildbot.json b/cmake/CMakePresets-buildbot.json new file mode 100644 index 0000000000000000000000000000000000000000..86d2440e2d50a5c5a08067df72284ca5b0f0b506 --- /dev/null +++ b/cmake/CMakePresets-buildbot.json @@ -0,0 +1,379 @@ +{ + "version": 6, + "include": [ + "CMakePresets-defaults.json" + ], + "configurePresets": [ + { + "name": "buildbot-base", + "hidden": true, + "inherits": [ + "default" + ], + "errors": { + "deprecated": true + }, + "cacheVariables": { + "FETCHCONTENT_TRY_FIND_PACKAGE_MODE": { + "type": "STRING", + "value": "ALWAYS" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "OCTOPUS_TESTS": { + "type": "BOOL", + "value": true + }, + "OCTOPUS_TESTS_FULL": { + "type": "BOOL", + "value": true + } + } + }, + { + "name": "buildbot-foss-base", + "hidden": true, + "inherits": [ + "buildbot-base" + ], + "cacheVariables": { + "CMAKE_C_COMPILER": { + "type": "FILEPATH", + "value": "gcc" + }, + "CMAKE_CXX_COMPILER": { + "type": "FILEPATH", + "value": "g++" + }, + "CMAKE_Fortran_COMPILER": { + "type": "FILEPATH", + "value": "gfortran" + }, + "OCTOPUS_FFTW": { + "type": "BOOL", + "value": true + }, + "OCTOPUS_MKL": { + "type": "BOOL", + "value": false + } + } + }, + { + "name": "buildbot-min", + "hidden": true, + "inherits": [ + "buildbot-base" + ], + "cacheVariables": { + "OCTOPUS_MPI": { + "type": "BOOL", + "value": false + }, + "OCTOPUS_OpenMP": { + "type": "BOOL", + "value": false + }, + "OCTOPUS_ScaLAPACK": { + "type": "BOOL", + "value": false + }, + "OCTOPUS_ELPA": { + "type": "BOOL", + "value": false + }, + "OCTOPUS_netCDF": { + "type": "BOOL", + "value": false + }, + "FETCHCONTENT_SOURCE_DIR_SPGLIB": { + "type": "FILEPATH", + "value": "${sourceDir}/third_party/Spglib" + } + } + }, + { + "name": "buildbot-mpi", + "hidden": true, + "inherits": [ + "buildbot-min" + ], + "cacheVariables": { + "OCTOPUS_MPI": { + "type": "BOOL", + "value": true + } + } + }, + { + "name": "buildbot-full", + "hidden": true, + "inherits": [ + "buildbot-min" + ], + "binaryDir": "cmake-build-ci-foss", + "cacheVariables": { + "OCTOPUS_ScaLAPACK": { + "type": "BOOL", + "value": true + }, + "OCTOPUS_ELPA": { + "type": "BOOL", + "value": true + }, + "OCTOPUS_netCDF": { + "type": "BOOL", + "value": true + } + } + }, + { + "name": "foss-min", + "displayName": "Configure preset for minimal Foss toolchain", + "inherits": [ + "buildbot-foss-base", + "buildbot-min" + ], + "binaryDir": "cmake-build-ci-foss-min" + }, + { + "name": "foss-min-mpi", + "displayName": "Configure preset for minimal Foss toolchain + MPI", + "inherits": [ + "buildbot-foss-base", + "buildbot-mpi" + ], + "binaryDir": "cmake-build-ci-foss-min-mpi" + }, + { + "name": "foss-full", + "displayName": "Configure preset for full Foss toolchain", + "inherits": [ + "buildbot-foss-base", + "buildbot-min" + ], + "binaryDir": "cmake-build-ci-foss-full" + }, + { + "name": "foss-full-mpi", + "displayName": "Configure preset for full Foss toolchain + MPI", + "inherits": [ + "buildbot-foss-base", + "buildbot-mpi" + ], + "binaryDir": "cmake-build-ci-foss-full-mpi" + } + ], + "buildPresets": [ + { + "name": "buildbot-base", + "hidden": true, + "inherits": [ + "default" + ], + "cleanFirst": true, + "jobs": 16 + }, + { + "name": "foss-min", + "displayName": "Build preset for minimal Foss toolchain", + "inherits": [ + "buildbot-base" + ], + "configurePreset": "foss-min" + }, + { + "name": "foss-min-mpi", + "displayName": "Build preset for minimal Foss toolchain + MPI", + "inherits": [ + "buildbot-base" + ], + "configurePreset": "foss-min-mpi" + }, + { + "name": "foss-full", + "displayName": "Build preset for full Foss toolchain", + "inherits": [ + "buildbot-base" + ], + "configurePreset": "foss-full" + }, + { + "name": "foss-full-mpi", + "displayName": "Build preset for full Foss toolchain + MPI", + "inherits": [ + "buildbot-base" + ], + "configurePreset": "foss-full-mpi" + } + ], + "testPresets": [ + { + "name": "buildbot-base", + "hidden": true, + "inherits": [ + "default" + ], + "output": { + "outputOnFailure": true + }, + "execution": { + "jobs": 16 + }, + "filter": { + "include": { + "label": ".*" + } + } + }, + { + "name": "buildbot-mpi", + "hidden": true, + "inherits": [ + "buildbot-base" + ], + "execution": { + "jobs": 8 + }, + "environment": { + "OCT_TEST_MPI_NPROCS": "2" + } + }, + { + "name": "foss-min", + "displayName": "Build preset for minimal Foss toolchain", + "inherits": [ + "buildbot-base" + ], + "configurePreset": "foss-min" + }, + { + "name": "foss-min-mpi", + "displayName": "Build preset for minimal Foss toolchain + MPI", + "inherits": [ + "buildbot-mpi" + ], + "configurePreset": "foss-min-mpi" + }, + { + "name": "foss-full", + "displayName": "Build preset for full Foss toolchain", + "inherits": [ + "buildbot-base" + ], + "configurePreset": "foss-full" + }, + { + "name": "foss-full-mpi", + "displayName": "Build preset for full Foss toolchain + MPI", + "inherits": [ + "buildbot-mpi" + ], + "configurePreset": "foss-full-mpi" + } + ], + "workflowPresets": [ + { + "name": "foss-build-only", + "displayName": "CI workflow for building Foss toolchain only", + "steps": [ + { + "type": "configure", + "name": "foss-min" + }, + { + "type": "build", + "name": "foss-min" + } + ] + }, + { + "name": "foss-build-only-mpi", + "displayName": "CI workflow for building Foss toolchain only + MPI", + "steps": [ + { + "type": "configure", + "name": "foss-min-mpi" + }, + { + "type": "build", + "name": "foss-min-mpi" + } + ] + }, + { + "name": "foss-min", + "displayName": "CI workflow for minimal Foss toolchain", + "steps": [ + { + "type": "configure", + "name": "foss-min" + }, + { + "type": "build", + "name": "foss-min" + }, + { + "type": "test", + "name": "foss-min" + } + ] + }, + { + "name": "foss-min-mpi", + "displayName": "CI workflow for minimal Foss toolchain + MPI", + "steps": [ + { + "type": "configure", + "name": "foss-min-mpi" + }, + { + "type": "build", + "name": "foss-min-mpi" + }, + { + "type": "test", + "name": "foss-min-mpi" + } + ] + }, + { + "name": "foss-full", + "displayName": "CI workflow for full Foss toolchain", + "steps": [ + { + "type": "configure", + "name": "foss-full" + }, + { + "type": "build", + "name": "foss-full" + }, + { + "type": "test", + "name": "foss-full" + } + ] + }, + { + "name": "foss-full-mpi", + "displayName": "CI workflow for full Foss toolchain + MPI", + "steps": [ + { + "type": "configure", + "name": "foss-full-mpi" + }, + { + "type": "build", + "name": "foss-full-mpi" + }, + { + "type": "test", + "name": "foss-full-mpi" + } + ] + } + ] +} diff --git a/cmake/CMakePresets-defaults.json b/cmake/CMakePresets-defaults.json new file mode 100644 index 0000000000000000000000000000000000000000..38ddb162f1b990180a0376877b7d4a685955d56c --- /dev/null +++ b/cmake/CMakePresets-defaults.json @@ -0,0 +1,55 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "displayName": "Default configuration preset", + "binaryDir": "cmake-build-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + } + } + } + ], + "buildPresets": [ + { + "name": "default", + "displayName": "Default build preset", + "configurePreset": "default" + } + ], + "testPresets": [ + { + "name": "default", + "displayName": "Default test preset", + "configurePreset": "default", + "filter": { + "include": { + "label": "short-run" + } + } + } + ], + "workflowPresets": [ + { + "name": "default", + "displayName": "Default workflow", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + } + ] + } + ] +} diff --git a/cmake/CheckFortranTypeSizes.cmake b/cmake/CheckFortranTypeSizes.cmake new file mode 100644 index 0000000000000000000000000000000000000000..4657a910cbe37a617942778c550102da2adf8309 --- /dev/null +++ b/cmake/CheckFortranTypeSizes.cmake @@ -0,0 +1,56 @@ +# This module performs several try-compiles to determine the default integer +# size being used by the fortran compiler +# +# After execution, the following variables are set. If they are un set then +# size detection was not possible +# +# SIZEOF_INTEGER - Number of bytes used to store the default INTEGER type +# SIZEOF_REAL - Number of bytes used to store the default REAL type +# SIZEOF_LOGICAL - Number of bytes used to store the default LOGICAL type +# SIZEOF_CHARACTER - Number of bytes used to store the default CHARACTER type +# +#============================================================================= +# Author: Chuck Atkins +# Copyright 2011 +# Original code: https://github.com/Reference-LAPACK/lapack/blob/f8fb0842d55c34ad2c26da58e9f55a3f10e52d0b/CMAKE/CheckFortranTypeSizes.cmake +# Additional changes by: Cristian Le +#============================================================================= + +# Check the size of a single fortran type +macro( _CHECK_FORTRAN_TYPE_SIZE _TYPE_NAME _TEST_SIZES ) + + foreach( __TEST_SIZE ${_TEST_SIZES} ) + set( __TEST_FILE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortran${_TYPE_NAME}Size${__TEST_SIZE}.f90 ) + file( WRITE ${__TEST_FILE} + " + PROGRAM check_size + ${_TYPE_NAME}*${__TEST_SIZE}, TARGET :: a + ${_TYPE_NAME}, POINTER :: pa + pa => a + END PROGRAM +") + try_compile( SIZEOF_${_TYPE_NAME} ${CMAKE_BINARY_DIR} ${__TEST_FILE} ) + if( SIZEOF_${_TYPE_NAME} ) + message( STATUS "Testing default ${_TYPE_NAME}*${__TEST_SIZE} - found" ) +# set( SIZEOF_${_TYPE_NAME} ${__TEST_SIZE} CACHE INTERNAL "Size of the default ${_TYPE_NAME} type" FORCE ) + set( SIZEOF_Fortran_${_TYPE_NAME} ${__TEST_SIZE} CACHE INTERNAL "Size of the default ${_TYPE_NAME} type" FORCE ) + break() + else() + message( STATUS "Testing default ${_TYPE_NAME}*${__TEST_SIZE} -" ) + endif() + endforeach() + +endmacro() + + +macro( CHECK_FORTRAN_TYPE_SIZES ) + if( NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90 ) + message( FATAL_ERROR "Type size tests require Fortran 90 support" ) + endif() + + _CHECK_FORTRAN_TYPE_SIZE( "INTEGER" "2;4;8;16" ) + _CHECK_FORTRAN_TYPE_SIZE( "REAL" "4;8;12;16" ) + _CHECK_FORTRAN_TYPE_SIZE( "LOGICAL" "1;2;4;8;16" ) + _CHECK_FORTRAN_TYPE_SIZE( "CHARACTER" "1;2;4;8;16" ) +endmacro() + diff --git a/cmake/ChecksumCopy.cmake b/cmake/ChecksumCopy.cmake new file mode 100644 index 0000000000000000000000000000000000000000..2791509580c502289de5986806ccee0e0b8b9ef4 --- /dev/null +++ b/cmake/ChecksumCopy.cmake @@ -0,0 +1,23 @@ +# Script to be called by the target in `oct_add_checksum_copy` in `helpers.cmake` +# Check the checksums of all the files in `checksum_src` and copy the files if they differ from `checksum_dest` + +# Variables:: +# checksum_src (path): location of the source to copy from +# checksum_dest (path): location of the source to copy to + +# Check if directory does not exist +if (NOT EXISTS ${checksum_dest}) + # If doesn't exist can just copy everything + message(VERBOSE + "ChecksumCopy: Destination folder not found. Copying everything\n" + "${checksum_src} -> ${checksum_dest}") + file(COPY ${checksum_src} ${checksum_dest}) + return() +endif () + +# Check each file +file(GLOB_RECURSE src_files RELATIVE ${checksum_src} ${checksum_src}/*) +foreach (file IN LISTS src_files) + file(COPY_FILE ${checksum_src}/${file} ${checksum_dest}/${file} + ONLY_IF_DIFFERENT) +endforeach () diff --git a/cmake/FindELPA.cmake b/cmake/FindELPA.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a5c1fa216130a7dc872143aab8785ae7604ecd75 --- /dev/null +++ b/cmake/FindELPA.cmake @@ -0,0 +1,51 @@ +#[==============================================================================================[ +# ELPA compatibility wrapper # +]==============================================================================================] + +#[===[.md +# FindELPA + +ELPA compatibility module for Octopus + +This file is specifically tuned for Octopus usage. + +]===] + +include(Octopus) + +set(_find_elpa True) +set(_elpa_fcflags) +set(_required_arg) +if (OpenMP IN_LIST ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS) + if (${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED_OpenMP) + list(APPEND _required_arg REQUIRED) + endif () + pkg_check_modules(${CMAKE_FIND_PACKAGE_NAME} + ${_required_arg} + ${${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY} + IMPORTED_TARGET + elpa_openmp) + if (${CMAKE_FIND_PACKAGE_NAME}_FOUND) + pkg_get_variable(_elpa_fcflags elpa_openmp fcflags) + add_library(ELPA::OpenMP ALIAS PkgConfig::${CMAKE_FIND_PACKAGE_NAME}) + set(_find_elpa False) + endif () +endif () +if (_find_elpa) + if (${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + list(APPEND _required_arg REQUIRED) + endif () + pkg_check_modules(${CMAKE_FIND_PACKAGE_NAME} + ${_required_arg} + ${${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY} + IMPORTED_TARGET + elpa) + pkg_get_variable(_elpa_fcflags elpa_openmp fcflags) +endif () +if (TARGET PkgConfig::${CMAKE_FIND_PACKAGE_NAME}) + add_library(ELPA::elpa ALIAS PkgConfig::${CMAKE_FIND_PACKAGE_NAME}) + if (_elpa_fcflags) + target_compile_options(PkgConfig::${CMAKE_FIND_PACKAGE_NAME} INTERFACE + $<$:${_elpa_fcflags}>) + endif () +endif () diff --git a/cmake/FindFFTW.cmake b/cmake/FindFFTW.cmake new file mode 100644 index 0000000000000000000000000000000000000000..fa9a548c0ed4bc3300b855a12f51168762b81ee8 --- /dev/null +++ b/cmake/FindFFTW.cmake @@ -0,0 +1,421 @@ +# Upstream version: https://github.com/egpbos/findFFTW +# Removed TODOs to not interfere with local development. Otherwise the following is a direct copy of +# ac788529392825067c9118f9f099aaa1efb77589 +# Additional changes by: Cristian Le +# ---------------------------------------------------------------------------------------------------------------------- +# - Find the FFTW library +# +# Original version of this file: +# Copyright (c) 2015, Wenzel Jakob +# https://github.com/wjakob/layerlab/blob/master/cmake/FindFFTW.cmake, commit 4d58bfdc28891b4f9373dfe46239dda5a0b561c6 +# Modifications: +# Copyright (c) 2017, Patrick Bos +# +# Usage: +# find_package(FFTW [REQUIRED] [QUIET] [COMPONENTS component1 ... componentX] ) +# +# It sets the following variables: +# FFTW_FOUND ... true if fftw is found on the system +# FFTW_[component]_LIB_FOUND ... true if the component is found on the system (see components below) +# FFTW_LIBRARIES ... full paths to all found fftw libraries +# FFTW_[component]_LIB ... full path to one of the components (see below) +# FFTW_INCLUDE_DIRS ... fftw include directory paths +# +# The following variables will be checked by the function +# FFTW_USE_STATIC_LIBS ... if true, only static libraries are found, otherwise both static and shared. +# FFTW_ROOT ... if set, the libraries are exclusively searched +# under this path +# +# This package supports the following components: +# FLOAT_LIB +# DOUBLE_LIB +# LONGDOUBLE_LIB +# FLOAT_THREADS_LIB +# DOUBLE_THREADS_LIB +# LONGDOUBLE_THREADS_LIB +# FLOAT_OPENMP_LIB +# DOUBLE_OPENMP_LIB +# LONGDOUBLE_OPENMP_LIB +# + + +if( NOT FFTW_ROOT AND DEFINED ENV{FFTWDIR} ) + set( FFTW_ROOT $ENV{FFTWDIR} ) +endif() + +# Check if we can use PkgConfig +find_package(PkgConfig) + +#Determine from PKG +if( PKG_CONFIG_FOUND AND NOT FFTW_ROOT ) + pkg_check_modules( PKG_FFTW QUIET "fftw3" ) +endif() + +#Check whether to search static or dynamic libs +set( CMAKE_FIND_LIBRARY_SUFFIXES_SAV ${CMAKE_FIND_LIBRARY_SUFFIXES} ) + +if( ${FFTW_USE_STATIC_LIBS} ) + set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} ) +else() + set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAV} ) +endif() + +if( FFTW_ROOT ) + # find libs + + find_library( + FFTW_DOUBLE_LIB + NAMES "fftw3" libfftw3-3 + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_DOUBLE_THREADS_LIB + NAMES "fftw3_threads" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_DOUBLE_OPENMP_LIB + NAMES "fftw3_omp" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_DOUBLE_MPI_LIB + NAMES "fftw3_mpi" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_FLOAT_LIB + NAMES "fftw3f" libfftw3f-3 + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_FLOAT_THREADS_LIB + NAMES "fftw3f_threads" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_FLOAT_OPENMP_LIB + NAMES "fftw3f_omp" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_FLOAT_MPI_LIB + NAMES "fftw3f_mpi" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_LONGDOUBLE_LIB + NAMES "fftw3l" libfftw3l-3 + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_LONGDOUBLE_THREADS_LIB + NAMES "fftw3l_threads" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_LONGDOUBLE_OPENMP_LIB + NAMES "fftw3l_omp" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + find_library( + FFTW_LONGDOUBLE_MPI_LIB + NAMES "fftw3l_mpi" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "lib" "lib64" + NO_DEFAULT_PATH + ) + + #find includes + find_path(FFTW_INCLUDE_DIRS + NAMES "fftw3.h" + PATHS ${FFTW_ROOT} + PATH_SUFFIXES "include" + NO_DEFAULT_PATH + ) + +else() + + find_library( + FFTW_DOUBLE_LIB + NAMES "fftw3" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_DOUBLE_THREADS_LIB + NAMES "fftw3_threads" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_DOUBLE_OPENMP_LIB + NAMES "fftw3_omp" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_DOUBLE_MPI_LIB + NAMES "fftw3_mpi" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_FLOAT_LIB + NAMES "fftw3f" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_FLOAT_THREADS_LIB + NAMES "fftw3f_threads" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_FLOAT_OPENMP_LIB + NAMES "fftw3f_omp" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_FLOAT_MPI_LIB + NAMES "fftw3f_mpi" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_LONGDOUBLE_LIB + NAMES "fftw3l" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library( + FFTW_LONGDOUBLE_THREADS_LIB + NAMES "fftw3l_threads" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library(FFTW_LONGDOUBLE_OPENMP_LIB + NAMES "fftw3l_omp" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_library(FFTW_LONGDOUBLE_MPI_LIB + NAMES "fftw3l_mpi" + PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} + ) + + find_path(FFTW_INCLUDE_DIRS + NAMES "fftw3.h" + PATHS ${PKG_FFTW_INCLUDE_DIRS} ${INCLUDE_INSTALL_DIR} + ) + +endif( FFTW_ROOT ) + +#--------------------------------------- components + +if (FFTW_DOUBLE_LIB) + set(FFTW_DOUBLE_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_LIB}) + add_library(FFTW::Double INTERFACE IMPORTED) + set_target_properties(FFTW::Double + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_LIB}" + ) +else() + set(FFTW_DOUBLE_LIB_FOUND FALSE) +endif() + +if (FFTW_FLOAT_LIB) + set(FFTW_FLOAT_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_FLOAT_LIB}) + add_library(FFTW::Float INTERFACE IMPORTED) + set_target_properties(FFTW::Float + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_LIB}" + ) +else() + set(FFTW_FLOAT_LIB_FOUND FALSE) +endif() + +if (FFTW_LONGDOUBLE_LIB) + set(FFTW_LONGDOUBLE_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_LONGDOUBLE_LIB}) + add_library(FFTW::LongDouble INTERFACE IMPORTED) + set_target_properties(FFTW::LongDouble + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_LIB}" + ) +else() + set(FFTW_LONGDOUBLE_LIB_FOUND FALSE) +endif() + +if (FFTW_DOUBLE_THREADS_LIB) + set(FFTW_DOUBLE_THREADS_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_THREADS_LIB}) + add_library(FFTW::DoubleThreads INTERFACE IMPORTED) + set_target_properties(FFTW::DoubleThreads + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_THREADS_LIB}" + ) +else() + set(FFTW_DOUBLE_THREADS_LIB_FOUND FALSE) +endif() + +if (FFTW_FLOAT_THREADS_LIB) + set(FFTW_FLOAT_THREADS_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_FLOAT_THREADS_LIB}) + add_library(FFTW::FloatThreads INTERFACE IMPORTED) + set_target_properties(FFTW::FloatThreads + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_THREADS_LIB}" + ) +else() + set(FFTW_FLOAT_THREADS_LIB_FOUND FALSE) +endif() + +if (FFTW_LONGDOUBLE_THREADS_LIB) + set(FFTW_LONGDOUBLE_THREADS_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_LONGDOUBLE_THREADS_LIB}) + add_library(FFTW::LongDoubleThreads INTERFACE IMPORTED) + set_target_properties(FFTW::LongDoubleThreads + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_THREADS_LIB}" + ) +else() + set(FFTW_LONGDOUBLE_THREADS_LIB_FOUND FALSE) +endif() + +if (FFTW_DOUBLE_OPENMP_LIB) + set(FFTW_DOUBLE_OPENMP_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_OPENMP_LIB}) + add_library(FFTW::DoubleOpenMP INTERFACE IMPORTED) + set_target_properties(FFTW::DoubleOpenMP + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_OPENMP_LIB}" + ) +else() + set(FFTW_DOUBLE_OPENMP_LIB_FOUND FALSE) +endif() + +if (FFTW_FLOAT_OPENMP_LIB) + set(FFTW_FLOAT_OPENMP_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_FLOAT_OPENMP_LIB}) + add_library(FFTW::FloatOpenMP INTERFACE IMPORTED) + set_target_properties(FFTW::FloatOpenMP + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_OPENMP_LIB}" + ) +else() + set(FFTW_FLOAT_OPENMP_LIB_FOUND FALSE) +endif() + +if (FFTW_LONGDOUBLE_OPENMP_LIB) + set(FFTW_LONGDOUBLE_OPENMP_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_LONGDOUBLE_OPENMP_LIB}) + add_library(FFTW::LongDoubleOpenMP INTERFACE IMPORTED) + set_target_properties(FFTW::LongDoubleOpenMP + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_OPENMP_LIB}" + ) +else() + set(FFTW_LONGDOUBLE_OPENMP_LIB_FOUND FALSE) +endif() + +if (FFTW_DOUBLE_MPI_LIB) + set(FFTW_DOUBLE_MPI_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_MPI_LIB}) + add_library(FFTW::DoubleMPI INTERFACE IMPORTED) + set_target_properties(FFTW::DoubleMPI + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_MPI_LIB}" + ) +else() + set(FFTW_DOUBLE_MPI_LIB_FOUND FALSE) +endif() + +if (FFTW_FLOAT_MPI_LIB) + set(FFTW_FLOAT_MPI_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_FLOAT_MPI_LIB}) + add_library(FFTW::FloatMPI INTERFACE IMPORTED) + set_target_properties(FFTW::FloatMPI + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_MPI_LIB}" + ) +else() + set(FFTW_FLOAT_MPI_LIB_FOUND FALSE) +endif() + +if (FFTW_LONGDOUBLE_MPI_LIB) + set(FFTW_LONGDOUBLE_MPI_LIB_FOUND TRUE) + set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_LONGDOUBLE_MPI_LIB}) + add_library(FFTW::LongDoubleMPI INTERFACE IMPORTED) + set_target_properties(FFTW::LongDoubleMPI + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_MPI_LIB}" + ) +else() + set(FFTW_LONGDOUBLE_MPI_LIB_FOUND FALSE) +endif() + +#--------------------------------------- end components + +set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAV} ) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(FFTW + REQUIRED_VARS FFTW_INCLUDE_DIRS + HANDLE_COMPONENTS + ) + +mark_as_advanced( + FFTW_INCLUDE_DIRS + FFTW_LIBRARIES + FFTW_FLOAT_LIB + FFTW_DOUBLE_LIB + FFTW_LONGDOUBLE_LIB + FFTW_FLOAT_THREADS_LIB + FFTW_DOUBLE_THREADS_LIB + FFTW_LONGDOUBLE_THREADS_LIB + FFTW_FLOAT_OPENMP_LIB + FFTW_DOUBLE_OPENMP_LIB + FFTW_LONGDOUBLE_OPENMP_LIB + FFTW_FLOAT_MPI_LIB + FFTW_DOUBLE_MPI_LIB + FFTW_LONGDOUBLE_MPI_LIB +) diff --git a/cmake/FindLibxc.cmake b/cmake/FindLibxc.cmake new file mode 100644 index 0000000000000000000000000000000000000000..b420bf11797383324153fe018d83474bf0d39f62 --- /dev/null +++ b/cmake/FindLibxc.cmake @@ -0,0 +1,29 @@ +#[==============================================================================================[ +# Libxc compatibility wrapper # +]==============================================================================================] + +# Upstream issues: +# https://gitlab.com/libxc/libxc/-/merge_requests/610 +# https://gitlab.com/libxc/libxc/-/merge_requests/604 + +#[===[.md +# FindLibxc + +Libxc compatibility module for Octopus + +This file is specifically tuned for Octopus usage. See `Octopus_FindPackage` for a more general +interface. + +]===] + +include(Octopus) +Octopus_FindPackage(${CMAKE_FIND_PACKAGE_NAME} + NAMES Libxc libxc + PKG_MODULE_NAMES libxcf03) + +# Create appropriate aliases +if (${CMAKE_FIND_PACKAGE_NAME}_PKGCONFIG) + add_library(Libxc::xcf03 ALIAS PkgConfig::${CMAKE_FIND_PACKAGE_NAME}) +elseif (NOT TARGET Libxc::xcf03) + add_library(Libxc::xcf03 ALIAS xcf03) +endif () diff --git a/cmake/FindSpglib.cmake b/cmake/FindSpglib.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e31e4e3d627255b2f6b4af4131db40ff8db8cb4a --- /dev/null +++ b/cmake/FindSpglib.cmake @@ -0,0 +1,25 @@ +#[==============================================================================================[ +# Spglib compatibility wrapper # +]==============================================================================================] + +#[===[.md +# FindSpglib + +Spglib compatibility module for Octopus + +This file is specifically tuned for Octopus usage. See `Octopus_FindPackage` for a more general +interface. + +]===] + +include(Octopus) +Octopus_FindPackage(${CMAKE_FIND_PACKAGE_NAME} + NAMES Spglib spglib + PKG_MODULE_NAMES spglib_f08) + +# Create appropriate aliases +if (${CMAKE_FIND_PACKAGE_NAME}_PKGCONFIG) + add_library(Spglib::fortran ALIAS PkgConfig::${CMAKE_FIND_PACKAGE_NAME}) +elseif (NOT TARGET Spglib::fortran) + add_library(Spglib::fortran ALIAS spglib_f08) +endif () diff --git a/cmake/FindnetCDF-Fortran.cmake b/cmake/FindnetCDF-Fortran.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a6d594454c1dc7c33d9c052580ffcc8b312ece9c --- /dev/null +++ b/cmake/FindnetCDF-Fortran.cmake @@ -0,0 +1,31 @@ +#[==============================================================================================[ +# netCDF compatibility wrapper # +]==============================================================================================] + +#[===[.md +# FindnetCDF-Fortran + +netCDF compatibility module for Octopus + +This file is specifically tuned for Octopus usage. See `Octopus_FindPackage` for a more general +interface. + +]===] + +include(Octopus) +Octopus_FindPackage(${CMAKE_FIND_PACKAGE_NAME} + NAMES netCDF-Fortran + PKG_MODULE_NAMES netcdf-fortran) + +# Create appropriate aliases +if (${CMAKE_FIND_PACKAGE_NAME}_PKGCONFIG) + add_library(netCDF::Fortran ALIAS PkgConfig::${CMAKE_FIND_PACKAGE_NAME}) +elseif (NOT TARGET netCDF::Fortran) + # Upstream has a horrible naming scheme :( + # https://github.com/Unidata/netcdf-fortran/issues/404 + if (TARGET netCDF::netcdff) + add_library(netCDF::Fortran ALIAS netCDF::netcdff) + else () + add_library(netCDF::Fortran ALIAS netcdff) + endif () +endif () diff --git a/cmake/Octopus.cmake b/cmake/Octopus.cmake new file mode 100644 index 0000000000000000000000000000000000000000..29697a697e5a7f1a607c47f6a96b603afcb7c04d --- /dev/null +++ b/cmake/Octopus.cmake @@ -0,0 +1,230 @@ +include_guard(GLOBAL) + +find_package(PkgConfig REQUIRED) + +# TODO: Remove when cmake_minimum_required >= 3.24 +macro(Octopus_FetchContent_Declare name) + #[===[.md + # Octopus_FetchContent_Declare + + A short compatibility function to mimic FIND_PACKAGE_ARGS functionality. All arguments are equivalent to + upstream `FetchContent_Declare` from version + [`3.24`](https://cmake.org/cmake/help/v3.24/module/FetchContent.html#command:fetchcontent_declare) + + This function also defines `LIST_VAR` + ]===] + + set(ARGS_Options "OVERRIDE_FIND_PACKAGE") + set(ARGS_OneValue "LIST_VAR") + set(ARGS_MultiValue "FIND_PACKAGE_ARGS") + cmake_parse_arguments(ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}" ${ARGN}) + + if (NOT DEFINED ARGS_LIST_VAR) + # Default to octopus variable + set(ARGS_LIST_VAR Octopus_ext_libs) + endif () + + # Note: Defining as macro due to find_package limitations + if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + # If cmake supports `FIND_PACKAGE_ARGS` simply pass the arguments to the native function + FetchContent_Declare(${name} + ${ARGN}) + else () + + if (ARGS_OVERRIDE_FIND_PACKAGE) + message(FATAL_ERROR + "Octopus_FetchContent_Declare: Cannot back-port OVERRIDE_FIND_PACKAGE") + endif () + + # First check for FETCHCONTENT_SOURCE_DIR_ + # this always takes precedence, and should be treated as a FetchContent package + string(TOUPPER ${name} upper_name) + if (NOT DEFINED FETCHCONTENT_SOURCE_DIR_${upper_name}) + # Next handle according to FETCHCONTENT_TRY_FIND_PACKAGE_MODE + if (NOT DEFINED FETCHCONTENT_TRY_FIND_PACKAGE_MODE) + set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE OPT_IN) + endif () + # Check if `FIND_PACKAGE_ARGS` was passed + if ((FETCHCONTENT_TRY_FIND_PACKAGE_MODE STREQUAL "OPT_IN" AND DEFINED ARGS_FIND_PACKAGE_ARGS) OR + (FETCHCONTENT_TRY_FIND_PACKAGE_MODE STREQUAL "ALWAYS")) + # Try to do find_package. If it fails fallthrough and use FetchContent + # The package should have `FIND_PACKAGE_ARGS REQUIRED` to deny fallthrough + find_package(${name} ${ARGS_FIND_PACKAGE_ARGS}) + # Check if package was found. The variable name should always be `${name}_FOUND` and set by + # cmake itself internally + if (${name}_FOUND) + # Early return to avoid adding to Octopus_ext_libs + # First sanitize local variables used + set(ARGS_Options) + set(ARGS_OneValue) + set(ARGS_MultiValue) + set(ARGS_UNPARSED_ARGUMENTS) + set(ARGS_OVERRIDE_FIND_PACKAGE) + set(ARGS_LIST_VAR) + set(ARGS_FIND_PACKAGE_ARGS) + return() + endif () + endif () + # The remaining case is `FETCHCONTENT_TRY_FIND_PACKAGE_MODE == NEVER` which should should fall through + endif () + # Continue to call `FetchContent_Declare` as usual + # Pass all other arguments that were used + FetchContent_Declare(${name} + ${ARGS_UNPARSED_ARGUMENTS}) + endif () + + # Finally add to LIST_VAR argument to be handled by FetchContent_MakeAvailable + list(APPEND ${ARGS_LIST_VAR} ${name}) + + # Sanitize local variables in order to not contaminate future calls + set(ARGS_Options) + set(ARGS_OneValue) + set(ARGS_MultiValue) + set(ARGS_UNPARSED_ARGUMENTS) + set(ARGS_OVERRIDE_FIND_PACKAGE) + set(ARGS_LIST_VAR) + set(ARGS_FIND_PACKAGE_ARGS) +endmacro() + +macro(Octopus_FindPackage name) + #[===[.md + # Octopus_FindPackage + + A compatibility macro that links `find_package(CONFIG)` packages with `pkg-config`. This should only + be called within the `Find.cmake` file. + + Note: Version range syntax is not supported for pkg-config searching. Only the lower bound will be respected. + + ]===] + + set(ARGS_Options "") + set(ARGS_OneValue "") + set(ARGS_MultiValue "NAMES;PKG_MODULE_NAMES;PKG_MODULE_SPECS") + cmake_parse_arguments(ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}" ${ARGN}) + + # First try to find native Config.cmake + # Build the arguments + # COMPONENTS + set(_comp_args) + set(_opt_comp_args) + if (DEFINED ${name}_FIND_COMPONENTS) + list(APPEND _comp_args COMPONENTS) + foreach (_comp IN LISTS ${name}_FIND_COMPONENTS) + if (${name}_FIND_REQUIRED_${_comp}) + list(APPEND _comp_args ${_comp}) + else () + if (NOT DEFINED _opt_comp_args) + list(APPEND _opt_comp_args OPTIONAL_COMPONENTS) + endif () + list(APPEND _opt_comp_args ${_comp}) + endif () + endforeach () + endif () + + # Version + # Try range format first, otherwise use the default + set(_version_args ${${name}_FIND_VERSION_RANGE}) + if (NOT DEFINED _version_args) + set(_version_args ${${name}_FIND_VERSION}) + endif () + if (${name}_FIND_VERSION_EXACT) + list(APPEND _version_args EXACT) + endif () + + # QUIET + set(_quiet_arg) + if (${name}_FIND_QUIETLY) + list(APPEND _quiet_arg QUIET) + endif () + + # REQUIRED + set(_required_arg) + if (${name}_FIND_REQUIRED) + list(APPEND _required_arg REQUIRED) + endif () + + # REGISTRY_VIEW + set(_registry_view_arg) + if (${name}_FIND_REGISTRY_VIEW) + list(APPEND _registry_view REGISTRY_VIEW ${${name}_FIND_REGISTRY_VIEW}) + endif () + + # NAMES + set(_names_args) + if (DEFINED ARGS_NAMES) + list(APPEND _names_args NAMES ${ARGS_NAMES}) + endif () + + # Try Config.cmake + find_package(${name} ${_version_args} ${_quiet_arg} CONFIG + ${_comp_args} + ${_opt_comp_args} + ${_registry_view_arg} + ${_names_args} + ) + + if (NOT ${name}_FOUND) + # Try pkg-config next + # Construct the moduleSpec to search for + if (NOT DEFINED ARGS_PKG_MODULE_SPECS) + if (NOT DEFINED ARGS_PKG_MODULE_NAMES) + set(ARGS_PKG_MODULE_NAMES ${name}) + endif () + if (DEFINED ${name}_FIND_VERSION_RANGE) + # Can only parse the minimum requirement + foreach (_pkg_name IN LISTS ARGS_PKG_MODULE_NAMES) + list(APPEND ARGS_PKG_MODULE_SPECS "${_pkg_name}>=${${name}_FIND_VERSION_MIN}") + endforeach () + elseif ({${name}_FIND_VERSION_EXACT) + # Requesting exact version + foreach (_pkg_name IN LISTS ARGS_PKG_MODULE_NAMES) + list(APPEND ARGS_PKG_MODULE_SPECS "${_pkg_name}=${${name}_FIND_VERSION}") + endforeach () + elseif (DEFINED ${name}_FIND_VERSION) + # Otherwise treat the request as minimum requirement + foreach (_pkg_name IN LISTS ARGS_PKG_MODULE_NAMES) + list(APPEND ARGS_PKG_MODULE_SPECS "${_pkg_name}>=${${name}_FIND_VERSION}") + endforeach () + else () + # Fallthrough if no version is required + foreach (_pkg_name IN LISTS ARGS_PKG_MODULE_NAMES) + list(APPEND ARGS_PKG_MODULE_SPECS "${_pkg_name}") + endforeach () + endif () + endif () + # Call pkg-config + if (CMAKE_VERSION VERSION_LESS 3.28) + # https://gitlab.kitware.com/cmake/cmake/-/issues/25228 + set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} 1) + endif () + if (CMAKE_VERSION VERSION_LESS 3.22) + # Back-porting + # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/6345 + set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} 1) + endif () + pkg_search_module(${name} + ${_required_arg} ${_quiet_arg} + IMPORTED_TARGET + ${ARGS_PKG_MODULE_SPECS}) + # Mark the package as found by pkg-config + if (${name}_FOUND) + set(${name}_PKGCONFIG True) + endif () + endif () + + # Sanitize local variables in order to not contaminate future calls + set(ARGS_Options) + set(ARGS_OneValue) + set(ARGS_MultiValue) + set(ARGS_UNPARSED_ARGUMENTS) + set(ARGS_NAMES) + set(ARGS_PKG_MODULE_NAMES) + set(ARGS_PKG_MODULE_SPECS) + set(_version_args) + set(_quiet_arg) + set(_comp_args) + set(_opt_comp_args) + set(_registry_view_arg) + set(_names_args) + set(_pkg_name) +endmacro() diff --git a/cmake/README.md b/cmake/README.md new file mode 100644 index 0000000000000000000000000000000000000000..01d777b3abd035b3fbe2afca33824394ff8f4e4b --- /dev/null +++ b/cmake/README.md @@ -0,0 +1,166 @@ +# Building with CMake + +This document goes over a few ways to build Octopus using cmake, how to configure it and how to run basic tests + +## Table of Contents + +1. [Running CMake](#running-cmake) +2. [Configuring the Cmake Build](#configuring-the-cmake-build) +3. [CMake Options](#cmake-options) +4. [Testing](#testing) +5. [Adding Modules to CMakeLists.txt](#adding-modules-to-cmakelists.txt) + + +## Running cmake + +The configure, build, test and install steps are all run through the `cmake` CLI: +```console +$ cmake -B ./build +$ cmake --build ./build +$ ctest --test-dir ./build -L short-run +$ cmake --install ./build +``` + +This will configure, build and run the tests in the `./build` directory, using the default options, i.e. compiling +without parallel or external library support (more on that in the next sections). If you are using `CMake >= 3.23` +you can use [`cmake-presets`](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html)to simplify this process +and use some pre-defined options, e.g.: +```console +$ cmake --preset default +$ cmake --build --preset default +$ ctest --preset default +$ cmake --install ./cmake-build-release +``` + +And if you are using `CMake >= 3.25` you can simplify this to a single step (except for `install` which has no presets): +```onsole +$ cmake --workflow --preset default +$ cmake --install ./cmake-build-release +``` + +You can find a list of these presets using `cmake --list-presets`. Note that some presets are customized for Octopus +buildbot. +```console +$ cmake --list-presets +Available configure presets: + + "default" - Default configuration preset +``` + +## Configuring the cmake build + +It is possible to run a GUI like `ccmake` to find all of the options available to configure, but it is encouraged to +see the available options directly in [`/CMakeLists.txt`](../CMakeLists.txt), e.g.: +```cmake +#[==============================================================================================[ +# Options # +]==============================================================================================] + +option(OCTOPUS_MPI "Octopus: Build with MPI support" OFF) +option(OCTOPUS_OpenMP "Octopus: Build with OpenMP support" OFF) +option(OCTOPUS_INSTALL "Octopus: Install project" ${PROJECT_IS_TOP_LEVEL}) +option(OCTOPUS_TESTS "Octopus: Build with unit-tests" ${PROJECT_IS_TOP_LEVEL}) +``` + +To configure these options you prepend a `-D` to the name of the option and pass them at the configure step along with +the value you wish, e.g.: +```console +$ cmake -B ./build -DOCTOPUS_MPI=ON +``` + +It might be cumbersome to define all of these variables. That is why we provide presets for some common scenarios, e.g. +`default` preset sets `CMAKE_BUILD_TYPE=Release` and the build directory to `cmake-build-release` so the following +command are equivalent: +```console +$ cmake -B ./cmake-build-release -DCMAKE_BUILD_TYPE=Release +$ cmake --preset default +Preset CMake variables: + + CMAKE_BUILD_TYPE:STRING="Release" +``` +To find out what variables are set by these presets, simply run the preset, and these variables will be printed at the +beginning (as shown in the snippet above), or navigate through their definition in +[`CMakePresets-defaults.json`](CMakePresets-defaults.json). + +And of course you can mix these approached such as: +```console +$ cmake --preset default -DOCTOPUS_MPI=ON +``` +But note that this does not work with workflow presets. + +### CMake options + +The Octopus defined options and what they do are defined in the source at [`/CMakeLists.txt`](../CMakeLists.txt). But +besides these options, there are a few CMake native options that you should consider. + +| Option | Default | Description | +|:------------------------------------------|:------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------| +| `CMAKE_INSTALL_PREFIX` | `/usr/local` | Path where to install Octopus | +| `CMAKE_Fortran_Flags` | \ | Additional Fortran compiler flags. There are also `C` and `CXX` equivalents. | +| `FETCHCONTENT_TRY_FIND_PACKAGE_MODE` | `OPT_IN` | Set to `NEVER` if you want to download all external dependencies, otherwise Octopus will use the system installed ones. | +| `FETCHCONTENT_SOURCE_DIR_` | \ | Path to the external dependency source to use. E.g. you can set it to the provided submodules:`FETCHCONTENT_SOURCE_DIR_SPGLIB=./third_party/Spglib` | + +If you are using downloaded external dependencies, you can configure those packages by simply adding those options e.g.: +`SPGLIB_USE_SANITIZER=address` (Note these options are passed unaltered to the dependencies so be aware of +name-clashes). See the upstream packages for available options. + +You can of course define a custom preset that contain all of these options in `/CMakeUserPresets.json`, e.g. a `debug` +preset might look like: +```json +{ + "version": 6, + "configurePresets": [ + { + "name": "debug", + "displayName": "Debug configure", + "inherits": [ + "default" + ], + "binaryDir": "build", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + } + ] +} +``` + +## Testing + +The default `ctest` will run all available tests, but you can select the tests you want using regex or labels: +```console +$ ctest --print-labels +Test project /octopus/cmake-build-release +All Labels: + components + errors + long-run + short-run + tutorials +$ ctest -N -L short-run +Test project /octopus/cmake-build-release + Test #1: components/01-derivatives_1d + Test #2: components/02-derivatives_2d + Test #3: components/03-derivatives_3d +$ ctest -N -R '.*octopus_basics-getting_started' +Test project /octopus/cmake-build-release + Test #259: tutorials/01-octopus_basics-getting_started + +Total Tests: 1 +``` + +Note that in this example `-N` was used to show the tests only. To run them, remove that option + + +## Adding Modules to CMakeLists.txt + +A `CMakeLists.txt` file is defined in each subfolder of the `src/`. In order to add a new fortran source file to +the build, simply append the `target_sources` arguments with the file name: + +```Cmake +target_sources(Octopus_lib PRIVATE + module.F90 + added_module.F90 +``` + +This specifies sources to use when building a target `Octopus_lib`. diff --git a/cmake/find_mpi_vendor.cpp b/cmake/find_mpi_vendor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4bd4ef6f6aedd062bd11850bc9bbbcd0ad89fc8a --- /dev/null +++ b/cmake/find_mpi_vendor.cpp @@ -0,0 +1,11 @@ +#include +#include + +int main(){ + char version[MPI_MAX_LIBRARY_VERSION_STRING]; + int version_len; + + int result = MPI_Get_library_version(version, &version_len); + std::cout << version; + return 0; +} diff --git a/cmake/mock_autotools.cmake b/cmake/mock_autotools.cmake new file mode 100644 index 0000000000000000000000000000000000000000..13ba74d4df515f9daee246fcf00b58685a823ff6 --- /dev/null +++ b/cmake/mock_autotools.cmake @@ -0,0 +1,101 @@ +# #639 TODO: When removing autotools, replace flags with target_compile_define + +string(TIMESTAMP BUILD_TIME) +execute_process( + COMMAND git log -1 --format=%h + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +if (CMAKE_BUILD_TYPE MATCHES Debug.*) + set(SHARE_DIR ${PROJECT_BINARY_DIR}/share) +else () + set(SHARE_DIR ${CMAKE_INSTALL_FULL_DATAROOTDIR}/octopus) +endif () + +include(CheckTypeSize) +check_type_size(size_t SIZEOF_SIZE_T LANGUAGE C) +check_type_size("unsigned int" SIZEOF_UNSIGNED_INT LANGUAGE C) +check_type_size("unsigned long" SIZEOF_UNSIGNED_LONG LANGUAGE C) +check_type_size("unsigned long long" SIZEOF_UNSIGNED_LONG_LONG LANGUAGE C) +check_type_size(uint32_t UINT32_T LANGUAGE C) +check_type_size(uint64_t UINT64_T LANGUAGE C) +include(cmake/CheckFortranTypeSizes.cmake) +check_fortran_type_sizes() +include(CheckIncludeFile) +include(CheckFunctionExists) +check_include_file(dirent.h HAVE_DIRENT_H) +check_include_file(errno.h HAVE_ERRNO_H) +check_include_file(signal.h HAVE_SIGNAL_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(string.h HAVE_STRING_H) +check_include_file(windows.h HAVE_WINDOWS_H) +#check_include_file(iotcl.h HAVE_IOCTL) +# #642 TODO: Eliminate unnecessary function checks in code +# NOTE: Some files do not have checks +check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) +check_function_exists(nanosleep HAVE_NANOSLEEP) +check_function_exists(closedir HAVE_CLOSEDIR) +check_function_exists(readdir HAVE_READDIR) +check_function_exists(strchr HAVE_STRCHR) +check_function_exists(strtod HAVE_STRTOD) +check_function_exists(alphasort HAVE_ALPHASORT) +check_function_exists(scandir HAVE_SCANDIR) +check_function_exists(getopt_long HAVE_GETOPT_LONG) +check_function_exists(getpid HAVE_GETPID) +check_function_exists(perror HAVE_PERROR) +check_function_exists(sbrk HAVE_SBRK) +check_function_exists(sigaction HAVE_SIGACTION) +check_function_exists(strcasestr HAVE_STRCASESTR) +check_function_exists(strndup HAVE_STRNDUP) +check_function_exists(strsignal HAVE_STRSIGNAL) +check_function_exists(sysconf HAVE_SYSCONF) +check_function_exists(tcgetpgrp HAVE_TCGETPGRP) +check_function_exists(uname HAVE_UNAME) + +# AVX optimization +check_function_exists(_mm_fmadd_pd HAVE_FMA3) +check_function_exists(_mm_macc_pd HAVE_FMA4) + +if (MPI_Fortran_FOUND) + set(MPI_MOD 1) + set(HAVE_MPI 1) +endif () +#message(FATAL_ERROR +# "PKG_FFTW_LIBRARY_DIRS = ${PKG_FFTW_LIBRARY_DIRS} +# LIB_INSTALL_DIR = ${LIB_INSTALL_DIR} +# FFTW_DOUBLE_LIB_FOUND = ${FFTW_DOUBLE_LIB_FOUND} +# FFTW_DOUBLE_THREADS_LIB_FOUND = ${FFTW_DOUBLE_THREADS_LIB_FOUND} +# FFTW_DOUBLE_MPI_LIB_FOUND = ${FFTW_DOUBLE_MPI_LIB_FOUND}") +if (TARGET FFTW::Double OR TARGET MKL::MKL) + set(HAVE_FFTW3 1) + if (OCTOPUS_OpenMP AND (TARGET FFTW::DoubleOpenMP OR TARGET FFTW::DoubleThreads) + OR (TARGET MKL::MKL AND MKL_THREADING AND NOT MKL_THREADING STREQUAL sequential)) + set(HAVE_FFTW3_THREADS 1) + endif () + if (OCTOPUS_MPI AND TARGET FFTW::DoubleMPI + OR (TARGET MKL::MKL AND MKL_THREADING AND NOT MKL_THREADING STREQUAL sequential)) + set(HAVE_FFTW3_MPI 1) + endif () +endif () +if (OCTOPUS_ScaLAPACK) + set(HAVE_SCALAPACK 1) +endif () + +# Currently long lines have to be supported to avoid preprocess.pl +if (CMAKE_Fortran_COMPILER_ID MATCHES GNU) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-none") +endif () +set(LONG_LINES 1) + +try_compile(FC_Test_SUCCESS ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test_compiler.F90 + OUTPUT_VARIABLE FC_Test_OUTPUT) +if (FC_Test_SUCCESS) +else () + message(SEND_ERROR "Failed to build test fortran file cmake/test_compiler.F90 with: + CMAKE_Fortran_COMPILER: ${CMAKE_Fortran_COMPILER} + CMAKE_Fortran_FLAGS: ${CMAKE_Fortran_FLAGS}") + message(FATAL_ERROR ${FC_Test_OUTPUT}) +endif () \ No newline at end of file diff --git a/cmake/test_compiler.F90 b/cmake/test_compiler.F90 new file mode 100644 index 0000000000000000000000000000000000000000..00aa94c13202fae1ff614e20cc2030e18c23abe7 --- /dev/null +++ b/cmake/test_compiler.F90 @@ -0,0 +1,4 @@ +program test_compiler + ! Test long lines are supported (beyond 132) + print *, "Testing if the fortran file compiles with long lines. Here we are just filling up the space until it surpasses the standard limit of 132 characters. We are just continuing to add to this file way beyond the 132 character, approaching 400 characters, to make sure there is not another higher limit that we are not taking into account. Realistically we don't need this high of a limit, but we just want to be sure." +end program test_compiler \ No newline at end of file diff --git a/external_libs/CMakeLists.txt b/external_libs/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6e5b159a5ee2c28eb44b9be0c19b3ba99ab604bb --- /dev/null +++ b/external_libs/CMakeLists.txt @@ -0,0 +1,32 @@ +# !1888 TODO: To be removed and switched to submodules + +add_library(bpdn STATIC + bpdn/expmm.c + bpdn/heap.c + bpdn/oneProjectorCore.c + bpdn/spgl1_projector.c + bpdn/bpdn.f90) +target_include_directories(bpdn PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/../src/include) +target_include_directories(bpdn INTERFACE + ${CMAKE_CURRENT_BINARY_DIR}) +add_library(dftd3 STATIC + dftd3/api.f90 + dftd3/common.f90 + dftd3/core.f90 + dftd3/pars.f90 + dftd3/sizes.f90) +target_include_directories(dftd3 PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/../src/include) +target_include_directories(dftd3 INTERFACE + ${CMAKE_CURRENT_BINARY_DIR}) +add_library(qshep STATIC + qshep/qshep2d.f90 + qshep/qshep3d.f90) +target_include_directories(qshep PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/../src/include) +target_include_directories(qshep INTERFACE + ${CMAKE_CURRENT_BINARY_DIR}) + +add_library(rapidxml INTERFACE) +target_include_directories(rapidxml INTERFACE rapidxml) \ No newline at end of file diff --git a/scripts/mk_varinfo.pl b/scripts/mk_varinfo.pl index 65c1627252414818819491737b7304357560f07c..f1fabc6b3b921d7215c323df97880580ec660b8d 100755 --- a/scripts/mk_varinfo.pl +++ b/scripts/mk_varinfo.pl @@ -21,6 +21,7 @@ use Getopt::Std; use File::Find; +use File::Path qw(make_path); getopts "hs:b:"; if($opt_h) { @@ -44,10 +45,10 @@ $src = "$top_srcdir/src"; $share = "$top_builddir/share"; $include = "$top_builddir/src/include"; -if(!-d $src && !-d $share) { +if(!-d $src || !-d $top_builddir) { print stderr <<"EndOfErrorMsg"; -The src and share directory could not be found. Please run +The src or build directory could not be found. Please run this script from the octopus toplevel directory or set -s and -b options appropriately. @@ -56,6 +57,14 @@ EndOfErrorMsg exit 1; } +# Make missing build directories if missing +if(!-d $share) { + make_path($share) +} +if(!-d $include) { + make_path($include) +} + # get all files named *.F90 recursively @F90 = (); finddepth (sub{ push @F90, $File::Find::name if /\.F90$/ }, "$src"); diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6d4b982939ec33f03521fa80afcfbfac80fbfb7a --- /dev/null +++ b/share/CMakeLists.txt @@ -0,0 +1,7 @@ +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ + REGEX "(CMakeLists.txt|\\.am$)" EXCLUDE) + +if (OCTOPUS_INSTALL) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/octopus + REGEX "(CMakeFiles|\\.cmake$)" EXCLUDE) +endif () diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d57ea874c8e1934e1e6e6c0bb50a1155c5b6c1e7 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,65 @@ +## Internal objects +# Basic objects and interface +add_library(fortran_cli OBJECT) +target_link_libraries(fortran_cli PRIVATE Octopus_base) + +# Dependent objects +set(OctopusDependentObjects "") +list(APPEND OctopusDependentObjects + basic_mpi # Depends on mpi (optional) + dftbplus_dftb # Depends on dftbplus (optional) + electrons_v_ks # Depends on dftd3 (bundled) + ions_symmetries # Depends on spglib (bundled) + math_blas # Depends on blas (required) + math_bpdn # Depends on bpdn (bundled) + math_fft # Depends on FFT libraries (various) + math_lapack # Depends on lapack libraries (required) + math_metis # Depends on metis (bundled) + math_qshep # Depends on qshep (bundled) + output_berkeleygw # Depends on berkleygw (optional) + species_rapidxml # Depends on rapidxml (bundled) + # Breaks naming convention, but this one is all over the place + xc_oct # Depends on libxc (required) + ) +# Folder based objects +set(OctopusFolderObjects "") +list(APPEND OctopusFolderObjects + basic + basis_set + boxes + classical + electrons + grid + hamiltonian + interactions + ions + math + maxwell + multisystem + opt_control + output + poisson + scf + species + states + sternheimer + td + ) + +foreach (subdir IN LISTS OctopusFolderObjects) + add_subdirectory(${subdir}) +endforeach () +# Leftover directories +add_subdirectory(dftbplus) +add_subdirectory(include) +add_subdirectory(library) +add_subdirectory(main) +add_subdirectory(utils) + +## Special treatment + +## Unused sources +# boxes/box_intersection.F90 +# electrons/pert.F90 +# grid/operate_inc.c +# scf/mixing_metric.F90 diff --git a/src/basic/CMakeLists.txt b/src/basic/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e6cbe14ec149ae4f0fd215c890cf992066758cc5 --- /dev/null +++ b/src/basic/CMakeLists.txt @@ -0,0 +1,99 @@ +target_sources(Octopus_lib PRIVATE + # #643 TODO: Separate as different library + ../../liboct_parser/gsl_userdef.c + ../../liboct_parser/parse.c + ../../liboct_parser/parse_exp.c + ../../liboct_parser/parser_f.c + ../../liboct_parser/symbols.c + accel.F90 + alloc_cache.F90 + alloc_cache_low.cc + blacs.F90 + blacs_proc_grid.F90 + calc_mode_par.F90 + cgal_polyhedra.F90 + clblas.F90 + clblas_low.c + clblast_low.c + clock.F90 + comm.F90 + cublas.cc + cuda.F90 + cuda_low.cc + debug.F90 + distributed.F90 + gdlib.F90 + gdlib_f.c + getopt_f.c + global.F90 + hardware.F90 + heap.F90 + iihash.F90 + iihash_low.cc + io.F90 + io_binary.c + io_binary_f.F90 + io_csv.c + io_csv_f.F90 + kind.F90 + lattice_vectors.F90 + linked_list.F90 + list_node.F90 + loct.F90 + lookup.F90 + merge_sorted.F90 + messages.F90 + multicomm.F90 + namespace.F90 + nvtx.F90 + nvtx_low.cc + oct_f.c + parser.F90 + profiling.F90 + recipes.c + signals.c + sihash.F90 + sihash_low.cc + sort.F90 + sort_low.cc + space.F90 + sphash.F90 + sphash_low.cc + string.F90 + types.F90 + unit.F90 + unit_system.F90 + utils.F90 + varia.c + varinfo.F90 + varinfo_low.c + walltimer.F90 + write_iter.F90 + write_iter_low.cc + mpi.F90 + mpi_debug.F90 + mpi_lib.F90 + mpi_test.F90 + ) +target_sources(fortran_cli PRIVATE + command_line.F90) + +## Link targets +target_link_libraries(fortran_cli PRIVATE Octopus_base) +target_include_directories(Octopus_lib PRIVATE ../../liboct_parser) + +## External libraries +target_link_libraries(Octopus_lib PRIVATE GSL::gsl) +if (TARGET OpenMP::OpenMP_Fortran) + target_link_libraries(Octopus_lib PRIVATE OpenMP::OpenMP_Fortran) + target_compile_definitions(Octopus_lib PRIVATE HAVE_OPENMP) +endif () +if (TARGET MPI::MPI_Fortran) + target_link_libraries(Octopus_lib PUBLIC MPI::MPI_Fortran) + if (CMAKE_Fortran_COMPILER_ID STREQUAL GNU) + target_compile_options(Octopus_lib PRIVATE $<$:-fallow-argument-mismatch>) + endif () +endif () +if (TARGET netCDF::Fortran) + target_link_libraries(Octopus_lib PRIVATE netCDF::Fortran) +endif () diff --git a/src/basic/messages.F90 b/src/basic/messages.F90 index da08e4015f0247bae10c3d24378a69ef812fc2e2..db060b67109c84df06cb8fdbe00511bc2225723a 100644 --- a/src/basic/messages.F90 +++ b/src/basic/messages.F90 @@ -49,8 +49,10 @@ module messages_oct_m alloc_error, & dealloc_error, & messages_input_error, & +#ifndef NDEBUG push_sub, & pop_sub, & +#endif messages_print_with_emphasis, & messages_print_var_info, & messages_print_var_option, & diff --git a/src/basis_set/CMakeLists.txt b/src/basis_set/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..11291c6c5677242cb650bdf61b0ad4cbdabdcdb5 --- /dev/null +++ b/src/basis_set/CMakeLists.txt @@ -0,0 +1,7 @@ +target_sources(Octopus_lib PRIVATE + atomic_orbital.F90 + loewdin.F90 + orbitalbasis.F90 + orbitalset.F90 + orbitalset_utils.F90 + ) diff --git a/src/boxes/CMakeLists.txt b/src/boxes/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7edfc59f5e07d562196c0073d0a81897128a146f --- /dev/null +++ b/src/boxes/CMakeLists.txt @@ -0,0 +1,16 @@ +target_sources(Octopus_lib PRIVATE + box.F90 + box_cgal.F90 + box_cylinder.F90 + box_factory.F90 + box_image.F90 + box_minimum.F90 + box_parallelepiped.F90 + box_shape.F90 + box_sphere.F90 + box_union.F90 + box_user_defined.F90 + multibox.F90 + ) +## Unused sources +# box_intersection.F90 diff --git a/src/classical/CMakeLists.txt b/src/classical/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9e122e5f72a90f26480bc2bc7f233c4208868110 --- /dev/null +++ b/src/classical/CMakeLists.txt @@ -0,0 +1,8 @@ +target_sources(Octopus_lib PRIVATE + charged_particle.F90 + charged_particles.F90 + classical_particle.F90 + classical_particles.F90 + propagator_data_classical_particles.F90 + td_write_classical.F90 + ) diff --git a/src/dftbplus/CMakeLists.txt b/src/dftbplus/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e1e6064346f074f51e305b6ffdae0a158d55ca50 --- /dev/null +++ b/src/dftbplus/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(Octopus_lib PRIVATE + dftb.F90 +) diff --git a/src/electrons/CMakeLists.txt b/src/electrons/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9915cfc005de7372e6b9fa73bf9f281ea7a0ea54 --- /dev/null +++ b/src/electrons/CMakeLists.txt @@ -0,0 +1,37 @@ +target_sources(Octopus_lib PRIVATE + chebyshev_filter_bounds.F90 + chebyshev_filter_oracle.F90 + current.F90 + dos.F90 + eigen_cg.F90 + eigen_chebyshev.F90 + eigen_rmmdiis.F90 + eigensolver.F90 + electrons.F90 + elf.F90 + energy_calc.F90 + exponential.F90 + forces.F90 + kpoints.F90 + linear_solver.F90 + magnetic.F90 + matter.F90 + partial_charges.F90 + perturbation.F90 + perturbation_electric.F90 + perturbation_ionic.F90 + perturbation_kdotp.F90 + perturbation_magnetic.F90 + perturbation_none.F90 + preconditioners.F90 + stress.F90 + subspace.F90 + x_fbe.F90 + x_slater.F90 + v_ks.F90 + xc_ks_inversion.F90 + xc_oep.F90 + xc_sic.F90) + +## External libraries +target_link_libraries(Octopus_lib PRIVATE dftd3) diff --git a/src/grid/CMakeLists.txt b/src/grid/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..20c07180cbea82e45de6e3f280d34384acd6fcd3 --- /dev/null +++ b/src/grid/CMakeLists.txt @@ -0,0 +1,57 @@ +target_sources(Octopus_lib PRIVATE + affine_coordinates.F90 + allocate_hardware_aware.cc + allocate_hardware_aware_f.F90 + basins.F90 + basis_set_abst.F90 + batch.F90 + batch_ops.F90 + boundaries.F90 + cartesian.F90 + coordinate_system.F90 + cube.F90 + cube_function.F90 + curv_briggs.F90 + curv_gygi.F90 + curv_modine.F90 + derivatives.F90 + fourier_shell.F90 + fourier_space.F90 + grid.F90 + hilbert.c + hypercube.F90 + index.F90 + io_function.F90 + mesh.F90 + mesh_batch.F90 + mesh_cube_map.F90 + mesh_cube_parallel_map.F90 + mesh_function.F90 + mesh_init.F90 + mesh_interpolation.F90 + mesh_partition.F90 + modelmb_1part.F90 + multigrid.F90 + nl_operator.F90 + operate.c + operate_f.F90 + par_vec.F90 + partition.F90 + partition_transfer.F90 + regridding.F90 + restart.F90 + stencil.F90 + stencil_cube.F90 + stencil_star.F90 + stencil_stargeneral.F90 + stencil_starplus.F90 + stencil_variational.F90 + submesh.F90 + symmetrizer.F90 + time_interpolation.F90 + transfer_table.F90 + volume.F90 + vtk.F90 + ) +## Unused sources +# operate_inc.c diff --git a/src/hamiltonian/CMakeLists.txt b/src/hamiltonian/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e278a702dd5ef32326935324fb9a984a41e3979 --- /dev/null +++ b/src/hamiltonian/CMakeLists.txt @@ -0,0 +1,41 @@ +target_sources(Octopus_lib PRIVATE + absorbing_boundaries.F90 + berry.F90 + energy.F90 + epot.F90 + exchange_operator.F90 + ext_partner_list.F90 + gauge_field.F90 + hamiltonian_abst.F90 + hamiltonian_elec.F90 + hamiltonian_elec_base.F90 + hgh_projector.F90 + hirshfeld.F90 + ion_interaction.F90 + kb_projector.F90 + kick.F90 + lasers.F90 + lda_u.F90 + lda_u_io.F90 + libvdwxc.F90 + magnetic_constrain.F90 + oct_exchange.F90 + pcm.F90 + pcm_eom.F90 + pcm_potential.F90 + projector.F90 + projector_matrix.F90 + rkb_projector.F90 + scf_tol.F90 + scissor.F90 + singularity.F90 + species_pot.F90 + vdw_ts.F90 + vdw_ts_low.c + xc.F90 + xc_functional.F90 + xc_vdw.F90 + ) + +## External libraries +target_link_libraries(Octopus_lib PRIVATE Libxc::xcf03) diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..35459a56686aa4651438c0f354ebca56e7908533 --- /dev/null +++ b/src/include/CMakeLists.txt @@ -0,0 +1,5 @@ +configure_file(config.h.in config_F90.h) +configure_file(config.h.in config.h) +target_include_directories(Octopus_base INTERFACE + $ + $) diff --git a/src/include/config.h.in b/src/include/config.h.in new file mode 100644 index 0000000000000000000000000000000000000000..e2909a8a6e5c736699b7f900c1ac50a681327773 --- /dev/null +++ b/src/include/config.h.in @@ -0,0 +1,158 @@ +/* This file is generated by CMake */ + +#ifndef OCTOPUS_H +#define OCTOPUS_H + +#define BUILD_TIME "@BUILD_TIME@" +#define PACKAGE_VERSION "@CMAKE_PROJECT_VERSION@" +/* TODO: Implement a search function via $OCTOPUS_DIR/share:$(pwd)/share:/usr/share/octopus */ +#define SHARE_DIR "@SHARE_DIR@" +#define MAX_DIM @OCTOPUS_MAX_DIM@ + +#define CC "@CMAKE_C_COMPILER@" +#define CFLAGS "@CMAKE_C_FLAGS@" +#define CFLAGS_EXTRA "" +#define CXX "@CMAKE_CXX_COMPILER@" +#define CXXFLAGS "@CMAKE_CXX_FLAGS@" +#define CXXFLAGS_EXTRA "" + +#define FC "@CMAKE_Fortran_COMPILER@" +#define FCFLAGS "@CMAKE_Fortran_FLAGS@" +#define FCFLAGS_EXTRA "" + +/* TODO: Deprecate old Fortran: Remove code */ +#define FC_COMMAND_LINE_ARGUMENTS 2003 +/* #undef FC_COMMAND_LINE_IMPLICIT */ +/* #undef FC_COMMAND_LINE_INCLUDE */ +/* #undef FC_COMMAND_LINE_INTRINSIC */ +/* #undef FC_COMMAND_LINE_MODULE */ + +/* TODO: Deprecate old Fortran: Use ISO_C_BINDING */ +#ifdef __GFORTRAN__ +#define FC_FUNC(name,NAME) name/**/_ +#define FC_FUNC_(name,NAME) name/**/_ +#else +#define FC_FUNC(name,NAME) name ## _ +#define FC_FUNC_(name,NAME) name ## _ +#endif +#define GIT_COMMIT "@GIT_HASH@" + +/* TODO: Might not need in modern compilers */ +#define SIZEOF_VOIDP @CMAKE_SIZEOF_VOID_P@ +#define SIZEOF_SIZE_T @SIZEOF_SIZE_T@ +#define SIZEOF_UNSIGNED_INT @SIZEOF_UNSIGNED_INT@ +#define SIZEOF_UNSIGNED_LONG @SIZEOF_UNSIGNED_LONG@ +#define SIZEOF_UNSIGNED_LONG_LONG @SIZEOF_UNSIGNED_LONG_LONG@ + +/* TODO: Deprecate old C: Remove check */ +#cmakedefine HAVE_UINT32_T +#cmakedefine HAVE_UINT64_T + + +#define FC_INTEGER_SIZE @SIZEOF_Fortran_INTEGER@ + +/* TODO: Deprecate old Fortran: Always assume long_lines are accepted. Use appropriate flags */ +#define LONG_LINES 1 +/* TODO: Deprecate old Fortran: Remove check */ +#define HAVE_FC_COMPILER_VERSION 1 +#define HAVE_FC_SIZEOF 1 +#define HAVE_FLUSH 1 +#define F90_ACCEPTS_LINE_NUMBERS 1 +#define HAVE_FORTRAN_LOC 1 + +/* TODO: Deprecate old C: Remove check */ +#cmakedefine HAVE_DIRENT_H +#cmakedefine HAVE_CLOSEDIR +#cmakedefine HAVE_READDIR +#cmakedefine HAVE_STRCHR +#cmakedefine HAVE_STRTOD +#cmakedefine HAVE_GETTIMEOFDAY +#cmakedefine HAVE_NANOSLEEP +#cmakedefine HAVE_SCANDIR +#cmakedefine HAVE_ALPHASORT +#cmakedefine HAVE_ERRNO_H +#cmakedefine HAVE_GETOPT_LONG +#cmakedefine HAVE_GETPID +#define HAVE_IOCTL 1 +#cmakedefine HAVE_PERROR +#cmakedefine HAVE_SBRK +#cmakedefine HAVE_SIGACTION +#cmakedefine HAVE_SIGNAL_H +#cmakedefine HAVE_STDINT_H +#cmakedefine HAVE_STRCASESTR +#cmakedefine HAVE_STRING_H + +#cmakedefine HAVE_STRNDUP +#cmakedefine HAVE_STRSIGNAL +#cmakedefine HAVE_SYSCONF +#cmakedefine HAVE_TCGETPGRP +#cmakedefine HAVE_UNAME +#cmakedefine HAVE_WINDOWS_H +#define HAVE_VEC 1 + +#cmakedefine MPI_MOD +#cmakedefine HAVE_MPI +#cmakedefine HAVE_FFTW3_MPI +#cmakedefine HAVE_FFTW3_THREADS + +#cmakedefine HAVE_ELPA + +#cmakedefine HAVE_NETCDF + +#cmakedefine HAVE_LIBXC5 +/* TODO: Extract the configuration */ +#define HAVE_LIBXC_FXC 1 +#define HAVE_LIBXC_KXC 1 + +#cmakedefine HAVE_FMA3 +#cmakedefine HAVE_FMA4 + +#cmakedefine HAVE_SCALAPACK + +/* Introduced in C11 */ +/* TODO: C++11 Uses thread_local instead */ +/* TODO: C23 Uses common thread_local instead */ +/* Only for METIS */ +#define TLS_SPECIFIER _Thread_local + + +#define OCT_ARCH @CMAKE_SYSTEM_PROCESSOR@ + +/* TODO: To remove */ +/* #undef MPI_H */ /* Should not have any setups using it */ + +/* TODO: Connect */ +/* #undef HAVE_BERKELEYGW */ +/* #undef HAVE_CGAL */ +/* #undef HAVE_CLBLAS */ +/* #undef HAVE_CLFFT */ +/* #undef HAVE_PFFT */ +/* #undef HAVE_PNFFT */ +/* #undef HAVE_CUDA */ +/* #undef HAVE_CUDA_MPI */ +/* #undef HAVE_DFTBPLUS */ +/* #undef HAVE_DFTBPLUS_DEVEL */ +/* #undef HAVE_ETSF_IO */ +/* #undef HAVE_GDLIB */ +/* #undef HAVE_GD_GIF */ +/* #undef HAVE_GD_JPEG */ +/* #undef HAVE_GD_PNG */ +/* #undef HAVE_LIBFM */ +/* #undef HAVE_LIBISF */ +/* #undef HAVE_LIBVDWXC */ +/* #undef HAVE_LIBVDWXC_MPI */ +/* #undef HAVE_LIKWID */ +/* #undef HAVE_METIS */ +/* #undef HAVE_PARMETIS */ +/* #define METIS_IDXTYPEWIDTH 32 */ +/* #undef HAVE_NFFT */ +/* #undef HAVE_NLOPT */ +/* #undef HAVE_NVTX */ +/* #undef HAVE_OPENCL */ +/* #undef HAVE_OPENCL_CL_H */ +/* #undef HAVE_POKE */ +/* #undef HAVE_PSOLVER */ +/* #undef HAVE_PSPIO */ +/* #undef HAVE_SPARSKIT */ + +#endif diff --git a/src/include/global.h b/src/include/global.h index fdbadb070070000afc27194da1ebea5512987541..60586e9264c37f63bdcc664c6ad936237ed51883 100644 --- a/src/include/global.h +++ b/src/include/global.h @@ -246,6 +246,7 @@ ! and finish it with the PUSH_SUB and POP_SUB macros, which are these ! pieces of code that call the push_sub and pop_sub routines defined ! in the messages_m module. +#ifndef NDEBUG #define PUSH_SUB(routine) \ if(debug%trace) then; if(not_in_openmp()) then; CARDINAL \ call push_sub(__FILE__+"." ACARDINAL +TOSTRING(routine)); CARDINAL \ @@ -256,6 +257,10 @@ call pop_sub(__FILE__+"." ACARDINAL +TOSTRING(routine)); CARDINAL \ endif; endif; \ CARDINAL +#else +#define PUSH_SUB(routine) +#define POP_SUB(routine) +#endif !! Local Variables: !! mode: f90 diff --git a/src/include/vectors.h b/src/include/vectors.h index 465d30ba0edadf7a4487a10c94c1e5576de0c2ce..9f7a86aab5f42bbe48101824d5477cd51801b6eb 100644 --- a/src/include/vectors.h +++ b/src/include/vectors.h @@ -23,9 +23,15 @@ #ifndef VECTORS_H #define VECTORS_H -#ifdef HAVE_VEC +#ifdef __AVX__ +// Check for intel avx + +#if defined(__AVX512F__) || defined(__AVX512PF__) || \ + defined(__AVX512BW__) || defined(__AVX512ER__) || \ + defined(__AVX512CD__) || defined(__AVX512DQ__) || \ + defined(__AVX512VL__) +// Use AVX512 -#ifdef HAVE_M512D #include #define VEC_SIZE 8 #define VEC_TYPE __m512d @@ -41,7 +47,9 @@ #define DEPTH 16 -#elif defined(HAVE_M256D) +#elif defined(__AVX2__) +// Use AVX2 + #include #if defined(HAVE_FMA4) || defined(HAVE_FMA3) #include @@ -65,9 +73,10 @@ #define FENCE _mm_mfence() #define DEPTH 16 -#endif -#if !defined(HAVE_M256D) && defined(HAVE_M128D) +#else +// Default to AVX + #include #if defined(HAVE_FMA4) || defined(HAVE_FMA3) #include @@ -92,7 +101,12 @@ #define DEPTH 16 #endif -#ifdef HAVE_BLUE_GENE_Q +#elif defined(__bg__) +// Check for ibm blue_gene + +#ifdef __bgq__ +// Check for blue_gene_q + #define VEC_SIZE 4 #define VEC_TYPE vector4double #define VEC_LD(addr) vec_ld(0, (double *)(addr)) @@ -110,9 +124,10 @@ #define VEC_ZERO ((vector4double){0.0, 0.0, 0.0, 0.0}) #define DEPTH 16 -#endif -#if defined(HAVE_BLUE_GENE) && !defined(HAVE_BLUE_GENE_Q) +#else +// Otherwise use default blue_gene + #define VEC_SIZE 2 #define VEC_TYPE double _Complex #define VEC_LD(addr) __lfpd(addr) @@ -128,9 +143,8 @@ #define DEPTH 16 #endif -#endif - -#ifndef VEC_SIZE +#else +// Not explicitly optimized #define VEC_SIZE 1 #define VEC_TYPE double diff --git a/src/interactions/CMakeLists.txt b/src/interactions/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f86a80a41b433393ed5352e8b0ccb8a7d79696f3 --- /dev/null +++ b/src/interactions/CMakeLists.txt @@ -0,0 +1,21 @@ +target_sources(Octopus_lib PRIVATE + coulomb_force.F90 + current_to_mxll_field.F90 + density_interaction.F90 + external_potential.F90 + field_transfer.F90 + force_interaction.F90 + gravity.F90 + interaction_enum.F90 + interactions_factory.F90 + ion_electron_local_potential.F90 + lennard_jones.F90 + linear_medium_to_em_field.F90 + lorentz_force.F90 + mxll_b_field_to_matter.F90 + mxll_e_field_to_matter.F90 + mxll_vec_pot_to_matter.F90 + nlcc.F90 + potential_interaction.F90 + xc_interaction.F90 + ) diff --git a/src/ions/CMakeLists.txt b/src/ions/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..20172d2c3b271fb07701792121913ea164186ccd --- /dev/null +++ b/src/ions/CMakeLists.txt @@ -0,0 +1,13 @@ +target_sources(Octopus_lib PRIVATE + atom.F90 + born_charges.F90 + ion_dynamics.F90 + ions.F90 + read_coords.F90 + vibrations.F90 + symmetries.F90 + symmetries_finite.c + ) + +## External libraries +target_link_libraries(Octopus_lib PRIVATE Spglib::fortran) diff --git a/src/library/CMakeLists.txt b/src/library/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..cee7d7f245a65b20e7e83abb21240dd1472460f2 --- /dev/null +++ b/src/library/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(Octopus_lib PRIVATE + octopus.F90) +target_link_libraries(Octopus_lib PRIVATE Octopus_base) diff --git a/src/library/octopus.F90 b/src/library/octopus.F90 new file mode 100644 index 0000000000000000000000000000000000000000..0a7f7e26abc158a9b61d982b9147fbc98051a272 --- /dev/null +++ b/src/library/octopus.F90 @@ -0,0 +1,21 @@ +!! Copyright (C) 2010-2016 X. Andrade +!! +!! This program is free software; you can redistribute it and/or modify +!! it under the terms of the GNU General Public License as published by +!! the Free Software Foundation; either version 2, or (at your option) +!! any later version. +!! +!! This program is distributed in the hope that it will be useful, +!! but WITHOUT ANY WARRANTY; without even the implied warranty of +!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +!! GNU General Public License for more details. +!! +!! You should have received a copy of the GNU General Public License +!! along with this program; if not, write to the Free Software +!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +!! 02110-1301, USA. +!! + +!> Exported library interface +module octopus +end module octopus diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..55b60d09d8f00d65b977dcb391f7afe24ad71b5b --- /dev/null +++ b/src/main/CMakeLists.txt @@ -0,0 +1,40 @@ +target_sources(Octopus_octopus PRIVATE + casida.F90 + geom_opt.F90 + ground_state.F90 + invert_ks.F90 + main.F90 + phonons_fd.F90 + pulpo.F90 + run.F90 + static_pol.F90 + system_factory.F90 + test.F90 + time_dependent.F90 + ) + +## Link targets +target_link_libraries(Octopus_octopus PRIVATE + Octopus_base Octopus_lib fortran_cli) +set_target_properties(Octopus_octopus PROPERTIES + LINKER_LANGUAGE Fortran) + +if (TARGET ELPA::OpenMP) + target_link_libraries(Octopus_octopus PRIVATE ELPA::OpenMP) +elseif (TARGET ELPA::elpa) + target_link_libraries(Octopus_octopus PRIVATE ELPA::elpa) +endif () +if (TARGET MKL::${MKL_SCALAPACK}) + target_link_libraries(Octopus_octopus PRIVATE MKL::${MKL_SCALAPACK}) +endif () +if (TARGET MPI::MPI_Fortran) + target_link_libraries(Octopus_octopus PUBLIC MPI::MPI_Fortran) + if (CMAKE_Fortran_COMPILER_ID STREQUAL GNU) + target_compile_options(Octopus_octopus PRIVATE $<$:-fallow-argument-mismatch>) + endif () +endif () + +if (OCTOPUS_INSTALL) + install(TARGETS Octopus_octopus + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif () diff --git a/src/math/CMakeLists.txt b/src/math/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..caa53fbafd6de14bfed8091e38c2314826a894d4 --- /dev/null +++ b/src/math/CMakeLists.txt @@ -0,0 +1,82 @@ +target_sources(Octopus_lib PRIVATE + accel_blas.F90 + basis_vectors.F90 + blas.F90 + checksum.c + checksum_interface.F90 + compressed_sensing.F90 + dablas.c + fft.F90 + fftw.F90 + fftw_low.c + gauss_legendre.F90 + helmholtz_decomposition.F90 + helmholtz_decomposition_test.F90 + lalg_adv.F90 + lalg_basic.F90 + lapack.F90 + loct_math.F90 + math.F90 + maxwell_function.F90 + metis.F90 + metis_f.c + minimizer.F90 + minimizer_low.c + nfft.F90 + nfft_f.c + oct_gsl_f.c + pblas.F90 + permutations.F90 + pfft.F90 + pnfft.F90 + qshep.F90 + quickrnd.F90 + root_solver.F90 + scalapack.F90 + sgfft.F90 + solvers.F90 + sparskit.F90 + spline_filter.F90 + spline_low.cc + splines.F90 + symm_op.F90 + tdfunction.F90 + ylm.c + young.F90 + ) + +## External libraries +if (TARGET MKL::MKL) + target_link_libraries(Octopus_lib PRIVATE MKL::MKL) + # FFTW interface for mkl is not automatically set + target_include_directories(Octopus_lib PRIVATE ${MKL_ROOT}/include/fftw) + if (TARGET MKL::${MKL_SCALAPACK}) + target_link_libraries(Octopus_lib PRIVATE MKL::${MKL_SCALAPACK}) + endif () + if (OCTOPUS_ScaLAPACK AND NOT TARGET MKL::${MKL_SCALAPACK}) + message(FATAL_ERROR "Octopus: Missing target") + endif () +else () + target_link_libraries(Octopus_lib PRIVATE BLAS::BLAS) + target_link_libraries(Octopus_lib PRIVATE LAPACK::LAPACK) + if (OCTOPUS_MPI AND TARGET FFTW::DoubleMPI) + target_link_libraries(Octopus_lib PRIVATE FFTW::DoubleMPI) + endif () + if (OCTOPUS_OpenMP AND TARGET FFTW::DoubleOpenMP) + target_link_libraries(Octopus_lib PRIVATE FFTW::DoubleOpenMP) + elseif (OCTOPUS_OpenMP AND TARGET FFTW::DoubleThreads) + target_link_libraries(Octopus_lib PRIVATE FFTW::DoubleThreads) + else () + target_link_libraries(Octopus_lib PRIVATE FFTW::Double) + endif () + if (OCTOPUS_ScaLAPACK) + message(FATAL_ERROR "Octopus: Other ScaLAPACK not implemented") + endif () +endif () +if (TARGET ELPA::OpenMP) + target_link_libraries(Octopus_lib PRIVATE ELPA::OpenMP) +elseif (TARGET ELPA::elpa) + target_link_libraries(Octopus_lib PRIVATE ELPA::elpa) +endif () +target_link_libraries(Octopus_lib PRIVATE qshep) +target_link_libraries(Octopus_lib PRIVATE bpdn) diff --git a/src/maxwell/CMakeLists.txt b/src/maxwell/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ae27631caba6289c51a28a58edf8c228ec09ebfb --- /dev/null +++ b/src/maxwell/CMakeLists.txt @@ -0,0 +1,12 @@ +target_sources(Octopus_lib PRIVATE + dispersive_medium.F90 + energy_mxll.F90 + external_densities.F90 + external_source.F90 + hamiltonian_mxll.F90 + linear_medium.F90 + maxwell.F90 + maxwell_boundary_op.F90 + plane_wave.F90 + propagator_mxll.F90 + ) diff --git a/src/multisystem/CMakeLists.txt b/src/multisystem/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..697cda63c63ab52c0299d87c4cc2c6c07406ed4b --- /dev/null +++ b/src/multisystem/CMakeLists.txt @@ -0,0 +1,27 @@ +target_sources(Octopus_lib PRIVATE + algorithm.F90 + algorithm_factory.F90 + convergence_criterion.F90 + ghost_interaction.F90 + interaction.F90 + interaction_partner.F90 + interaction_with_partner.F90 + interactions_factory_abst.F90 + multisystem.F90 + multisystem_basic.F90 + multisystem_debug.F90 + propagator.F90 + propagator_aetrs.F90 + propagator_beeman.F90 + propagator_bomd.F90 + propagator_exp_mid.F90 + propagator_exp_mid_2step.F90 + propagator_factory.F90 + propagator_leapfrog.F90 + propagator_rk4.F90 + propagator_static.F90 + propagator_verlet.F90 + quantity.F90 + system.F90 + system_factory_abst.F90 + ) diff --git a/src/opt_control/CMakeLists.txt b/src/opt_control/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..daf5642b6f580a3e60362d28d0c6777f9091a9fe --- /dev/null +++ b/src/opt_control/CMakeLists.txt @@ -0,0 +1,10 @@ +target_sources(Octopus_lib PRIVATE + controlfunction.F90 + filter.F90 + initst.F90 + opt_control.F90 + opt_control_global.F90 + opt_control_iter.F90 + propagation.F90 + target.F90 + ) diff --git a/src/output/CMakeLists.txt b/src/output/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2439c2e679577f00da932295b2b4d609ba7bc081 --- /dev/null +++ b/src/output/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(Octopus_lib PRIVATE + output.F90 + output_linear_medium.F90 + output_low.F90 + output_me.F90 + output_modelmb.F90 + output_mxll.F90 + output_berkeleygw.F90 + ) diff --git a/src/poisson/CMakeLists.txt b/src/poisson/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8fed7dfb225386001d0d7970390cff1a46d06656 --- /dev/null +++ b/src/poisson/CMakeLists.txt @@ -0,0 +1,16 @@ +target_sources(Octopus_lib PRIVATE + photon_mode.F90 + photon_mode_mf.F90 + poisson.F90 + poisson_cg.F90 + poisson_corrections.F90 + poisson_cutoff.F90 + poisson_cutoffs.c + poisson_fft.F90 + poisson_fmm.F90 + poisson_isf.F90 + poisson_multigrid.F90 + poisson_no.F90 + poisson_psolver.F90 + scaling_function.F90 + ) diff --git a/src/scf/CMakeLists.txt b/src/scf/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d86f047eb85cac875d071cc1eef0d43b468d368f --- /dev/null +++ b/src/scf/CMakeLists.txt @@ -0,0 +1,15 @@ +target_sources(Octopus_lib PRIVATE + criteria_factory.F90 + density_criterion.F90 + eigenval_criterion.F90 + electrons_ground_state.F90 + energy_criterion.F90 + lcao.F90 + lda_u_mixer.F90 + mix.F90 + rdmft.F90 + scf.F90 + unocc.F90 + ) +## Unused sources +# mixing_metric.F90 diff --git a/src/species/CMakeLists.txt b/src/species/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ff31c26a64b1d2ef3a522ee650d6adc1041b8344 --- /dev/null +++ b/src/species/CMakeLists.txt @@ -0,0 +1,27 @@ +target_sources(Octopus_lib PRIVATE + atomic.F90 + element.F90 + element_low.cc + logrid.F90 + ps.F90 + ps_cpi.F90 + ps_cpi_file.F90 + ps_fhi.F90 + ps_fhi_file.F90 + ps_hgh.F90 + ps_in_grid.F90 + ps_psf.F90 + ps_psf_file.F90 + ps_xml.F90 + share_directory.F90 + share_directory_low.cc + species.F90 + spline.cc + pseudo.F90 + pseudo_low.cc + pseudo_set.F90 + pseudo_set_low.cc + ) + +## External libraries +target_link_libraries(Octopus_lib PRIVATE rapidxml) diff --git a/src/species/share_directory.hpp b/src/species/share_directory.hpp index bfe94ffaee0ea4bb3bb3732feb8138a114bcef66..e3bbbceb9ebfe410dce8a55dc846e3a1e304ebd1 100644 --- a/src/species/share_directory.hpp +++ b/src/species/share_directory.hpp @@ -20,6 +20,7 @@ */ #include +#include "config.h" namespace pseudopotential { diff --git a/src/states/CMakeLists.txt b/src/states/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..afef80671de3c042a959f960dceae0d2c075c2c6 --- /dev/null +++ b/src/states/CMakeLists.txt @@ -0,0 +1,23 @@ +target_sources(Octopus_lib PRIVATE + density.F90 + elec_matrix_elements.F90 + excited_states.F90 + linear_response.F90 + modelmb_density_matrix.F90 + modelmb_exchange_syms.F90 + modelmb_particles.F90 + opt_control_state.F90 + physics_op.F90 + smear.F90 + states_abst.F90 + states_elec.F90 + states_elec_calc.F90 + states_elec_dim.F90 + states_elec_group.F90 + states_elec_io.F90 + states_elec_parallel.F90 + states_elec_restart.F90 + states_mxll.F90 + states_mxll_restart.F90 + wfs_elec.F90 +) diff --git a/src/sternheimer/CMakeLists.txt b/src/sternheimer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3f867ff706cef3fabd1f695969db3da9cba6b80b --- /dev/null +++ b/src/sternheimer/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(Octopus_lib PRIVATE + em_resp.F90 + em_resp_calc.F90 + kdotp.F90 + kdotp_calc.F90 + phonons_lr.F90 + sternheimer.F90 + vdw.F90 + ) diff --git a/src/td/CMakeLists.txt b/src/td/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7d266368fd1e19334a5d24526599af309d6f61cf --- /dev/null +++ b/src/td/CMakeLists.txt @@ -0,0 +1,22 @@ +target_sources(Octopus_lib PRIVATE + pes.F90 + pes_flux.F90 + pes_mask.F90 + pes_out.F90 + pes_spm.F90 + potential_interpolation.F90 + propagation_ops_elec.F90 + propagator_base.F90 + propagator_cn.F90 + propagator_elec.F90 + propagator_etrs.F90 + propagator_expmid.F90 + propagator_magnus.F90 + propagator_qoct.F90 + propagator_rk.F90 + spectrum.F90 + td.F90 + td_calc.F90 + td_write.F90 + td_write_low.F90 + ) diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6a16c5447a2fb00e1a4a2c89d575348d33af1bd6 --- /dev/null +++ b/src/utils/CMakeLists.txt @@ -0,0 +1,147 @@ +add_executable(Octopus_Utils_casida_spectrum casida_spectrum.F90) +set_target_properties(Octopus_Utils_casida_spectrum PROPERTIES + OUTPUT_NAME oct-casida_spectrum) +target_link_libraries(Octopus_Utils_casida_spectrum PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_center-geom centergeom.F90) +set_target_properties(Octopus_Utils_center-geom PROPERTIES + OUTPUT_NAME oct-center-geom) +target_link_libraries(Octopus_Utils_center-geom PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_conductivity conductivity.F90) +set_target_properties(Octopus_Utils_conductivity PROPERTIES + OUTPUT_NAME oct-conductivity) +target_link_libraries(Octopus_Utils_conductivity PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_convert convert.F90) +set_target_properties(Octopus_Utils_convert PROPERTIES + OUTPUT_NAME oct-convert) +target_link_libraries(Octopus_Utils_convert PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_dielectric-function dielectric_function.F90) +set_target_properties(Octopus_Utils_dielectric-function PROPERTIES + OUTPUT_NAME oct-dielectric-function) +target_link_libraries(Octopus_Utils_dielectric-function PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_floquet floquet.F90) +set_target_properties(Octopus_Utils_floquet PROPERTIES + OUTPUT_NAME oct-floquet) +target_link_libraries(Octopus_Utils_floquet PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_harmonic-spectrum harmonic_spectrum.F90) +set_target_properties(Octopus_Utils_harmonic-spectrum PROPERTIES + OUTPUT_NAME oct-harmonic-spectrum) +target_link_libraries(Octopus_Utils_harmonic-spectrum PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_help help.F90) +set_target_properties(Octopus_Utils_help PROPERTIES + OUTPUT_NAME oct-help) +target_link_libraries(Octopus_Utils_help PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_infrared_spectrum infrared.F90) +set_target_properties(Octopus_Utils_infrared_spectrum PROPERTIES + OUTPUT_NAME oct-infrared_spectrum) +target_link_libraries(Octopus_Utils_infrared_spectrum PRIVATE + Octopus_base Octopus_lib fortran_cli) +if (TARGET OpenMP::OpenMP_Fortran) + target_link_libraries(Octopus_Utils_infrared_spectrum PRIVATE OpenMP::OpenMP_Fortran) + target_compile_definitions(Octopus_Utils_infrared_spectrum PRIVATE HAVE_OPENMP) +endif () + +add_executable(Octopus_Utils_local_multipoles local_multipoles.F90) +set_target_properties(Octopus_Utils_local_multipoles PROPERTIES + OUTPUT_NAME oct-local_multipoles) +target_sources(Octopus_Utils_local_multipoles PRIVATE + local_write.F90) +target_link_libraries(Octopus_Utils_local_multipoles PRIVATE + Octopus_base Octopus_lib fortran_cli) +if (TARGET OpenMP::OpenMP_Fortran) + target_link_libraries(Octopus_Utils_local_multipoles PRIVATE OpenMP::OpenMP_Fortran) + target_compile_definitions(Octopus_Utils_local_multipoles PRIVATE HAVE_OPENMP) +endif () + +add_executable(Octopus_Utils_oscillator-strength oscillator_strength.F90) +set_target_properties(Octopus_Utils_oscillator-strength PROPERTIES + OUTPUT_NAME oct-oscillator-strength) +target_link_libraries(Octopus_Utils_oscillator-strength PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_photoelectron_spectrum photoelectron_spectrum.F90) +set_target_properties(Octopus_Utils_photoelectron_spectrum PROPERTIES + OUTPUT_NAME oct-photoelectron_spectrum) +target_link_libraries(Octopus_Utils_photoelectron_spectrum PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_propagation_spectrum propagation_spectrum.F90) +set_target_properties(Octopus_Utils_propagation_spectrum PROPERTIES + OUTPUT_NAME oct-propagation_spectrum) +target_link_libraries(Octopus_Utils_propagation_spectrum PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_spin_susceptibility spin_susceptibility.F90) +set_target_properties(Octopus_Utils_spin_susceptibility PROPERTIES + OUTPUT_NAME oct-spin_susceptibility) +target_link_libraries(Octopus_Utils_spin_susceptibility PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_tdtdm tdtdm.F90) +set_target_properties(Octopus_Utils_tdtdm PROPERTIES + OUTPUT_NAME oct-tdtdm) +target_link_libraries(Octopus_Utils_tdtdm PRIVATE + Octopus_base Octopus_lib fortran_cli) +if (TARGET MPI::MPI_Fortran) + target_link_libraries(Octopus_lib PUBLIC MPI::MPI_Fortran) + if (CMAKE_Fortran_COMPILER_ID STREQUAL GNU) + target_compile_options(Octopus_lib PRIVATE $<$:-fallow-argument-mismatch>) + endif () +endif () + +add_executable(Octopus_Utils_unfold unfold.F90) +set_target_properties(Octopus_Utils_unfold PROPERTIES + OUTPUT_NAME oct-unfold) +target_link_libraries(Octopus_Utils_unfold PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_vibrational_spectrum vibrational.F90) +set_target_properties(Octopus_Utils_vibrational_spectrum PROPERTIES + OUTPUT_NAME oct-vibrational_spectrum) +target_link_libraries(Octopus_Utils_vibrational_spectrum PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_wannier90 wannier90_interface.F90) +set_target_properties(Octopus_Utils_wannier90 PROPERTIES + OUTPUT_NAME oct-wannier90) +target_sources(Octopus_Utils_wannier90 PRIVATE + ../math/ylm_wannier.F90) +target_link_libraries(Octopus_Utils_wannier90 PRIVATE + Octopus_base Octopus_lib fortran_cli) + +add_executable(Octopus_Utils_xyz-anim xyzanim.F90) +set_target_properties(Octopus_Utils_xyz-anim PROPERTIES + OUTPUT_NAME oct-xyz-anim) +target_link_libraries(Octopus_Utils_xyz-anim PRIVATE + Octopus_base Octopus_lib fortran_cli) + +get_directory_property(UtilTargets BUILDSYSTEM_TARGETS) +set_target_properties(${UtilTargets} PROPERTIES + LINKER_LANGUAGE Fortran) +if (OCTOPUS_INSTALL) + install(TARGETS ${UtilTargets} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif () + +# TODO: Remove hardcoded file structure in testsuite +foreach(oct_exec IN ITEMS ${UtilTargets}) + add_custom_command(TARGET ${oct_exec} POST_BUILD + COMMAND mkdir -p ${PROJECT_BINARY_DIR} + COMMAND ln -f -s $ ${PROJECT_BINARY_DIR}/$ + COMMENT "Generate default symbolic link to ${oct_exec} to default build directory") +endforeach() \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8597d14f53f3e7a432509ee34a340c089c98e2e3 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,32 @@ +# Use Catch for more control of C++ unit tests +# TODO: To be implemented +return() + +# Otherwise for fortran use ctest directly +# Bundle some helpful C->Fortran translation functions +# Source: FortranWiki https://fortranwiki.org/fortran/show/c_interface_module +add_library(c_interface_module STATIC c_interface_module.F90) + +# Generated ctest file that switches and displays tests +# Note must be plain C because generated CPP file does not include extern "C" +set(TestsDriver fortran_test.c) + +# Add fortran tests here +create_test_sourcelist(FortranTests_Files + ${TestsDriver} + test_dummy.F90) + +add_executable(FortranTests ${FortranTests_Files}) +target_link_libraries(FortranTests PRIVATE c_interface_module) + +# Remove the driver executable from the list for add_test +set(TestsToRun ${FortranTests_Files}) +list(REMOVE_ITEM TestsToRun ${TestsDriver}) + +foreach(test ${TestsToRun}) + get_filename_component(test_name ${test} NAME_WE) + # First argument is the name of the test + # Can add more cli arguments that will be passed to the fortran test + add_test(NAME ${test_name} + COMMAND $ ${test_name}) +endforeach() diff --git a/test/c_interface_module.F90 b/test/c_interface_module.F90 new file mode 100644 index 0000000000000000000000000000000000000000..07214244bd2efc686355a32a0c2ded9ceba78d23 --- /dev/null +++ b/test/c_interface_module.F90 @@ -0,0 +1,448 @@ +! FILE: c_interface_module.F90 +! PURPOSE: Supplement ISO-C-Binding to provide type aliases and interfaces +! to common ISO-C string functions to aid working with strings. +! AUTHOR: Joseph M. Krahn +! STATUS: Still in development. Reasonably complete, but somewhat limited testing. +! +! The idea is to provide type aliases for all ISO-C types, so that the +! Fortran interface code more explicitly defines the actual C interface. +! This should be updated to support F2008 variable-length allocatable +! strings. +! +! Entity names all have the "C_" prefix, as with ISO-C-Binding, with a +! few exceptions. +! +module C_interface_module + use, intrinsic :: ISO_C_Binding, & + ! C type aliases for pointer derived types: + C_ptr => C_ptr , & + C_char_ptr => C_ptr, & + C_const_char_ptr => C_ptr, & + C_void_ptr => C_ptr, & + C_const_void_ptr => C_ptr + + implicit none + + !---------------------------------------------------------------------------- + ! C type aliases for intrinsic type KIND parameters: + + ! NOTE: a C enum may not always be a standard C int + integer, parameter :: C_enum = C_int + + ! Defining off_t is difficult, because it may depend on "LARGEFILE" selection. + ! integer, parameter :: C_off_t = ?? + + ! C string terminator alais using the 3-letter ASCII name. + ! The C_ prefix is not used because it is just an ASCII character. + character(len=1,kind=C_char), parameter :: NUL = C_NULL_char + + ! NOTE: In C, "char" is distinct from "signed char", unlike integers. + ! The plain "char" type is specific for text/string values, whereas + ! "signed char" should indicate 1-byte integer data. + ! + ! Most ISO-C systems have wide chars "wchar_t", but Fortran compilers + ! have limited support for different character kinds. UTF encoding + ! adds more complexity. This should be updated as Fortran compilers + ! include support for more character types. + ! + + ! Fortran does not (yet) support unsigned types. + integer, parameter :: & + C_unsigned = C_int, & + C_unsigned_short = C_short, & + C_unsigned_long = C_long, & + C_unsigned_long_long = C_long_long, & + C_unsigned_char = C_signed_char, & + C_ssize_t = C_size_t, & + C_uint8_t = C_int8_t, & + C_uint16_t = C_int16_t, & + C_uint32_t = C_int32_t, & + C_uint64_t = C_int64_t, & + C_uint_least8_t = C_int_least8_t, & + C_uint_least16_t = C_int_least16_t, & + C_uint_least32_t = C_int_least32_t, & + C_uint_least64_t = C_int_least64_t, & + C_uint_fast8_t = C_int_fast8_t, & + C_uint_fast16_t = C_int_fast16_t, & + C_uint_fast32_t = C_int_fast32_t, & + C_uint_fast64_t = C_int_fast64_t, & + C_uintmax_t = C_intmax_t + ! Note: ptrdiff_t cannot be reliably defined from other types. + ! When practical, it is larger than a pointer because it benefits + ! from the full unsigned range in both positive and negative directions. + + ! Integer versions including 'int', where the 'int' is optional: + integer, parameter :: & + C_short_int = C_short, & + C_long_int = C_long, & + C_long_long_int = C_long_long, & + C_unsigned_int = C_unsigned, & + C_unsigned_short_int = C_short, & + C_unsigned_long_int = C_long, & + C_unsigned_long_long_int = C_long_long + + interface C_F_string + module procedure C_F_string_ptr + module procedure C_F_string_chars + end interface C_F_string + + interface F_C_string + module procedure F_C_string_ptr + module procedure F_C_string_chars + end interface F_C_string + + !======================================================================= + ! Some useful ISO C library string functions from + ! These are based on GCC header sections marked as NAMESPACE_STD + interface + + ! Copy N bytes of SRC to DEST, no aliasing or overlapping allowed. + !extern void *memcpy (void *dest, const void *src, size_t n); + function C_memcpy(dest, src, n) result(result) bind(C,name="memcpy") + import C_void_ptr, C_size_t + type(C_void_ptr) :: result + type(C_void_ptr), value, intent(in) :: dest ! target=intent(out) + type(C_void_ptr), value, intent(in) :: src ! target=intent(in) + integer(C_size_t), value, intent(in) :: n + end function C_memcpy + + ! Copy N bytes of SRC to DEST, guaranteeing correct behavior for overlapping strings. + !extern void *memmove (void *dest, const void *src, size_t n) + function C_memmove(dest, src, n) result(result) bind(C,name="memmove") + import C_void_ptr, C_size_t + type(C_void_ptr) :: result + type(C_void_ptr), value, intent(in) :: dest ! target=intent(out) + type(C_void_ptr), value, intent(in) :: src + integer(C_size_t), value, intent(in) :: n + end function C_memmove + + ! Set N bytes of S to C. + !extern void *memset (void *s, int c, size_t n) + function C_memset(s, c, n) result(result) bind(C,name="memset") + import C_void_ptr, C_int, C_size_t + type(C_void_ptr) :: result + type(C_void_ptr), value, intent(in) :: s ! target=intent(out) + integer(C_int), value, intent(in) :: c + integer(C_size_t), value, intent(in) :: n + end function C_memset + + ! Compare N bytes of S1 and S2. + !extern int memcmp (const void *s1, const void *s2, size_t n) + pure & + function C_memcmp(s1, s2, n) result(result) bind(C,name="memcmp") + import C_int, C_void_ptr, C_size_t + integer(C_int) :: result + type(C_void_ptr), value, intent(in) :: s1 + type(C_void_ptr), value, intent(in) :: s2 + integer(C_size_t), value, intent(in) :: n + end function C_memcmp + + ! Search N bytes of S for C. + !extern void *memchr (const void *s, int c, size_t n) + pure & + function C_memchr(s, c, n) result(result) bind(C,name="memchr") + import C_void_ptr, C_int, C_size_t + type(C_void_ptr) :: result + type(C_void_ptr), value, intent(in) :: s + integer(C_int), value, intent(in) :: c + integer(C_size_t), value, intent(in) :: n + end function C_memchr + + ! Copy SRC to DEST. + !extern char *strcpy (char *dest, const char *src) + function C_strcpy(dest, src) result(result) bind(C,name="strcpy") + import C_char_ptr, C_size_t + type(C_char_ptr) :: result + type(C_char_ptr), value, intent(in) :: dest ! target=intent(out) + type(C_char_ptr), value, intent(in) :: src + end function C_strcpy + + ! Copy no more than N characters of SRC to DEST. + !extern char *strncpy (char *dest, const char *src, size_t n) + function C_strncpy(dest, src, n) result(result) bind(C,name="strncpy") + import C_char_ptr, C_size_t + type(C_char_ptr) :: result + type(C_char_ptr), value, intent(in) :: dest ! target=intent(out) + type(C_char_ptr), value, intent(in) :: src + integer(C_size_t), value, intent(in) :: n + end function C_strncpy + + ! Append SRC onto DEST. + !extern char *strcat (char *dest, const char *src) + function C_strcat(dest, src) result(result) bind(C,name="strcat") + import C_char_ptr, C_size_t + type(C_char_ptr) :: result + type(C_char_ptr), value, intent(in) :: dest ! target=intent(out) + type(C_char_ptr), value, intent(in) :: src + end function C_strcat + + ! Append no more than N characters from SRC onto DEST. + !extern char *strncat (char *dest, const char *src, size_t n) + function C_strncat(dest, src, n) result(result) bind(C,name="strncat") + import C_char_ptr, C_size_t + type(C_char_ptr) :: result + type(C_char_ptr), value, intent(in) :: dest ! target=intent(out) + type(C_char_ptr), value, intent(in) :: src + integer(C_size_t), value, intent(in) :: n + end function C_strncat + + ! Compare S1 and S2. + !extern int strcmp (const char *s1, const char *s2) + pure & + function C_strcmp(s1, s2) result(result) bind(C,name="strcmp") + import C_int, C_char_ptr, C_size_t + integer(C_int) :: result + type(C_char_ptr), value, intent(in) :: s1 + type(C_char_ptr), value, intent(in) :: s2 + end function C_strcmp + + ! Compare N characters of S1 and S2. + !extern int strncmp (const char *s1, const char *s2, size_t n) + pure & + function C_strncmp(s1, s2, n) result(result) bind(C,name="strncmp") + import C_int, C_char_ptr, C_size_t + integer(C_int) :: result + type(C_char_ptr), value, intent(in) :: s1 + type(C_char_ptr), value, intent(in) :: s2 + integer(C_size_t), value, intent(in) :: n + end function C_strncmp + + ! Return the length of S. + !extern size_t strlen (const char *s) + pure & + function C_strlen(s) result(result) bind(C,name="strlen") + import C_char_ptr, C_size_t + integer(C_size_t) :: result + type(C_char_ptr), value, intent(in) :: s !character(len=*), intent(in) + end function C_strlen + + end interface + + ! End of + !========================================================================= + ! Standard ISO-C malloc routines: + interface + + ! void *calloc(size_t nmemb, size_t size); + type(C_void_ptr) & + function C_calloc(nmemb, size) bind(C,name="calloc") + import C_void_ptr, C_size_t + integer(C_size_t), value, intent(in) :: nmemb, size + end function C_calloc + + ! void *malloc(size_t size); + type(C_void_ptr) & + function C_malloc(size) bind(C,name="malloc") + import C_void_ptr, C_size_t + integer(C_size_t), value, intent(in) :: size + end function C_malloc + + ! void free(void *ptr); + subroutine C_free(ptr) bind(C,name="free") + import C_void_ptr + type(C_void_ptr), value, intent(in) :: ptr + end subroutine C_free + + ! void *realloc(void *ptr, size_t size); + type(C_void_ptr) & + function C_realloc(ptr,size) bind(C,name="realloc") + import C_void_ptr, C_size_t + type(C_void_ptr), value, intent(in) :: ptr + integer(C_size_t), value, intent(in) :: size + end function C_realloc + + end interface + + interface assignment(=) + module procedure F_string_assign_C_string + end interface assignment(=) + + !========================================================================== + +contains + + ! HACK: For some reason, C_associated was not defined as pure. + pure logical & + function C_associated_pure(ptr) result(associated) + type(C_ptr), intent(in) :: ptr + integer(C_intptr_t) :: iptr + iptr = transfer(ptr,iptr) + associated = (iptr /= 0) + end function C_associated_pure + + ! Set a fixed-length Fortran string to the value of a C string. + subroutine F_string_assign_C_string(F_string, C_string) + character(len=*), intent(out) :: F_string + type(C_ptr), intent(in) :: C_string + character(len=1,kind=C_char), pointer :: p_chars(:) + integer :: i + if (.not. C_associated(C_string) ) then + F_string = ' ' + else + call C_F_pointer(C_string,p_chars,[huge(0)]) + i=1 + do while(p_chars(i)/=NUL .and. i<=len(F_string)) + F_string(i:i) = p_chars(i) + i=i+1 + end do + if (i