1#ifndef DUNE_COPASI_GRID_CELL_DATA_HH
2#define DUNE_COPASI_GRID_CELL_DATA_HH
7#include <dune/grid/common/mcmgmapper.hh>
9#include <dune/grid/concepts/gridview.hh>
23template<Dune::Concept::Gr
idView GV,
class T>
27 using IndexMapper = MultipleCodimMultipleGeomTypeMapper<GV>;
28 using IndexSet =
typename GV::IndexSet;
37 using Entity =
typename GridView::template Codim<0>::Entity;
40 : _index_mapper{ grid_view, mcmgElementLayout() }
43 if (std::same_as<GridView, typename GridView::Grid::LevelGridView>) {
44 auto entity_it = grid_view.template begin<0>();
45 if (entity_it != grid_view.template end<0>())
46 _grid_view_level.emplace(0);
59 using LeafGridView =
typename GV::Grid::LeafGridView;
60 if constexpr (std::same_as<GV, LeafGridView>) {
61 return std::make_unique<CellData<LeafGridView, T>>(*this);
63 if (_grid_view_level and _grid_view_level.value() != 0)
65 InvalidStateException{},
66 "Leaf grid view cell data can only be made out of other leaf grid view (copy) or a 0-th level grid view (projection)");
69 auto leaf_gv = _index_mapper.gridView().grid().leafGridView();
70 auto leaf_cd = std::make_unique<CellData<LeafGridView, T>>(leaf_gv);
71 leaf_cd->reserve(_keys.size());
73 auto leaf_cap = leaf_cd->capacity();
75 for (
const auto& entity : elements(leaf_gv)) {
76 auto lvl_offset = index(entity) * lvl_cap;
77 auto leaf_offset = leaf_cd->index(entity) * leaf_cap;
78 for (std::size_t
id = 0;
id != sz; ++id) {
79 bool mask = leaf_cd->_cell_mask[leaf_offset + id] = _cell_mask[lvl_offset + id];
80 leaf_cd->_cell_data[leaf_offset + id] = mask ? _cell_data[lvl_offset + id] : std::numeric_limits<T>::quiet_NaN();
83 leaf_cd->_keys = _keys;
89 std::size_t
capacity() const noexcept {
return _cell_data.size() / _index_mapper.size(); }
92 std::size_t
size() const noexcept {
return _keys.size(); }
95 std::size_t
max_size() const noexcept {
return _cell_data.max_size() / _index_mapper.size(); }
98 std::size_t
gridview_size() const noexcept {
return _index_mapper.size(); }
101 const std::vector<std::string>&
keys() const noexcept {
return _keys; }
119 template<std::ranges::input_range R,
120 class Proj = std::identity,
121 std::indirect_unary_predicate<std::projected<std::ranges::iterator_t<R>, Proj>> Pred>
122 requires std::assignable_from<T&, std::ranges::range_value_t<R>>
123 void addData(std::string_view key, R&& r, Pred pred, Proj proj = {})
130 for (std::size_t i = 0; i != _index_mapper.size(); ++i, ++it) {
131 bool mask = _cell_mask[i * cap + ei] = std::invoke(pred, std::invoke(proj, *it));
132 _cell_data[i * cap + ei] = mask ? *it : std::numeric_limits<T>::quiet_NaN();
136 InvalidStateException{},
137 "Range has a size of '{}', but there are '{}' entities in the container",
138 std::ranges::size(r),
139 _index_mapper.size());
142 template<std::ranges::input_range R>
143 requires std::assignable_from<T&, std::ranges::range_value_t<R>>
147 key, std::forward<R>(r), [](
auto&&) {
return std::true_type{}; }, std::identity{});
151 template<std::ranges::input_range R,
152 class Proj = std::identity,
153 std::indirect_unary_predicate<std::projected<std::ranges::iterator_t<R>, Proj>> Pred>
154 requires std::assignable_from<T&, std::tuple_element_t<1, std::ranges::range_value_t<R>>>
155 void addData(std::string_view key, R&& r, Pred pred, Proj proj = {})
161 auto imsz = _index_mapper.size();
162 for (
const auto& [i, val] : r) {
163 if(i >= _index_mapper.size())
164 throw format_exception(RangeError{},
"Key '{}' assinges a values in an index '{}' bigger than the size of the grid view '{}'", key, i, imsz);
165 bool mask = _cell_mask[i * cap + ei] = std::invoke(pred, std::invoke(proj, val));
166 _cell_data[i * cap + ei] = mask ? val : std::numeric_limits<T>::quiet_NaN();
171 template<std::ranges::input_range R>
172 requires std::assignable_from<T&, std::tuple_element_t<1, std::ranges::range_value_t<R>>>
176 key, std::forward<R>(r), [](
auto&&) {
return std::true_type{}; }, std::identity{});
181 std::vector<T>& cell_data,
182 std::vector<bool>& cell_mask)
const
184 auto entity_index = index(entity);
187 cell_data.resize(sz);
188 cell_mask.resize(sz);
189 auto offset = entity_index * cap;
190 for (std::size_t
id = 0;
id != sz; ++id) {
191 bool mask = cell_mask[id] = _cell_mask[offset + id];
192 cell_data[id] = mask ? _cell_data[offset + id] : std::numeric_limits<T>::quiet_NaN();
200 auto entity_index = index(entity);
201 auto data_id = entity_index *
capacity() + id;
202 return _cell_mask[data_id] ? std::make_optional<T>(_cell_data[data_id]) : std::nullopt;
206 std::optional<T>
getData(std::string_view key,
209 auto key_it = std::find(_keys.begin(), _keys.end(), key);
210 if (key_it == _keys.end())
211 throw format_exception(RangeError{},
"Key '{}' does not exist in cell data manager", key);
212 auto id = std::distance(_keys.begin(), key_it);
217 template<Concept::IndexableEntity<IndexSet> E>
218 auto index(
const E& entity)
const
220 if (_grid_view_level and (*_grid_view_level != entity.level())) {
222 while (_entity.level() > *_grid_view_level) {
223 _entity = _entity.father();
225 if (_entity.level() != *_grid_view_level)
227 "Invoking a cell data manager with an entity of lower level than "
228 "the grid view attached to it is an invalid operation!");
229 return _index_mapper.index(_entity);
231 return _index_mapper.index(entity);
235 void pushKey(std::string_view key)
237 auto key_it = std::find(_keys.begin(), _keys.end(), key);
238 if (key_it != _keys.end())
240 InvalidStateException{},
"Key '{}' is already present in the cell data", key);
241 _keys.push_back(std::string{ key });
244 void grow(std::size_t new_size)
248 if (
auto ms =
max_size(); new_size > ms / 2)
254 void realloc(std::size_t new_cap)
257 if (new_cap <
size())
258 throw std::length_error{
"Requested raw capacity is smaller than current size" };
260 throw std::length_error{
"Requested capacity is bigger than maximum size" };
262 std::vector<T> new_cell_data;
263 new_cell_data.reserve(new_cap * _index_mapper.size());
264 auto data_begin = _cell_data.begin();
266 std::vector<bool> new_cell_mask;
267 new_cell_mask.reserve(new_cap * _index_mapper.size());
268 auto mask_begin = _cell_mask.begin();
270 for (std::size_t i = 0; i != _index_mapper.size(); ++i) {
272 auto data_end = std::next(data_begin, cap);
273 new_cell_data.insert(new_cell_data.end(),
274 std::make_move_iterator(data_begin),
275 std::make_move_iterator(data_end));
276 new_cell_data.resize(new_cap * (i + 1), std::numeric_limits<T>::quiet_NaN());
277 data_begin = data_end;
279 auto mask_end = std::next(mask_begin, cap);
280 new_cell_mask.insert(new_cell_mask.end(),
281 std::make_move_iterator(mask_begin),
282 std::make_move_iterator(mask_end));
283 new_cell_mask.resize(new_cap * (i + 1),
false);
284 mask_begin = mask_end;
286 std::swap(_cell_data, new_cell_data);
287 std::swap(_cell_mask, new_cell_mask);
290 IndexMapper _index_mapper;
293 std::optional<int> _grid_view_level;
295 std::vector<std::string> _keys;
297 std::vector<T> _cell_data;
298 std::vector<bool> _cell_mask;
Container for cell data of a grid view.
Definition: cell_data.hh:25
void addData(std::string_view key, R &&r, Pred pred, Proj proj={})
Definition: cell_data.hh:155
GV GridView
Definition: cell_data.hh:34
CellData(GridView grid_view)
Definition: cell_data.hh:39
void addData(std::string_view key, R &&r)
Definition: cell_data.hh:144
void addData(std::string_view key, R &&r)
Definition: cell_data.hh:173
std::size_t size() const noexcept
Number of elements per entity in the container.
Definition: cell_data.hh:92
typename GridView::template Codim< 0 >::Entity Entity
Definition: cell_data.hh:37
void getData(const Concept::IndexableEntity< IndexSet > auto &entity, std::vector< T > &cell_data, std::vector< bool > &cell_mask) const
Definition: cell_data.hh:180
std::size_t max_size() const noexcept
Number of elements per entity that the container can ever hold container.
Definition: cell_data.hh:95
std::optional< T > getData(std::string_view key, const Concept::IndexableEntity< IndexSet > auto &entity) const
Definition: cell_data.hh:206
std::unique_ptr< CellData< typename GV::Grid::LeafGridView, T > > makeLeafGridViewCellData() const
creates a cell data object with a copy data for the leaf grid view
Definition: cell_data.hh:58
std::size_t gridview_size() const noexcept
The size of the gridview - This gives the number of elements in the grid view.
Definition: cell_data.hh:98
void addData(std::string_view key, R &&r, Pred pred, Proj proj={})
Definition: cell_data.hh:123
const std::vector< std::string > & keys() const noexcept
Return the keys of the cell data.
Definition: cell_data.hh:101
std::optional< T > getData(std::size_t id, const Concept::IndexableEntity< IndexSet > auto &entity) const
Definition: cell_data.hh:197
void reserve(std::size_t new_cap)
Reservers new_cap elements per entity in the container.
Definition: cell_data.hh:106
std::size_t capacity() const noexcept
Number of elements per entity that the container has currently allocated space for.
Definition: cell_data.hh:89
void shrink_to_fit()
Definition: cell_data.hh:112
Definition: axis_names.hh:7
auto format_exception(Exception &&e, fmt::format_string< Args... > format, Args &&... args)
Definition: exceptions.hh:23