3 #include <Caribou/config.h>
4 #include <Caribou/Topology/BaseMesh.h>
5 #include <Caribou/Topology/Domain.h>
11 namespace caribou::topology {
14 UNSIGNED_INTEGER_TYPE WorldDimension,
15 typename MatrixType = Eigen::Matrix<FLOATING_POINT_TYPE, Eigen::Dynamic, WorldDimension, (WorldDimension>1?Eigen::RowMajor:Eigen::ColMajor)>>
18 using PositionsContainer = MatrixType;
20 static_assert(std::is_base_of_v<Eigen::MatrixBase<PositionsContainer>, PositionsContainer>,
"The matrix type must inherit Eigen::MatrixBase");
21 static_assert(Eigen::MatrixBase<PositionsContainer>::ColsAtCompileTime == WorldDimension,
"The matrix type must have N columns at compile time for a mesh of dimension N.");
22 static_assert(WorldDimension == 1 or WorldDimension == 2 or WorldDimension == 3,
"The world dimension must be 1, 2 or 3.");
24 static constexpr INTEGER_TYPE Dimension = WorldDimension;
25 using Real =
typename PositionsContainer::Scalar;
26 using WorldCoordinates = Eigen::Matrix<Real, 1, Dimension>;
28 template <
typename Element,
typename NodeIndex = UNSIGNED_INTEGER_TYPE>
29 using Domain = Domain<Mesh<Dimension, MatrixType>, Element, NodeIndex>;
46 explicit Mesh(
const std::vector<WorldCoordinates> & positions) {
47 p_positions.resize(positions.size(), Dimension);
48 for (std::size_t i = 0; i < positions.size(); ++i) {
49 p_positions.row(
static_cast<Eigen::Index
>(i)) = positions[i];
58 explicit Mesh(
const MatrixType & positions) : p_positions(positions) {}
65 template <
typename EigenDerived>
66 explicit Mesh(
const EigenDerived * positions) : p_positions(*positions) {}
70 : p_positions(other.p_positions) {}
88 inline auto dimension() const -> UNSIGNED_INTEGER_TYPE final {
97 return p_domains.size();
104 inline auto number_of_nodes() const -> UNSIGNED_INTEGER_TYPE final {
return p_positions.rows();};
111 std::vector<std::pair<std::string, const BaseDomain *>> domains;
112 domains.reserve(p_domains.size());
113 for (
const auto & d : p_domains) {
114 domains.emplace_back(d.first, d.second.get());
126 (i < p_domains.size()) &&
127 "Trying to get a domain outside from a domain id larger than the number of domains."
130 return p_domains[i].second.get();
136 for (
const auto & d : p_domains) {
137 if (d.first == name) {
138 return d.second.get();
153 template<
typename Element,
typename NodeIndex,
typename... Args>
158 for (
const auto & d : p_domains) {
159 if (d.first == name) {
160 throw std::domain_error(std::string(
"A domain with the name ") + name +
" already exists.");
164 auto domain_ptr =
new Domain<Element, NodeIndex>(
this, std::forward<Args>(args)...);
165 auto res = p_domains.emplace(p_domains.end(), name, std::unique_ptr<BaseDomain>(
static_cast<BaseDomain *
>(domain_ptr)));
170 return static_cast<Domain<Element, NodeIndex>*
> (
nullptr);
182 template<
typename Element,
typename NodeIndex,
typename... Args>
188 auto domain_ptr =
new Domain<Element, NodeIndex>(
this, std::forward<Args>(args)...);
190 std::ostringstream ss;
191 ss <<
"domain_" << domain_ptr;
193 auto res = p_domains.emplace(p_domains.end(), ss.str(), std::unique_ptr<BaseDomain>(
static_cast<BaseDomain *
>(domain_ptr)));
198 return static_cast<Domain<Element, NodeIndex>*
> (
nullptr);
210 template<
typename Element,
typename... Args>
211 inline auto add_domain(
const std::string & name, Args ...args) -> Domain<Element> * {
213 return add_domain<Element, UNSIGNED_INTEGER_TYPE, Args...>(name, std::forward<Args>(args)...);
224 template<
typename Element,
typename... Args>
225 inline auto add_domain(
const char * name, Args ...args) -> Domain<Element> * {
226 return add_domain<Element, Args...>(std::string(name), std::forward<Args>(args)...);
236 template<
typename Element,
typename... Args>
239 auto domain_ptr =
new Domain<Element>(
this, std::forward<Args>(args)...);
241 std::ostringstream ss;
242 ss <<
"domain_" << domain_ptr;
244 auto res = p_domains.emplace(p_domains.end(), ss.str(), std::unique_ptr<BaseDomain>(
static_cast<BaseDomain *
>(domain_ptr)));
249 return static_cast<Domain<Element>*
> (
nullptr);
259 auto it = p_domains.begin();
260 while (it != p_domains.end() and it->first != name);
261 if (it != p_domains.end()) {
274 auto it = p_domains.begin();
275 while (it != p_domains.end() and it->second.get() != domain);
276 if (it != p_domains.end()) {
287 inline auto position(UNSIGNED_INTEGER_TYPE index)
const {
288 caribou_assert(
static_cast<Eigen::Index
>(index) < p_positions.rows()
289 &&
"Trying to access the position vector at a node index greater "
290 "than the number of nodes in the mesh.");
291 return p_positions.row(index);
308 template <
typename IntegerType, std::
size_t N>
309 inline auto positions(
const IntegerType(&indices)[N])
const {
310 Eigen::Matrix<Real, N, Dimension, (Dimension>1?Eigen::RowMajor:Eigen::ColMajor)> positions;
311 for (std::size_t i = 0; i < N; ++i) {
312 positions.row(i) = p_positions.row(indices[i]);
332 template <
typename IntegerType, std::
size_t N>
333 inline auto positions(
const std::array<IntegerType, N> & indices)
const {
334 return positions<IntegerType, N>(indices.data());
352 template <
typename IntegerType>
353 inline auto positions(
const std::vector<IntegerType> & indices)
const {
354 const auto number_of_indices = indices.size();
355 Eigen::Matrix<Real, Eigen::Dynamic, Dimension, (Dimension == 1) ? Eigen::ColMajor : Eigen::RowMajor> positions;
356 positions.resize(number_of_indices, Dimension);
357 for (std::size_t i = 0; i < number_of_indices; ++i) {
358 positions.row(i) = p_positions.row(indices[i]);
379 template <
typename EigenDerived>
380 inline auto positions(
const Eigen::EigenBase<EigenDerived> & indices)
const {
381 static_assert(EigenDerived::RowsAtCompileTime == 1 or EigenDerived::ColsAtCompileTime == 1,
382 "Only vector type matrix can be used as the indices container.");
383 const auto number_of_indices = indices.size();
385 EigenDerived::RowsAtCompileTime == 1 ? EigenDerived::ColsAtCompileTime : EigenDerived::RowsAtCompileTime,
387 (Dimension>1 ? Eigen::RowMajor : Eigen::ColMajor)> positions;
388 positions.resize(number_of_indices, Dimension);
389 for (Eigen::Index i = 0; i < number_of_indices; ++i) {
390 positions.row(i) = p_positions.row(indices.derived()[i]);
400 swap(first.p_positions, second.p_positions);
404 PositionsContainer p_positions;
405 std::vector<std::pair<std::string, std::unique_ptr<BaseDomain>>> p_domains;
409 template <
typename MatrixType>
410 Mesh(
const MatrixType &) -> Mesh<MatrixType::ColsAtCompileTime, MatrixType>;
412 template <
typename MatrixType>
413 Mesh(
const MatrixType *) ->
415 MatrixType::ColsAtCompileTime,
417 const std::decay_t<MatrixType>,
418 Eigen::internal::traits<MatrixType>::Alignment,
419 Eigen::Stride<MatrixType::OuterStrideAtCompileTime,MatrixType::InnerStrideAtCompileTime>