diff --git a/python/py_dof_manager.cc b/python/py_dof_manager.cc
index 31bcdcf75..1a073da25 100644
--- a/python/py_dof_manager.cc
+++ b/python/py_dof_manager.cc
@@ -1,215 +1,216 @@
/*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* 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_dof_manager.hh"
#include "py_aka_array.hh"
#include "py_akantu_pybind11_compatibility.hh"
/* -------------------------------------------------------------------------- */
#include
#include
#include
#include
/* -------------------------------------------------------------------------- */
#include
#include
#include
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace {
class PySolverCallback : public SolverCallback {
public:
using SolverCallback::SolverCallback;
/// get the type of matrix needed
MatrixType getMatrixType(const ID & matrix_id) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE(MatrixType, SolverCallback, getMatrixType,
matrix_id);
}
/// callback to assemble a Matrix
void assembleMatrix(const ID & matrix_id) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE(void, SolverCallback, assembleMatrix, matrix_id);
}
/// callback to assemble a lumped Matrix
void assembleLumpedMatrix(const ID & matrix_id) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE(void, SolverCallback, assembleLumpedMatrix,
matrix_id);
}
/// callback to assemble the residual (rhs)
void assembleResidual() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE_PURE(void, SolverCallback, assembleResidual);
}
/// callback for the predictor (in case of dynamic simulation)
void predictor() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, SolverCallback, predictor);
}
/// callback for the corrector (in case of dynamic simulation)
void corrector() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, SolverCallback, corrector);
}
void beforeSolveStep() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, SolverCallback, beforeSolveStep);
}
void afterSolveStep(bool converged) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, SolverCallback, afterSolveStep, converged);
}
};
class PyInterceptSolverCallback : public InterceptSolverCallback {
public:
using InterceptSolverCallback::InterceptSolverCallback;
MatrixType getMatrixType(const ID & matrix_id) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(MatrixType, InterceptSolverCallback, getMatrixType,
matrix_id);
}
void assembleMatrix(const ID & matrix_id) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, assembleMatrix,
matrix_id);
}
/// callback to assemble a lumped Matrix
void assembleLumpedMatrix(const ID & matrix_id) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, assembleLumpedMatrix,
matrix_id);
}
void assembleResidual() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, assembleResidual);
}
void predictor() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, predictor);
}
void corrector() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, corrector);
}
void beforeSolveStep() override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, beforeSolveStep);
}
void afterSolveStep(bool converged) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, InterceptSolverCallback, afterSolveStep,
converged);
}
};
} // namespace
/* -------------------------------------------------------------------------- */
void register_dof_manager(py::module & mod) {
py::class_>(mod, "DOFManager")
.def("getMatrix", &DOFManager::getMatrix,
py::return_value_policy::reference)
.def(
"getNewMatrix",
[](DOFManager & self, const std::string & name,
const std::string & matrix_to_copy_id) -> decltype(auto) {
return self.getNewMatrix(name, matrix_to_copy_id);
},
py::return_value_policy::reference)
.def(
"getResidual",
[](DOFManager & self) -> decltype(auto) {
return self.getResidual();
},
py::return_value_policy::reference)
.def("getArrayPerDOFs", &DOFManager::getArrayPerDOFs)
.def(
"hasMatrix",
[](DOFManager & self, const ID & name) -> bool {
return self.hasMatrix(name);
},
py::arg("name"))
.def("assembleToResidual", &DOFManager::assembleToResidual,
py::arg("dof_id"), py::arg("array_to_assemble"),
py::arg("scale_factor") = 1.)
.def("assembleToLumpedMatrix", &DOFManager::assembleToLumpedMatrix,
py::arg("dof_id"), py::arg("array_to_assemble"),
py::arg("lumped_mtx"), py::arg("scale_factor") = 1.)
.def("assemblePreassembledMatrix",
&DOFManager::assemblePreassembledMatrix, py::arg("matrix_id"),
- py::arg("terms"));
+ py::arg("terms"))
+ .def("zeroResidual", &DOFManager::zeroResidual);
py::class_(mod, "NonLinearSolver")
.def(
"set",
[](NonLinearSolver & self, const std::string & id, const Real & val) {
if (id == "max_iterations") {
self.set(id, int(val));
} else {
self.set(id, val);
}
})
.def("set",
[](NonLinearSolver & self, const std::string & id,
const SolveConvergenceCriteria & val) { self.set(id, val); });
py::class_(mod, "TimeStepSolver")
.def("getIntegrationScheme", &TimeStepSolver::getIntegrationScheme);
py::class_(mod, "SolverCallback")
.def(py::init_alias())
.def("getMatrixType", &SolverCallback::getMatrixType)
.def("assembleMatrix", &SolverCallback::assembleMatrix)
.def("assembleLumpedMatrix", &SolverCallback::assembleLumpedMatrix)
.def("assembleResidual",
[](SolverCallback & self) { self.assembleResidual(); })
.def("predictor", &SolverCallback::predictor)
.def("corrector", &SolverCallback::corrector)
.def("beforeSolveStep", &SolverCallback::beforeSolveStep)
.def("afterSolveStep", &SolverCallback::afterSolveStep)
.def_property_readonly("dof_manager", &SolverCallback::getSCDOFManager,
py::return_value_policy::reference);
py::class_(mod, "InterceptSolverCallback")
.def(py::init_alias());
}
} // namespace akantu
diff --git a/python/py_solver.cc b/python/py_solver.cc
index bbcd931c3..d5e20670d 100644
--- a/python/py_solver.cc
+++ b/python/py_solver.cc
@@ -1,113 +1,119 @@
/**
* @file py_solver.cc
*
* @author Nicolas Richart
*
* @date creation: Tue Sep 29 2020
* @date last modification: Sat Mar 06 2021
*
* @brief pybind11 interface to Solver and SparseMatrix
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* 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_solver.hh"
#include "py_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include
#include
#include
#include
/* -------------------------------------------------------------------------- */
#include
#include
#include
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
void register_solvers(py::module & mod) {
py::class_(mod, "SparseMatrix")
.def("getMatrixType", &SparseMatrix::getMatrixType)
.def("size", &SparseMatrix::size)
.def("zero", &SparseMatrix::zero)
.def("saveProfile", &SparseMatrix::saveProfile)
.def("saveMatrix", &SparseMatrix::saveMatrix)
.def(
"add", [](SparseMatrix & self, UInt i, UInt j) { self.add(i, j); },
"Add entry in the profile")
.def(
"add",
[](SparseMatrix & self, UInt i, UInt j, Real value) {
self.add(i, j, value);
},
"Add the value to the matrix")
.def(
"add",
[](SparseMatrix & self, SparseMatrix & A, Real alpha) {
self.add(A, alpha);
},
"Add a matrix to the matrix", py::arg("A"), py::arg("alpha") = 1.)
+
+ .def("isFinite", &SparseMatrix::isFinite)
+
+ .def("getRelease",
+ [](const SparseMatrix & self) -> UInt { return self.getRelease(); })
.def("__call__",
[](const SparseMatrix & self, UInt i, UInt j) { return self(i, j); })
.def("getRelease", &SparseMatrix::getRelease);
py::class_(mod, "SparseMatrixAIJ")
.def("getIRN", &SparseMatrixAIJ::getIRN)
.def("getJCN", &SparseMatrixAIJ::getJCN)
.def("getA", &SparseMatrixAIJ::getA);
py::class_(mod, "SolverVector")
- .def("getValues",
- [](SolverVector& self) -> decltype(auto) {
- return static_cast& >(self);
- },
- py::return_value_policy::reference_internal,
- "Transform this into a vector, Is not copied.")
- .def("isDistributed", [](const SolverVector& self) { return self.isDistributed(); })
- ;
+ .def(
+ "getValues",
+ [](SolverVector & self) -> decltype(auto) {
+ return static_cast &>(self);
+ },
+ py::return_value_policy::reference_internal,
+ "Transform this into a vector, Is not copied.")
+ .def("isDistributed",
+ [](const SolverVector & self) { return self.isDistributed(); });
py::class_(mod, "TermToAssemble")
.def(py::init())
.def(py::self += Real())
.def_property_readonly("i", &TermsToAssemble::TermToAssemble::i)
.def_property_readonly("j", &TermsToAssemble::TermToAssemble::j);
py::class_(mod, "TermsToAssemble")
.def(py::init())
.def("getDOFIdM", &TermsToAssemble::getDOFIdM)
.def("getDOFIdN", &TermsToAssemble::getDOFIdN)
.def(
"__call__",
[](TermsToAssemble & self, UInt i, UInt j, Real val) {
auto & term = self(i, j);
term = val;
return term;
},
py::arg("i"), py::arg("j"), py::arg("val") = 0.,
py::return_value_policy::reference);
}
} // namespace akantu
diff --git a/python/py_structural_mechanics_model.cc b/python/py_structural_mechanics_model.cc
index a80b6a529..366953881 100644
--- a/python/py_structural_mechanics_model.cc
+++ b/python/py_structural_mechanics_model.cc
@@ -1,162 +1,179 @@
/**
* @file py_structural_mechanics_model.cc
*
* @author Philip Mueller
* @author Mohit Pundir
* @author Nicolas Richart
*
* @date creation: Wed Feb 03 2021
* @date last modification: Thu Apr 01 2021
*
* @brief pybind11 interface to StructuralMechanicsModel
*
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* 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_aka_array.hh"
/* -------------------------------------------------------------------------- */
#include
/* -------------------------------------------------------------------------- */
#include
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
#define def_deprecated(func_name, mesg) \
def(func_name, [](py::args, py::kwargs) { AKANTU_ERROR(mesg); })
#define def_function_nocopy(func_name) \
def( \
#func_name, \
[](StructuralMechanicsModel & self) -> decltype(auto) { \
return self.func_name(); \
}, \
py::return_value_policy::reference)
#define def_function_(func_name) \
def(#func_name, [](StructuralMechanicsModel & self) -> decltype(auto) { \
return self.func_name(); \
})
#define def_plainmember(M) def_readwrite(#M, &StructuralMaterial::M)
/* -------------------------------------------------------------------------- */
void register_structural_mechanics_model(pybind11::module & mod) {
/* First we have to register the material class
* The wrapper aims to mimic the behaviour of the real material.
*/
py::class_(mod, "StructuralMaterial")
.def(py::init<>())
.def(py::init())
.def_plainmember(E)
.def_plainmember(A)
.def_plainmember(I)
.def_plainmember(Iz)
.def_plainmember(Iy)
.def_plainmember(GJ)
.def_plainmember(rho)
.def_plainmember(t)
.def_plainmember(nu);
/* Now we create the structural model wrapper
* Note that this is basically a port from the solid mechanic part.
*/
py::class_(mod, "StructuralMechanicsModel")
.def(py::init(), py::arg("mesh"),
py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "structural_mechanics_model")
.def(
"initFull",
[](StructuralMechanicsModel & self,
const AnalysisMethod & analysis_method) -> void {
self.initFull(_analysis_method = analysis_method);
},
py::arg("_analysis_method"))
.def("initFull",
[](StructuralMechanicsModel & self) -> void { self.initFull(); })
.def_function_nocopy(getExternalForce)
.def_function_nocopy(getDisplacement)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getVelocity)
.def_function_nocopy(getAcceleration)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getBlockedDOFs)
.def_function_nocopy(getMesh)
.def("setTimeStep", &StructuralMechanicsModel::setTimeStep,
py::arg("time_step"), py::arg("solver_id") = "")
.def(
"getElementMaterial",
[](StructuralMechanicsModel & self, const ElementType & type,
GhostType ghost_type) -> decltype(auto) {
return self.getElementMaterial(type, ghost_type);
},
"This function returns the map that maps elements to materials.",
py::arg("type"), py::arg("ghost_type") = _not_ghost,
py::return_value_policy::reference)
.def(
"getMaterialByElement",
[](StructuralMechanicsModel & self, Element element)
-> decltype(auto) { return self.getMaterialByElement(element); },
"This function returns the `StructuralMaterial` instance that is "
"associated with element `element`.",
py::arg("element"), py::return_value_policy::reference)
.def(
"addMaterial",
[](StructuralMechanicsModel & self, StructuralMaterial & mat,
const ID & name) -> UInt { return self.addMaterial(mat, name); },
"This function adds the `StructuralMaterial` `mat` to `self`."
" The function returns the ID of the new material.",
py::arg("mat"), py::arg("name") = "")
.def(
"getMaterial",
- [](StructuralMechanicsModel & self, UInt material_index)
- -> decltype(auto) { return self.getMaterial(material_index); },
+ [](const StructuralMechanicsModel & self,
+ UInt material_index) -> StructuralMaterial {
+ return self.getMaterial(material_index);
+ },
"This function returns the `i`th material of `self`."
- " Note a reference is returned which allows to modify the material "
- "inside `self`.",
- py::arg("i"), py::return_value_policy::reference)
+ " The function returns a copy of the material.",
+ py::arg("material_index"), py::return_value_policy::copy)
.def(
"getMaterial",
- [](StructuralMechanicsModel & self, const ID & name)
- -> decltype(auto) { return self.getMaterial(name); },
- "This function returns the material with name `i` of `self`."
- " Note a reference is returned which allows to modify the material "
- "inside `self`.",
- py::arg("i"), py::return_value_policy::reference)
+ [](const StructuralMechanicsModel & self, const ID & name)
+ -> StructuralMaterial { return self.getMaterial(name); },
+ "This function returns the `i`th material of `self`."
+ " The function returns a copy of the material.",
+ py::arg("material_index"), py::return_value_policy::copy)
.def(
"getNbMaterials",
[](StructuralMechanicsModel & self) { return self.getNbMaterials(); },
"Returns the number of different materials inside `self`.")
+
.def("getKineticEnergy", &StructuralMechanicsModel::getKineticEnergy,
"Compute kinetic energy")
.def("getPotentialEnergy", &StructuralMechanicsModel::getPotentialEnergy,
"Compute potential energy")
.def("getEnergy", &StructuralMechanicsModel::getEnergy,
- "Compute the specified energy");
+ "Compute the specified energy")
-} // End: register structural mechanical model
+ .def(
+ "getLumpedMass",
+ [](const StructuralMechanicsModel & self) -> decltype(auto) {
+ return self.getLumpedMass();
+ },
+ py::return_value_policy::reference_internal)
+ .def(
+ "getMass",
+ [](const StructuralMechanicsModel & self) -> decltype(auto) {
+ return self.getMass();
+ },
+ py::return_value_policy::reference_internal)
+ .def("assembleLumpedMassMatrix",
+ &StructuralMechanicsModel::assembleLumpedMassMatrix,
+ "Assembles the lumped mass matrix")
+ .def("hasLumpedMass", &StructuralMechanicsModel::hasLumpedMass);
+}
} // namespace akantu
diff --git a/src/common/aka_array.hh b/src/common/aka_array.hh
index 3a346fc5d..21d980519 100644
--- a/src/common/aka_array.hh
+++ b/src/common/aka_array.hh
@@ -1,445 +1,450 @@
/**
* @file aka_array.hh
*
* @author Till Junge
* @author Nicolas Richart
*
* @date creation: Fri Jun 18 2010
* @date last modification: Sun Nov 22 2020
*
* @brief Array container for Akantu This container differs from the
* std::vector from the fact it as 2 dimensions a main dimension and the size
* stored per entries
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* 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
#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:
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 UInt getMemorySize() const = 0;
// changed empty to match std::vector empty
inline bool empty() const __attribute__((warn_unused_result)) {
return size_ == 0;
}
/// function to print the containt of the class
virtual void printself(std::ostream & stream, int indent = 0) const = 0;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// Get the Size of the Array
UInt size() const { return size_; }
/// Get the number of components
AKANTU_GET_MACRO(NbComponent, nb_component, UInt);
/// Get the name of th array
AKANTU_GET_MACRO(ID, id, const 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
UInt size_{0};
/// number of components
UInt nb_component{1};
};
/* -------------------------------------------------------------------------- */
namespace {
template struct IteratorHelper {};
template struct IteratorHelper<0, T> { using type = T; };
template struct IteratorHelper<1, T> { using type = Vector; };
template struct IteratorHelper<2, T> { using type = Matrix; };
template struct IteratorHelper<3, T> {
using type = Tensor3;
};
template
using IteratorHelper_t = typename IteratorHelper::type;
} // namespace
/* -------------------------------------------------------------------------- */
/* Memory handling layer */
/* -------------------------------------------------------------------------- */
enum class ArrayAllocationType {
_default,
_pod,
};
template
struct ArrayAllocationTrait
: public std::conditional_t<
std::is_scalar::value,
std::integral_constant,
std::integral_constant> {};
/* -------------------------------------------------------------------------- */
template ::value>
class ArrayDataLayer : public ArrayBase {
public:
using value_type = T;
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(UInt size = 0, UInt nb_component = 1,
const ID & id = "");
/// Allocation of a new vector with a default value
ArrayDataLayer(UInt size, UInt 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(UInt size, UInt nb_component);
// allocate and initialize the memory
virtual void allocate(UInt size, UInt 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 class C,
typename = std::enable_if_t>::value or
aka::is_tensor_proxy>::value>>
inline void push_back(const C & 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(UInt size, UInt new_size = UInt(-1));
/// change the size of the Array
virtual void resize(UInt size);
/// change the size of the Array and initialize the values
virtual void resize(UInt size, const T & val);
/// get the amount of space allocated in bytes
inline UInt getMemorySize() const override;
/// Get the real size allocated in memory
inline UInt getAllocatedSize() const;
/// give the address of the memory allocated for this vector
T * storage() const { 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 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(UInt size, UInt nb_component = 1, const ID & id = "");
/// Allocation of a new vector with a default value
explicit Array(UInt size, UInt 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 */
/* ------------------------------------------------------------------------ */
/// \todo protected: does not compile with intel check why
public:
template >::value>
class iterator_internal;
public:
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
template class const_iterator;
template class iterator;
/* ------------------------------------------------------------------------ */
/// iterator for Array of nb_component = 1
using scalar_iterator = iterator;
/// const_iterator for Array of nb_component = 1
using const_scalar_iterator = const_iterator;
/// iterator returning Vectors of size n on entries of Array with
/// nb_component = n
using vector_iterator = iterator>;
/// const_iterator returning Vectors of n size on entries of Array with
/// nb_component = n
using const_vector_iterator = const_iterator>;
/// iterator returning Matrices of size (m, n) on entries of Array with
/// nb_component = m*n
using matrix_iterator = iterator>;
/// const iterator returning Matrices of size (m, n) on entries of Array with
/// nb_component = m*n
using const_matrix_iterator = const_iterator>;
/// iterator returning Tensor3 of size (m, n, k) on entries of Array with
/// nb_component = m*n*k
using tensor3_iterator = 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_iterator>;
/* ------------------------------------------------------------------------ */
template inline decltype(auto) begin(Ns &&... n);
template inline decltype(auto) end(Ns &&... n);
template inline decltype(auto) begin(Ns &&... n) const;
template inline decltype(auto) end(Ns &&... n) const;
template inline decltype(auto) begin_reinterpret(Ns &&... n);
template inline decltype(auto) end_reinterpret(Ns &&... n);
template
inline decltype(auto) begin_reinterpret(Ns &&... n) const;
template
inline decltype(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
UInt find(const_reference elem) const;
/// @see Array::find(const_reference elem) const
// UInt 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 class C,
typename = std::enable_if_t>::value or
aka::is_tensor_proxy>::value>>
inline void push_back(const C & new_elem) {
parent::push_back(new_elem);
}
/// append the content of the iterator at the end of the Array
template inline void push_back(const iterator & it) {
push_back(*it);
}
/// erase the value at position i
inline void erase(UInt i);
/// ask Nico, clarify
template inline iterator erase(const iterator & it);
/// @see Array::find(const_reference elem) const
template class C,
typename = std::enable_if_t>::value or
aka::is_tensor_proxy>::value>>
inline UInt 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 the array to T{}
inline void zero() { this->set({}); }
/// resize the array to 0
inline void clear() { this->resize(0); }
/// set all tuples of the array to a given vector or matrix
/// @param vm Matrix or Vector to fill the array with
template class C,
typename = std::enable_if_t>::value or
aka::is_tensor_proxy>::value>>
inline void set(const C & vm);
/// 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 & other);
/// addition entry-wise
Array & operator+=(const Array & other);
/// 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()(UInt i, UInt j = 0);
/// return a const reference to the j-th entry of the i-th tuple
inline const_reference operator()(UInt i, UInt j = 0) const;
/// return a reference to the ith component of the 1D array
inline reference operator[](UInt i);
/// return a const reference to the ith component of the 1D array
inline const_reference operator[](UInt 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 6813a95d7..664bbba09 100644
--- a/src/common/aka_array_tmpl.hh
+++ b/src/common/aka_array_tmpl.hh
@@ -1,1363 +1,1372 @@
/**
* @file aka_array_tmpl.hh
*
* @author Guillaume Anciaux
* @author Nicolas Richart
*
* @date creation: Thu Jul 15 2010
* @date last modification: Fri Feb 26 2021
*
* @brief Inline functions of the classes Array and ArrayBase
*
*
* @section LICENSE
*
* Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* 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
/* -------------------------------------------------------------------------- */
#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(UInt size,
UInt nb_component,
const ID & id)
: ArrayBase(id) {
allocate(size, nb_component);
}
/* -------------------------------------------------------------------------- */
template
ArrayDataLayer::ArrayDataLayer(UInt size,
UInt 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(UInt new_size,
UInt nb_component) {
this->nb_component = nb_component;
this->resize(new_size);
}
/* -------------------------------------------------------------------------- */
template
void ArrayDataLayer::allocate(UInt new_size,
UInt nb_component,
const T & val) {
this->nb_component = nb_component;
this->resize(new_size, val);
}
/* -------------------------------------------------------------------------- */
template
void ArrayDataLayer::resize(UInt 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(UInt 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(UInt size, UInt new_size) {
if (new_size != UInt(-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 class C, typename>
inline void
ArrayDataLayer::push_back(const C & 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 (UInt i = 0; i < new_elem.size(); ++i) {
this->data_storage.push_back(new_elem[i]);
}
this->values = this->data_storage.data();
this->size_ += 1;
}
/* -------------------------------------------------------------------------- */
template
inline UInt ArrayDataLayer::getAllocatedSize() const {
return this->data_storage.capacity() / this->nb_component;
}
/* -------------------------------------------------------------------------- */
template
inline UInt 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 const_reference = const value_type &;
public:
~ArrayDataLayer() override { deallocate(); }
/// Allocation of a new vector
ArrayDataLayer(UInt size = 0, UInt nb_component = 1, const ID & id = "")
: ArrayBase(id) {
allocate(size, nb_component);
}
/// Allocation of a new vector with a default value
ArrayDataLayer(UInt size, UInt 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.storage(), 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.storage(), 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(UInt size, UInt 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(UInt size, UInt 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 class C,
typename = std::enable_if_t>::value or
aka::is_tensor_proxy>::value>>
inline void push_back(const C & 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);
std::copy_n(new_elem.storage(), new_elem.size(),
values + this->nb_component * (this->size_ - 1));
}
/// changes the allocated size but not the size
virtual void reserve(UInt size, UInt new_size = UInt(-1)) {
UInt tmp_size = this->size_;
if (new_size != UInt(-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(UInt 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;
UInt 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(UInt size, const T & val) {
UInt 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 UInt getMemorySize() const final {
return this->allocated_size * this->nb_component * sizeof(T);
}
/// Get the real size allocated in memory
inline UInt getAllocatedSize() const { return this->allocated_size; }
/// give the address of the memory allocated for this vector
T * storage() const { return values; };
protected:
/// allocation type agnostic data access
T * values{nullptr};
UInt allocated_size{0};
};
/* -------------------------------------------------------------------------- */
template
inline auto Array::operator()(UInt i, UInt 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()(UInt i, UInt 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[](UInt 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[](UInt 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(UInt 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 (UInt j = 0; j < this->nb_component; ++j) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
this->values[i * this->nb_component + j] =
this->values[(this->size_ - 1) * this->nb_component + j];
}
}
this->resize(this->size_ - 1);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
/**
* 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 & other) {
AKANTU_DEBUG_ASSERT((this->size_ == other.size_) &&
(this->nb_component == other.nb_component),
"The too array don't have the same sizes");
T * a = this->values;
T * b = other.storage();
for (UInt 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 & other) {
AKANTU_DEBUG_ASSERT((this->size_ == other.size()) &&
(this->nb_component == other.nb_component),
"The too array don't have the same sizes");
T * a = this->values;
T * b = other.storage();
for (UInt 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
Array & Array::operator*=(const T & alpha) {
T * a = this->values;
for (UInt 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.storage()) {
return true;
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
return std::equal(this->values,
this->values + this->size_ * this->nb_component,
other.storage());
}
/* --------------------------------------------------------------------------
*/
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 class C, typename>
inline void Array::set(const C & vm) {
AKANTU_DEBUG_ASSERT(this->nb_component == vm.size(),
"The size of the object does not "
"match the number of components");
for (T * it = this->values;
it < this->values + this->nb_component * this->size_;
it += this->nb_component) {
std::copy_n(vm.storage(), this->nb_component, it);
}
}
/* --------------------------------------------------------------------------
*/
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");
UInt old_size = this->size_;
this->resize(this->size_ + other.size());
T * tmp = this->values + this->nb_component * old_size;
std::copy_n(other.storage(), other.size() * this->nb_component, tmp);
}
/* --------------------------------------------------------------------------
*/
/* Functions Array */
/* --------------------------------------------------------------------------
*/
template
Array::Array(UInt size, UInt nb_component, const ID & id)
: parent(size, nb_component, id) {}
template <>
inline Array::Array(UInt size, UInt nb_component,
const ID & id)
: parent(size, nb_component, "", id) {}
/* --------------------------------------------------------------------------
*/
template
Array::Array(UInt size, UInt 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
Array &
Array::operator=(const Array & other) {
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
UInt 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 : UInt(-1);
}
/* --------------------------------------------------------------------------
*/
// template UInt Array::find(T elem[]) const
// {
// AKANTU_DEBUG_IN();
// T * it = this->values;
// UInt i = 0;
// for (; i < this->size_; ++i) {
// if (*it == elem[0]) {
// T * cit = it;
// UInt c = 0;
// for (; (c < this->nb_component) && (*cit ==
// elem[c]); ++c, ++cit)
// ;
// if (c == this->nb_component) {
// AKANTU_DEBUG_OUT();
// return i;
// }
// }
// it += this->nb_component;
// }
// return UInt(-1);
// }
/* --------------------------------------------------------------------------
*/
template
template class C, typename>
inline UInt Array::find(const C & elem) {
AKANTU_DEBUG_ASSERT(elem.size() == this->nb_component,
"Cannot find an element with a wrong size ("
<< elem.size() << ") != " << this->nb_component);
return this->find(*elem.storage());
}
/* --------------------------------------------------------------------------
*/
/**
* 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.storage(), 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 (UInt i = 0; i < vect.size(); ++i) {
stream << "{";
for (UInt 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); });
+}
+
+/* -------------------------------------------------------------------------- */
/* Inline Functions ArrayBase */
-/* --------------------------------------------------------------------------
- */
+/* -------------------------------------------------------------------------- */
// inline bool ArrayBase::empty() { return (this->size_ ==
// 0); }
-/* --------------------------------------------------------------------------
- */
+/* -------------------------------------------------------------------------- */
/* Iterators */
-/* --------------------------------------------------------------------------
- */
+/* -------------------------------------------------------------------------- */
template
template
class Array::iterator_internal {
public:
using value_type = R;
using pointer = R *;
using reference = R &;
using const_reference = const R &;
using internal_value_type = IR;
using internal_pointer = IR *;
using difference_type = std::ptrdiff_t;
using iterator_category = std::random_access_iterator_tag;
static_assert(not is_tensor, "Cannot handle tensors");
public:
iterator_internal(pointer data = nullptr) : ret(data), initial(data){};
iterator_internal(const iterator_internal & it) = default;
iterator_internal(iterator_internal && it) noexcept = default;
virtual ~iterator_internal() = default;
inline iterator_internal & operator=(const iterator_internal & it) = default;
inline iterator_internal &
operator=(iterator_internal && it) noexcept = default;
UInt getCurrentIndex() { return (this->ret - this->initial); };
inline reference operator*() { return *ret; };
inline const_reference operator*() const { return *ret; };
inline pointer operator->() { return ret; };
inline daughter & operator++() {
++ret;
return static_cast(*this);
};
inline daughter & operator--() {
--ret;
return static_cast(*this);
};
inline daughter & operator+=(const UInt n) {
ret += n;
return static_cast(*this);
}
inline daughter & operator-=(const UInt n) {
ret -= n;
return static_cast(*this);
}
inline reference operator[](const UInt n) { return ret[n]; }
inline bool operator==(const iterator_internal & other) const {
return ret == other.ret;
}
inline bool operator!=(const iterator_internal & other) const {
return ret != other.ret;
}
inline bool operator<(const iterator_internal & other) const {
return ret < other.ret;
}
inline bool operator<=(const iterator_internal & other) const {
return ret <= other.ret;
}
inline bool operator>(const iterator_internal & other) const {
return ret > other.ret;
}
inline bool operator>=(const iterator_internal & other) const {
return ret >= other.ret;
}
- inline daughter operator-(difference_type n) { return daughter(ret - n); }
- inline daughter operator+(difference_type n) { return daughter(ret + n); }
+ inline daughter operator-(difference_type n) const {
+ return daughter(ret - n);
+ }
+ inline daughter operator+(difference_type n) const {
+ return daughter(ret + n);
+ }
- inline difference_type operator-(const iterator_internal & b) {
+ inline difference_type operator-(const iterator_internal & b) const {
return ret - b.ret;
}
inline pointer data() const { return ret; }
protected:
pointer ret{nullptr};
pointer initial{nullptr};
};
/* --------------------------------------------------------------------------
*/
/**
* Specialization for scalar types
*/
template
template
class Array::iterator_internal {
public:
using value_type = R;
using pointer = R *;
using pointer_type = typename Array