Commit 044c378b authored by ESTERIE Pierre's avatar ESTERIE Pierre

First step with cmake, units, tools, basic components

parent e35676b5
...@@ -4,3 +4,9 @@ ...@@ -4,3 +4,9 @@
[submodule "inastemp"] [submodule "inastemp"]
path = inastemp path = inastemp
url = https://gitlab.inria.fr/coulaud/inastemp.git url = https://gitlab.inria.fr/coulaud/inastemp.git
[submodule "experimental/modules/morse_cmake"]
path = experimental/modules/morse_cmake
url = https://gitlab.inria.fr/solverstack/morse_cmake
[submodule "experimental/modules/xsimd"]
path = experimental/modules/xsimd
url = https://github.com/QuantStack/xsimd
This diff is collapsed.
set(CPACK_PACKAGE_VERSION_PATCH 0)
execute_process(
COMMAND git rev-list HEAD --count
OUTPUT_VARIABLE CPACK_PACKAGE_VERSION_PATCH
RESULT_VARIABLE RET
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
#string_TRIM(PATCH1 PATCH)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY "ON")
#
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENCE")
set(CPACK_PACKAGE_VERSION_MAJOR "${${CMAKE_PROJECT_NAME}_MAJOR_VERSION}")
set(CPACK_PACKAGE_VERSION_MINOR "${${CMAKE_PROJECT_NAME}_MINOR_VERSION}")
#
set(PACK_PACKAGE_VERSION "${${CMAKE_PROJECT_NAME}_VERSION}.${${CMAKE_PROJECT_NAME}_MINOR_VERSION}-${CPACK_PACKAGE_VERSION_PATCH}")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "SCALFMM-${${CMAKE_PROJECT_NAME}_MAJOR_VERSION}.${${CMAKE_PROJECT_NAME}_MINOR_VERSION}-${CPACK_PACKAGE_VERSION_PATCH}")
set(CPACK_SOURCE_IGNORE_FILES "\\\\.git;.DS_Store;.*~;/*.aux;/*.idx;/*.log;/*.out;/*.toc;/*.ilg;CMakeLists.txt.user;/.settings/")
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/Utils/;/Build*;/Obsolete/")
#
## This file should be placed in the root directory of your project.
## Then modify the CMakeLists.txt file in the root directory of your
## project to incorporate the testing dashboard.
## # The following are required to uses Dart and the Cdash dashboard
## ENABLE_TESTING()
## INCLUDE(CTest)
set(CTEST_PROJECT_NAME "ScalFMM")
set(CTEST_NIGHTLY_START_TIME "00:00:00 GMT")
set(CTEST_SUBMIT_URL "http://cdash.inria.fr/CDash/submit.php?project=scalfmm")
#--------------------------------------------------------------------
# BUILDNAME variable construction
# This variable will be used to set the build name which will appear
# on the Chameleon dashboard http://cdash.inria.fr/CDash/
#--------------------------------------------------------------------
# Start with the short system name, e.g. "Linux", "FreeBSD" or "Windows"
if(NOT BUILDNAME)
set(BUILDNAME "${CMAKE_SYSTEM_NAME}")
# Add i386 or amd64
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BUILDNAME "${BUILDNAME}-amd64")
else()
set(BUILDNAME "${BUILDNAME}-i386")
endif()
# Add compiler name
get_filename_component(CMAKE_CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER} NAME)
set(BUILDNAME "${BUILDNAME}-${CMAKE_CXX_COMPILER_NAME}")
# Add the build type, e.g. "Debug, Release..."
if(CMAKE_BUILD_TYPE)
set(BUILDNAME "${BUILDNAME}-${CMAKE_BUILD_TYPE}")
endif(CMAKE_BUILD_TYPE)
# Specific options of Scalfmm
if(SCALFMM_USE_SSE)
set(BUILDNAME "${BUILDNAME}-sse")
endif()
if(SCALFMM_USE_BLAS)
set(BUILDNAME "${BUILDNAME}-blas")
endif()
if(SCALFMM_USE_MPI)
set(BUILDNAME "${BUILDNAME}-mpi")
endif()
endif()
# Examples
#---------
# List of source files
set(source_tests_files
sandbox.cpp
)
# Add execs - 1 cpp = 1 exec
foreach(exec ${source_tests_files})
set(compile_exec TRUE)
get_filename_component( execname ${exec} NAME_WE )
foreach(fuse_key ${FUSE_DEP_AVAILABLE})
file(STRINGS "${exec}" lines_fuse REGEX "@FUSE_${fuse_key}")
if(lines_fuse AND NOT ${fuse_key} IN_LIST FUSE_LIST)
message( STATUS "This needs ${fuse_key} = ${exec}" )
set(compile_exec FALSE)
endif()
endforeach()
# Dependency are OK
if( compile_exec )
add_executable( ${execname} ${exec})
list(APPEND SCALFMM_EXAMPLES_TARGETS ${execname})
list(APPEND SCALFMM_TESTS_TARGETS ${execname})
set_target_properties(${execname} PROPERTIES ENABLE_EXPORTS TRUE
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BUILD_TYPE}
)
target_link_libraries( ${execname} ${CMAKE_PROJECT_NAME})
install(TARGETS ${execname} RUNTIME DESTINATION bin)
endif()
endforeach(exec)
add_custom_target(scalfmm_examples ALL DEPENDS ${SCALFMM_EXAMPLES_TARGETS})
//---------------------
// Experimental example
//---------------------
#include <string>
#include <vector>
#include <iostream>
#include <tuple>
#include <inria/tcli/help_descriptor.hpp>
#include <inria/tcli/tcli.hpp>
#include <scalfmm/container/particle_container.hpp>
namespace args
{
struct tree_height : inria::tcli::required_tag
{
inria::tcli::str_vec flags = {"--height", "-H"};
const char* description = "Tree height (or initial height in case of an adaptive tree).";
using type = int;
};
struct thread_count : inria::tcli::required_tag
{
inria::tcli::str_vec flags = {"--threads", "-t"};
const char* description = "Maximum thread count to be used.";
using type = int;
type def{1};
};
struct file : inria::tcli::required_tag
{
inria::tcli::str_vec flags = {"--input-file", "-fin"};
const char* description = "Input filename (.fma or .bfma).";
using type = std::string;
};
struct chunk_size
{
inria::tcli::str_vec flags = {"--group-size"};
const char* description = "Group tree chunk size.";
using type = int;
type def{250};
};
auto cli = inria::tcli::make_parser(
tree_height{}, thread_count{},
file{}, inria::tcli::help{},
chunk_size{}
);
} // namespace args
/**
* \brief Store the PerfTest program parameters.
*/
struct params {
int _tree_height{}; ///< Tree height.
int _nb_threads{}; ///< Maximum thread count (when used).
std::string _filename{}; ///< Particles file.
int _group_size{}; ///< Group tree group size
params() = default;
params(const decltype(args::cli)& cli)
{
_tree_height = cli.get<args::tree_height>();
_nb_threads = cli.get<args::thread_count>();
_filename = cli.get<args::file>();
_group_size = cli.get<args::chunk_size>();
}
};
using namespace scalfmm;
int main()
{
using particle_t = std::tuple<float,float,float,float>;
struct curve{};
using container_t = container::particle_container<particle_t, curve>;
return 0;
}
// --------------------------------
// See LICENCE file at project root
// File : particle_container.cpp
// --------------------------------
#ifndef SCALFMM_CONCEPTS_LIBRARY_HPP
#define SCALFMM_CONCEPTS_LIBRARY_HPP
namespace scalfmm::concepts
{
template<typename R, typename Enabler> struct require_impl;
template<typename R> struct require_impl<R, void> { using type = R; };
template<typename Return, typename... Ts>
struct require_check : require_impl<Return,std::void_t<Ts...>>
{};
template<typename From, typename To>
using Convertible = std::enable_if_t<std::is_convertible_v<From,To>>;
template<typename T>
using Arithmetic = std::enable_if_t<std::is_arithmetic_v<T>>;
template<typename T>
using Integral = std::enable_if_t<std::is_integral_v<T>>;
template<bool Condition>
using If = std::enable_if_t<Condition>;
} // end namespace scalfmm::concepts
// Pseudo require macro
#define requires(...) -> typename ::concept::require_check<__VA_ARGS__>::type
#endif // SCALFMM_CONCEPTS_LIBRARY_HPP
// See LICENCE file at project root
///
/// File generated by cmake
// Do not remove any line
///////////////////////////////////////////////////////
#ifndef SCALFMM_CONFIG_SCALFMM_CONFIG_HPP
#define SCALFMM_CONFIG_SCALFMM_CONFIG_HPP
// Uncomment the next line to use debug mode
#cmakedefine SCALFMM_USE_LOG
///////////////////////////////////////////////////////
// Blas
///////////////////////////////////////////////////////
#cmakedefine SCALFMM_USE_BLAS
#cmakedefine SCALFMM_USE_MKL_AS_BLAS
// Fortran Mangling
#cmakedefine SCALFMM_BLAS_ADD_
#cmakedefine SCALFMM_BLAS_UPCASE
#cmakedefine SCALFMM_BLAS_NOCHANGE
////////////////////////////////////////////////////////
// FFT
///////////////////////////////////////////////////////
#cmakedefine SCALFMM_USE_FFT
#cmakedefine SCALFMM_USE_MKL_AS_FFTW
#cmakedefine SCALFMM_USE_ESSL_AS_FFTW
//////////////////////////////////////////////////////
// MPI
///////////////////////////////////////////////////////
#cmakedefine SCALFMM_USE_MPI
///////////////////////////////////////////////////////
// Memory trace
///////////////////////////////////////////////////////
#cmakedefine SCALFMM_USE_MEM_STATS
///////////////////////////////////////////////////////
// CUDA
///////////////////////////////////////////////////////
#cmakedefine SCALFMM_USE_CUDA
///////////////////////////////////////////////////////
// OPENCL
///////////////////////////////////////////////////////
#cmakedefine SCALFMM_USE_OPENCL
///////////////////////////////////////////////////////
// STARPU
///////////////////////////////////////////////////////
#cmakedefine SCALFMM_USE_STARPU
#cmakedefine SCALFMM_DISABLE_NATIVE_OMP4
///////////////////////////////////////////////////////
// To control starpu config
///////////////////////////////////////////////////////
#cmakedefine SCALFMM_STARPU_USE_COMMUTE
#cmakedefine SCALFMM_STARPU_USE_REDUX
#cmakedefine SCALFMM_STARPU_USE_PRIO
#cmakedefine SCALFMM_STARPU_FORCE_NO_SCHEDULER
#cmakedefine SCALFMM_USE_STARPU_EXTRACT
#endif // CONFIG_H
#ifndef SCALFMM_SPACE_CURVE_HPP_
#define SCALFMM_SPACE_CURVE_HPP_
#include "Utils/FPoint.hpp"
/** Provides the corner traversal order of an N dimension hypercube
*
* The positions returned are array of booleans. Each boolean tells where
* to place the element in the binary grid.
*
* For instance, in 2D:
*
*
* __0__ __1__
* | | |
* 0| | X | pos(X) = [true, false]
* |_____|_____|
* | | |
* 1| | Y | pos(Y) = [true, true ]
* |_____|_____|
*
*
* \tparam Dim The hypercube dimension.
*/
template<std::size_t _Dim>
class FZCurve {
public:
/// Space dimension count
constexpr static const std::size_t Dim = _Dim;
/// Position type used
using position_t = FPoint<bool, Dim>;
/// Position count in the grid
constexpr static std::size_t pos_count = Fpow(2,Dim);
private:
/// Array of positions type
using position_array_t = std::array<position_t, pos_count>;
/// Array to cache the positions corresponding to indexes
static const position_array_t _positions;
/** Creates an array of positions to initialize #_positions */
static position_array_t create_array() noexcept {
position_array_t positions;
for(std::size_t i = 0; i < pos_count; ++i) {
for(std::size_t j = Dim-1, k = i; k != 0; --j, k >>=1) {
positions[i][j] = k % 2;
}
}
return positions;
}
public:
/** The position corresponding to an index
*
* \param idx The index of the point in the space filling curve
* \return The position corresponding to the space filling curve index
*/
static position_t position(std::size_t idx) noexcept {
return _positions[idx];
}
/** Index in the space filling curve of a boolean position
*
* \param p The position
* \return The space filling curve index corresponding to the position
*/
static std::size_t index(const position_t& p) noexcept {
std::size_t idx = 0;
for(auto i : p) {
idx <<= 1;
idx += i;
}
return idx;
}
/** Index in the space filling curve of a real position relative to the center of the hypercube
*
* \param p The position
* \param center The center of the hypercube
* \return The space filling curve index corresponding to the position
*/
template<typename FReal>
static std::size_t index(const FPoint<FReal, Dim>& p, const FPoint<FReal, Dim>& center) noexcept {
std::size_t idx = 0;
for(std::size_t i = 0; i < Dim; ++i) {
idx <<= 1;
idx += p[i] > center[i];
}
return idx;
}
};
// Initialization of static variable
template<std::size_t _Dim>
const typename FZCurve<_Dim>::position_array_t FZCurve<_Dim>::_positions(FZCurve<_Dim>::create_array());
#endif
// --------------------------------
// See LICENCE file at project root
// File : particle_container.hpp
// --------------------------------
#ifndef SCALFMM_CONTAINER_PARTICLE_CONTAINER_HPP
#define SCALFMM_CONTAINER_PARTICLE_CONTAINER_HPP
#include <xsimd/config/xsimd_align.hpp>
#include <scalfmm/memory/aligned_allocator.hpp>
#include <scalfmm/container/variadic_container.hpp>
namespace scalfmm::container
{
//template<typename Tuple, typename Curve, typename Allocator = memory::aligned_allocator<Tuple, XSIMD_DEFAULT_ALIGNMENT>>
//class particle_container;
template<typename Tuple, typename Curve, typename Allocator = memory::aligned_allocator<XSIMD_DEFAULT_ALIGNMENT, Tuple>>
class particle_container : public variadic_container<Allocator, Tuple>
{
};
}
#endif // SCALFMM_MEMORY_PARTICLE_CONTAINER_HPP
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
//==============================================================================
// This file is a test for a clean scalfmm code.
// It's a attempt to a cleaner and more expressive code for the user.
// Author : Pierre Esterie
//==============================================================================
#ifndef SCALFMM_META_IS_VALID_HPP
#define SCALFMM_META_IS_VALID_HPP
#include <type_traits>
namespace scalfmm::meta
{
namespace detail
{
template <typename F, typename... Args
, typename = decltype(std::declval<F &&>()(std::declval<Args &&>()...))>
constexpr auto is_valid_impl(int) { return std::true_type{}; }
template <typename F, typename... Args>
constexpr auto is_valid_impl(...) { return std::false_type{}; }
template <typename F>
struct is_valid_fun
{
template <typename... Args>
constexpr auto operator()(Args &&...) const
{
return is_valid_impl<F, Args &&...>(int{});
}
};
} // namespace detail
struct is_valid_t
{
template <typename F>
constexpr auto operator()(F&&) const
{ return detail::is_valid_fun<F&&>{}; }
template <typename F, typename ...Args>
constexpr auto operator()(F&&, Args&& ...) const
{ return detail::is_valid_impl<F&&, Args&&...>(int{}); }
};
template <typename T>
struct type_w
{
using type = T;
};
template <typename T>
constexpr type_w<T> type_c{};
constexpr is_valid_t is_valid{};
} // namespace scalfmm::meta
#endif
//==============================================================================
// This file is a test for a clean scalfmm code.
// It's a attempt to a cleaner and more expressive code for the user.
// Author : Pierre Esterie
//==============================================================================
#ifndef SCALFMM_META_TRAITS_HPP
#define SCALFMM_META_TRAITS_HPP
#include <scalfmm/meta/is_valid.hpp>
namespace scalfmm::meta
{
// Equality comparable traits
namespace details
{
inline constexpr auto is_equality_comparable_impl = meta::is_valid([](auto&& a, auto&& b)->decltype(a==b){});
inline constexpr auto has_begin = meta::is_valid([](auto&& a)->decltype(a.begin()){});
inline constexpr auto has_end = meta::is_valid([](auto&& a)->decltype(a.end()){});
}
template<class T>
struct is_equality_comparable
{
static const bool value = decltype(details::is_equality_comparable_impl(T{},T{}))::value;
};
template<class T>
struct has_begin { static const bool value = decltype(details::has_begin(T{}))::value; };
template<typename T>
struct has_end { static const bool value = decltype(details::has_end(T{}))::value; };
template<class T>
struct has_range_interface { static const bool value = has_begin<T>::value && has_end<T>::value; };
template< class, class = std::void_t<> >
struct is_float : std::false_type { };
// specialization recognizes types that do have a nested ::type member:
template< class T >
struct is_float<T, std::void_t<float>> : std::true_type { };
template< class, class = std::void_t<> >
struct is_double : std::false_type { };
// specialization recognizes types that do have a nested ::type member:
template< class T >
struct is_double<T, std::void_t<double>> : std::true_type { };
} // namespace scalfmm::meta
#endif
This diff is collapsed.
// == file : colorized.hpp
// == author : Pierre Esterie
#ifndef SCALFMM_TOOLS_COLORIZED_HPP
#define SCALFMM_TOOLS_COLORIZED_HPP
// ESC[ 38;5;<n> m Select foreground color
// ESC[ 48;5;<n> m Select background color
// 0- 7: standard colors (as in ESC [ 30–37 m)
// 8- 15: high intensity colors (as in ESC [ 90–97 m)
// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
// 232-255: grayscale from black to white in 24 steps
#include <ostream>
#include <string>
namespace scalfmm::colors
{
inline constexpr int get_color(const int R, const int G, const int B)
{
return (16+36*R+6*G+B);
}
template<const int R, const int G, const int B>
using are_less_than_6 = std::enable_if<R<6 && G<6 && B<6>;
template<const int R, const int G, const int B, bool Background = false, typename Enable = void>
struct color
{ static_assert(R<6 && G<6 && B<6, "R,G & B must be < 6 !"); };
template<const int R, const int G, const int B, bool Background>
struct color<R, G, B, Background, typename are_less_than_6<R, G, B>::type>
: std::string
{
constexpr color() : std::string("\033[38;5;"+std::to_string(get_color(R,G,B))+"m") {}
};
template<const int R, const int G, const int B>
struct color<R, G, B, true, typename are_less_than_6<R, G, B>::type>
: std::string
{
constexpr color() : std::string("\033[48;5;"+std::to_string(get_color(R,G,B))+"m") {}
};
template<const int R, const int G, const int B>
using on_color = color<R, G, B, true>;
template<const int Code>
struct code : std::string
{
constexpr code() : std::string("\033["+std::to_string(Code)+"m") {}
};
static auto black = code<30>{};
static auto red = code<31>{};
static auto green = code<32>{};
static auto yellow = code<33>{};
static auto blue = code<34>{};
static auto magenta = code<35>{};
static auto cyan = code<36>{};
static auto white = code<37>{};
static auto on_black = code<41>{};
static auto on_red = code<41>{};
static auto on_green = code<42>{};
static auto on_yellow = code<43>{};
static auto on_blue = code<44>{};
static auto on_magenta = code<45>{};
static auto on_cyan = code<46>{};
static auto on_white = code<47>{};
static auto reset = code<0>{};
static auto bold = code<1>{};
static auto faint = code<2>{};
static auto italic = code<3>{};
static auto underline = code<4>{};
static auto underline_off = code<24>{};
static auto slow_blink = code<5>{};
static auto rapid_blink = code<6>{};
static auto blink_off = code<25>{};
static auto reverse = code<7>{};
static auto overlined = code<53>{};
}
#endif
This diff is collapsed.
// == file : progress_bar.hpp
// == author : Pierre Esterie
#ifndef TIMIT_UTILS_PROGRESS_BAR_HPP
#define TIMIT_UTILS_PROGRESS_BAR_HPP
#include <sstream>
#include <memory>
#include <thread>
#include <iostream>
namespace timit { namespace utils
{
template<typename Object>
int progress(Object& obj);
struct progress_bar {
std::stringstream sstr{};
std::thread t;
template<typename Object>
void follow(Object& obj) {
this->t = std::thread(
[this, &obj]() {
bool run = true;
while(run) {
sstr.str("");
sstr.clear();
sstr.precision(4);
int p = timit::utils::progress(obj);
std::cout << p << std::endl;
sstr << "[";
for(int i = 0; i < 100; ++i)
{
sstr << (i < p ? "\u2038" : " ");
}
sstr << "] " << p << "% ";
std::cout << '\r' << sstr.str() << std::flush;
run = p < 100;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
});
}
void finish() {
this->t.join();
}
};
}}
#endif
// --------------------------------
// See LICENCE file at project root