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 : };