Line data Source code
1 : // This file is part of the Mamico project. For conditions of distribution
2 : // and use, please see the copyright notice in Mamico's main folder
3 : #pragma once
4 :
5 : #include "coupling/CouplingMDDefinitions.h"
6 : #include "coupling/datastructures/CouplingCell.h"
7 : #include "coupling/datastructures/FlexibleCellContainer.h"
8 : #include "coupling/indexing/IndexingService.h"
9 : #include <cstddef>
10 : #include <iostream>
11 : #include <iterator>
12 : #include <utility>
13 : #include <vector>
14 :
15 : namespace coupling {
16 : namespace datastructures {
17 : template <unsigned int dim> class FlexibleCellContainer;
18 : }
19 : } // namespace coupling
20 :
21 : /**
22 : * @brief provides access to coupling cells, which may belong to different indexing domains
23 : *
24 : * The FlexibleCellContainer is intended for use in cell domains which do not neatly correspond to a predefined indexing domain. For example, a CellContainer
25 : * cannot store cells in the macro2md overlap layers, and hence a FlexibleCellContainer is needed. Due to the "holes" expected due to the
26 : * non-contiguous nature of this container, index-based access is not possible or expected.
27 : * @tparam dim Number of dimensions; it can be 1, 2 or 3
28 : */
29 :
30 36 : template <unsigned int dim> class coupling::datastructures::FlexibleCellContainer {
31 : public:
32 8 : FlexibleCellContainer() {}
33 36 : FlexibleCellContainer(std::vector<coupling::datastructures::CouplingCell<dim>*> couplingCells, std::vector<I01> idxs) {
34 : #if (COUPLING_MD_DEBUG == COUPLING_MD_YES)
35 : if (couplingCells.size() != idxs.size()) {
36 : std::cout << "ERROR size of index vector and coupling cell vector sent to FlexibleCellContainer constructor do not match";
37 : exit(EXIT_FAILURE);
38 : }
39 : #endif
40 36 : _couplingCells.reserve(couplingCells.size());
41 36 : _idxs.reserve(idxs.size());
42 396 : for (std::size_t i = 0; i < couplingCells.size(); ++i) {
43 360 : _couplingCells.push_back(couplingCells[i]);
44 360 : _idxs.push_back(idxs[i]);
45 : }
46 36 : }
47 :
48 : template <class Container_T> FlexibleCellContainer(Container_T cells) {
49 : if constexpr (std::is_same_v<Container_T, FlexibleCellContainer>) {
50 : _idxs = cells._idxs;
51 : _couplingCells = cells._couplingCells;
52 : } else {
53 : auto numCells = cells.size();
54 : _idxs.reserve(numCells);
55 : _couplingCells.reserve(numCells);
56 : for (auto pair : cells)
57 : *this << pair;
58 : }
59 : }
60 :
61 : /** Adds a new coupling cell to the datastructure at the next index
62 : * @param cell a pointer to the cell to be inserted
63 : */
64 44 : void operator<<(std::pair<coupling::datastructures::CouplingCell<dim>*, I01> pair) {
65 44 : I01 idx;
66 : coupling::datastructures::CouplingCell<dim>* couplingCell;
67 44 : std::tie(couplingCell, idx) = pair;
68 44 : _couplingCells.push_back(couplingCell);
69 44 : _idxs.push_back(idx);
70 44 : }
71 :
72 : /**
73 : * Returns size of the underlying container.
74 : *
75 : * The number of indices stored should be equal to the number of cells stored, hence returning either is okay
76 : * @return the number of cells stored currently
77 : */
78 8 : unsigned int size() const { return _couplingCells.size(); }
79 :
80 : /**
81 : * @brief Provides iterator functionality (increment, access as <*cell, index> pair, equality)
82 : */
83 : class Iterator {
84 : public:
85 : using CouplingCellIterator = typename std::vector<coupling::datastructures::CouplingCell<dim>*>::const_iterator;
86 : using IndexIterator = std::vector<I01>::const_iterator;
87 :
88 140 : Iterator(CouplingCellIterator itCouplingCells, IndexIterator itIdxs) : _itCouplingCells(itCouplingCells), _itIdxs(itIdxs) {}
89 :
90 : /**
91 : * Iterator access, returning the data at the current iterator location
92 : *
93 : * @return a std::pair with the cell pointer and the index of the data that the iterator points to
94 : */
95 408 : const std::pair<coupling::datastructures::CouplingCell<dim>*, I01> operator*() const { return std::make_pair(*_itCouplingCells, *_itIdxs); }
96 :
97 320 : Iterator& operator++() {
98 120 : ++_itCouplingCells;
99 320 : ++_itIdxs;
100 120 : return *this;
101 : }
102 :
103 200 : Iterator operator++(int) {
104 200 : Iterator tmp = *this;
105 200 : ++(*this);
106 200 : return tmp;
107 : }
108 :
109 56 : friend bool operator==(const Iterator& a, const Iterator& b) { return a._itCouplingCells == b._itCouplingCells && a._itIdxs == b._itIdxs; }
110 :
111 232 : friend bool operator!=(const Iterator& a, const Iterator& b) { return !(a == b); }
112 :
113 : private:
114 : /**Iterator to underlying cell* vector */
115 : CouplingCellIterator _itCouplingCells;
116 :
117 : /**Iterator to underlying index vector */
118 : IndexIterator _itIdxs;
119 : };
120 : /** Provides pointer to beginning of iterator of this container */
121 44 : Iterator begin() const { return Iterator(_couplingCells.begin(), _idxs.begin()); }
122 :
123 : /** Provides pointer to end of iterator of this container */
124 96 : Iterator end() const { return Iterator(_couplingCells.end(), _idxs.end()); }
125 :
126 : private:
127 : /**Vector to store pointers to cells */
128 : std::vector<coupling::datastructures::CouplingCell<dim>*> _couplingCells;
129 :
130 : /**Vector to store indices corresponding to cells in container
131 : * Since the cells can be part of any domain, they're stores as I01 (global noghost) type.
132 : */
133 : std::vector<I01> _idxs;
134 : };
|