diff --git a/.gitignore b/.gitignore index de19d1d..7d0b8c3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build/ Debug/ Testing/ +compile_commands.json # Google Tests tests/lib/ @@ -12,3 +13,4 @@ cmake-build-debug/ # Cache dir .cache + diff --git a/CMakeLists.txt b/CMakeLists.txt index e177680..fb27a81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,9 +8,19 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Default settings add_compile_options(-Wall -Wextra -Wpedantic) +add_compile_options($<$:-Wno-pedantic>) + +# Add pedantic just for + set(CMAKE_CXX_STANDARD 17) + +# Cuda Settings set(CMAKE_CUDA_ARCHITECTURES 61) set(CUDA_SEPARABLE_COMPILATION ON) +# Cuda settings to get correct compile_commands.json +set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0) +set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0) +set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0) # Add Vec3 as a dependency include(FetchContent) @@ -24,9 +34,9 @@ if(NOT Vec3_POPULATED) include_directories(${Vec3_SOURCE_DIR}) endif() +include_directories(/usr/local/cuda-12.8/include) include_directories(src) include_directories(kernels) -include_directories(/usr/local/cuda-12.8/include) add_subdirectory(src) add_subdirectory(kernels) @@ -35,21 +45,19 @@ add_subdirectory(tests) add_executable(${NAME} main.cpp) install(DIRECTORY src/ DESTINATION src/) - target_link_libraries( ${NAME} PRIVATE ${NAME}_lib ${NAME}_cuda_lib - ${CUDA_LIBRARIES} ) # Doxygen Build -option(BUILD_DOC "Build Documentation" ON) +option(BUILD_DOC "Build Documentation" OFF) find_package(Doxygen) -if(DOXYGEN_FOUND) +if(DOXYGEN_FOUND AND BUILD_DOC) set(BUILD_DOC_DIR ${CMAKE_SOURCE_DIR}/build/docs) if(NOT EXISTS ${BUILD_DOC_DIR}) file(MAKE_DIRECTORY ${BUILD_DOC_DIR}) @@ -65,6 +73,6 @@ if(DOXYGEN_FOUND) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM) -else(DOXYGEN_FOUND) +else(DOXYGEN_FOUND AND BUILD_DOC) message("Doxygen needs to be installed to generate the documentation.") -endif(DOXYGEN_FOUND) +endif(DOXYGEN_FOUND AND BUILD_DOC) diff --git a/kernels/CMakeLists.txt b/kernels/CMakeLists.txt index be62649..baa8a60 100644 --- a/kernels/CMakeLists.txt +++ b/kernels/CMakeLists.txt @@ -1,16 +1,14 @@ project(${NAME}_cuda_lib CUDA CXX) set(HEADER_FILES - hello_world.h + pair_potentials.cuh ) set(SOURCE_FILES - hello_world.cu ) # The library contains header and source files. -add_library(${NAME}_cuda_lib STATIC +add_library(${NAME}_cuda_lib INTERFACE ${SOURCE_FILES} ${HEADER_FILES} ) -target_compile_options(${CMAKE_PROJECT_NAME}_cuda_lib PRIVATE -Wno-gnu-line-marker -Wno-pedantic) diff --git a/kernels/hello_world.cu b/kernels/hello_world.cu deleted file mode 100644 index 7c65115..0000000 --- a/kernels/hello_world.cu +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include - -__global__ void hello_cuda() { - printf("Hello CUDA from thread %d\n", threadIdx.x); -} - -extern "C" void launch_hello_cuda() { - // First check device properties - cudaDeviceProp prop; - cudaGetDeviceProperties(&prop, 1); - printf("Using device: %s with compute capability %d.%d\n", prop.name, - prop.major, prop.minor); - - hello_cuda<<<1, 10>>>(); - cudaDeviceSynchronize(); - fflush(stdout); -} - -extern "C" void check_cuda() { - int deviceCount = 0; - cudaError_t error = cudaGetDeviceCount(&deviceCount); - - if (error != cudaSuccess) { - printf("CUDA error: %s\n", cudaGetErrorString(error)); - } - - printf("Found %d CUDA devices\n", deviceCount); - - for (int i = 0; i < deviceCount; i++) { - cudaDeviceProp prop; - cudaGetDeviceProperties(&prop, i); - - printf("Device %d: %s\n", i, prop.name); - printf(" Compute capability: %d.%d\n", prop.major, prop.minor); - printf(" Total global memory: %.2f GB\n", - static_cast(prop.totalGlobalMem) / (1024 * 1024 * 1024)); - printf(" Multiprocessors: %d\n", prop.multiProcessorCount); - printf(" Max threads per block: %d\n", prop.maxThreadsPerBlock); - printf(" Max threads dimensions: (%d, %d, %d)\n", prop.maxThreadsDim[0], - prop.maxThreadsDim[1], prop.maxThreadsDim[2]); - printf(" Max grid dimensions: (%d, %d, %d)\n", prop.maxGridSize[0], - prop.maxGridSize[1], prop.maxGridSize[2]); - printf("\n"); - } -} diff --git a/kernels/hello_world.h b/kernels/hello_world.h deleted file mode 100644 index 4024e2e..0000000 --- a/kernels/hello_world.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef HELLO_WORLD_CU_H -#define HELLO_WORLD_CU_H - -extern "C" { -// Declaration of the CUDA function that will be called from C++ -void launch_hello_cuda(); -void check_cuda(); -} - -#endif // HELLO_WORLD_CU_H diff --git a/kernels/pair_potentials.cuh b/kernels/pair_potentials.cuh new file mode 100644 index 0000000..ab45648 --- /dev/null +++ b/kernels/pair_potentials.cuh @@ -0,0 +1,91 @@ +#ifndef POTENTIALS_H +#define POTENTIALS_H + +#include "precision.hpp" +#include "vec3.h" + +#ifdef __CUDACC__ +#define CUDA_CALLABLE __host__ __device__ +#else +#define CUDA_CALLABLE +#endif + +/** + * Result struct for the Pair Potential + */ +struct ForceAndEnergy { + real energy; + Vec3 force; + + CUDA_CALLABLE inline static ForceAndEnergy zero() { + return {0.0, {0.0, 0.0, 0.0}}; + }; +}; + +/** + * Abstract implementation of a Pair Potential. + * Pair potentials are potentials which depend solely on the distance + * between two particles. These do not include multi-body potentials such as + * EAM + * + */ +struct PairPotential { + real m_rcutoffsq; + + PairPotential(real rcutoff) : m_rcutoffsq(rcutoff * rcutoff) {}; +#ifdef __CUDACC__ + CUDA_CALLABLE ~PairPotential(); +#else + virtual ~PairPotential() = 0; +#endif + + /** + * Calculate the force and energy for a specific atom pair based on a + * displacement vector r. + */ + CUDA_CALLABLE virtual ForceAndEnergy calc_force_and_energy(Vec3 r) = 0; +}; + +/** + * Calculate the Lennard-Jones energy and force for the current particle pair + * described by displacement vector r + */ +struct LennardJones : PairPotential { + real m_epsilon; + real m_sigma; + + CUDA_CALLABLE LennardJones(real sigma, real epsilon, real rcutoff) + : PairPotential(rcutoff), m_epsilon(epsilon), m_sigma(sigma) {}; + + CUDA_CALLABLE ForceAndEnergy calc_force_and_energy(Vec3 r) { + real rmagsq = r.squared_norm2(); + if (rmagsq < this->m_rcutoffsq && rmagsq > 0.0) { + real inv_rmag = 1 / std::sqrt(rmagsq); + + // Pre-Compute the terms (doing this saves on multiple devisions/pow + // function call) + real sigma_r = m_sigma * inv_rmag; + real sigma_r6 = sigma_r * sigma_r * sigma_r * sigma_r * sigma_r * sigma_r; + real sigma_r12 = sigma_r6 * sigma_r6; + + // Get the energy + real energy = 4.0 * m_epsilon * (sigma_r12 - sigma_r6); + + // Get the force vector + real force_mag = + 4.0 * m_epsilon * + (12.0 * sigma_r12 * inv_rmag - 6.0 * sigma_r6 * inv_rmag); + Vec3 force = r.scale(force_mag * inv_rmag); + + return {energy, force}; + + } else { + return ForceAndEnergy::zero(); + } + }; + + ~LennardJones() {}; +}; + +PairPotential::~PairPotential() {}; +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b8ed52a..48c2307 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,14 +4,13 @@ set(HEADER_FILES particle.hpp simulation.hpp box.hpp - pair_potentials.hpp + ) set(SOURCE_FILES - pair_potentials.cpp ) # The library contains header and source files. -add_library(${NAME}_lib +add_library(${NAME}_lib INTERFACE ${HEADER_FILES} ${SOURCE_FILES} ) diff --git a/src/pair_potentials.cpp b/src/pair_potentials.cpp deleted file mode 100644 index 19b7ef8..0000000 --- a/src/pair_potentials.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "pair_potentials.hpp" -#include - -PairPotential::~PairPotential() {}; -/** - * Calculate the Lennard-Jones energy and force for the current particle pair - * described by displacement vector r - */ -ForceAndEnergy LennardJones::calc_force_and_energy(Vec3 r) { - real rmagsq = r.squared_norm2(); - if (rmagsq < this->m_rcutoffsq && rmagsq > 0.0) { - real inv_rmag = 1 / std::sqrt(rmagsq); - - // Pre-Compute the terms (doing this saves on multiple devisions/pow - // function call) - real sigma_r = m_sigma * inv_rmag; - real sigma_r6 = sigma_r * sigma_r * sigma_r * sigma_r * sigma_r * sigma_r; - real sigma_r12 = sigma_r6 * sigma_r6; - - // Get the energy - real energy = 4.0 * m_epsilon * (sigma_r12 - sigma_r6); - - // Get the force vector - real force_mag = 4.0 * m_epsilon * - (12.0 * sigma_r12 * inv_rmag - 6.0 * sigma_r6 * inv_rmag); - Vec3 force = r.scale(force_mag * inv_rmag); - - return {energy, force}; - - } else { - return ForceAndEnergy::zero(); - } -}; diff --git a/src/pair_potentials.hpp b/src/pair_potentials.hpp deleted file mode 100644 index 04f64d4..0000000 --- a/src/pair_potentials.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef POTENTIALS_H -#define POTENTIALS_H - -#include "precision.hpp" -#include "vec3.h" - -/** - * Result struct for the Pair Potential - */ -struct ForceAndEnergy { - real energy; - Vec3 force; - - inline static ForceAndEnergy zero() { return {0.0, {0.0, 0.0, 0.0}}; }; -}; - -/** - * Abstract implementation of a Pair Potential. - * Pair potentials are potentials which depend solely on the distance - * between two particles. These do not include multi-body potentials such as - * EAM - * - */ -struct PairPotential { - real m_rcutoffsq; - - PairPotential(real rcutoff) : m_rcutoffsq(rcutoff * rcutoff) {}; - virtual ~PairPotential() = 0; - - /** - * Calculate the force and energy for a specific atom pair based on a - * displacement vector r. - */ - virtual ForceAndEnergy calc_force_and_energy(Vec3 r) = 0; -}; - -struct LennardJones : PairPotential { - real m_epsilon; - real m_sigma; - - LennardJones(real sigma, real epsilon, real rcutoff) - : PairPotential(rcutoff), m_epsilon(epsilon), m_sigma(sigma) {}; - - ForceAndEnergy calc_force_and_energy(Vec3 r); - - ~LennardJones() {}; -}; - -#endif diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 75a4347..c396ab7 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -5,5 +5,5 @@ add_executable(${NAME}_tests ) target_link_libraries(${NAME}_tests gtest gtest_main) -target_link_libraries(${NAME}_tests ${CMAKE_PROJECT_NAME}_lib) +target_link_libraries(${NAME}_tests ${CMAKE_PROJECT_NAME}_cuda_lib) add_test(NAME ${NAME}Tests COMMAND ${CMAKE_BINARY_DIR}/tests/unit_tests/${NAME}_tests) diff --git a/tests/unit_tests/test_potential.cpp b/tests/unit_tests/test_potential.cpp index 7bc0dcb..a94f022 100644 --- a/tests/unit_tests/test_potential.cpp +++ b/tests/unit_tests/test_potential.cpp @@ -1,4 +1,4 @@ -#include "pair_potentials.hpp" +#include "pair_potentials.cuh" #include "precision.hpp" #include "gtest/gtest.h" #include