diff --git a/cmake/AkantuExtraCompilationProfiles.cmake b/cmake/AkantuExtraCompilationProfiles.cmake
index 9a3b7c819..b8e18096e 100644
--- a/cmake/AkantuExtraCompilationProfiles.cmake
+++ b/cmake/AkantuExtraCompilationProfiles.cmake
@@ -1,114 +1,121 @@
#===============================================================================
# Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu 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 Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see .
#
#===============================================================================
option (FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." FALSE)
mark_as_advanced(FORCE_COLORED_OUTPUT)
if(FORCE_COLORED_OUTPUT)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_flags(cxx "-fcolor-diagnostics")
else()
add_flags(cxx "-fdiagnostics-color=always")
endif()
endif()
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DAKANTU_NDEBUG"
CACHE STRING "Flags used by the compiler during release builds" FORCE)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT} -ggdb3"
CACHE STRING "Flags used by the compiler during debug builds" FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT} -ggdb3"
CACHE STRING "Flags used by the compiler during debug builds" FORCE)
endif()
function(declare_compilation_profile name)
include(CMakeParseArguments)
cmake_parse_arguments(_args
"" "COMPILER;LINKER;DOC" "" ${ARGN})
string(TOUPPER "${name}" _u_name)
if(NOT _args_DOC)
string(TOLOWER "${name}" _args_DOC)
endif()
if(NOT _args_COMPILER)
message(FATAL_ERROR "declare_compilation_profile: you should at least give COMPILER flags")
endif()
if(NOT _args_LINKER)
set(_args_LINKER ${_args_COMPILER})
endif()
foreach(_flag CXX C Fortran SHARED_LINKER EXE_LINKER)
set(_stage "compiler")
set(_flags ${_args_COMPILER})
if(_stage MATCHES ".*LINKER")
set(_stage "linker")
set(_flags ${_args_LINKER})
endif()
set(CMAKE_${_flag}_FLAGS_${_u_name} ${_flags}
CACHE STRING "Flags used by the ${_stage} during coverage builds" FORCE)
mark_as_advanced(CMAKE_${_flag}_FLAGS_${_u_name})
endforeach()
endfunction()
# Profiling
declare_compilation_profile(PROFILING
COMPILER "-g -ggdb3 -pg -DNDEBUG -DAKANTU_NDEBUG -O3")
# Valgrind
declare_compilation_profile(VALGRIND
COMPILER "-g -ggdb3 -DNDEBUG -DAKANTU_NDEBUG -O3")
# Coverage
declare_compilation_profile(COVERAGE
COMPILER "-g -ggdb3 -DNDEBUG -DAKANTU_NDEBUG -O2 --coverage")
# Sanitize the code
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.2") OR
CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(_blacklist " -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/cmake/sanitize-blacklist.txt")
endif()
declare_compilation_profile(SANITIZE
COMPILER "-g -ggdb3 -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer${_blacklist}")
declare_compilation_profile(SANITIZE_DEBUG
COMPILER "-g -ggdb3 -DNDEBUG -DAKANTU_NDEBUG -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer${_blacklist}")
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
declare_compilation_profile(SANITIZEMEMORY
COMPILER "-g -ggdb3 -O2 -fPIE -fsanitize=memory -fsanitize-memory-track-origins -fsanitize-recover=all -fno-omit-frame-pointer -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/cmake/sanitize-blacklist.txt"
DOC "\"sanitize memory\"")
endif()
string(TOLOWER "${CMAKE_BUILD_TYPE}" _cmake_build_type_lower)
if (_cmake_build_type_lower MATCHES "valgrind")
find_program(VALGRIND_EXECUTABLE valgrind)
endif()
+
+option(AKANTU_USE_CCACHE "Use ccache if available to build akantu" ON)
+
+if (AKANTU_USE_CCACHE)
+ find_program(CCACHE_EXECUTABLE ccache)
+ set(AKANTU_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}")
+endif()
diff --git a/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc b/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc
index e805b5f61..8d975d462 100644
--- a/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc
+++ b/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc
@@ -1,78 +1,78 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see .
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include
#include
/* -------------------------------------------------------------------------- */
using namespace akantu;
class SineBoundary : public BC::Dirichlet::DirichletFunctor {
public:
SineBoundary(Real amp, Real phase, BC::Axis ax = _x)
: DirichletFunctor(ax), amplitude(amp), phase(phase) {}
public:
- inline void operator()(__attribute__((unused)) UInt node,
- Vector & flags, Vector & primal,
- const Vector & coord) const {
+ inline void operator()(Idx /*node*/, VectorProxy & flags,
+ VectorProxy & primal,
+ const VectorProxy & coord) {
DIRICHLET_SANITY_CHECK;
flags(axis) = true;
primal(axis) = -amplitude * std::sin(phase * coord(1));
}
protected:
Real amplitude;
Real phase;
};
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("fine_mesh.msh");
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull();
/// boundary conditions
Vector traction{.2, .2};
model.applyBC(SineBoundary(.2, 10., _x), "Fixed_x");
model.applyBC(BC::Dirichlet::FixedValue(0., _y), "Fixed_y");
model.applyBC(BC::Neumann::FromTraction(traction), "Traction");
// output a paraview file with the boundary conditions
model.setBaseName("plate");
model.addDumpFieldVector("displacement");
model.addDumpFieldVector("external_force");
model.addDumpField("blocked_dofs");
model.dump();
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc b/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
index eb5110fb7..3808c9b4b 100644
--- a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
+++ b/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
@@ -1,141 +1,141 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see .
*/
/* -------------------------------------------------------------------------- */
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
#include
/* -------------------------------------------------------------------------- */
using namespace akantu;
/* -------------------------------------------------------------------------- */
class Velocity : public BC::Dirichlet::DirichletFunctor {
public:
explicit Velocity(SolidMechanicsModel & model, Real vel, BC::Axis ax = _x)
: DirichletFunctor(ax), model(model), vel(vel) {
disp = vel * model.getTimeStep();
}
public:
- inline void operator()(UInt node, Vector & /*flags*/,
- Vector & disp,
- const Vector & coord) const {
+ inline void operator()(Idx node, VectorProxy & /*flags*/,
+ VectorProxy & disp,
+ const VectorProxy & coord) {
Real sign = std::signbit(coord(axis)) ? -1. : 1.;
disp(axis) += sign * this->disp;
model.getVelocity()(node, axis) = sign * vel;
}
private:
SolidMechanicsModel & model;
Real vel, disp;
};
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
const Int spatial_dimension = 2;
const Int max_steps = 1000;
Mesh mesh(spatial_dimension);
mesh.read("square.msh");
SolidMechanicsModelCohesive model(mesh);
MaterialCohesiveRules rules{{{"btop", "bbottom"}, "tg_cohesive"},
{{"btop", "btop"}, "ig_cohesive"},
{{"bbottom", "bbottom"}, "ig_cohesive"}};
/// model initialization
auto cohesive_material_selector =
std::make_shared(model, rules);
auto bulk_material_selector =
std::make_shared>("physical_names",
model);
auto && current_selector = model.getMaterialSelector();
cohesive_material_selector->setFallback(bulk_material_selector);
bulk_material_selector->setFallback(current_selector);
model.setMaterialSelector(cohesive_material_selector);
model.initFull(_analysis_method = _explicit_lumped_mass,
_is_extrinsic = true);
Real time_step = model.getStableTimeStep() * 0.05;
model.setTimeStep(time_step);
std::cout << "Time step: " << time_step << std::endl;
model.assembleMassLumped();
auto & position = mesh.getNodes();
auto & velocity = model.getVelocity();
model.applyBC(BC::Dirichlet::FlagOnly(_y), "top");
model.applyBC(BC::Dirichlet::FlagOnly(_y), "bottom");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "left");
model.applyBC(BC::Dirichlet::FlagOnly(_x), "right");
model.setBaseName("extrinsic");
model.addDumpFieldVector("displacement");
model.addDumpField("velocity");
model.addDumpField("acceleration");
model.addDumpField("internal_force");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpField("material_index");
model.dump();
/// initial conditions
Real loading_rate = 0.1;
// bar_height = 2
Real VI = loading_rate * 2 * 0.5;
for (auto && data : zip(make_view(position, spatial_dimension),
make_view(velocity, spatial_dimension))) {
std::get<1>(data) = loading_rate * std::get<0>(data);
}
model.dump();
Velocity vely(model, VI, _y);
Velocity velx(model, VI, _x);
/// Main loop
for (Int s = 1; s <= max_steps; ++s) {
model.applyBC(vely, "top");
model.applyBC(vely, "bottom");
model.applyBC(velx, "left");
model.applyBC(velx, "right");
model.checkCohesiveStress();
model.solveStep();
if (s % 10 == 0) {
model.dump();
std::cout << "passing step " << s << "/" << max_steps << std::endl;
}
}
return 0;
}
diff --git a/examples/phase_field/phase_field_notch.cc b/examples/phase_field/phase_field_notch.cc
index 9a9a6a88d..18371775a 100644
--- a/examples/phase_field/phase_field_notch.cc
+++ b/examples/phase_field/phase_field_notch.cc
@@ -1,128 +1,126 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see .
*/
/* -------------------------------------------------------------------------- */
#include "coupler_solid_phasefield.hh"
#include "group_manager.hh"
#include "non_linear_solver.hh"
#include "phase_field_element_filter.hh"
#include "phase_field_model.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include
#include
#include
/* -------------------------------------------------------------------------- */
using namespace akantu;
using clk = std::chrono::high_resolution_clock;
using second = std::chrono::duration;
using millisecond = std::chrono::duration;
const Int spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material_notch.dat", argc, argv);
// create mesh
Mesh mesh(spatial_dimension);
mesh.read("square_notch.msh");
CouplerSolidPhaseField coupler(mesh);
auto & model = coupler.getSolidMechanicsModel();
auto & phase = coupler.getPhaseFieldModel();
model.initFull(_analysis_method = _static);
auto && mat_selector =
std::make_shared>("physical_names",
model);
model.setMaterialSelector(mat_selector);
auto && selector = std::make_shared>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
model.applyBC(BC::Dirichlet::FixedValue(0., _y), "bottom");
model.applyBC(BC::Dirichlet::FixedValue(0., _x), "left");
model.setBaseName("phase_notch");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpFieldVector("displacement");
model.addDumpField("damage");
model.dump();
Int nbSteps = 1000;
Real increment = 6e-6;
Int nb_staggered_steps = 5;
auto start_time = clk::now();
for (Int s = 1; s < nbSteps; ++s) {
if (s >= 500) {
increment = 2e-6;
nb_staggered_steps = 10;
}
if (s % 200 == 0) {
constexpr char wheel[] = "/-\\|";
auto elapsed = clk::now() - start_time;
auto time_per_step = elapsed / s;
std::cout << "\r[" << wheel[(s / 10) % 4] << "] " << std::setw(5) << s
<< "/" << nbSteps << " (" << std::setprecision(2) << std::fixed
<< std::setw(8) << millisecond(time_per_step).count()
<< "ms/step - elapsed: " << std::setw(8)
<< second(elapsed).count() << "s - ETA: " << std::setw(8)
<< second((nbSteps - s) * time_per_step).count() << "s)"
<< std::string(' ', 20) << std::flush;
}
model.applyBC(BC::Dirichlet::IncrementValue(increment, _y), "top");
for (Idx i = 0; i < nb_staggered_steps; ++i) {
coupler.solve();
}
- auto energy = phase.getEnergy();
-
if (s % 100 == 0) {
model.dump();
}
}
Real damage_limit = 0.15;
auto global_nb_clusters = mesh.createClusters(
spatial_dimension, "crack", PhaseFieldElementFilter(phase, damage_limit));
auto nb_fragment = mesh.getNbElementGroups(spatial_dimension);
model.dumpGroup("crack_0");
std::cout << std::endl;
std::cout << "Nb clusters: " << global_nb_clusters << std::endl;
std::cout << "Nb fragments: " << nb_fragment << std::endl;
finalize();
return EXIT_SUCCESS;
}
diff --git a/python/py_boundary_conditions.cc b/python/py_boundary_conditions.cc
index fd270deed..3f6acbc06 100644
--- a/python/py_boundary_conditions.cc
+++ b/python/py_boundary_conditions.cc
@@ -1,118 +1,120 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see .
*/
/* -------------------------------------------------------------------------- */
#include "py_boundary_conditions.hh"
-#include "py_aka_array.hh"
#include "py_akantu_pybind11_compatibility.hh"
/* -------------------------------------------------------------------------- */
#include
/* -------------------------------------------------------------------------- */
+#include
#include
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
namespace akantu {
namespace {
/* ------------------------------------------------------------------------ */
template
class PyDirichletFunctor : public daughter {
public:
/* Inherit the constructors */
using daughter::daughter;
/* Trampoline (need one for each virtual function) */
- void operator()(Int node, Vector & flags, Vector & primal,
- const Vector & coord) const override {
+ void operator()(Int node, VectorProxy & flags,
+ VectorProxy & primal,
+ const VectorProxy & coord) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_NAME(void, daughter, "__call__", operator(), node,
flags, primal, coord);
}
};
/* ------------------------------------------------------------------------ */
template
class PyNeumannFunctor : public daughter {
public:
/* Inherit the constructors */
using daughter::daughter;
/* Trampoline (need one for each virtual function) */
- void operator()(const IntegrationPoint & quad_point, Vector & dual,
- const Vector & coord,
- const Vector & normals) const override {
+ void operator()(const IntegrationPoint & quad_point,
+ VectorProxy & dual,
+ const VectorProxy & coord,
+ const VectorProxy & normals) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE_NAME(void, daughter, "__call__", operator(),
quad_point, dual, coord, normals);
}
};
/* ------------------------------------------------------------------------ */
template
decltype(auto) register_dirichlet_functor(py::module mod, const char * name,
Constructor && cons) {
py::class_,
BC::Dirichlet::DirichletFunctor>(mod, name)
.def(cons);
}
/* ------------------------------------------------------------------------ */
template
decltype(auto) register_neumann_functor(py::module mod, const char * name,
Constructor && cons) {
py::class_, BC::Neumann::NeumannFunctor>(
mod, name)
.def(cons);
}
} // namespace
/* -------------------------------------------------------------------------- */
void register_boundary_conditions(py::module & mod) {
py::class_(mod, "BCFunctor");
py::class_,
BC::Functor>(mod, "DirichletFunctor")
.def(py::init())
.def(py::init());
py::class_, BC::Functor>(
mod, "NeumannFunctor")
.def(py::init());
register_dirichlet_functor(
mod, "FixedValue", py::init());
register_dirichlet_functor(
mod, "IncrementValue", py::init());
register_dirichlet_functor(
mod, "Increment", py::init &>());
register_neumann_functor(
mod, "FromHigherDim", py::init &>());
register_neumann_functor(
mod, "FromSameDim", py::init &>());
register_neumann_functor(mod, "FreeBoundary",
py::init());
}
} // namespace akantu
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bb43e03c2..5dd68a051 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,241 +1,246 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu 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 Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see .
#
#===============================================================================
#===============================================================================
# Package Management
#===============================================================================
package_get_all_source_files(
AKANTU_LIBRARY_SRCS
AKANTU_LIBRARY_PUBLIC_HDRS
AKANTU_LIBRARY_PRIVATE_HDRS
)
package_get_all_include_directories(
AKANTU_LIBRARY_INCLUDE_DIRS
)
package_get_all_external_informations(
PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR
INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR
LIBRARIES AKANTU_EXTERNAL_LIBRARIES
)
package_get_all_compilation_flags(CXX _cxx_flags)
set(AKANTU_EXTRA_CXX_FLAGS
"${_cxx_flags}" CACHE STRING "Extra flags defined by loaded packages" FORCE)
mark_as_advanced(AKANTU_EXTRA_CXX_FLAGS)
foreach(src_ ${AKANTU_SPIRIT_SOURCES})
set_property(SOURCE ${src_} PROPERTY COMPILE_FLAGS "-g0 -Werror")
endforeach()
list(APPEND AKANTU_LIBRARY_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}")
set(AKANTU_INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR} ${AKANTU_LIBRARY_INCLUDE_DIRS}
CACHE INTERNAL "Internal include directories to link with Akantu as a subproject")
#===========================================================================
# configurations
#===========================================================================
package_get_all_material_includes(AKANTU_MATERIAL_INCLUDES)
package_get_all_material_lists(AKANTU_MATERIAL_LISTS)
configure_file(model/solid_mechanics/material_list.hh.in
"${CMAKE_CURRENT_BINARY_DIR}/material_list.hh" @ONLY)
configure_file(common/aka_config.hh.in
"${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh" @ONLY)
list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS
"${CMAKE_CURRENT_BINARY_DIR}/material_list.hh"
"${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh")
configure_file(common/aka_config.cc.in
"${CMAKE_CURRENT_BINARY_DIR}/aka_config.cc" @ONLY)
list(APPEND AKANTU_LIBRARY_SRCS
"${CMAKE_CURRENT_BINARY_DIR}/aka_config.cc")
#===============================================================================
# Debug infos
#===============================================================================
set(AKANTU_GDB_DIR ${PROJECT_SOURCE_DIR}/cmake)
if(UNIX AND NOT APPLE)
string(TOUPPER "${CMAKE_BUILD_TYPE}" _u_build_type)
if(_u_build_type STREQUAL "DEBUG" OR _u_build_type STREQUAL "RELWITHDEBINFO")
configure_file(${PROJECT_SOURCE_DIR}/cmake/libakantu-gdb.py.in
"${PROJECT_BINARY_DIR}/libakantu-gdb.py"
@ONLY)
configure_file(${PROJECT_SOURCE_DIR}/cmake/akantu-debug.cc.in
"${PROJECT_BINARY_DIR}/akantu-debug.cc" @ONLY)
list(APPEND AKANTU_LIBRARY_SRCS ${PROJECT_BINARY_DIR}/akantu-debug.cc)
endif()
else()
find_program(GDB_EXECUTABLE gdb)
if(GDB_EXECUTABLE)
execute_process(COMMAND
${GDB_EXECUTABLE} --batch -x "${PROJECT_SOURCE_DIR}/cmake/gdb_python_path"
OUTPUT_VARIABLE AKANTU_PYTHON_GDB_DIR
ERROR_QUIET
RESULT_VARIABLE _res)
if(_res EQUAL 0 AND UNIX)
set(GDB_USER_CONFIG $ENV{HOME}/.gdb/auto-load)
file(MAKE_DIRECTORY ${GDB_USER_CONFIG})
configure_file(${PROJECT_SOURCE_DIR}/cmake/libakantu-gdb.py.in
"${GDB_USER_CONFIG}/${CMAKE_SHARED_LIBRARY_PREFIX}akantu${CMAKE_SHARED_LIBRARY_SUFFIX}.${AKANTU_VERSION}-gdb.py"
@ONLY)
endif()
endif()
endif()
#===============================================================================
# GIT info
#===============================================================================
#include(AkantuBuildOptions)
#git_version_info(akantu_git_info ALL
# OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/akantu_git_info.hh
# )
#list(APPEND AKANTU_LIBRARY_SRCS ${CMAKE_CURRENT_BINARY_DIR}/akantu_git_info.hh)
#===============================================================================
# Library generation
#===============================================================================
add_library(akantu ${AKANTU_LIBRARY_SRCS})
target_include_directories(akantu
PRIVATE $
INTERFACE $
)
# small trick for build includes in public
set_property(TARGET akantu APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
$)
target_include_directories(akantu SYSTEM
PUBLIC ${AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR}
)
target_include_directories(akantu SYSTEM
PRIVATE ${AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR}
)
target_link_libraries(akantu PUBLIC ${AKANTU_EXTERNAL_LIBRARIES})
separate_arguments(_separated_cxx_flags UNIX_COMMAND ${_cxx_flags})
target_compile_options(akantu PUBLIC ${_separated_cxx_flags})
if(AKANTU_LIBRARY_PROPERTIES)
set_target_properties(akantu
PROPERTIES ${AKANTU_LIBRARY_PROPERTIES} # this contains the version
)
endif()
if(NOT AKANTU_SHARED)
set_property(TARGET akantu PROPERTY
POSITION_INDEPENDENT_CODE ${AKANTU_POSITION_INDEPENDENT})
endif()
if(AKANTU_LIBRARY_PUBLIC_HDRS)
set_property(TARGET akantu PROPERTY PUBLIC_HEADER ${AKANTU_LIBRARY_PUBLIC_HDRS})
endif()
if(AKANTU_LIBRARY_PRIVATE_HDRS)
set_property(TARGET akantu PROPERTY PRIVATE_HEADER ${AKANTU_LIBRARY_PRIVATE_HDRS})
endif()
target_compile_features(akantu PUBLIC cxx_std_${AKANTU_CXX_STANDARD})
set_target_properties(akantu
PROPERTIES CXX_STANDARD ${AKANTU_CXX_STANDARD})
+if (AKANTU_COMPILER_LAUNCHER)
+ set_target_properties(akantu
+ PROPERTIES CXX_COMPILER_LAUNCHER ${AKANTU_COMPILER_LAUNCHER})
+endif()
+
package_get_all_extra_dependencies(_extra_target_dependencies)
if(_extra_target_dependencies)
# This only adding todo: find a solution for when a dependency was add the is removed...
add_dependencies(akantu ${_extra_target_dependencies})
endif()
package_get_all_export_list(AKANTU_EXPORT_LIST)
list(APPEND AKANTU_EXPORT_LIST akantu)
# TODO separate public from private headers
install(TARGETS akantu
EXPORT ${AKANTU_TARGETS_EXPORT}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Akantu_runtime
# NAMELINK_ONLY
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
# COMPONENT Akantu_development
# NAMELINK_SKIP Akantu_development
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Akantu_runtime
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT Akantu_runtime
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/akantu/
COMPONENT Akantu_development
)
if("${AKANTU_TARGETS_EXPORT}" STREQUAL "AkantuTargets")
install(EXPORT AkantuTargets
DESTINATION lib/cmake/${PROJECT_NAME}
COMPONENT dev)
#Export for build tree
export(EXPORT AkantuTargets
FILE "${CMAKE_BINARY_DIR}/AkantuTargets.cmake")
export(PACKAGE Akantu)
endif()
#===============================================================================
# Adding module names for debug
package_get_all_packages(_pkg_list)
foreach(_pkg ${_pkg_list})
_package_get_real_name(${_pkg} _pkg_name)
_package_get_source_files(${_pkg} _srcs _public_hdrs _private_hdrs)
string(TOLOWER "${_pkg_name}" _l_package_name)
set_property(SOURCE ${_srcs} ${_public_hdrs} ${_private_hdrs}
APPEND PROPERTY COMPILE_DEFINITIONS AKANTU_MODULE=${_l_package_name})
endforeach()
# print out the list of materials
generate_material_list()
register_target_to_tidy(akantu)
register_tidy_all(${AKANTU_LIBRARY_SRCS})
register_code_to_format(
${AKANTU_LIBRARY_SRCS}
${AKANTU_LIBRARY_PUBLIC_HDRS}
${AKANTU_LIBRARY_PRIVATE_HDRS}
)
cmake_policy(SET CMP0069 NEW)
include(CheckIPOSupported)
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_error LANGUAGES CXX)
if(ipo_supported)
message(STATUS "IPO/LTO enabled")
set_property(TARGET akantu PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
message(STATUS "IPO/LTO not supported: <${ipo_error}>")
endif()
diff --git a/src/common/aka_array.hh b/src/common/aka_array.hh
index 882256acd..30220ca0a 100644
--- a/src/common/aka_array.hh
+++ b/src/common/aka_array.hh
@@ -1,417 +1,411 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see .
*/
/* -------------------------------------------------------------------------- */
#include "aka_common.hh"
#include "aka_types.hh"
#include "aka_view_iterators.hh"
/* -------------------------------------------------------------------------- */
#include
#include
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_ARRAY_HH_
#define AKANTU_ARRAY_HH_
namespace akantu {
/// class that afford to store vectors in static memory
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
class ArrayBase {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using size_type = Int;
explicit ArrayBase(const ID & id = "") : id(id) {}
ArrayBase(const ArrayBase & other, const ID & id = "") {
this->id = (id.empty()) ? other.id : id;
}
ArrayBase(ArrayBase && other) = default;
ArrayBase & operator=(const ArrayBase & other) = default;
ArrayBase & operator=(ArrayBase && other) noexcept = default;
virtual ~ArrayBase() = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// get the amount of space allocated in bytes
virtual Int getMemorySize() const = 0;
// changed empty to match std::vector empty
[[nodiscard]] inline bool empty() const { return size_ == 0; }
/// function to print the content of the class
virtual void printself(std::ostream & stream, int indent = 0) const = 0;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// Get the Size of the Array
[[nodiscard]] decltype(auto) size() const { return size_; }
/// Get the number of components
[[nodiscard]] decltype(auto) getNbComponent() const { return nb_component; }
/// Get the name of the array
AKANTU_GET_MACRO_AUTO(ID, id);
/// Set the name of th array
AKANTU_SET_MACRO(ID, id, const ID &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// id of the vector
ID id;
/// the size used
Int size_{0};
/// number of components
Int nb_component{1};
};
/* -------------------------------------------------------------------------- */
/* Memory handling layer */
/* -------------------------------------------------------------------------- */
enum class ArrayAllocationType {
_default,
_pod,
};
template
struct ArrayAllocationTrait
: public std::conditional_t<
aka::is_scalar::value,
std::integral_constant,
std::integral_constant> {};
/* -------------------------------------------------------------------------- */
template ::value>
class ArrayDataLayer : public ArrayBase {
public:
using value_type = T;
using size_type = typename ArrayBase::size_type;
using reference = value_type &;
using pointer_type = value_type *;
using const_reference = const value_type &;
public:
~ArrayDataLayer() override = default;
/// Allocation of a new vector
explicit ArrayDataLayer(Int size = 0, Int nb_component = 1,
const ID & id = "");
/// Allocation of a new vector with a default value
ArrayDataLayer(Int size, Int nb_component, const_reference value,
const ID & id = "");
/// Copy constructor (deep copy)
ArrayDataLayer(const ArrayDataLayer & vect, const ID & id = "");
/// Copy constructor (deep copy)
explicit ArrayDataLayer(const std::vector & vect);
// copy operator
ArrayDataLayer & operator=(const ArrayDataLayer & other);
// move constructor
ArrayDataLayer(ArrayDataLayer && other) noexcept = default;
// move assign
ArrayDataLayer & operator=(ArrayDataLayer && other) noexcept = default;
protected:
// deallocate the memory
virtual void deallocate() {}
// allocate the memory
virtual void allocate(Int size, Int nb_component);
// allocate and initialize the memory
virtual void allocate(Int size, Int nb_component, const T & value);
public:
/// append a tuple of size nb_component containing value
inline void push_back(const_reference value);
/// append a vector
// inline void push_back(const value_type new_elem[]);
/// append a Vector or a Matrix
template
inline void push_back(const Eigen::MatrixBase & new_elem);
/// changes the allocated size but not the size, if new_size = 0, the size is
/// set to min(current_size and reserve size)
virtual void reserve(Int size, Int new_size = Int(-1));
/// change the size of the Array
virtual void resize(Int size);
/// change the size of the Array and initialize the values
virtual void resize(Int size, const T & val);
/// get the amount of space allocated in bytes
inline Int getMemorySize() const override;
/// Get the real size allocated in memory
inline Int getAllocatedSize() const;
/// give the address of the memory allocated for this vector
[[deprecated("use data instead to be stl compatible")]] T * storage() const {
return values;
};
- T * data() const { return values; };
+ const T * data() const { return values; };
+ T * data() { return values; };
protected:
/// allocation type agnostic data access
T * values{nullptr};
/// data storage
std::vector data_storage;
};
/* -------------------------------------------------------------------------- */
/* Actual Array */
/* -------------------------------------------------------------------------- */
template class Array : public ArrayDataLayer {
private:
using parent = ArrayDataLayer;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using value_type = typename parent::value_type;
using size_type = typename parent::size_type;
using reference = typename parent::reference;
using pointer_type = typename parent::pointer_type;
using const_reference = typename parent::const_reference;
using array_type = Array;
~Array() override;
Array() : Array(0){};
/// Allocation of a new vector
explicit Array(Int size, Int nb_component = 1, const ID & id = "");
/// Allocation of a new vector with a default value
explicit Array(Int size, Int nb_component, const_reference value,
const ID & id = "");
/// Copy constructor
Array(const Array & vect, const ID & id = "");
/// Copy constructor (deep copy)
explicit Array(const std::vector & vect);
// copy operator
Array & operator=(const Array & other);
// move constructor
Array(Array && other) noexcept = default;
// move assign
Array & operator=(Array && other) noexcept = default;
/* ------------------------------------------------------------------------ */
/* Iterator */
/* ------------------------------------------------------------------------ */
/// iterator for Array of nb_component = 1
using scalar_iterator = view_iterator;
/// const_iterator for Array of nb_component = 1
- using const_scalar_iterator = const_view_iterator;
+ using const_scalar_iterator = const_view_iterator;
/// iterator returning Vectors of size n on entries of Array with
/// nb_component = n
using vector_iterator = view_iterator>;
/// const_iterator returning Vectors of n size on entries of Array with
/// nb_component = n
using const_vector_iterator = const_view_iterator>;
/// iterator returning Matrices of size (m, n) on entries of Array with
/// nb_component = m*n
using matrix_iterator = view_iterator>;
/// const iterator returning Matrices of size (m, n) on entries of Array with
/// nb_component = m*n
using const_matrix_iterator = const_view_iterator>;
- /// iterator returning Tensor3 of size (m, n, k) on entries of Array with
- /// nb_component = m*n*k
- using tensor3_iterator = view_iterator>;
- /// const iterator returning Tensor3 of size (m, n, k) on entries of Array
- /// with nb_component = m*n*k
- using const_tensor3_iterator = const_view_iterator>;
-
/* ------------------------------------------------------------------------ */
template inline auto begin(Ns &&... n);
template inline auto end(Ns &&... n);
template inline auto begin(Ns &&... n) const;
template inline auto end(Ns &&... n) const;
template inline auto cbegin(Ns &&... n) const;
template inline auto cend(Ns &&... n) const;
template
[[deprecated("use make_view instead")]] inline auto
begin_reinterpret(Ns &&... n);
template
[[deprecated("use make_view instead")]] inline auto
end_reinterpret(Ns &&... n);
template
[[deprecated("use make_view instead")]] inline auto
begin_reinterpret(Ns &&... n) const;
template
[[deprecated("use make_view instead")]] inline auto
end_reinterpret(Ns &&... n) const;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// search elem in the vector, return the position of the first occurrence or
/// -1 if not found
Idx find(const_reference elem) const;
/// @see Array::find(const_reference elem) const
// Int find(T elem[]) const;
/// append a value to the end of the Array
inline void push_back(const_reference value) { parent::push_back(value); }
/// append a Vector or a Matrix
template
inline void push_back(const Eigen::MatrixBase & new_elem) {
parent::push_back(new_elem);
}
template
inline void push_back(const const_view_iterator & it) {
push_back(*it);
}
template inline void push_back(const view_iterator & it) {
push_back(*it);
}
/// erase the value at position i
inline void erase(Idx i);
/// erase the entry corresponding to the iterator
template inline auto erase(const view_iterator & it);
/// @see Array::find(const_reference elem) const
template ::value> * = nullptr>
inline Idx find(const C & elem);
/// set all entries of the array to the value t
/// @param t value to fill the array with
inline void set(T t) {
std::fill_n(this->values, this->size_ * this->nb_component, t);
}
/// set all tuples of the array to a given vector or matrix
/// @param vm Matrix or Vector to fill the array with
template ::value> * = nullptr>
inline void set(const C & vm);
/// set the array to T{}
inline void zero() { this->set({}); }
/// resize the array to 0
inline void clear() { this->resize(0); }
/// Append the content of the other array to the current one
void append(const Array & other);
/// copy another Array in the current Array, the no_sanity_check allows you to
/// force the copy in cases where you know what you do with two non matching
/// Arrays in terms of n
void copy(const Array & other, bool no_sanity_check = false);
/// function to print the containt of the class
void printself(std::ostream & stream, int indent = 0) const override;
/// Tests if all elements are finite.
template ::value> * = nullptr>
bool isFinite() const noexcept;
/* ------------------------------------------------------------------------ */
/* Operators */
/* ------------------------------------------------------------------------ */
public:
/// substraction entry-wise
Array & operator-=(const Array & vect);
/// addition entry-wise
Array & operator+=(const Array & vect);
/// multiply evry entry by alpha
Array & operator*=(const T & alpha);
/// check if the array are identical entry-wise
bool operator==(const Array & other) const;
/// @see Array::operator==(const Array & other) const
bool operator!=(const Array & other) const;
/// return a reference to the j-th entry of the i-th tuple
inline reference operator()(Idx i, Idx j = 0);
/// return a const reference to the j-th entry of the i-th tuple
inline const_reference operator()(Idx i, Idx j = 0) const;
/// return a reference to the ith component of the 1D array
inline reference operator[](Idx i);
/// return a const reference to the ith component of the 1D array
inline const_reference operator[](Idx i) const;
};
/* -------------------------------------------------------------------------- */
/* Inline Functions Array */
/* -------------------------------------------------------------------------- */
template
inline std::ostream & operator<<(std::ostream & stream,
const Array & _this) {
_this.printself(stream);
return stream;
}
/* -------------------------------------------------------------------------- */
/* Inline Functions ArrayBase */
/* -------------------------------------------------------------------------- */
inline std::ostream & operator<<(std::ostream & stream,
const ArrayBase & _this) {
_this.printself(stream);
return stream;
}
} // namespace akantu
#include "aka_array_tmpl.hh"
#endif /* AKANTU_ARRAY_HH_ */
diff --git a/src/common/aka_array_tmpl.hh b/src/common/aka_array_tmpl.hh
index 90642d9d8..b0426c796 100644
--- a/src/common/aka_array_tmpl.hh
+++ b/src/common/aka_array_tmpl.hh
@@ -1,1186 +1,1198 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see .
*/
/* -------------------------------------------------------------------------- */
/* Inline Functions Array */
/* -------------------------------------------------------------------------- */
#include "aka_array.hh" // NOLINT
/* -------------------------------------------------------------------------- */
#include
#include
#include
/* -------------------------------------------------------------------------- */
//#ifndef __AKANTU_AKA_ARRAY_TMPL_HH__
//#define __AKANTU_AKA_ARRAY_TMPL_HH__
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace debug {
struct ArrayException : public Exception {};
} // namespace debug
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template
ArrayDataLayer::ArrayDataLayer(Int size, Int nb_component,
const ID & id)
: ArrayBase(id) {
allocate(size, nb_component);
}
/* -------------------------------------------------------------------------- */
template
ArrayDataLayer::ArrayDataLayer(Int size, Int nb_component,
const_reference value,
const ID & id)
: ArrayBase(id) {
allocate(size, nb_component, value);
}
/* -------------------------------------------------------------------------- */
template
ArrayDataLayer::ArrayDataLayer(const ArrayDataLayer & vect,
const ID & id)
: ArrayBase(vect, id) {
this->data_storage = vect.data_storage;
this->size_ = vect.size_;
this->nb_component = vect.nb_component;
this->values = this->data_storage.data();
}
/* -------------------------------------------------------------------------- */
template
ArrayDataLayer::ArrayDataLayer(
const std::vector & vect) {
this->data_storage = vect;
this->size_ = vect.size();
this->nb_component = 1;
this->values = this->data_storage.data();
}
/* -------------------------------------------------------------------------- */
template
ArrayDataLayer &
ArrayDataLayer::operator=(const ArrayDataLayer & other) {
if (this != &other) {
this->data_storage = other.data_storage;
this->nb_component = other.nb_component;
this->size_ = other.size_;
this->values = this->data_storage.data();
}
return *this;
}
/* -------------------------------------------------------------------------- */
template
void ArrayDataLayer::allocate(Int new_size,
Int nb_component) {
this->nb_component = nb_component;
this->resize(new_size);
}
/* -------------------------------------------------------------------------- */
template
void ArrayDataLayer::allocate(Int new_size,
Int nb_component,
const T & val) {
this->nb_component = nb_component;
this->resize(new_size, val);
}
/* -------------------------------------------------------------------------- */
template
void ArrayDataLayer::resize(Int new_size) {
this->data_storage.resize(new_size * this->nb_component);
this->values = this->data_storage.data();
this->size_ = new_size;
}
/* -------------------------------------------------------------------------- */
template
void ArrayDataLayer::resize(Int new_size,
const T & value) {
this->data_storage.resize(new_size * this->nb_component, value);
this->values = this->data_storage.data();
this->size_ = new_size;
}
/* -------------------------------------------------------------------------- */
template
void ArrayDataLayer::reserve(Int size, Int new_size) {
if (new_size != -1) {
this->data_storage.resize(new_size * this->nb_component);
}
this->data_storage.reserve(size * this->nb_component);
this->values = this->data_storage.data();
}
/* -------------------------------------------------------------------------- */
/**
* append a tuple to the array with the value value for all components
* @param value the new last tuple or the array will contain nb_component copies
* of value
*/
template
inline void ArrayDataLayer::push_back(const T & value) {
this->data_storage.push_back(value);
this->values = this->data_storage.data();
this->size_ += 1;
}
/* -------------------------------------------------------------------------- */
/**
* append a matrix or a vector to the array
* @param new_elem a reference to a Matrix or Vector */
template
template
inline void ArrayDataLayer::push_back(
const Eigen::MatrixBase & new_elem) {
AKANTU_DEBUG_ASSERT(
nb_component == new_elem.size(),
"The vector("
<< new_elem.size()
<< ") as not a size compatible with the Array (nb_component="
<< nb_component << ").");
for (Idx i = 0; i < new_elem.size(); ++i) {
this->data_storage.push_back(new_elem.array()[i]);
}
this->values = this->data_storage.data();
this->size_ += 1;
}
/* -------------------------------------------------------------------------- */
template
inline Int ArrayDataLayer::getAllocatedSize() const {
return this->data_storage.capacity() / this->nb_component;
}
/* -------------------------------------------------------------------------- */
template
inline Int ArrayDataLayer::getMemorySize() const {
return this->data_storage.capacity() * sizeof(T);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template
class ArrayDataLayer : public ArrayBase {
public:
using value_type = T;
using reference = value_type &;
using pointer_type = value_type *;
using size_type = typename ArrayBase::size_type;
using const_reference = const value_type &;
public:
~ArrayDataLayer() override { deallocate(); }
/// Allocation of a new vector
ArrayDataLayer(Int size = 0, Int nb_component = 1, const ID & id = "")
: ArrayBase(id) {
allocate(size, nb_component);
}
/// Allocation of a new vector with a default value
ArrayDataLayer(Int size, Int nb_component, const_reference value,
const ID & id = "")
: ArrayBase(id) {
allocate(size, nb_component, value);
}
/// Copy constructor (deep copy)
ArrayDataLayer(const ArrayDataLayer & vect, const ID & id = "")
: ArrayBase(vect, id) {
allocate(vect.size(), vect.getNbComponent());
std::copy_n(vect.data(), this->size_ * this->nb_component, values);
}
/// Copy constructor (deep copy)
explicit ArrayDataLayer(const std::vector & vect) {
allocate(vect.size(), 1);
std::copy_n(vect.data(), this->size_ * this->nb_component, values);
}
// copy operator
inline ArrayDataLayer & operator=(const ArrayDataLayer & other) {
if (this != &other) {
allocate(other.size(), other.getNbComponent());
std::copy_n(other.data(), this->size_ * this->nb_component, values);
}
return *this;
}
// move constructor
inline ArrayDataLayer(ArrayDataLayer && other) noexcept = default;
// move assign
inline ArrayDataLayer & operator=(ArrayDataLayer && other) noexcept = default;
protected:
// deallocate the memory
virtual void deallocate() {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory,
// cppcoreguidelines-no-malloc)
free(this->values);
}
// allocate the memory
virtual inline void allocate(Int size, Int nb_component) {
if (size != 0) { // malloc can return a non NULL pointer in case size is 0
this->values = static_cast( // NOLINT
std::malloc(nb_component * size * sizeof(T))); // NOLINT
}
if (this->values == nullptr and size != 0) {
throw std::bad_alloc();
}
this->nb_component = nb_component;
this->allocated_size = this->size_ = size;
}
// allocate and initialize the memory
virtual inline void allocate(Int size, Int nb_component, const T & value) {
allocate(size, nb_component);
std::fill_n(values, size * nb_component, value);
}
public:
/// append a tuple of size nb_component containing value
inline void push_back(const_reference value) {
resize(this->size_ + 1, value);
}
/// append a Vector or a Matrix
template
inline void push_back(const Eigen::MatrixBase & new_elem) {
AKANTU_DEBUG_ASSERT(
nb_component == new_elem.size(),
"The vector("
<< new_elem.size()
<< ") as not a size compatible with the Array (nb_component="
<< nb_component << ").");
this->resize(this->size_ + 1);
make_view(*this, new_elem.rows(), new_elem.cols())
.begin()[this->size_ - 1] = new_elem;
}
/// changes the allocated size but not the size
virtual void reserve(Int size, Int new_size = Int(-1)) {
auto tmp_size = this->size_;
if (new_size != Int(-1)) {
tmp_size = new_size;
}
this->resize(size);
this->size_ = std::min(this->size_, tmp_size);
}
/// change the size of the Array
virtual void resize(Int size) {
if (size * this->nb_component == 0) {
free(values); // NOLINT: cppcoreguidelines-no-malloc
values = nullptr;
this->allocated_size = 0;
} else {
if (this->values == nullptr) {
this->allocate(size, this->nb_component);
return;
}
Int diff = size - allocated_size;
Int size_to_allocate = (std::abs(diff) > AKANTU_MIN_ALLOCATION) ? size
: (diff > 0)
? allocated_size + AKANTU_MIN_ALLOCATION
: allocated_size;
if (size_to_allocate ==
allocated_size) { // otherwhy the reserve + push_back might fail...
this->size_ = size;
return;
}
auto * tmp_ptr = reinterpret_cast( // NOLINT
realloc(this->values,
size_to_allocate * this->nb_component * sizeof(T)));
if (tmp_ptr == nullptr) {
throw std::bad_alloc();
}
this->values = tmp_ptr;
this->allocated_size = size_to_allocate;
}
this->size_ = size;
}
/// change the size of the Array and initialize the values
virtual void resize(Int size, const T & val) {
Int tmp_size = this->size_;
this->resize(size);
if (size > tmp_size) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
std::fill_n(values + this->nb_component * tmp_size,
(size - tmp_size) * this->nb_component, val);
}
}
/// get the amount of space allocated in bytes
inline size_type getMemorySize() const final {
return this->allocated_size * this->nb_component * sizeof(T);
}
/// Get the real size allocated in memory
inline Int getAllocatedSize() const { return this->allocated_size; }
/// give the address of the memory allocated for this vector
[[deprecated("use data instead to be stl compatible")]] T * storage() const {
return values;
};
- T * data() const { return values; };
+ const T * data() const { return values; };
+ T * data() { return values; };
protected:
/// allocation type agnostic data access
T * values{nullptr};
Int allocated_size{0};
};
/* -------------------------------------------------------------------------- */
template
inline auto Array::operator()(Int i, Int j) -> reference {
AKANTU_DEBUG_ASSERT(this->size_ > 0,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT((i < this->size_) && (j < this->nb_component),
"The value at position ["
<< i << "," << j << "] is out of range in array \""
<< this->id << "\"");
return this->values[i * this->nb_component + j];
}
/* -------------------------------------------------------------------------- */
template
inline auto Array::operator()(Int i, Int j) const
-> const_reference {
AKANTU_DEBUG_ASSERT(this->size_ > 0,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT((i < this->size_) && (j < this->nb_component),
"The value at position ["
<< i << "," << j << "] is out of range in array \""
<< this->id << "\"");
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
return this->values[i * this->nb_component + j];
}
template
inline auto Array::operator[](Int i) -> reference {
AKANTU_DEBUG_ASSERT(this->size_ > 0,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT((i < this->size_ * this->nb_component),
"The value at position ["
<< i << "] is out of range in array \"" << this->id
<< "\"");
return this->values[i];
}
/* -------------------------------------------------------------------------- */
template
inline auto Array::operator[](Int i) const -> const_reference {
AKANTU_DEBUG_ASSERT(this->size_ > 0,
"The array \"" << this->id << "\" is empty");
AKANTU_DEBUG_ASSERT((i < this->size_ * this->nb_component),
"The value at position ["
<< i << "] is out of range in array \"" << this->id
<< "\"");
return this->values[i];
}
/* -------------------------------------------------------------------------- */
/**
* erase an element. If the erased element is not the last of the array, the
* last element is moved into the hole in order to maintain contiguity. This
* may invalidate existing iterators (For instance an iterator obtained by
* Array::end() is no longer correct) and will change the order of the
* elements.
* @param i index of element to erase
*/
template inline void Array::erase(Idx i) {
- AKANTU_DEBUG_IN();
AKANTU_DEBUG_ASSERT((this->size_ > 0), "The array is empty");
AKANTU_DEBUG_ASSERT((i < this->size_), "The element at position ["
<< i << "] is out of range (" << i
<< ">=" << this->size_ << ")");
if (i != (this->size_ - 1)) {
for (Idx j = 0; j < this->nb_component; ++j) {
this->values[i * this->nb_component + j] =
this->values[(this->size_ - 1) * this->nb_component + j];
}
}
this->resize(this->size_ - 1);
- AKANTU_DEBUG_OUT();
}
/* ------------------------------------------------------------------------ */
template
template
inline auto Array::erase(const view_iterator & it) {
auto && curr = it.data();
Idx pos = (curr - this->values) / this->nb_component;
erase(pos);
view_iterator rit = it;
return --rit;
}
/* -------------------------------------------------------------------------- */
/**
* Subtract another array entry by entry from this array in place. Both arrays
* must
* have the same size and nb_component. If the arrays have different shapes,
* code compiled in debug mode will throw an expeption and optimised code
* will behave in an unpredicted manner
* @param other array to subtract from this
* @return reference to modified this
*/
template
Array &
Array::operator-=(const Array & vect) {
AKANTU_DEBUG_ASSERT((this->size_ == vect.size_) &&
(this->nb_component == vect.nb_component),
"The too array don't have the same sizes");
T * a = this->values;
- T * b = vect.data();
+ const T * b = vect.data();
for (Idx i = 0; i < this->size_ * this->nb_component; ++i) {
*a -= *b;
++a;
++b;
}
return *this;
}
/* --------------------------------------------------------------------------
*/
/**
* Add another array entry by entry to this array in
* place. Both arrays must have the same size and
* nb_component. If the arrays have different shapes, code
* compiled in debug mode will throw an expeption and
* optimised code will behave in an unpredicted manner
* @param other array to add to this
* @return reference to modified this
*/
template
Array &
Array::operator+=(const Array & vect) {
AKANTU_DEBUG_ASSERT((this->size_ == vect.size()) &&
(this->nb_component == vect.nb_component),
"The too array don't have the same sizes");
T * a = this->values;
- T * b = vect.data();
+ const T * b = vect.data();
for (Idx i = 0; i < this->size_ * this->nb_component; ++i) {
*a++ += *b++;
}
return *this;
}
/* --------------------------------------------------------------------------
*/
/**
* Multiply all entries of this array by a scalar in place
* @param alpha scalar multiplicant
* @return reference to modified this
*/
template
auto Array::operator*=(const T & alpha) -> Array & {
T * a = this->values;
for (Idx i = 0; i < this->size_ * this->nb_component; ++i) {
*a++ *= alpha;
}
return *this;
}
/* ------------------------------------------------------------------------- */
/**
* Compare this array element by element to another.
* @param other array to compare to
* @return true it all element are equal and arrays have
* the same shape, else false
*/
template
bool Array::operator==(const Array & other) const {
bool equal = this->nb_component == other.nb_component &&
this->size_ == other.size_ && this->id == other.id;
if (not equal) {
return false;
}
if (this->values == other.data()) {
return true;
}
return std::equal(this->values,
this->values + this->size_ * this->nb_component,
other.data());
}
/* ------------------------------------------------------------------------ */
template
bool Array::operator!=(const Array & other) const {
return !operator==(other);
}
/* ------------------------------------------------------------------------ */
/**
* set all tuples of the array to a given vector or matrix
* @param vm Matrix or Vector to fill the array with
*/
template
template ::value> *>
inline void Array::set(const C & elem) {
AKANTU_DEBUG_ASSERT(
this->nb_component == elem.array().size(),
"The size of the object does not match the number of components");
for (auto && v : make_view(*this, this->nb_component)) {
std::copy_n(elem.data(), this->nb_component, v.data());
}
}
/* ------------------------------------------------------------------------ */
template
void Array::append(const Array & other) {
AKANTU_DEBUG_ASSERT(
this->nb_component == other.nb_component,
"Cannot append an array with a different number of component");
Idx old_size = this->size_;
this->resize(this->size_ + other.size());
T * tmp = this->values + this->nb_component * old_size;
std::copy_n(other.data(), other.size() * this->nb_component, tmp);
}
/* ------------------------------------------------------------------------ */
/* Functions Array */
/* ------------------------------------------------------------------------ */
template
Array::Array(Int size, Int nb_component, const ID & id)
: parent(size, nb_component, id) {}
template <>
inline Array::Array(Int size, Int nb_component,
const ID & id)
: parent(size, nb_component, "", id) {}
/* ------------------------------------------------------------------------ */
template
Array::Array(Int size, Int nb_component, const_reference value,
const ID & id)
: parent(size, nb_component, value, id) {}
/* ------------------------------------------------------------------------ */
template
Array::Array(const Array & vect, const ID & id)
: parent(vect, id) {}
/* ------------------------------------------------------------------------ */
template
auto Array::operator=(const Array & other) -> Array & {
AKANTU_DEBUG_WARNING("You are copying the array "
<< this->id << " are you sure it is on purpose");
if (&other == this) {
return *this;
}
parent::operator=(other);
return *this;
}
/* ------------------------------------------------------------------------ */
template
Array::Array(const std::vector & vect) : parent(vect) {}
/* ------------------------------------------------------------------------ */
template Array::~Array() = default;
/* ------------------------------------------------------------------------ */
/**
* search elem in the array, return the position of the
* first occurrence or -1 if not found
* @param elem the element to look for
* @return index of the first occurrence of elem or -1 if
* elem is not present
*/
template
Idx Array::find(const_reference elem) const {
- AKANTU_DEBUG_IN();
-
auto begin = this->begin();
auto end = this->end();
auto it = std::find(begin, end, elem);
- AKANTU_DEBUG_OUT();
return (it != end) ? it - begin : Idx(-1);
}
/* ------------------------------------------------------------------------ */
template
template ::value> *>
inline Idx Array::find(const V & elem) {
AKANTU_DEBUG_ASSERT(elem.size() == this->nb_component,
"Cannot find an element with a wrong size ("
<< elem.size() << ") != " << this->nb_component);
auto && view = make_view(*this, elem.size());
auto begin = view.begin();
auto end = view.end();
auto it = std::find(begin, end, elem);
return (it != end) ? it - begin : Idx(-1);
}
/* ------------------------------------------------------------------------ */
/**
* copy the content of another array. This overwrites the
* current content.
* @param other Array to copy into this array. It has to
* have the same nb_component as this. If compiled in
* debug mode, an incorrect other will result in an
* exception being thrown. Optimised code may result in
* unpredicted behaviour.
* @param no_sanity_check turns off all checkes
*/
template
void Array::copy(const Array & other,
bool no_sanity_check) {
- AKANTU_DEBUG_IN();
-
if (not no_sanity_check and (other.nb_component != this->nb_component)) {
AKANTU_ERROR("The two arrays do not have the same "
"number of components");
}
this->resize((other.size_ * other.nb_component) / this->nb_component);
std::copy_n(other.data(), this->size_ * this->nb_component, this->values);
-
- AKANTU_DEBUG_OUT();
}
/* ------------------------------------------------------------------------ */
template class ArrayPrintHelper {
public:
template
static void print_content(const Array & vect, std::ostream & stream,
int indent) {
std::string space(indent, AKANTU_INDENT);
stream << space << " + values : {";
for (Idx i = 0; i < vect.size(); ++i) {
stream << "{";
for (Idx j = 0; j < vect.getNbComponent(); ++j) {
stream << vect(i, j);
if (j != vect.getNbComponent() - 1) {
stream << ", ";
}
}
stream << "}";
if (i != vect.size() - 1) {
stream << ", ";
}
}
stream << "}" << std::endl;
}
};
template <> class ArrayPrintHelper {
public:
template
static void print_content(__attribute__((unused)) const Array & vect,
__attribute__((unused)) std::ostream & stream,
__attribute__((unused)) int indent) {}
};
/* ------------------------------------------------------------------------ */
template
void Array::printself(std::ostream & stream, int indent) const {
std::string space(indent, AKANTU_INDENT);
std::streamsize prec = stream.precision();
std::ios_base::fmtflags ff = stream.flags();
stream.setf(std::ios_base::showbase);
stream.precision(2);
stream << space << "Array<" << debug::demangle(typeid(T).name()) << "> ["
<< std::endl;
stream << space << " + id : " << this->id << std::endl;
stream << space << " + size : " << this->size_ << std::endl;
stream << space << " + nb_component : " << this->nb_component << std::endl;
stream << space << " + allocated size : " << this->getAllocatedSize()
<< std::endl;
stream << space
<< " + memory size : " << printMemorySize(this->getMemorySize())
<< std::endl;
if (not AKANTU_DEBUG_LEVEL_IS_TEST()) {
stream << space << " + address : " << std::hex << this->values
<< std::dec << std::endl;
}
stream.precision(prec);
stream.flags(ff);
if (AKANTU_DEBUG_TEST(dblDump) || AKANTU_DEBUG_LEVEL_IS_TEST()) {
ArrayPrintHelper::value>::print_content(
*this, stream, indent);
}
stream << space << "]" << std::endl;
}
/* -------------------------------------------------------------------------- */
template
template ::value> *>
bool Array::isFinite() const noexcept {
return std::all_of(this->values,
this->values + this->size_ * this->nb_component,
[](auto && a) { return std::isfinite(a); });
}
/* ------------------------------------------------------------------------ */
/* ArrayFilter */
/* ------------------------------------------------------------------------ */
template class ArrayFilter {
public:
/// const iterator
template
class const_iterator {
public:
Idx getCurrentIndex() {
return (*this->filter_it * this->nb_item_per_elem +
this->sub_element_counter);
}
inline const_iterator() = default;
inline const_iterator(original_iterator origin_it,
filter_iterator filter_it, Int nb_item_per_elem)
: origin_it(std::move(origin_it)), filter_it(std::move(filter_it)),
nb_item_per_elem(nb_item_per_elem), sub_element_counter(0){};
inline bool operator!=(const_iterator & other) const {
return !((*this) == other);
}
inline bool operator==(const_iterator & other) const {
return (this->origin_it == other.origin_it &&
this->filter_it == other.filter_it &&
this->sub_element_counter == other.sub_element_counter);
}
inline bool operator!=(const const_iterator & other) const {
return !((*this) == other);
}
inline bool operator==(const const_iterator & other) const {
return (this->origin_it == other.origin_it &&
this->filter_it == other.filter_it &&
this->sub_element_counter == other.sub_element_counter);
}
inline const_iterator & operator++() {
++sub_element_counter;
if (sub_element_counter == nb_item_per_elem) {
sub_element_counter = 0;
++filter_it;
}
return *this;
};
inline decltype(auto) operator*() {
return origin_it[nb_item_per_elem * (*filter_it) + sub_element_counter];
};
private:
original_iterator origin_it;
filter_iterator filter_it;
/// the number of item per element
Int nb_item_per_elem;
/// counter for every sub element group
Int sub_element_counter;
};
using vector_iterator = void; // iterator>;
using array_type = Array;
using const_vector_iterator =
const_iterator::const_scalar_iterator>;
using value_type = typename array_type::value_type;
private:
/* ---------------------------------------------------------------------- */
/* Constructors/Destructors */
/* ---------------------------------------------------------------------- */
public:
ArrayFilter(const Array & array, const Array & filter,
Int nb_item_per_elem)
: array(array), filter(filter), nb_item_per_elem(nb_item_per_elem){};
decltype(auto) begin_reinterpret(Int n, Int new_size) const {
Int new_nb_item_per_elem = this->nb_item_per_elem;
if (new_size != 0 && n != 0)
new_nb_item_per_elem = this->array.getNbComponent() *
this->filter.size() * this->nb_item_per_elem /
(n * new_size);
return const_vector_iterator(make_view(this->array, n).begin(),
this->filter.begin(), new_nb_item_per_elem);
};
decltype(auto) end_reinterpret(Int n, Int new_size) const {
Int new_nb_item_per_elem = this->nb_item_per_elem;
if (new_size != 0 && n != 0)
new_nb_item_per_elem = this->array.getNbComponent() *
this->filter.size() * this->nb_item_per_elem /
(n * new_size);
return const_vector_iterator(make_view(this->array, n).begin(),
this->filter.end(), new_nb_item_per_elem);
};
// vector_iterator begin_reinterpret(Int, Int) { throw; };
// vector_iterator end_reinterpret(Int, Int) { throw; };
/// return the size of the filtered array which is the filter size
Int size() const { return this->filter.size() * this->nb_item_per_elem; };
/// the number of components of the filtered array
Int getNbComponent() const { return this->array.getNbComponent(); };
/// tells if the container is empty
[[nodiscard]] bool empty() const { return (size() == 0); }
/* ---------------------------------------------------------------------- */
/* Class Members */
/* ---------------------------------------------------------------------- */
private:
/// reference to array of data
const Array & array;
/// reference to the filter used to select elements
const Array & filter;
/// the number of item per element
Int nb_item_per_elem;
};
/* ------------------------------------------------------------------------ */
/* Begin/End functions implementation */
/* ------------------------------------------------------------------------ */
namespace detail {
+ template struct GetNbComponent {
+ static auto getNbComponent(const C & /*cont*/) { return 1; }
+ };
+
+ template struct GetNbComponent> {
+ static auto getNbComponent(const Array & cont) {
+ return cont.getNbComponent();
+ }
+ };
+
template
constexpr auto take_front_impl(Tuple && t,
std::index_sequence /*idxs*/) {
return std::make_tuple(std::get(std::forward(t))...);
}
template constexpr auto take_front(Tuple && t) {
return take_front_impl(std::forward(t),
std::make_index_sequence{});
}
template std::string to_string_all(T &&... t) {
if (sizeof...(T) == 0) {
return "";
}
std::stringstream ss;
bool noComma = true;
ss << "(";
(void)std::initializer_list{
(ss << (noComma ? "" : ", ") << t, noComma = false)...};
ss << ")";
return ss.str();
}
template