CoMMA 1.3.2
A geometric agglomerator for unstructured meshes
Loading...
Searching...
No Matches
Neighbourhood.h
Go to the documentation of this file.
1#ifndef COMMA_PROJECT_FIRST_ORDER_NEIGHBOURHOOD_H
2#define COMMA_PROJECT_FIRST_ORDER_NEIGHBOURHOOD_H
3
4/*
5 * CoMMA
6 *
7 * Copyright © 2024 ONERA
8 *
9 * Authors: Nicolas Lantos, Alberto Remigi, and Riccardo Milani
10 * Contributors: Karim Anemiche
11 *
12 * This Source Code Form is subject to the terms of the Mozilla Public
13 * License, v. 2.0. If a copy of the MPL was not distributed with this
14 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
15 */
16
17#include <algorithm>
18#include <cassert>
19#include <deque>
20#include <memory>
21#include <queue>
22#include <set>
23#include <unordered_set>
24#include <vector>
25
26#include "CoMMA/Util.h"
27
28namespace comma {
29
38template<
39 typename CoMMAIndexType,
40 typename CoMMAWeightType,
41 typename CoMMAIntType>
43#if 0
44Some remarks about the implementation. All the work is done in the function "update",
45hence that is where we have to focus on. There are only two constraints for the
46returned object: it should be an iterable, and the content (the indices of the neighbours)
47must be ordered using their weights. An ordered set of pair of (index, weight) with
48CustomPairGreaterFunctor as comparator would not work as because we want unique indices
49and that would have been quite hard to achieve even if defining a custom operator==,
50have a look here, https://stackoverflow.com/a/1114862
51We still use sets, but we have an extra check before inserting whether there already is
52a pair with the same index.
53#endif
54
55public:
57 using CoMMAPairType = std::pair<CoMMAIndexType, CoMMAWeightType>;
60 std::set<CoMMAPairType, CustomPairGreaterFunctor<CoMMAPairType>>;
65 using CandidatesContainerType = std::deque<CoMMAIndexType>;
67 using ContainerIndexType = std::vector<CoMMAIndexType>;
69 using ContainerIndexConstIt = typename ContainerIndexType::const_iterator;
70
78 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
79 const std::vector<CoMMAWeightType> &weights
80 ) :
81 _s_neighbours_of_seed(std::move(s_neighbours_of_seed)),
82 _weights(weights),
83 _s_fc(),
84 _candidates() {}
85
89 ) = default;
90
92 virtual ~Neighbourhood() = default;
93
101 inline void update(
102 const CoMMAIndexType new_fc, const ContainerIndexType &new_neighbours
103 ) {
104 update_it(new_fc, new_neighbours.cbegin(), new_neighbours.cend());
105 }
106
116 virtual void update_it(
117 const CoMMAIndexType new_fc,
118 ContainerIndexConstIt neighs_begin,
119 ContainerIndexConstIt neighs_end
120 ) = 0;
121
127 return this->_candidates;
128 }
129
130protected:
135 const std::unordered_set<CoMMAIndexType> _s_neighbours_of_seed;
136
138 const std::vector<CoMMAWeightType> &_weights;
139
141 std::unordered_set<CoMMAIndexType> _s_fc;
142
147
152 const CoMMASetOfPairType &candidates_w_weights
153 ) {
154 for (const auto &[idx, w] : candidates_w_weights)
155 this->_candidates.push_back(idx);
156 }
157};
158
167template<
168 typename CoMMAIndexType,
169 typename CoMMAWeightType,
170 typename CoMMAIntType>
172 public Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
173public:
188
196 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
197 const std::vector<CoMMAWeightType> &weights
198 ) :
199 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
200 s_neighbours_of_seed, weights
201 ) {}
202
206 &other
207 ) = default;
208
210 ~Neighbourhood_Extended() override = default;
211
222 const CoMMAIndexType new_fc,
223 ContainerIndexConstIt neighs_begin,
224 ContainerIndexConstIt neighs_end
225 ) override {
226 // Add new_fc to current CC and remove it from previous neighbourhoods
227 this->_s_fc.insert(new_fc);
228 auto new_fc_ptr =
229 std::find(this->_candidates.begin(), this->_candidates.end(), new_fc);
230 if (new_fc_ptr != this->_candidates.end())
231 this->_candidates.erase(new_fc_ptr);
232
233 // Compute the set of direct neighbours allowed by original
234 // neighbourhood-order
235 CoMMASetOfPairType neighs;
236 for (auto it_fc = neighs_begin; it_fc != neighs_end; ++it_fc) {
237 if ((std::find(this->_candidates.begin(), this->_candidates.end(), *it_fc)
238 == this->_candidates.end())
239 && (this->_s_fc.count(*it_fc) == 0)
240 && (this->_s_neighbours_of_seed.count(*it_fc) > 0)) {
241 // If not yet in the FON, not yet in the coarse cell and among the
242 // allowed neighbours, insert
243 neighs.emplace(*it_fc, this->_weights[*it_fc]);
244 }
245 }
246 // Just add new candidates at the back. This will leave candidates closer to
247 // the original seed at the top, hence giving them a slightly higher
248 // priority
249 this->extract_and_update_candidates(neighs);
250 }
251};
252
262template<
263 typename CoMMAIndexType,
264 typename CoMMAWeightType,
265 typename CoMMAIntType>
267 public Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
268public:
283
292 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
293 const std::vector<CoMMAWeightType> &weights,
294 CoMMAIntType dimension
295 ) :
296 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
297 s_neighbours_of_seed, weights
298 ),
300 _dimension(dimension) {}
301
304 CoMMAIndexType,
305 CoMMAWeightType,
306 CoMMAIntType> &other) = default;
307
309 ~Neighbourhood_Pure_Front() override = default;
310
321 const CoMMAIndexType new_fc,
322 ContainerIndexConstIt neighs_begin,
323 ContainerIndexConstIt neighs_end
324 ) override {
325 this->_candidates.clear();
326 // Add new_fc to current CC and remove it from previous neighbourhoods
327 this->_s_fc.insert(new_fc);
328 for (auto &queue : this->_q_neighs_w_weights) {
329 // There is erase_if for sets in C++20
330 // erase_if(queue, [&new_fc](const CoMMAPairType &p){return p.first ==
331 // new_fc;});
332 auto it = std::find_if(
333 queue.begin(), queue.end(), CoMMAPairFindFirstBasedType(new_fc)
334 );
335 //[&new_fc](const CoMMAPairType &p){return p.first == new_fc;});
336 if (it != queue.end()) queue.erase(it);
337 }
338
339 // Compute the set of direct neighbours allowed by original
340 // neighbourhood-order
342 for (auto it_fc = neighs_begin; it_fc != neighs_end; ++it_fc) {
343 if ((this->_s_fc.count(*it_fc) == 0)
344 && (this->_s_neighbours_of_seed.count(*it_fc) > 0)) {
345 // If not yet in coarse cell and among the allowed neighbours, insert
346 curr_set.emplace(*it_fc, this->_weights[*it_fc]);
347 }
348 }
349
350 this->_q_neighs_w_weights.push_front(curr_set);
351
352 // Now, see which neighbours to return. Here is the strategy:
353 // If most recent list is not empty, return it. If not, check the oldest
354 // list: if not empty return it, otherwise check the previous list. If
355 // empty, check the second oldest, and so on... We grant ourselves one
356 // exception...
357 if (this->_q_neighs_w_weights.size()
358 <= static_cast<decltype(this->_q_neighs_w_weights.size())>(
359 this->_dimension
360 )) {
361 // If at the (very) beginning of the agglomeration, still consider every
362 // possible neighbour. This will allow to obtain nice quads from quads
363 // TODO[RM]: I think this workaround is needed because we are not able to
364 // compute exactly the AR; if we ever we will be able we should try to
365 // remove it
366 for (auto prev_q = this->_q_neighs_w_weights.begin() + 1;
367 prev_q != this->_q_neighs_w_weights.end();
368 ++prev_q)
369 curr_set.insert(prev_q->begin(), prev_q->end());
370 this->extract_and_update_candidates(curr_set);
371 } else {
372 auto cur_front = decltype(this->_q_neighs_w_weights.size()){0};
373 auto cur_back = decltype(this->_q_neighs_w_weights.size()
374 ){this->_q_neighs_w_weights.size() - 1};
375 while (cur_front <= cur_back) {
376 // typename decltype(this->_q_neighs_w_weights)::iterator it =
377 auto it = this->_q_neighs_w_weights.begin() + (cur_front++);
378 if (!it->empty()) {
380 break;
381 }
382 it = this->_q_neighs_w_weights.begin() + (cur_back--);
383 if (!it->empty()) {
385 break;
386 }
387 }
388 }
389 }
390
397 const CoMMAIntType lvl
398 ) const {
399 assert(
400 lvl >= 0
401 && lvl < static_cast<CoMMAIntType>(this->_q_neighs_w_weights.size())
402 );
403 return this->_q_neighs_w_weights[lvl];
404 }
405
406protected:
409 std::deque<CoMMASetOfPairType> _q_neighs_w_weights;
410
413 CoMMAIntType _dimension;
414};
415
423template<
424 typename CoMMAIndexType,
425 typename CoMMAWeightType,
426 typename CoMMAIntType>
428public:
432
435
437 virtual ~NeighbourhoodCreator() = default;
438
448 virtual std::shared_ptr<NeighbourhoodBaseType> create(
449 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
450 const std::vector<CoMMAWeightType> &priority_weights,
451 const CoMMAIntType dimension
452 ) const = 0;
453
458 virtual std::shared_ptr<NeighbourhoodBaseType> clone(
459 std::shared_ptr<NeighbourhoodBaseType> other
460 ) const = 0;
461};
462
470template<
471 typename CoMMAIndexType,
472 typename CoMMAWeightType,
473 typename CoMMAIntType>
475 public NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
476public:
487
490 CreatorBaseType() {}
491
493 ~NeighbourhoodExtendedCreator() override = default;
494
505 inline std::shared_ptr<NeighbourhoodBaseType> create(
506 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
507 const std::vector<CoMMAWeightType> &priority_weights,
508 const CoMMAIntType dimension
509 ) const override {
510 CoMMAUnused(dimension);
511 return std::make_shared<NeighbourhoodDerivedType>(
512 s_neighbours_of_seed, priority_weights
513 );
514 }
515
521 inline std::shared_ptr<NeighbourhoodBaseType> clone(
522 std::shared_ptr<NeighbourhoodBaseType> other
523 ) const override {
524 // Using copy-constructor
525 return std::make_shared<NeighbourhoodDerivedType>(
526 *std::dynamic_pointer_cast<NeighbourhoodDerivedType>(other)
527 );
528 }
529};
530
538template<
539 typename CoMMAIndexType,
540 typename CoMMAWeightType,
541 typename CoMMAIntType>
543 public NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
544public:
555
558 CreatorBaseType() {}
559
561 ~NeighbourhoodPureFrontCreator() override = default;
562
573 inline std::shared_ptr<NeighbourhoodBaseType> create(
574 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
575 const std::vector<CoMMAWeightType> &priority_weights,
576 const CoMMAIntType dimension
577 ) const override {
578 return std::make_shared<NeighbourhoodDerivedType>(
579 s_neighbours_of_seed, priority_weights, dimension
580 );
581 }
582
588 inline std::shared_ptr<NeighbourhoodBaseType> clone(
589 std::shared_ptr<NeighbourhoodBaseType> other
590 ) const override {
591 // Using copy-constructor
592 return std::make_shared<NeighbourhoodDerivedType>(
593 *std::dynamic_pointer_cast<NeighbourhoodDerivedType>(other)
594 );
595 }
596};
597
598} // end namespace comma
599
600#endif // COMMA_PROJECT_FIRST_ORDER_NEIGHBOURHOOD_H
#define CoMMAUnused(var)
Convenient function to avoid unused warnings.
Definition: Util.h:38
Class representing the neighbourhood of a given cell in the graph. In this derived class the neighbou...
Definition: Neighbourhood.h:172
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Neighbourhood.h:60
void update_it(const CoMMAIndexType new_fc, ContainerIndexConstIt neighs_begin, ContainerIndexConstIt neighs_end) override
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
Definition: Neighbourhood.h:221
Neighbourhood_Extended(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &weights)
Constructor.
Definition: Neighbourhood.h:195
~Neighbourhood_Extended() override=default
Destructor.
Neighbourhood_Extended(const Neighbourhood_Extended< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > &other)=default
Copy constructor.
typename ContainerIndexType::const_iterator ContainerIndexConstIt
Type for constant iterators of containers of indices.
Definition: Neighbourhood.h:69
Class representing the neighbourhood of a given cell in the graph. In this derived class,...
Definition: Neighbourhood.h:267
~Neighbourhood_Pure_Front() override=default
Destructor.
void update_it(const CoMMAIndexType new_fc, ContainerIndexConstIt neighs_begin, ContainerIndexConstIt neighs_end) override
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
Definition: Neighbourhood.h:320
Neighbourhood_Pure_Front(const Neighbourhood_Pure_Front< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > &other)=default
Copy constructor.
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Neighbourhood.h:60
const CoMMASetOfPairType & get_neighbours_by_level(const CoMMAIntType lvl) const
Get the neighbours from a previous stage.
Definition: Neighbourhood.h:396
std::deque< CoMMASetOfPairType > _q_neighs_w_weights
History of the first-order-neighbourhoods of the fine cells recently agglomerated.
Definition: Neighbourhood.h:409
CoMMAIntType _dimension
Dimensionality of the problem (_dimension = 2 -> 2D, _dimension = 3 -> 3D)
Definition: Neighbourhood.h:413
Neighbourhood_Pure_Front(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &weights, CoMMAIntType dimension)
Constructor.
Definition: Neighbourhood.h:291
typename ContainerIndexType::const_iterator ContainerIndexConstIt
Type for constant iterators of containers of indices.
Definition: Neighbourhood.h:69
Pure abstract class for a creator of Neighbourhood objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:427
virtual std::shared_ptr< NeighbourhoodBaseType > clone(std::shared_ptr< NeighbourhoodBaseType > other) const =0
Create a new Neighbourhood object by copy.
Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > NeighbourhoodBaseType
Shortcut for the Neighborhood object type.
Definition: Neighbourhood.h:431
virtual ~NeighbourhoodCreator()=default
Destructor.
NeighbourhoodCreator()=default
Constructor.
virtual std::shared_ptr< NeighbourhoodBaseType > create(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &priority_weights, const CoMMAIntType dimension) const =0
Create a new Neighbourhood object from scratch using the given arguments.
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:475
~NeighbourhoodExtendedCreator() override=default
Destructor.
std::shared_ptr< NeighbourhoodBaseType > create(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &priority_weights, const CoMMAIntType dimension) const override
Create a new Neighbourhood object from scratch using the given arguments.
Definition: Neighbourhood.h:505
NeighbourhoodExtendedCreator()
Constructor.
Definition: Neighbourhood.h:489
std::shared_ptr< NeighbourhoodBaseType > clone(std::shared_ptr< NeighbourhoodBaseType > other) const override
Create a new Neighbourhood object by copy.
Definition: Neighbourhood.h:521
Class representing the neighbourhood of a given cell in the graph. Mind that no information about the...
Definition: Neighbourhood.h:42
const std::vector< CoMMAWeightType > & _weights
Priority weights.
Definition: Neighbourhood.h:138
PairFindFirstBasedFunctor< CoMMAPairType > CoMMAPairFindFirstBasedType
Functor used if find-like function relying only on first element of the pair.
Definition: Neighbourhood.h:63
Neighbourhood(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &weights)
Constructor.
Definition: Neighbourhood.h:77
const std::unordered_set< CoMMAIndexType > _s_neighbours_of_seed
Set of the neighbours of seed given as an input in the constructor. Here, we can find all the neighbo...
Definition: Neighbourhood.h:135
void update(const CoMMAIndexType new_fc, const ContainerIndexType &new_neighbours)
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
Definition: Neighbourhood.h:101
const CandidatesContainerType & get_candidates() const
Get candidates that should be consider in the next step of the agglomeration.
Definition: Neighbourhood.h:126
CandidatesContainerType _candidates
Candidates that should be considered when choosing the next fine cell to add to the coarse one.
Definition: Neighbourhood.h:146
std::deque< CoMMAIndexType > CandidatesContainerType
Type for container of candidates.
Definition: Neighbourhood.h:65
std::vector< CoMMAIndexType > ContainerIndexType
Type for containers of indices.
Definition: Neighbourhood.h:67
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Neighbourhood.h:60
Neighbourhood(const Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > &other)=default
Copy constructor.
std::unordered_set< CoMMAIndexType > _s_fc
Set of the fine cells composing the coarse cell.
Definition: Neighbourhood.h:141
void extract_and_update_candidates(const CoMMASetOfPairType &candidates_w_weights)
Extract the indices from a list of index-weight pairs and add them at the back of the candidates list...
Definition: Neighbourhood.h:151
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Neighbourhood.h:57
virtual void update_it(const CoMMAIndexType new_fc, ContainerIndexConstIt neighs_begin, ContainerIndexConstIt neighs_end)=0
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
virtual ~Neighbourhood()=default
Destructor.
typename ContainerIndexType::const_iterator ContainerIndexConstIt
Type for constant iterators of containers of indices.
Definition: Neighbourhood.h:69
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:543
NeighbourhoodPureFrontCreator()
Constructor.
Definition: Neighbourhood.h:557
std::shared_ptr< NeighbourhoodBaseType > clone(std::shared_ptr< NeighbourhoodBaseType > other) const override
Create a new Neighbourhood object by copy.
Definition: Neighbourhood.h:588
~NeighbourhoodPureFrontCreator() override=default
Destructor.
std::shared_ptr< NeighbourhoodBaseType > create(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &priority_weights, const CoMMAIntType dimension) const override
Create a new Neighbourhood object from scratch using the given arguments.
Definition: Neighbourhood.h:573
Functor implementing an operator telling if a given value if the first one of pair.
Definition: Util.h:258
Definition: Agglomerator.h:37
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:201