diff --git a/_agglomerator_8h_source.html b/_agglomerator_8h_source.html index 627a030..8b53243 100644 --- a/_agglomerator_8h_source.html +++ b/_agglomerator_8h_source.html @@ -152,1252 +152,1345 @@
76 cc_graph,
77 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
78 seeds_pool,
-
79 CoMMAIntType dimension = 3) :
-
80 _dimension(dimension),
-
81 _fc_graph(graph),
-
82 _cc_graph(cc_graph),
-
83 _seeds_pool(seeds_pool) {
-
84 if ((_dimension != 2) && (_dimension != 3)) {
-
85 throw std::range_error("dimension can only be 2 or 3");
-
86 }
-
87 if (_dimension == 2) {
-
88 _min_neighbourhood = 2;
-
89 _compute_AR = [](const CoMMAWeightType diam, const CoMMAWeightType area)
-
90 -> CoMMAWeightType { return diam / sqrt(area); };
-
91 } else {
-
92 _min_neighbourhood = 3;
-
93 _compute_AR = [](const CoMMAWeightType diam, const CoMMAWeightType vol)
-
94 -> CoMMAWeightType { return diam / cbrt(vol); };
-
95 }
-
96 _l_nb_of_cells.push_back(graph->_number_of_cells);
-
97 }
-
98
-
100 virtual ~Agglomerator() = default;
+
79 CoMMAIntType dimension = 3
+
80 ) :
+
81 _dimension(dimension),
+
82 _fc_graph(graph),
+
83 _cc_graph(cc_graph),
+
84 _seeds_pool(seeds_pool) {
+
85 if ((_dimension != 2) && (_dimension != 3)) {
+
86 throw std::range_error("dimension can only be 2 or 3");
+
87 }
+
88 if (_dimension == 2) {
+
89 _min_neighbourhood = 2;
+
90 _compute_AR = [](
+
91 const CoMMAWeightType diam, const CoMMAWeightType area
+
92 ) -> CoMMAWeightType { return diam / sqrt(area); };
+
93 } else {
+
94 _min_neighbourhood = 3;
+
95 _compute_AR = [](
+
96 const CoMMAWeightType diam, const CoMMAWeightType vol
+
97 ) -> CoMMAWeightType { return diam / cbrt(vol); };
+
98 }
+
99 _l_nb_of_cells.push_back(graph->_number_of_cells);
+
100 }
101
-
105 inline std::vector<CoMMAIndexType> get_fc_2_cc() const {
-
106 return _cc_graph->_fc_2_cc;
-
107 }
-
108
-
120 virtual void agglomerate_one_level(
-
121 const CoMMAIntType goal_card,
-
122 const CoMMAIntType min_card,
-
123 const CoMMAIntType max_card,
-
124 const std::vector<CoMMAWeightType> &priority_weights,
-
125 bool correction_steps) = 0;
-
126
-
127protected:
-
130 CoMMAIntType _dimension;
-
133 CoMMAIntType _min_neighbourhood = 3;
-
136 CoMMAIntType _min_card = 0;
-
140 CoMMAIntType _max_card = 0;
-
144 CoMMAIntType _goal_card = 0;
-
148 CoMMAIntType _threshold_card = 0;
-
150 std::vector<CoMMAIndexType> _l_nb_of_cells;
-
154 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
155 _fc_graph;
-
158 std::shared_ptr<
-
159 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
160 _cc_graph;
-
164 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
165 _seeds_pool;
-
166};
-
167
-
176template<
-
177 typename CoMMAIndexType,
-
178 typename CoMMAWeightType,
-
179 typename CoMMAIntType>
-
180class Agglomerator_Anisotropic :
-
181 public Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
182public:
-
184 using AnisotropicLine = std::deque<CoMMAIndexType>;
-
185
-
187 using AnisotropicLinePtr = std::shared_ptr<AnisotropicLine>;
-
188
-
190 using CoMMAPairType = std::pair<CoMMAIndexType, CoMMAWeightType>;
-
192 using CoMMASetOfPairType =
-
193 std::set<CoMMAPairType, CustomPairGreaterFunctor<CoMMAPairType>>;
-
194
-
219 Agglomerator_Anisotropic(
-
220 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
221 graph,
-
222 std::shared_ptr<
-
223 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
224 cc_graph,
-
225 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
226 seeds_pool,
-
227 const CoMMAWeightType threshold_anisotropy,
-
228 const std::vector<CoMMAIndexType> &agglomerationLines_Idx,
-
229 const std::vector<CoMMAIndexType> &agglomerationLines,
-
230 const std::vector<CoMMAWeightType> &priority_weights,
-
231 const bool build_lines,
-
232 const bool odd_line_length,
-
233 const std::optional<CoMMAIndexType> max_cells_in_line,
-
234 CoMMAIntType dimension = 3) :
-
235 Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
236 graph, cc_graph, seeds_pool, dimension),
-
237 _should_agglomerate(true),
-
238 _aniso_neighbours(),
-
239 _odd_line_length(odd_line_length),
-
240 _max_cells_in_line(max_cells_in_line) {
-
241 // for every defined level (1 by default), contains the number of cells
-
242 // e.g. _l_nb_of_cells[0]= number of cells on finest level
-
243 // _l_nb_of_cells[1]= number of cells on the first coarse level
-
244 this->_l_nb_of_cells.push_back(graph->_number_of_cells);
-
245
-
246 this->_nb_lines = std::vector<CoMMAIndexType>(2);
-
247 this->_v_lines = std::vector<std::vector<AnisotropicLinePtr>>(2);
-
248
-
249 if (build_lines) {
-
250 const CoMMAWeightType thr =
-
251 (threshold_anisotropy > 1 || threshold_anisotropy < 0)
-
252 ? threshold_anisotropy
-
253 : static_cast<CoMMAWeightType>(1. / threshold_anisotropy);
-
254 // if the finest agglomeration line is not computed, hence compute it
-
255 // (REMEMBER! We compute the agglomeration lines only on the (original)
-
256 // finest level
-
257 this->_should_agglomerate =
-
258 this->build_anisotropic_lines(priority_weights, thr);
-
259 } else {
-
260 // case in which we have already agglomerated one level and hence we have
-
261 // already agglomeration lines available; no need to recreate them.
-
262 this->_nb_lines[0] = 0;
-
263 for (auto idx_ptr = agglomerationLines_Idx.cbegin() + 1;
-
264 idx_ptr != agglomerationLines_Idx.cend(); ++idx_ptr) {
-
265 const auto ln_sz = *idx_ptr - (*(idx_ptr - 1));
-
266 if (ln_sz > 1) {
-
267 this->_v_lines[0].push_back(std::make_shared<AnisotropicLine>(
-
268 agglomerationLines.cbegin() + (*(idx_ptr - 1)),
-
269 agglomerationLines.cbegin() + (*idx_ptr)));
-
270 this->_nb_lines[0]++;
-
271 }
-
272 }
-
273 this->_should_agglomerate = this->_nb_lines[0] > 0;
-
274 if (!this->_should_agglomerate)
-
275 std::cout
-
276 << "CoMMA - No anisotropic line was built (e.g., only one-cell "
-
277 "lines). Skipping anisotropic agglomeration"
-
278 << std::endl;
-
279 }
-
280 }
-
281
-
283 ~Agglomerator_Anisotropic() override = default;
-
284
-
301 void agglomerate_one_level(
-
302 const CoMMAIntType goal_card,
-
303 const CoMMAIntType min_card,
-
304 const CoMMAIntType max_card,
-
305 const std::vector<CoMMAWeightType> &priority_weights,
-
306 bool correction_steps) override {
-
307 // Unused parameters
-
308 CoMMAUnused(goal_card);
-
309 CoMMAUnused(min_card);
-
310 CoMMAUnused(max_card);
-
311 CoMMAUnused(correction_steps);
-
312
-
313 if (this->_should_agglomerate) {
-
314 // Necessary for the create_cc but maybe we need in
-
315 // some way to change that.
-
316 constexpr bool is_anisotropic = true;
-
317 constexpr CoMMAIntType compactness = 1;
-
318
-
319 // Setting up lambda function that will perform the loop. This is needed
-
320 // since we want to loop forwards or backwards according to some runtime
-
321 // value See, e.g., https://stackoverflow.com/a/56133699/12152457
-
322 auto loop_line = [&](auto begin, auto end) {
-
323 AnisotropicLinePtr line_lvl_p_one = std::make_shared<AnisotropicLine>();
-
324 typename decltype(this->_max_cells_in_line)::value_type n_cells{0};
-
325 for (auto line_it = begin; line_it != end; line_it += 2) {
-
326 if (
-
327 this->_max_cells_in_line.has_value()
-
328 && n_cells + 2 > this->_max_cells_in_line.value()) {
-
329 // Max length reached, break
-
330 break;
-
331 }
-
332 // we agglomerate cells along the agglomeration line, hence we have to
-
333 // go through the faces and agglomerate two faces together
-
334 // Here we have to consider a special case when we have an odd number
-
335 // of cells: THIS IS FUNDAMENTAL FOR THE CONVERGENCE OF THE MULTIGRID
-
336 // ALGORITHM
-
337 std::unordered_set<CoMMAIndexType> s_fc = {*line_it, *(line_it + 1)};
-
338 n_cells += 2;
-
339 // We update the neighbours. At this stage, we do not check if it is
-
340 // or will be agglomerated since there will be a cleaning step after
-
341 // the anisotropic agglomeration
-
342 this->_aniso_neighbours.insert(
-
343 this->_aniso_neighbours.end(),
-
344 this->_fc_graph->neighbours_cbegin(*line_it),
-
345 this->_fc_graph->neighbours_cend(*line_it));
-
346 this->_aniso_neighbours.insert(
-
347 this->_aniso_neighbours.end(),
-
348 this->_fc_graph->neighbours_cbegin(*(line_it + 1)),
-
349 this->_fc_graph->neighbours_cend(*(line_it + 1)));
-
350 if (
-
351 std::distance(line_it, end) == 3
-
352 || (
-
353 this->_max_cells_in_line.has_value()
-
354 && n_cells + 1 == this->_max_cells_in_line.value())) {
-
355 if (this->_odd_line_length) {
-
356 // If only three cells left, agglomerate them
-
357 s_fc.insert(*(line_it + 2));
-
358 n_cells++;
-
359 this->_aniso_neighbours.insert(
-
360 this->_aniso_neighbours.end(),
-
361 this->_fc_graph->neighbours_cbegin(*(line_it + 2)),
-
362 this->_fc_graph->neighbours_cend(*(line_it + 2)));
-
363 }
-
364 line_it++; // Ensure to break the loop after current iteration
-
365 }
-
366 // We create the coarse cell
-
367 const CoMMAIndexType i_cc =
-
368 this->_cc_graph->create_cc(s_fc, compactness, is_anisotropic);
-
369 line_lvl_p_one->push_back(i_cc);
-
370 }
-
371
-
372 this->_v_lines[1].push_back(line_lvl_p_one);
-
373 }; // End lambda def
-
374
-
375 // Process of every agglomeration lines:
-
376 for (auto line_ptr = this->_v_lines[0].begin();
-
377 line_ptr != this->_v_lines[0].end(); line_ptr++) {
-
378 // We iterate on the anisotropic lines of a particular level (the level
-
379 // 1, where they were copied from level 0). We create a pointer to an
-
380 // empty deque for the line + 1, and hence for the next level of
-
381 // agglomeration
-
382 auto line = **line_ptr;
-
383 if (line.size() <= 1) {
-
384 // the agglomeration_line is empty and hence the iterator points again
-
385 // to the empty deque, updating what is pointed by it and hence
-
386 // __v_lines[1] (each time we iterate on the line, a new deque
-
387 // line_lvl_p_one is defined)
-
388 continue;
-
389 }
-
390 // We start agglomerating from the head or the tail of the line
-
391 // according to which of the two has more boundary faces, or priority or
-
392 // ID
-
393 const auto l_fr = line.front(), l_bk = line.back();
-
394 const auto bnd_fr = this->_fc_graph->get_n_boundary_faces(l_fr),
-
395 bnd_bk = this->_fc_graph->get_n_boundary_faces(l_bk);
-
396 const auto w_fr = priority_weights[l_fr], w_bk = priority_weights[l_bk];
-
397 const bool forward_line =
-
398 bnd_fr > bnd_bk // Greater boundaries...
-
399 || (bnd_fr == bnd_bk &&
-
400 (w_fr > w_bk // ...or greater priority...
-
401 || (w_fr == w_bk && l_fr < l_bk) // ..or smaller index
-
402 ));
-
403
-
404 if (forward_line)
-
405 loop_line(line.cbegin(), line.cend());
-
406 else
-
407 loop_line(line.crbegin(), line.crend());
-
408
-
409 } // End loop on lines
-
410
-
411 this->update_seeds_pool();
-
412
-
413 } // End if should agglomerate
-
414 else
-
415 // If it didn't agglomerate, initialize for sure
-
416 this->_seeds_pool->initialize();
-
417 }
-
418
-
422 void update_seeds_pool() {
-
423 if (!this->_aniso_neighbours.empty()) {
-
424 // Example of erase taken from
-
425 // https://en.cppreference.com/w/cpp/container/deque/erase
-
426 for (auto it = this->_aniso_neighbours.begin();
-
427 it != this->_aniso_neighbours.end();) {
-
428 if (this->_cc_graph->_is_fc_agglomerated[*it])
-
429 it = this->_aniso_neighbours.erase(it);
-
430 else
-
431 ++it;
-
432 }
-
433 if (!this->_aniso_neighbours.empty()) {
-
434 // The master queue is the one of the first agglomerated cell:
-
435 // It is important to set it in the case the user asked for
-
436 // neighbourhood priority
-
437 this->_seeds_pool->set_top_queue(this->_fc_graph->get_n_boundary_faces(
-
438 this->_aniso_neighbours.front()));
-
439 this->_seeds_pool->update(this->_aniso_neighbours);
-
440 }
-
441 }
-
442 // Even if we have updated it, the seeds pool might need initialization, for
-
443 // instance, if it was set up with boundary priority
-
444 if (this->_seeds_pool->need_initialization(
-
445 this->_cc_graph->_is_fc_agglomerated))
-
446 this->_seeds_pool->initialize();
-
447 }
-
448
-
456 void export_anisotropic_lines(
-
457 CoMMAIntType level,
-
458 std::vector<CoMMAIndexType> &aniso_lines_idx,
-
459 std::vector<CoMMAIndexType> &aniso_lines) const {
-
460 // Reset lines
-
461 aniso_lines_idx.clear();
-
462 aniso_lines.clear();
-
463 if (this->_should_agglomerate && !this->_v_lines[level].empty()) {
-
464 // If at the level of agglomeration "level" the vector containing the
-
465 // number of lines is empty, hence it means no line has been found at the
-
466 // current level. variable cumulating the number of fine cells in the
-
467 // agglomeration lines of the current level
-
468 CoMMAIndexType number_of_fc_in_agglomeration_lines = 0;
-
469 aniso_lines_idx.push_back(0);
-
470 // We cycle over the line (in _v_lines)
-
471 for (const auto &line_ptr : this->_v_lines[level]) {
-
472 const auto line = *line_ptr; // Convenience
-
473 const CoMMAIndexType size_of_line = line.size();
-
474 // This vector store the end of a line and the start of a new
-
475 // anisotropic line WARNING! We are storing the anisotropic lines in a
-
476 // vector so we need a way to point to the end of a line and the
-
477 // starting of a new one.
-
478 aniso_lines_idx.push_back(
-
479 size_of_line + number_of_fc_in_agglomeration_lines);
-
480 // Here we store the index of the cell.
-
481 for (const auto cell : line) {
-
482 aniso_lines.push_back(cell);
-
483 }
-
484 number_of_fc_in_agglomeration_lines += size_of_line;
-
485 }
-
486 }
-
487 }
-
488
-
490 std::vector<CoMMAIndexType> _nb_lines;
-
491
-
498 std::vector<std::vector<AnisotropicLinePtr>> _v_lines;
-
499
-
503 bool _should_agglomerate;
+
103 virtual ~Agglomerator() = default;
+
104
+
108 inline std::vector<CoMMAIndexType> get_fc_2_cc() const {
+
109 return _cc_graph->_fc_2_cc;
+
110 }
+
111
+
123 virtual void agglomerate_one_level(
+
124 const CoMMAIntType goal_card,
+
125 const CoMMAIntType min_card,
+
126 const CoMMAIntType max_card,
+
127 const std::vector<CoMMAWeightType> &priority_weights,
+
128 bool correction_steps
+
129 ) = 0;
+
130
+
131protected:
+
134 CoMMAIntType _dimension;
+
137 CoMMAIntType _min_neighbourhood = 3;
+
140 CoMMAIntType _min_card = 0;
+
144 CoMMAIntType _max_card = 0;
+
148 CoMMAIntType _goal_card = 0;
+
152 CoMMAIntType _threshold_card = 0;
+
154 std::vector<CoMMAIndexType> _l_nb_of_cells;
+
158 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
159 _fc_graph;
+
162 std::shared_ptr<
+
163 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
164 _cc_graph;
+
168 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
169 _seeds_pool;
+
170};
+
171
+
180template<
+
181 typename CoMMAIndexType,
+
182 typename CoMMAWeightType,
+
183 typename CoMMAIntType>
+
184class Agglomerator_Anisotropic :
+
185 public Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
186public:
+
188 using AnisotropicLine = std::deque<CoMMAIndexType>;
+
189
+
191 using AnisotropicLinePtr = std::shared_ptr<AnisotropicLine>;
+
192
+
194 using CoMMAPairType = std::pair<CoMMAIndexType, CoMMAWeightType>;
+
196 using CoMMASetOfPairType =
+
197 std::set<CoMMAPairType, CustomPairGreaterFunctor<CoMMAPairType>>;
+
198
+
223 Agglomerator_Anisotropic(
+
224 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
225 graph,
+
226 std::shared_ptr<
+
227 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
228 cc_graph,
+
229 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
230 seeds_pool,
+
231 const CoMMAWeightType threshold_anisotropy,
+
232 const std::vector<CoMMAIndexType> &agglomerationLines_Idx,
+
233 const std::vector<CoMMAIndexType> &agglomerationLines,
+
234 const std::vector<CoMMAWeightType> &priority_weights,
+
235 const bool build_lines,
+
236 const bool odd_line_length,
+
237 const std::optional<CoMMAIndexType> max_cells_in_line,
+
238 CoMMAIntType dimension = 3
+
239 ) :
+
240 Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
241 graph, cc_graph, seeds_pool, dimension
+
242 ),
+
243 _should_agglomerate(true),
+
244 _aniso_neighbours(),
+
245 _odd_line_length(odd_line_length),
+
246 _max_cells_in_line(max_cells_in_line) {
+
247 // for every defined level (1 by default), contains the number of cells
+
248 // e.g. _l_nb_of_cells[0]= number of cells on finest level
+
249 // _l_nb_of_cells[1]= number of cells on the first coarse level
+
250 this->_l_nb_of_cells.push_back(graph->_number_of_cells);
+
251
+
252 this->_nb_lines = std::vector<CoMMAIndexType>(2);
+
253 this->_v_lines = std::vector<std::vector<AnisotropicLinePtr>>(2);
+
254
+
255 if (build_lines) {
+
256 const CoMMAWeightType thr =
+
257 (threshold_anisotropy > 1 || threshold_anisotropy < 0)
+
258 ? threshold_anisotropy
+
259 : static_cast<CoMMAWeightType>(1. / threshold_anisotropy);
+
260 // if the finest agglomeration line is not computed, hence compute it
+
261 // (REMEMBER! We compute the agglomeration lines only on the (original)
+
262 // finest level
+
263 this->_should_agglomerate =
+
264 this->build_anisotropic_lines(priority_weights, thr);
+
265 } else {
+
266 // case in which we have already agglomerated one level and hence we have
+
267 // already agglomeration lines available; no need to recreate them.
+
268 this->_nb_lines[0] = 0;
+
269 for (auto idx_ptr = agglomerationLines_Idx.cbegin() + 1;
+
270 idx_ptr != agglomerationLines_Idx.cend();
+
271 ++idx_ptr) {
+
272 const auto ln_sz = *idx_ptr - (*(idx_ptr - 1));
+
273 if (ln_sz > 1) {
+
274 this->_v_lines[0].push_back(std::make_shared<AnisotropicLine>(
+
275 agglomerationLines.cbegin() + (*(idx_ptr - 1)),
+
276 agglomerationLines.cbegin() + (*idx_ptr)
+
277 ));
+
278 this->_nb_lines[0]++;
+
279 }
+
280 }
+
281 this->_should_agglomerate = this->_nb_lines[0] > 0;
+
282 if (!this->_should_agglomerate)
+
283 std::cout
+
284 << "CoMMA - No anisotropic line was built (e.g., only one-cell "
+
285 "lines). Skipping anisotropic agglomeration"
+
286 << std::endl;
+
287 }
+
288 }
+
289
+
291 ~Agglomerator_Anisotropic() override = default;
+
292
+
309 void agglomerate_one_level(
+
310 const CoMMAIntType goal_card,
+
311 const CoMMAIntType min_card,
+
312 const CoMMAIntType max_card,
+
313 const std::vector<CoMMAWeightType> &priority_weights,
+
314 bool correction_steps
+
315 ) override {
+
316 // Unused parameters
+
317 CoMMAUnused(goal_card);
+
318 CoMMAUnused(min_card);
+
319 CoMMAUnused(max_card);
+
320 CoMMAUnused(correction_steps);
+
321
+
322 if (this->_should_agglomerate) {
+
323 // Necessary for the create_cc but maybe we need in
+
324 // some way to change that.
+
325 constexpr bool is_anisotropic = true;
+
326 constexpr CoMMAIntType compactness = 1;
+
327
+
328 // Setting up lambda function that will perform the loop. This is needed
+
329 // since we want to loop forwards or backwards according to some runtime
+
330 // value See, e.g., https://stackoverflow.com/a/56133699/12152457
+
331 auto loop_line = [&](auto begin, auto end) {
+
332 AnisotropicLinePtr line_lvl_p_one = std::make_shared<AnisotropicLine>();
+
333 typename decltype(this->_max_cells_in_line)::value_type n_cells{0};
+
334 for (auto line_it = begin; line_it != end; line_it += 2) {
+
335 if (this->_max_cells_in_line.has_value()
+
336 && n_cells + 2 > this->_max_cells_in_line.value()) {
+
337 // Max length reached, break
+
338 break;
+
339 }
+
340 // we agglomerate cells along the agglomeration line, hence we have to
+
341 // go through the faces and agglomerate two faces together
+
342 // Here we have to consider a special case when we have an odd number
+
343 // of cells: THIS IS FUNDAMENTAL FOR THE CONVERGENCE OF THE MULTIGRID
+
344 // ALGORITHM
+
345 std::unordered_set<CoMMAIndexType> s_fc = {*line_it, *(line_it + 1)};
+
346 n_cells += 2;
+
347 // We update the neighbours. At this stage, we do not check if it is
+
348 // or will be agglomerated since there will be a cleaning step after
+
349 // the anisotropic agglomeration
+
350 this->_aniso_neighbours.insert(
+
351 this->_aniso_neighbours.end(),
+
352 this->_fc_graph->neighbours_cbegin(*line_it),
+
353 this->_fc_graph->neighbours_cend(*line_it)
+
354 );
+
355 this->_aniso_neighbours.insert(
+
356 this->_aniso_neighbours.end(),
+
357 this->_fc_graph->neighbours_cbegin(*(line_it + 1)),
+
358 this->_fc_graph->neighbours_cend(*(line_it + 1))
+
359 );
+
360 if (
+
361 std::distance(line_it, end) == 3
+
362 || (
+
363 this->_max_cells_in_line.has_value()
+
364 && n_cells + 1 == this->_max_cells_in_line.value())) {
+
365 if (this->_odd_line_length) {
+
366 // If only three cells left, agglomerate them
+
367 s_fc.insert(*(line_it + 2));
+
368 n_cells++;
+
369 this->_aniso_neighbours.insert(
+
370 this->_aniso_neighbours.end(),
+
371 this->_fc_graph->neighbours_cbegin(*(line_it + 2)),
+
372 this->_fc_graph->neighbours_cend(*(line_it + 2))
+
373 );
+
374 }
+
375 line_it++; // Ensure to break the loop after current iteration
+
376 }
+
377 // We create the coarse cell
+
378 const CoMMAIndexType i_cc =
+
379 this->_cc_graph->create_cc(s_fc, compactness, is_anisotropic);
+
380 line_lvl_p_one->push_back(i_cc);
+
381 }
+
382
+
383 this->_v_lines[1].push_back(line_lvl_p_one);
+
384 }; // End lambda def
+
385
+
386 // Process of every agglomeration lines:
+
387 for (auto line_ptr = this->_v_lines[0].begin();
+
388 line_ptr != this->_v_lines[0].end();
+
389 line_ptr++) {
+
390 // We iterate on the anisotropic lines of a particular level (the level
+
391 // 1, where they were copied from level 0). We create a pointer to an
+
392 // empty deque for the line + 1, and hence for the next level of
+
393 // agglomeration
+
394 auto line = **line_ptr;
+
395 if (line.size() <= 1) {
+
396 // the agglomeration_line is empty and hence the iterator points again
+
397 // to the empty deque, updating what is pointed by it and hence
+
398 // __v_lines[1] (each time we iterate on the line, a new deque
+
399 // line_lvl_p_one is defined)
+
400 continue;
+
401 }
+
402 // We start agglomerating from the head or the tail of the line
+
403 // according to which of the two has more boundary faces, or priority or
+
404 // ID
+
405 const auto l_fr = line.front(), l_bk = line.back();
+
406 const auto bnd_fr = this->_fc_graph->get_n_boundary_faces(l_fr),
+
407 bnd_bk = this->_fc_graph->get_n_boundary_faces(l_bk);
+
408 const auto w_fr = priority_weights[l_fr], w_bk = priority_weights[l_bk];
+
409 const bool forward_line =
+
410 bnd_fr > bnd_bk // Greater boundaries...
+
411 || (bnd_fr == bnd_bk &&
+
412 (w_fr > w_bk // ...or greater priority...
+
413 || (w_fr == w_bk && l_fr < l_bk) // ..or smaller index
+
414 ));
+
415
+
416 if (forward_line)
+
417 loop_line(line.cbegin(), line.cend());
+
418 else
+
419 loop_line(line.crbegin(), line.crend());
+
420
+
421 } // End loop on lines
+
422
+
423 this->update_seeds_pool();
+
424
+
425 } // End if should agglomerate
+
426 else
+
427 // If it didn't agglomerate, initialize for sure
+
428 this->_seeds_pool->initialize();
+
429 }
+
430
+
434 void update_seeds_pool() {
+
435 if (!this->_aniso_neighbours.empty()) {
+
436 // Example of erase taken from
+
437 // https://en.cppreference.com/w/cpp/container/deque/erase
+
438 for (auto it = this->_aniso_neighbours.begin();
+
439 it != this->_aniso_neighbours.end();) {
+
440 if (this->_cc_graph->_is_fc_agglomerated[*it])
+
441 it = this->_aniso_neighbours.erase(it);
+
442 else
+
443 ++it;
+
444 }
+
445 if (!this->_aniso_neighbours.empty()) {
+
446 // The master queue is the one of the first agglomerated cell:
+
447 // It is important to set it in the case the user asked for
+
448 // neighbourhood priority
+
449 this->_seeds_pool->set_top_queue(
+
450 this->_fc_graph->get_n_boundary_faces(this->_aniso_neighbours.front())
+
451 );
+
452 this->_seeds_pool->update(this->_aniso_neighbours);
+
453 }
+
454 }
+
455 // Even if we have updated it, the seeds pool might need initialization, for
+
456 // instance, if it was set up with boundary priority
+
457 if (this->_seeds_pool->need_initialization(
+
458 this->_cc_graph->_is_fc_agglomerated
+
459 ))
+
460 this->_seeds_pool->initialize();
+
461 }
+
462
+
470 void export_anisotropic_lines(
+
471 CoMMAIntType level,
+
472 std::vector<CoMMAIndexType> &aniso_lines_idx,
+
473 std::vector<CoMMAIndexType> &aniso_lines
+
474 ) const {
+
475 // Reset lines
+
476 aniso_lines_idx.clear();
+
477 aniso_lines.clear();
+
478 if (this->_should_agglomerate && !this->_v_lines[level].empty()) {
+
479 // If at the level of agglomeration "level" the vector containing the
+
480 // number of lines is empty, hence it means no line has been found at the
+
481 // current level. variable cumulating the number of fine cells in the
+
482 // agglomeration lines of the current level
+
483 CoMMAIndexType number_of_fc_in_agglomeration_lines = 0;
+
484 aniso_lines_idx.push_back(0);
+
485 // We cycle over the line (in _v_lines)
+
486 for (const auto &line_ptr : this->_v_lines[level]) {
+
487 const auto line = *line_ptr; // Convenience
+
488 const CoMMAIndexType size_of_line = line.size();
+
489 // This vector store the end of a line and the start of a new
+
490 // anisotropic line WARNING! We are storing the anisotropic lines in a
+
491 // vector so we need a way to point to the end of a line and the
+
492 // starting of a new one.
+
493 aniso_lines_idx.push_back(
+
494 size_of_line + number_of_fc_in_agglomeration_lines
+
495 );
+
496 // Here we store the index of the cell.
+
497 for (const auto cell : line) {
+
498 aniso_lines.push_back(cell);
+
499 }
+
500 number_of_fc_in_agglomeration_lines += size_of_line;
+
501 }
+
502 }
+
503 }
504
-
505protected:
-
517 bool build_anisotropic_lines(
-
518 const std::vector<CoMMAWeightType> &priority_weights,
-
519 const CoMMAWeightType threshold_anisotropy) {
-
520 std::deque<CoMMAIndexType> aniso_seeds_pool;
-
521 // It is the max_weight, hence the maximum area among the faces composing
-
522 // the cell. Used to recognized the face
-
523 std::vector<CoMMAWeightType> max_weights(
-
524 this->_fc_graph->_number_of_cells, 0.0);
-
525 std::vector<bool> to_treat(this->_fc_graph->_number_of_cells, false);
-
526 // Computation of the anisotropic cell, alias of the cells for which the
-
527 // ratio between the face with maximum area and the face with minimum area
-
528 // is more than a given threshold.
-
529 this->_fc_graph->tag_anisotropic_cells(
-
530 max_weights, to_treat, aniso_seeds_pool, threshold_anisotropy,
-
531 priority_weights, 0);
-
532 if (aniso_seeds_pool.empty()) {
-
533 std::cout << "CoMMA - No anisotropic cell found. Skipping anisotropic "
-
534 "agglomeration"
-
535 << std::endl;
-
536 return false;
-
537 }
-
538 // Size might not be the dimension
-
539 const auto pts_dim = this->_fc_graph->_centers[0].size();
-
540 // size of the line
-
541 this->_nb_lines[0] = 0;
-
542 // we cycle on all the anisotropic cells identified before
-
543 for (auto &i_fc : aniso_seeds_pool) {
-
544 // seed from where we start building the line
-
545 if (!to_treat[i_fc]) {
-
546 // If the cell has been already treated, continue to the next
-
547 // anisotropic cell
-
548 continue;
-
549 }
-
550 // we save the primal seed for the opposite direction check that will
-
551 // happen later
-
552 const auto primal_seed = i_fc;
-
553 std::optional<std::vector<CoMMAWeightType>> primal_dir = std::nullopt;
-
554 // seed to be considered to add or not a new cell to the line
-
555 CoMMAIndexType seed = primal_seed;
-
556 // Create the new line
-
557 AnisotropicLinePtr cur_line = std::make_shared<AnisotropicLine>();
-
558 // we add the first seed
-
559 cur_line->push_back(seed);
-
560 to_treat[seed] = false;
-
561 // Flag to determine end of line
-
562 bool end = false;
-
563 // Flag to determine if we arrived at the end of an extreme of a line
-
564 bool opposite_direction_check = false;
-
565 // Info about growth direction
-
566 std::vector<CoMMAWeightType> prev_cen =
-
567 this->_fc_graph->_centers[seed]; // OK copy
-
568 std::vector<CoMMAWeightType> prev_dir(pts_dim);
-
569 bool empty_line = true;
-
570 // Start the check from the seed
-
571 // while the line is not ended
-
572 while (!end) {
-
573 // for the seed (that is updated each time end!= true) we fill the
-
574 // neighbours and the weights
-
575 const std::vector<CoMMAIndexType> v_neighbours =
-
576 this->_fc_graph->get_neighbours(seed);
-
577 const std::vector<CoMMAWeightType> v_w_neighbours =
-
578 this->_fc_graph->get_weights(seed);
-
579 auto n_it = this->_fc_graph->neighbours_cbegin(seed);
-
580 auto w_it = this->_fc_graph->weights_cbegin(seed);
-
581 // std::vector of the candidates to continue the line
-
582 CoMMASetOfPairType candidates;
-
583 // If the line is long enough, we use the direction. Otherwise, we use
-
584 // the weight. Putting a high-level if to reduce the branching inside
-
585 // the loop over the neighbours.
-
586 if (empty_line) {
-
587 for (; n_it != this->_fc_graph->neighbours_cend(seed);
-
588 ++n_it, ++w_it) {
-
589 if (to_treat[*n_it] && *w_it > 0.90 * max_weights[seed]) {
-
590 candidates.emplace(*w_it, *n_it);
-
591 }
-
592 } // end for loop
-
593 } else {
-
594 // If not an empty line, we check the direction, see
-
595 // !dot_deviate below
-
596 for (; n_it != this->_fc_graph->neighbours_cend(seed);
-
597 ++n_it, ++w_it) {
-
598 if (to_treat[*n_it] && *w_it > 0.90 * max_weights[seed]) {
-
599 std::vector<CoMMAWeightType> cur_dir(pts_dim);
-
600 get_direction<CoMMAWeightType>(
-
601 prev_cen, this->_fc_graph->_centers[*n_it], cur_dir);
-
602 const auto dot = dot_product<CoMMAWeightType>(prev_dir, cur_dir);
-
603 if (!dot_deviate<CoMMAWeightType>(dot))
-
604 candidates.emplace(fabs(dot), *n_it);
-
605 }
-
606 } // end for loop
-
607 }
-
608 if (!candidates.empty()) {
-
609 // Even if we have more than one candidate, we choose just one
-
610 // otherwise we risk to add 2 (problematic with primal seed)
-
611 // It is what is done in Mavriplis
-
612 // https://scicomp.stackexchange.com/questions/41830/anisotropic-lines-identification-algorithm
-
616 // update the seed to the actual candidate
-
617 seed = candidates.begin()->second;
-
618 if (!opposite_direction_check) {
-
619 cur_line->push_back(seed);
-
620 } else {
-
621 cur_line->push_front(seed);
-
622 }
-
623 to_treat[seed] = false;
-
624 empty_line = false;
-
625 const auto &cur_cen = this->_fc_graph->_centers[seed];
-
626 get_direction<CoMMAWeightType>(prev_cen, cur_cen, prev_dir);
-
627 prev_cen = cur_cen; // this->_fc_graph->_centers[seed];
-
628 if (!primal_dir.has_value()) primal_dir = prev_dir;
-
629 }
-
630 // 0 candidate, we are at the end of the line or at the end of one
-
631 // direction
-
632 else /*if (candidates.size() == 0)*/ {
-
633 // Before giving up, let's try another thing: Doing the same things as
-
634 // above with the only difference that we allow to move through any
-
635 // faces and not only the maximum one but still checking for direction
-
636 if (!empty_line) {
-
637 // If not an empty line, we check the direction, see is_parallel
-
638 // below
-
639 for (auto it = this->_fc_graph->neighbours_cbegin(seed);
-
640 it != this->_fc_graph->neighbours_cend(seed); ++it) {
-
641 if (to_treat[*it]) {
-
642 std::vector<CoMMAWeightType> cur_dir(pts_dim);
-
643 get_direction<CoMMAWeightType>(
-
644 prev_cen, this->_fc_graph->_centers[*it], cur_dir);
-
645 const auto dot =
-
646 dot_product<CoMMAWeightType>(prev_dir, cur_dir);
-
647 if (!dot_deviate<CoMMAWeightType>(dot))
-
648 candidates.emplace(fabs(dot), *it);
-
649 }
-
650 } // end for loop
-
651 if (!candidates.empty()) {
-
652 // We found one! Keep going!
-
653 seed = candidates.begin()->second;
-
654 if (!opposite_direction_check) {
-
655 cur_line->push_back(seed);
-
656 } else {
-
657 cur_line->push_front(seed);
-
658 }
-
659 to_treat[seed] = false;
-
660 empty_line = false;
-
661 const auto &cur_cen = this->_fc_graph->_centers[seed];
-
662 get_direction<CoMMAWeightType>(prev_cen, cur_cen, prev_dir);
-
663 prev_cen = cur_cen; // this->_fc_graph->_centers[seed];
-
664 if (!primal_dir.has_value()) primal_dir = prev_dir;
-
665 } else {
-
666 if (opposite_direction_check) {
-
667 end = true;
-
668 } else {
-
669 seed = primal_seed;
-
670 prev_dir = primal_dir.value();
-
671 prev_cen = this->_fc_graph->_centers[seed];
-
672 opposite_direction_check = true;
-
673 }
-
674 }
-
675 } // End last step check on neighbours
-
676 else {
-
677 end = true;
-
678 }
-
679 } // End of no candidates case
-
680 } // End of a line
-
681 // we push the deque to the list if are bigger than 1
-
682 if (cur_line->size() > 1) {
-
683 this->_v_lines[0].push_back(cur_line);
-
684 this->_nb_lines[0] += 1;
-
685 }
-
686 } // End of loop over anisotropic cells
-
687
-
688 if (this->_nb_lines[0] == 0) {
-
689 std::cout << "CoMMA - No anisotropic line was built (e.g., only isolated "
-
690 "anisotropic cells). Skipping anisotropic agglomeration"
-
691 << std::endl;
-
692 return false;
-
693 }
-
694 return true;
-
695 }
-
696
-
700 std::deque<CoMMAIndexType> _aniso_neighbours;
-
701
-
703 bool _odd_line_length;
-
704
-
708 std::optional<CoMMAIndexType> _max_cells_in_line;
-
709};
-
710
-
719template<
-
720 typename CoMMAIndexType,
-
721 typename CoMMAWeightType,
-
722 typename CoMMAIntType>
-
723class Agglomerator_Isotropic :
-
724 public Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
725public:
-
727 using NeighbourhoodCreatorBaseType =
-
728 NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
730 using NeighbourhoodCreatorExtType =
-
731 NeighbourhoodExtendedCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
733 using NeighbourhoodCreatorPFType = NeighbourhoodPureFrontCreator<
-
734 CoMMAIndexType,
-
735 CoMMAWeightType,
-
736 CoMMAIntType>;
-
740 CoMMAIntType _fc_iter;
-
741
-
743 std::shared_ptr<NeighbourhoodCreatorBaseType> _neigh_crtor;
-
744
-
760 Agglomerator_Isotropic(
-
761 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
762 graph,
-
763 std::shared_ptr<
-
764 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
765 cc_graph,
-
766 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
767 seeds_pool,
-
768 CoMMAIntType neighbourhood_type,
-
769 CoMMAIntType fc_iter,
-
770 CoMMAIntType dimension = 3) :
-
771 Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
772 graph, cc_graph, seeds_pool, dimension),
-
773 _fc_iter(fc_iter) {
-
774 if (neighbourhood_type == CoMMANeighbourhoodT::EXTENDED)
-
775 _neigh_crtor = std::make_shared<NeighbourhoodCreatorExtType>();
-
776 else
-
777 _neigh_crtor = std::make_shared<NeighbourhoodCreatorPFType>();
-
778 }
-
779
-
781 ~Agglomerator_Isotropic() override = default;
-
782
-
792 void set_agglomeration_parameter(
-
793 CoMMAIntType goal_card = 0,
-
794 CoMMAIntType min_card = 0,
-
795 CoMMAIntType max_card = 0) {
-
796 // Note[RM]: I tried make the following const static but ended up
-
797 // with some SEGFAULT with Intel possibly linked to the following
-
798 // https://stackoverflow.com/a/36406774
-
799 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_min_card = {
-
800 {2, 3}, {3, 6}};
-
801 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_max_card = {
-
802 {2, 5}, {3, 10}};
-
803 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_goal_card = {
-
804 {2, 4}, {3, 8}};
-
805 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_threshold_card = {
-
806 {2, 2}, {3, 3}};
-
807 // Definition of _min_card
-
808 if (min_card == 0) {
-
809 this->_min_card = d_default_min_card.at(this->_dimension);
-
810 } else {
-
811 this->_min_card = min_card;
-
812 }
-
813
-
814 // Definition of _max_card
-
815 if (max_card == 0) {
-
816 this->_max_card = d_default_max_card.at(this->_dimension);
-
817 } else {
-
818 this->_max_card = max_card;
-
819 }
-
820 // Definition of _goal_card
-
821 if (goal_card == 0) {
-
822 this->_goal_card = d_default_goal_card.at(this->_dimension);
-
823 } else {
-
824 this->_goal_card = goal_card;
-
825 }
-
826
-
827 // Definition of _threshold_card
-
828 this->_threshold_card = d_default_threshold_card.at(this->_dimension);
-
829 }
-
830
-
854 void agglomerate_one_level(
-
855 const CoMMAIntType goal_card,
-
856 const CoMMAIntType min_card,
-
857 const CoMMAIntType max_card,
-
858 const std::vector<CoMMAWeightType> &priority_weights,
-
859 bool correction_steps) override {
-
860 set_agglomeration_parameter(goal_card, min_card, max_card);
-
861 constexpr bool is_anistropic = false;
-
862 // We define a while for which we control the number of agglomerated cells
-
863 const CoMMAIndexType nb_of_fc = this->_l_nb_of_cells[0];
-
864 while (this->_cc_graph->get_number_of_fc_agglomerated() < nb_of_fc) {
-
865 // 1) Choose a new seed
-
866 const auto seed = this->_seeds_pool->choose_new_seed(
-
867 this->_cc_graph->_is_fc_agglomerated);
-
868 assert(seed.has_value());
-
869 // 2) Choose the set of Coarse Cells with the specification of the
-
870 // algorithm in the children class
-
871 CoMMAIntType compactness = 0;
-
872 const std::unordered_set<CoMMAIndexType> set_current_cc =
-
873 choose_optimal_cc_and_update_seeds_pool(
-
874 seed.value(), priority_weights, compactness);
-
875 // 3) Creation of cc
-
876 // We check that threshold cardinality is reached
-
877 // const bool creation_delayed =
-
878 // (static_cast<CoMMAIntType>(s_current_cc.size()) <=
-
879 // this->_threshold_card);
-
880 // @TODO: We prefer to have coarse cells created right now, it might be
-
881 // interesting to explore if delaying was allowed
-
882 constexpr bool is_creation_delayed = false;
-
883 this->_cc_graph->create_cc(
-
884 set_current_cc, compactness, is_anistropic, is_creation_delayed);
-
885 }
-
886 // When we exit from this process all the cells are agglomerated, apart the
-
887 // delayed ones
-
888 // We proceed in creating the delayed ones
-
889 this->_cc_graph->cc_create_all_delayed_cc();
-
890 // Correct if necessary
-
891 if (correction_steps) { this->_cc_graph->correct(this->_max_card); }
-
892 this->_l_nb_of_cells.push_back(this->_cc_graph->_cc_counter);
-
893 }
-
894
-
901 inline CoMMAWeightType estimate_boundary_face(
-
902 const std::vector<CoMMAWeightType> &int_faces) const {
-
903 // Approximate with an average of the internal faces
-
904 // We could choose many kinds of average, e.g. arithmetic or geometric, I
-
905 // honestly don't know if one is better then the other...
-
906 // Here, we use the geometric one, which should be less sensitive to
-
907 // outliers
-
908 return pow(
-
909 accumulate(
-
910 int_faces.begin(), int_faces.end(), CoMMAWeightType{1.},
-
911 std::multiplies<>()),
-
912 CoMMAWeightType{1.} / int_faces.size());
-
913 }
-
914
-
931 inline void compute_next_cc_features(
-
932 const CoMMAIndexType i_fc,
-
933 const CoMMAWeightType cc_diam,
-
934 const CoMMAWeightType cc_vol,
-
935 const std::unordered_set<CoMMAIndexType> &fc_of_cc,
-
936 // out
-
937 CoMMAIntType &shared_faces,
-
938 CoMMAWeightType &aspect_ratio,
-
939 CoMMAWeightType &new_diam,
-
940 CoMMAWeightType &new_vol) const {
-
941 // Compute shared faces
-
942 shared_faces = 0;
-
943 for (auto it = this->_fc_graph->neighbours_cbegin(i_fc);
-
944 it != this->_fc_graph->neighbours_cend(i_fc); ++it) {
-
945 if (*it != i_fc && (fc_of_cc.count(*it) != 0)) shared_faces++;
-
946 }
-
947
-
948 // Compute new diameter
-
949 const std::vector<CoMMAWeightType> &cen_fc =
-
950 this->_fc_graph->_centers[i_fc];
-
951 CoMMAWeightType max_diam = cc_diam * cc_diam;
-
952 for (const auto i_fc_cc : fc_of_cc) {
-
953 const auto dist = squared_euclidean_distance<CoMMAWeightType>(
-
954 cen_fc, this->_fc_graph->_centers[i_fc_cc]);
-
955 if (dist > max_diam) max_diam = dist;
-
956 } // for i_fc_cc
-
957 new_diam = sqrt(max_diam);
+
506 std::vector<CoMMAIndexType> _nb_lines;
+
507
+
514 std::vector<std::vector<AnisotropicLinePtr>> _v_lines;
+
515
+
519 bool _should_agglomerate;
+
520
+
521protected:
+
533 bool build_anisotropic_lines(
+
534 const std::vector<CoMMAWeightType> &priority_weights,
+
535 const CoMMAWeightType threshold_anisotropy
+
536 ) {
+
537 std::deque<CoMMAIndexType> aniso_seeds_pool;
+
538 // It is the max_weight, hence the maximum area among the faces composing
+
539 // the cell. Used to recognized the face
+
540 std::vector<CoMMAWeightType> max_weights(
+
541 this->_fc_graph->_number_of_cells, 0.0
+
542 );
+
543 std::vector<bool> to_treat(this->_fc_graph->_number_of_cells, false);
+
544 // Computation of the anisotropic cell, alias of the cells for which the
+
545 // ratio between the face with maximum area and the face with minimum area
+
546 // is more than a given threshold.
+
547 this->_fc_graph->tag_anisotropic_cells(
+
548 max_weights,
+
549 to_treat,
+
550 aniso_seeds_pool,
+
551 threshold_anisotropy,
+
552 priority_weights,
+
553 0
+
554 );
+
555 if (aniso_seeds_pool.empty()) {
+
556 std::cout << "CoMMA - No anisotropic cell found. Skipping anisotropic "
+
557 "agglomeration"
+
558 << std::endl;
+
559 return false;
+
560 }
+
561 // Size might not be the dimension
+
562 const auto pts_dim = this->_fc_graph->_centers[0].size();
+
563 // size of the line
+
564 this->_nb_lines[0] = 0;
+
565 // we cycle on all the anisotropic cells identified before
+
566 for (auto &i_fc : aniso_seeds_pool) {
+
567 // seed from where we start building the line
+
568 if (!to_treat[i_fc]) {
+
569 // If the cell has been already treated, continue to the next
+
570 // anisotropic cell
+
571 continue;
+
572 }
+
573 // we save the primal seed for the opposite direction check that will
+
574 // happen later
+
575 const auto primal_seed = i_fc;
+
576 std::optional<std::vector<CoMMAWeightType>> primal_dir = std::nullopt;
+
577 // seed to be considered to add or not a new cell to the line
+
578 CoMMAIndexType seed = primal_seed;
+
579 // Create the new line
+
580 AnisotropicLinePtr cur_line = std::make_shared<AnisotropicLine>();
+
581 // we add the first seed
+
582 cur_line->push_back(seed);
+
583 to_treat[seed] = false;
+
584 // Flag to determine end of line
+
585 bool end = false;
+
586 // Flag to determine if we arrived at the end of an extreme of a line
+
587 bool opposite_direction_check = false;
+
588 // Info about growth direction
+
589 std::vector<CoMMAWeightType> prev_cen =
+
590 this->_fc_graph->_centers[seed]; // OK copy
+
591 std::vector<CoMMAWeightType> prev_dir(pts_dim);
+
592 bool empty_line = true;
+
593 // Start the check from the seed
+
594 // while the line is not ended
+
595 while (!end) {
+
596 // for the seed (that is updated each time end!= true) we fill the
+
597 // neighbours and the weights
+
598 const std::vector<CoMMAIndexType> v_neighbours =
+
599 this->_fc_graph->get_neighbours(seed);
+
600 const std::vector<CoMMAWeightType> v_w_neighbours =
+
601 this->_fc_graph->get_weights(seed);
+
602 auto n_it = this->_fc_graph->neighbours_cbegin(seed);
+
603 auto w_it = this->_fc_graph->weights_cbegin(seed);
+
604 // std::vector of the candidates to continue the line
+
605 CoMMASetOfPairType candidates;
+
606 // If the line is long enough, we use the direction. Otherwise, we use
+
607 // the weight. Putting a high-level if to reduce the branching inside
+
608 // the loop over the neighbours.
+
609 if (empty_line) {
+
610 for (; n_it != this->_fc_graph->neighbours_cend(seed);
+
611 ++n_it, ++w_it) {
+
612 if (to_treat[*n_it] && *w_it > 0.90 * max_weights[seed]) {
+
613 candidates.emplace(*w_it, *n_it);
+
614 }
+
615 } // end for loop
+
616 } else {
+
617 // If not an empty line, we check the direction, see
+
618 // !dot_deviate below
+
619 for (; n_it != this->_fc_graph->neighbours_cend(seed);
+
620 ++n_it, ++w_it) {
+
621 if (to_treat[*n_it] && *w_it > 0.90 * max_weights[seed]) {
+
622 std::vector<CoMMAWeightType> cur_dir(pts_dim);
+
623 get_direction<CoMMAWeightType>(
+
624 prev_cen, this->_fc_graph->_centers[*n_it], cur_dir
+
625 );
+
626 const auto dot = dot_product<CoMMAWeightType>(prev_dir, cur_dir);
+
627 if (!dot_deviate<CoMMAWeightType>(dot))
+
628 candidates.emplace(fabs(dot), *n_it);
+
629 }
+
630 } // end for loop
+
631 }
+
632 if (!candidates.empty()) {
+
633 // Even if we have more than one candidate, we choose just one
+
634 // otherwise we risk to add 2 (problematic with primal seed)
+
635 // It is what is done in Mavriplis
+
636 // https://scicomp.stackexchange.com/questions/41830/anisotropic-lines-identification-algorithm
+
640 // update the seed to the actual candidate
+
641 seed = candidates.begin()->second;
+
642 if (!opposite_direction_check) {
+
643 cur_line->push_back(seed);
+
644 } else {
+
645 cur_line->push_front(seed);
+
646 }
+
647 to_treat[seed] = false;
+
648 empty_line = false;
+
649 const auto &cur_cen = this->_fc_graph->_centers[seed];
+
650 get_direction<CoMMAWeightType>(prev_cen, cur_cen, prev_dir);
+
651 prev_cen = cur_cen; // this->_fc_graph->_centers[seed];
+
652 if (!primal_dir.has_value()) primal_dir = prev_dir;
+
653 }
+
654 // 0 candidate, we are at the end of the line or at the end of one
+
655 // direction
+
656 else /*if (candidates.size() == 0)*/ {
+
657 // Before giving up, let's try another thing: Doing the same things as
+
658 // above with the only difference that we allow to move through any
+
659 // faces and not only the maximum one but still checking for direction
+
660 if (!empty_line) {
+
661 // If not an empty line, we check the direction, see is_parallel
+
662 // below
+
663 for (auto it = this->_fc_graph->neighbours_cbegin(seed);
+
664 it != this->_fc_graph->neighbours_cend(seed);
+
665 ++it) {
+
666 if (to_treat[*it]) {
+
667 std::vector<CoMMAWeightType> cur_dir(pts_dim);
+
668 get_direction<CoMMAWeightType>(
+
669 prev_cen, this->_fc_graph->_centers[*it], cur_dir
+
670 );
+
671 const auto dot =
+
672 dot_product<CoMMAWeightType>(prev_dir, cur_dir);
+
673 if (!dot_deviate<CoMMAWeightType>(dot))
+
674 candidates.emplace(fabs(dot), *it);
+
675 }
+
676 } // end for loop
+
677 if (!candidates.empty()) {
+
678 // We found one! Keep going!
+
679 seed = candidates.begin()->second;
+
680 if (!opposite_direction_check) {
+
681 cur_line->push_back(seed);
+
682 } else {
+
683 cur_line->push_front(seed);
+
684 }
+
685 to_treat[seed] = false;
+
686 empty_line = false;
+
687 const auto &cur_cen = this->_fc_graph->_centers[seed];
+
688 get_direction<CoMMAWeightType>(prev_cen, cur_cen, prev_dir);
+
689 prev_cen = cur_cen; // this->_fc_graph->_centers[seed];
+
690 if (!primal_dir.has_value()) primal_dir = prev_dir;
+
691 } else {
+
692 if (opposite_direction_check) {
+
693 end = true;
+
694 } else {
+
695 seed = primal_seed;
+
696 prev_dir = primal_dir.value();
+
697 prev_cen = this->_fc_graph->_centers[seed];
+
698 opposite_direction_check = true;
+
699 }
+
700 }
+
701 } // End last step check on neighbours
+
702 else {
+
703 end = true;
+
704 }
+
705 } // End of no candidates case
+
706 } // End of a line
+
707 // we push the deque to the list if are bigger than 1
+
708 if (cur_line->size() > 1) {
+
709 this->_v_lines[0].push_back(cur_line);
+
710 this->_nb_lines[0] += 1;
+
711 }
+
712 } // End of loop over anisotropic cells
+
713
+
714 if (this->_nb_lines[0] == 0) {
+
715 std::cout << "CoMMA - No anisotropic line was built (e.g., only isolated "
+
716 "anisotropic cells). Skipping anisotropic agglomeration"
+
717 << std::endl;
+
718 return false;
+
719 }
+
720 return true;
+
721 }
+
722
+
726 std::deque<CoMMAIndexType> _aniso_neighbours;
+
727
+
729 bool _odd_line_length;
+
730
+
734 std::optional<CoMMAIndexType> _max_cells_in_line;
+
735};
+
736
+
745template<
+
746 typename CoMMAIndexType,
+
747 typename CoMMAWeightType,
+
748 typename CoMMAIntType>
+
749class Agglomerator_Isotropic :
+
750 public Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
751public:
+
753 using NeighbourhoodCreatorBaseType =
+
754 NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
756 using NeighbourhoodCreatorExtType =
+
757 NeighbourhoodExtendedCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
759 using NeighbourhoodCreatorPFType = NeighbourhoodPureFrontCreator<
+
760 CoMMAIndexType,
+
761 CoMMAWeightType,
+
762 CoMMAIntType>;
+
766 CoMMAIntType _fc_iter;
+
767
+
769 std::shared_ptr<NeighbourhoodCreatorBaseType> _neigh_crtor;
+
770
+
786 Agglomerator_Isotropic(
+
787 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
788 graph,
+
789 std::shared_ptr<
+
790 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
791 cc_graph,
+
792 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
793 seeds_pool,
+
794 CoMMAIntType neighbourhood_type,
+
795 CoMMAIntType fc_iter,
+
796 CoMMAIntType dimension = 3
+
797 ) :
+
798 Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
799 graph, cc_graph, seeds_pool, dimension
+
800 ),
+
801 _fc_iter(fc_iter) {
+
802 if (neighbourhood_type == CoMMANeighbourhoodT::EXTENDED)
+
803 _neigh_crtor = std::make_shared<NeighbourhoodCreatorExtType>();
+
804 else
+
805 _neigh_crtor = std::make_shared<NeighbourhoodCreatorPFType>();
+
806 }
+
807
+
809 ~Agglomerator_Isotropic() override = default;
+
810
+
820 void set_agglomeration_parameter(
+
821 CoMMAIntType goal_card = 0,
+
822 CoMMAIntType min_card = 0,
+
823 CoMMAIntType max_card = 0
+
824 ) {
+
825 // Note[RM]: I tried make the following const static but ended up
+
826 // with some SEGFAULT with Intel possibly linked to the following
+
827 // https://stackoverflow.com/a/36406774
+
828 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_min_card = {
+
829 {2, 3}, {3, 6}
+
830 };
+
831 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_max_card = {
+
832 {2, 5}, {3, 10}
+
833 };
+
834 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_goal_card = {
+
835 {2, 4}, {3, 8}
+
836 };
+
837 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_threshold_card = {
+
838 {2, 2}, {3, 3}
+
839 };
+
840 // Definition of _min_card
+
841 if (min_card == 0) {
+
842 this->_min_card = d_default_min_card.at(this->_dimension);
+
843 } else {
+
844 this->_min_card = min_card;
+
845 }
+
846
+
847 // Definition of _max_card
+
848 if (max_card == 0) {
+
849 this->_max_card = d_default_max_card.at(this->_dimension);
+
850 } else {
+
851 this->_max_card = max_card;
+
852 }
+
853 // Definition of _goal_card
+
854 if (goal_card == 0) {
+
855 this->_goal_card = d_default_goal_card.at(this->_dimension);
+
856 } else {
+
857 this->_goal_card = goal_card;
+
858 }
+
859
+
860 // Definition of _threshold_card
+
861 this->_threshold_card = d_default_threshold_card.at(this->_dimension);
+
862 }
+
863
+
887 void agglomerate_one_level(
+
888 const CoMMAIntType goal_card,
+
889 const CoMMAIntType min_card,
+
890 const CoMMAIntType max_card,
+
891 const std::vector<CoMMAWeightType> &priority_weights,
+
892 bool correction_steps
+
893 ) override {
+
894 set_agglomeration_parameter(goal_card, min_card, max_card);
+
895 constexpr bool is_anistropic = false;
+
896 // We define a while for which we control the number of agglomerated cells
+
897 const CoMMAIndexType nb_of_fc = this->_l_nb_of_cells[0];
+
898 while (this->_cc_graph->get_number_of_fc_agglomerated() < nb_of_fc) {
+
899 // 1) Choose a new seed
+
900 const auto seed =
+
901 this->_seeds_pool->choose_new_seed(this->_cc_graph->_is_fc_agglomerated
+
902 );
+
903 assert(seed.has_value());
+
904 // 2) Choose the set of Coarse Cells with the specification of the
+
905 // algorithm in the children class
+
906 CoMMAIntType compactness = 0;
+
907 const std::unordered_set<CoMMAIndexType> set_current_cc =
+
908 choose_optimal_cc_and_update_seeds_pool(
+
909 seed.value(), priority_weights, compactness
+
910 );
+
911 // 3) Creation of cc
+
912 // We check that threshold cardinality is reached
+
913 // const bool creation_delayed =
+
914 // (static_cast<CoMMAIntType>(s_current_cc.size()) <=
+
915 // this->_threshold_card);
+
916 // @TODO: We prefer to have coarse cells created right now, it might be
+
917 // interesting to explore if delaying was allowed
+
918 constexpr bool is_creation_delayed = false;
+
919 this->_cc_graph->create_cc(
+
920 set_current_cc, compactness, is_anistropic, is_creation_delayed
+
921 );
+
922 }
+
923 // When we exit from this process all the cells are agglomerated, apart the
+
924 // delayed ones
+
925 // We proceed in creating the delayed ones
+
926 this->_cc_graph->cc_create_all_delayed_cc();
+
927 // Correct if necessary
+
928 if (correction_steps) {
+
929 this->_cc_graph->correct(this->_max_card);
+
930 }
+
931 this->_l_nb_of_cells.push_back(this->_cc_graph->_cc_counter);
+
932 }
+
933
+
940 inline CoMMAWeightType estimate_boundary_face(
+
941 const std::vector<CoMMAWeightType> &int_faces
+
942 ) const {
+
943 // Approximate with an average of the internal faces
+
944 // We could choose many kinds of average, e.g. arithmetic or geometric, I
+
945 // honestly don't know if one is better then the other...
+
946 // Here, we use the geometric one, which should be less sensitive to
+
947 // outliers
+
948 return pow(
+
949 accumulate(
+
950 int_faces.begin(),
+
951 int_faces.end(),
+
952 CoMMAWeightType{1.},
+
953 std::multiplies<>()
+
954 ),
+
955 CoMMAWeightType{1.} / int_faces.size()
+
956 );
+
957 }
958
-
959 new_vol = cc_vol + this->_fc_graph->_volumes[i_fc];
-
960
-
961 aspect_ratio = this->_compute_AR(new_diam, new_vol);
-
962 }
-
963
-
973 virtual std::unordered_set<CoMMAIndexType>
-
974 choose_optimal_cc_and_update_seeds_pool(
-
975 const CoMMAIndexType seed,
-
976 const std::vector<CoMMAWeightType> &priority_weights,
-
977 CoMMAIntType &compactness) = 0;
-
978};
-
979
-
988template<
-
989 typename CoMMAIndexType,
-
990 typename CoMMAWeightType,
-
991 typename CoMMAIntType>
-
992class Agglomerator_Biconnected :
-
993 public Agglomerator_Isotropic<
-
994 CoMMAIndexType,
-
995 CoMMAWeightType,
-
996 CoMMAIntType> {
-
997public:
-
1012 Agglomerator_Biconnected(
-
1013 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1014 graph,
-
1015 std::shared_ptr<
-
1016 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1017 cc_graph,
-
1018 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1019 seeds_pool,
-
1020 CoMMAIntType neighbourhood_type,
-
1021 CoMMAIntType fc_iter,
-
1022 CoMMAIntType dimension = 3) :
-
1023 Agglomerator_Isotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
1024 graph, cc_graph, seeds_pool, neighbourhood_type, fc_iter, dimension) {
-
1025 // no particular constructor
-
1026 }
+
975 inline void compute_next_cc_features(
+
976 const CoMMAIndexType i_fc,
+
977 const CoMMAWeightType cc_diam,
+
978 const CoMMAWeightType cc_vol,
+
979 const std::unordered_set<CoMMAIndexType> &fc_of_cc,
+
980 // out
+
981 CoMMAIntType &shared_faces,
+
982 CoMMAWeightType &aspect_ratio,
+
983 CoMMAWeightType &new_diam,
+
984 CoMMAWeightType &new_vol
+
985 ) const {
+
986 // Compute shared faces
+
987 shared_faces = 0;
+
988 for (auto it = this->_fc_graph->neighbours_cbegin(i_fc);
+
989 it != this->_fc_graph->neighbours_cend(i_fc);
+
990 ++it) {
+
991 if (*it != i_fc && (fc_of_cc.count(*it) != 0)) shared_faces++;
+
992 }
+
993
+
994 // Compute new diameter
+
995 const std::vector<CoMMAWeightType> &cen_fc =
+
996 this->_fc_graph->_centers[i_fc];
+
997 CoMMAWeightType max_diam = cc_diam * cc_diam;
+
998 for (const auto i_fc_cc : fc_of_cc) {
+
999 const auto dist = squared_euclidean_distance<CoMMAWeightType>(
+
1000 cen_fc, this->_fc_graph->_centers[i_fc_cc]
+
1001 );
+
1002 if (dist > max_diam) max_diam = dist;
+
1003 } // for i_fc_cc
+
1004 new_diam = sqrt(max_diam);
+
1005
+
1006 new_vol = cc_vol + this->_fc_graph->_volumes[i_fc];
+
1007
+
1008 aspect_ratio = this->_compute_AR(new_diam, new_vol);
+
1009 }
+
1010
+
1020 virtual std::unordered_set<CoMMAIndexType>
+
1021 choose_optimal_cc_and_update_seeds_pool(
+
1022 const CoMMAIndexType seed,
+
1023 const std::vector<CoMMAWeightType> &priority_weights,
+
1024 CoMMAIntType &compactness
+
1025 ) = 0;
+
1026};
1027
-
1029 ~Agglomerator_Biconnected() override = default;
-
1030
-
1041 std::unordered_set<CoMMAIndexType> choose_optimal_cc_and_update_seeds_pool(
-
1042 const CoMMAIndexType seed,
-
1043 const std::vector<CoMMAWeightType> &priority_weights,
-
1044 CoMMAIntType &compactness) override {
-
1045 bool is_order_primary = false;
-
1046 // The goal of this function is to choose from a pool of neighbour the
-
1047 // better one to build a compact coarse cell
-
1048 assert(this->_goal_card > 1); // _goal_card has been initialized
-
1049 // OUTPUT: Definition of the current cc, IT WILL BE GIVEN AS AN OUTPUT
-
1050 std::unordered_set<CoMMAIndexType> s_current_cc = {seed};
-
1051 // Dictionary of the neighbourhood of the seed, the key is the global index
-
1052 // of the cell and the value the order of distance from the seed (1 order
-
1053 // direct neighbourhood, 2 order etc.)
-
1054 std::unordered_map<CoMMAIndexType, CoMMAIntType> d_n_of_seed;
-
1055 // Number of fine cells constituting the current coarse cell in
-
1056 // construction.
-
1057 CoMMAIntType size_current_cc = 1; // CC contains only one cell: the seed
-
1058 // set to 3 as default we set to this value the maximum order to which we
-
1059 // search to compose the coarse cell
-
1060 CoMMAIntType max_order_of_neighbourhood =
-
1061 std::max(this->_min_neighbourhood, this->_max_card / this->_dimension);
-
1062
-
1063 // We fill the d_n_of_seeds considering the initial seed passed
-
1064 this->_fc_graph->compute_neighbourhood_of_cc(
-
1065 s_current_cc,
-
1066 max_order_of_neighbourhood, // in and out
-
1067 d_n_of_seed, // output, the function fills the dictionary
-
1068 this->_max_card,
-
1069 // anisotropic cells agglomerated (not to take into account in the
-
1070 // process)
-
1071 this->_cc_graph->_is_fc_agglomerated);
-
1072
-
1073 // If no neighbour is found for seed: this case happened only when isotropic
-
1074 // cell is surrounded by anisotropic cells.
-
1075 if (d_n_of_seed.empty()) {
-
1076 // d_n_of_seed is empty, i.e: the cc is not complete and no neighbour are
-
1077 // available!
-
1078 compactness = 0;
-
1079 } else if (
-
1080 static_cast<CoMMAIntType>(d_n_of_seed.size() + s_current_cc.size())
-
1081 < this->_goal_card) {
-
1082 // Not enough available neighbour, the dictionary of the available cells
-
1083 // size summed with the current cell size is not enough to reach the goal
-
1084 // cardinality: creation of a (too small) coarse cell.
-
1085 // We add ALL the cells of the dictionary to the set of current coarse
-
1086 // cell.
-
1087 for (auto &i_k_v : d_n_of_seed) {
-
1088 s_current_cc.insert(i_k_v.first);
-
1089 }
-
1090 compactness =
-
1091 this->_fc_graph->compute_min_fc_compactness_inside_a_cc(s_current_cc);
-
1092 } else {
-
1093 // If we passed the two previous checks, the minimum size is the goal
-
1094 // cardinality required
-
1095 // TODO: CHECK THAT, if the goal is 2, the minimum size would be 3?
-
1096 // ARGUABLE! Let's think to 3
-
1097 // Computation of the initial aspect ratio
-
1098 CoMMAWeightType diam_cc{-1.};
-
1099 // CC in construction
-
1100 decltype(s_current_cc) tmp_cc = {seed};
-
1101 // volume of cc is at first the volume of the seed.
-
1102 CoMMAWeightType vol_cc = this->_fc_graph->_volumes[seed];
-
1103 // This dictionary is used to store the eligible cc: i.e. its size is
-
1104 // inside the permitted range. This is useful to track back our step if
-
1105 // needed. [size of the current, [cell set, d_n_of seed]]
-
1106 std::unordered_map<
-
1107 CoMMAIntType, std::pair<
-
1108 std::unordered_set<CoMMAIndexType>,
-
1109 std::unordered_map<CoMMAIndexType, CoMMAIntType>>>
-
1110 dict_cc_in_creation;
-
1111 CoMMAIntType min_external_faces =
-
1112 std::numeric_limits<CoMMAIntType>::max();
-
1113 CoMMAIntType max_compact = 0;
-
1114 CoMMAIntType arg_min_card = this->_min_card;
-
1115 // Here we define the exact dimension of the coarse cell as the min
-
1116 // between the max cardinality given as an input (remember the constructor
-
1117 // choice in case of -1) and the dictionary of the boundary cells, it
-
1118 // means the total number of neighbourhood cells until the order we have
-
1119 // given (as default 3, so until the third order)
-
1120 const CoMMAIntType max_ind = std::min(
-
1121 this->_max_card, static_cast<CoMMAIntType>(d_n_of_seed.size() + 1));
-
1122 // This formula does not work
-
1123 CoMMAIntType number_of_external_faces_current_cc =
-
1124 this->_fc_graph->get_nb_of_neighbours(seed)
-
1125 + this->_fc_graph->get_n_boundary_faces(seed) - 1;
-
1126 // d_keys_to_set from Util.h, it takes the keys of the unordered map and
-
1127 // create an unordered set. The unordered set is representing hence all
-
1128 // the neighbours of seed until a given order.
-
1129 const std::unordered_set<CoMMAIndexType> s_neighbours_of_seed =
-
1130 d_keys_to_set<CoMMAIndexType, CoMMAIntType>(d_n_of_seed);
-
1131 // Build the class neighbourhood
-
1132 auto neighbourhood = this->_neigh_crtor->create(
-
1133 s_neighbours_of_seed, priority_weights, this->_dimension);
-
1134 // Compactness is used when choosing the best cell. We compute it
-
1135 // iteratively as the agglomeration advances.
-
1136 std::unordered_map<CoMMAIndexType, CoMMAIntType> cur_compact_by_fc{};
-
1137 cur_compact_by_fc.reserve(max_ind);
-
1138 cur_compact_by_fc[seed] = 0;
-
1139 constexpr auto second_less = [](const auto &left, const auto &right) {
-
1140 return left.second < right.second;
-
1141 };
-
1142 CoMMAIndexType next_cell = seed; // Dummy initialization
-
1143 // Choice of the fine cells to agglomerate we enter in a while, we store
-
1144 // anyways all the possible coarse cells (not only the max dimension one)
-
1145 while (size_current_cc < max_ind) {
-
1146 // Update the neighbourhood and generate the candidates
-
1147 neighbourhood->update(
-
1148 next_cell, this->_fc_graph->get_neighbours(next_cell));
-
1149 next_cell = 0; // Dummy initialization
-
1150 CoMMAWeightType min_ar_diam =
-
1151 std::numeric_limits<CoMMAWeightType>::max();
-
1152 CoMMAWeightType min_ar_vol =
-
1153 std::numeric_limits<CoMMAWeightType>::max();
-
1154 CoMMAIntType max_faces_in_common = 0;
-
1155 // We compute the best fine cell to add, based on the aspect
-
1156 // ratio and is given back in next_cell. It takes account also
-
1157 // the fine cells that has been added until now.
-
1158 // min(max_ind - size_current_cc, this->_fc_iter)
-
1159 this->compute_best_fc_to_add(
-
1160 std::min(max_ind - size_current_cc, this->_fc_iter), neighbourhood,
-
1161 d_n_of_seed, is_order_primary, diam_cc, vol_cc, tmp_cc, next_cell,
-
1162 // output
-
1163 max_faces_in_common, min_ar_diam, min_ar_vol);
-
1164
-
1165 // This formula does not work
-
1166 number_of_external_faces_current_cc +=
-
1167 this->_fc_graph->get_nb_of_neighbours(next_cell)
-
1168 + this->_fc_graph->get_n_boundary_faces(next_cell) - 1
-
1169 - 2 * max_faces_in_common;
-
1170 // we increase the cc
-
1171 size_current_cc++;
-
1172 tmp_cc.insert(next_cell);
-
1173
-
1174 // Update compactness
-
1175 CoMMAIntType argmin_compact{0};
-
1176 for (auto neigh = this->_fc_graph->neighbours_cbegin(next_cell);
-
1177 neigh != this->_fc_graph->neighbours_cend(next_cell); ++neigh) {
-
1178 if (tmp_cc.find(*neigh) != tmp_cc.end()) {
-
1179 ++argmin_compact;
-
1180 ++cur_compact_by_fc[*neigh];
-
1181 }
-
1182 }
-
1183 cur_compact_by_fc[next_cell] = argmin_compact;
-
1184 const CoMMAIntType cur_compact =
-
1185 min_element(
-
1186 cur_compact_by_fc.cbegin(), cur_compact_by_fc.cend(), second_less)
-
1187 ->second;
-
1188 // Equivalent to:
-
1189 // this->_fc_graph->compute_min_fc_compactness_inside_a_cc(tmp_cc);
-
1190
-
1191 // if the constructed cc is eligible, i.e. its size is inside the
-
1192 // permitted range we store it inside dict_cc_in_creation This choice is
-
1193 // based on the idea that the smallest cc (w.r.t. card) is may be not
-
1194 // the one that minimized the number of external faces. If this if is
-
1195 // satisfied it means we have an eligible cell
-
1196 if (
-
1197 (this->_min_card <= size_current_cc) || size_current_cc == max_ind) {
-
1198 if (cur_compact > max_compact) {
-
1199 max_compact = cur_compact;
-
1200 min_external_faces = number_of_external_faces_current_cc;
-
1201 arg_min_card = size_current_cc;
-
1202
-
1203 } else if (cur_compact == max_compact) {
-
1204 if (
-
1205 (number_of_external_faces_current_cc < min_external_faces) ||
-
1206 (number_of_external_faces_current_cc == min_external_faces &&
-
1207 arg_min_card != this->_goal_card)) {
-
1208 min_external_faces = number_of_external_faces_current_cc;
-
1209 arg_min_card = size_current_cc;
-
1210 }
-
1211 }
-
1212
-
1213 // We update the dictionary of eligible coarse cells
-
1214 std::unordered_map<CoMMAIndexType, CoMMAIntType> new_dict;
-
1215 new_dict[next_cell] = d_n_of_seed[next_cell];
-
1216 std::pair<
-
1217 std::unordered_set<CoMMAIndexType>,
-
1218 std::unordered_map<CoMMAIndexType, CoMMAIntType>>
-
1219 tmp_pair = std::make_pair(tmp_cc, new_dict);
-
1220 dict_cc_in_creation[size_current_cc] = tmp_pair;
-
1221 }
-
1222
-
1223 // Update of diam_cc and vol_cc with the new fc added
-
1224 diam_cc = min_ar_diam;
-
1225 vol_cc = min_ar_vol;
-
1226
-
1227 // Remove added fc from the available neighbours
-
1228 d_n_of_seed.erase(next_cell);
-
1229 }
+
1036template<
+
1037 typename CoMMAIndexType,
+
1038 typename CoMMAWeightType,
+
1039 typename CoMMAIntType>
+
1040class Agglomerator_Biconnected :
+
1041 public Agglomerator_Isotropic<
+
1042 CoMMAIndexType,
+
1043 CoMMAWeightType,
+
1044 CoMMAIntType> {
+
1045public:
+
1060 Agglomerator_Biconnected(
+
1061 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
1062 graph,
+
1063 std::shared_ptr<
+
1064 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
1065 cc_graph,
+
1066 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
1067 seeds_pool,
+
1068 CoMMAIntType neighbourhood_type,
+
1069 CoMMAIntType fc_iter,
+
1070 CoMMAIntType dimension = 3
+
1071 ) :
+
1072 Agglomerator_Isotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
1073 graph, cc_graph, seeds_pool, neighbourhood_type, fc_iter, dimension
+
1074 ) {
+
1075 // no particular constructor
+
1076 }
+
1077
+
1079 ~Agglomerator_Biconnected() override = default;
+
1080
+
1091 std::unordered_set<CoMMAIndexType> choose_optimal_cc_and_update_seeds_pool(
+
1092 const CoMMAIndexType seed,
+
1093 const std::vector<CoMMAWeightType> &priority_weights,
+
1094 CoMMAIntType &compactness
+
1095 ) override {
+
1096 bool is_order_primary = false;
+
1097 // The goal of this function is to choose from a pool of neighbour the
+
1098 // better one to build a compact coarse cell
+
1099 assert(this->_goal_card > 1); // _goal_card has been initialized
+
1100 // OUTPUT: Definition of the current cc, IT WILL BE GIVEN AS AN OUTPUT
+
1101 std::unordered_set<CoMMAIndexType> s_current_cc = {seed};
+
1102 // Dictionary of the neighbourhood of the seed, the key is the global index
+
1103 // of the cell and the value the order of distance from the seed (1 order
+
1104 // direct neighbourhood, 2 order etc.)
+
1105 std::unordered_map<CoMMAIndexType, CoMMAIntType> d_n_of_seed;
+
1106 // Number of fine cells constituting the current coarse cell in
+
1107 // construction.
+
1108 CoMMAIntType size_current_cc = 1; // CC contains only one cell: the seed
+
1109 // set to 3 as default we set to this value the maximum order to which we
+
1110 // search to compose the coarse cell
+
1111 CoMMAIntType max_order_of_neighbourhood =
+
1112 std::max(this->_min_neighbourhood, this->_max_card / this->_dimension);
+
1113
+
1114 // We fill the d_n_of_seeds considering the initial seed passed
+
1115 this->_fc_graph->compute_neighbourhood_of_cc(
+
1116 s_current_cc,
+
1117 max_order_of_neighbourhood, // in and out
+
1118 d_n_of_seed, // output, the function fills the dictionary
+
1119 this->_max_card,
+
1120 // anisotropic cells agglomerated (not to take into account in the
+
1121 // process)
+
1122 this->_cc_graph->_is_fc_agglomerated
+
1123 );
+
1124
+
1125 // If no neighbour is found for seed: this case happened only when isotropic
+
1126 // cell is surrounded by anisotropic cells.
+
1127 if (d_n_of_seed.empty()) {
+
1128 // d_n_of_seed is empty, i.e: the cc is not complete and no neighbour are
+
1129 // available!
+
1130 compactness = 0;
+
1131 } else if (static_cast<CoMMAIntType>(
+
1132 d_n_of_seed.size() + s_current_cc.size()
+
1133 )
+
1134 < this->_goal_card) {
+
1135 // Not enough available neighbour, the dictionary of the available cells
+
1136 // size summed with the current cell size is not enough to reach the goal
+
1137 // cardinality: creation of a (too small) coarse cell.
+
1138 // We add ALL the cells of the dictionary to the set of current coarse
+
1139 // cell.
+
1140 for (auto &i_k_v : d_n_of_seed) {
+
1141 s_current_cc.insert(i_k_v.first);
+
1142 }
+
1143 compactness =
+
1144 this->_fc_graph->compute_min_fc_compactness_inside_a_cc(s_current_cc);
+
1145 } else {
+
1146 // If we passed the two previous checks, the minimum size is the goal
+
1147 // cardinality required
+
1148 // TODO: CHECK THAT, if the goal is 2, the minimum size would be 3?
+
1149 // ARGUABLE! Let's think to 3
+
1150 // Computation of the initial aspect ratio
+
1151 CoMMAWeightType diam_cc{-1.};
+
1152 // CC in construction
+
1153 decltype(s_current_cc) tmp_cc = {seed};
+
1154 // volume of cc is at first the volume of the seed.
+
1155 CoMMAWeightType vol_cc = this->_fc_graph->_volumes[seed];
+
1156 // This dictionary is used to store the eligible cc: i.e. its size is
+
1157 // inside the permitted range. This is useful to track back our step if
+
1158 // needed. [size of the current, [cell set, d_n_of seed]]
+
1159 std::unordered_map<
+
1160 CoMMAIntType,
+
1161 std::pair<
+
1162 std::unordered_set<CoMMAIndexType>,
+
1163 std::unordered_map<CoMMAIndexType, CoMMAIntType>>>
+
1164 dict_cc_in_creation;
+
1165 CoMMAIntType min_external_faces =
+
1166 std::numeric_limits<CoMMAIntType>::max();
+
1167 CoMMAIntType max_compact = 0;
+
1168 CoMMAIntType arg_min_card = this->_min_card;
+
1169 // Here we define the exact dimension of the coarse cell as the min
+
1170 // between the max cardinality given as an input (remember the constructor
+
1171 // choice in case of -1) and the dictionary of the boundary cells, it
+
1172 // means the total number of neighbourhood cells until the order we have
+
1173 // given (as default 3, so until the third order)
+
1174 const CoMMAIntType max_ind = std::min(
+
1175 this->_max_card, static_cast<CoMMAIntType>(d_n_of_seed.size() + 1)
+
1176 );
+
1177 // This formula does not work
+
1178 CoMMAIntType number_of_external_faces_current_cc =
+
1179 this->_fc_graph->get_nb_of_neighbours(seed)
+
1180 + this->_fc_graph->get_n_boundary_faces(seed) - 1;
+
1181 // d_keys_to_set from Util.h, it takes the keys of the unordered map and
+
1182 // create an unordered set. The unordered set is representing hence all
+
1183 // the neighbours of seed until a given order.
+
1184 const std::unordered_set<CoMMAIndexType> s_neighbours_of_seed =
+
1185 d_keys_to_set<CoMMAIndexType, CoMMAIntType>(d_n_of_seed);
+
1186 // Build the class neighbourhood
+
1187 auto neighbourhood = this->_neigh_crtor->create(
+
1188 s_neighbours_of_seed, priority_weights, this->_dimension
+
1189 );
+
1190 // Compactness is used when choosing the best cell. We compute it
+
1191 // iteratively as the agglomeration advances.
+
1192 std::unordered_map<CoMMAIndexType, CoMMAIntType> cur_compact_by_fc{};
+
1193 cur_compact_by_fc.reserve(max_ind);
+
1194 cur_compact_by_fc[seed] = 0;
+
1195 constexpr auto second_less = [](const auto &left, const auto &right) {
+
1196 return left.second < right.second;
+
1197 };
+
1198 CoMMAIndexType next_cell = seed; // Dummy initialization
+
1199 // Choice of the fine cells to agglomerate we enter in a while, we store
+
1200 // anyways all the possible coarse cells (not only the max dimension one)
+
1201 while (size_current_cc < max_ind) {
+
1202 // Update the neighbourhood and generate the candidates
+
1203 neighbourhood->update(
+
1204 next_cell, this->_fc_graph->get_neighbours(next_cell)
+
1205 );
+
1206 next_cell = 0; // Dummy initialization
+
1207 CoMMAWeightType min_ar_diam =
+
1208 std::numeric_limits<CoMMAWeightType>::max();
+
1209 CoMMAWeightType min_ar_vol =
+
1210 std::numeric_limits<CoMMAWeightType>::max();
+
1211 CoMMAIntType max_faces_in_common = 0;
+
1212 // We compute the best fine cell to add, based on the aspect
+
1213 // ratio and is given back in next_cell. It takes account also
+
1214 // the fine cells that has been added until now.
+
1215 // min(max_ind - size_current_cc, this->_fc_iter)
+
1216 this->compute_best_fc_to_add(
+
1217 std::min(max_ind - size_current_cc, this->_fc_iter),
+
1218 neighbourhood,
+
1219 d_n_of_seed,
+
1220 is_order_primary,
+
1221 diam_cc,
+
1222 vol_cc,
+
1223 tmp_cc,
+
1224 next_cell,
+
1225 // output
+
1226 max_faces_in_common,
+
1227 min_ar_diam,
+
1228 min_ar_vol
+
1229 );
1230
-
1231 // Selecting best CC to return
-
1232 s_current_cc = std::move(dict_cc_in_creation[arg_min_card].first);
-
1233
-
1234 // If we do not chose the biggest cc, we put the useless fc back to the
-
1235 // pool
-
1236 for (auto i_s = arg_min_card + 1; i_s < max_ind + 1; i_s++) {
-
1237 // for all size of Cell from arg_min_card+1 to min(max_card,
-
1238 // len(d_n_of_seed) + 1) + 1
-
1239 // d_n_of_seed.
-
1240 for (auto iKV : dict_cc_in_creation[i_s].second) {
-
1241 d_n_of_seed[iKV.first] = iKV.second;
-
1242 }
-
1243 }
-
1244
-
1245 // Updating Seeds Pool with the neighbours of the final CC. Strategy:
-
1246 // - Compute the direct neighbours of the CC (not yet agglomerated)
-
1247 // - Insert in the queue starting with those of lowest neighbourhood order
-
1248 // wrt
-
1249 // to the original seed
-
1250 // - If more than one cell with the same order, use priority weights
-
1251 const auto cc_neighs = this->_fc_graph->get_neighbourhood_of_cc(
-
1252 s_current_cc, this->_cc_graph->_is_fc_agglomerated);
-
1253 // Basically, like d_n_of_seed but with key and value swapped
-
1254 std::map<CoMMAIntType, std::unordered_set<CoMMAIndexType>>
-
1255 neighs_by_order{};
-
1256 // For those that were outside max neighbourhood order
-
1257 std::unordered_set<CoMMAIndexType> neighs_not_found{};
-
1258 for (const auto &neigh : cc_neighs) {
-
1259 if (d_n_of_seed.find(neigh) != d_n_of_seed.end())
-
1260 neighs_by_order[d_n_of_seed.at(neigh)].insert(neigh);
-
1261 else
-
1262 neighs_not_found.insert(neigh);
-
1263 }
-
1264 for (const auto &[o, neighs] : neighs_by_order)
-
1265 if (!neighs.empty())
-
1266 this->_seeds_pool->order_new_seeds_and_update(neighs);
-
1267 if (!neighs_not_found.empty())
-
1268 this->_seeds_pool->order_new_seeds_and_update(neighs_not_found);
-
1269
-
1270 assert(arg_min_card == static_cast<CoMMAIntType>(s_current_cc.size()));
-
1271
-
1272 compactness = max_compact;
-
1273 } // end else
-
1274 return s_current_cc;
-
1275 }
-
1276
-
1302 virtual void compute_best_fc_to_add(
-
1303 const CoMMAIntType fc_iter,
-
1304 const std::shared_ptr<
-
1305 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1306 neighbourhood,
-
1307 const std::unordered_map<CoMMAIndexType, CoMMAIntType> &d_n_of_seed,
-
1308 const bool &is_order_primary,
-
1309 const CoMMAWeightType &diam_cc,
-
1310 const CoMMAWeightType &vol_cc,
-
1311 const std::unordered_set<CoMMAIndexType> &s_of_fc_for_current_cc,
-
1312 CoMMAIndexType &argmin_ar,
-
1313 CoMMAIntType &max_faces_in_common,
-
1314 CoMMAWeightType &min_ar_diam,
-
1315 CoMMAWeightType &min_ar_vol) const {
-
1316 CoMMAUnused(fc_iter);
-
1317 // this function defines the best fine cells to add to create the coarse
-
1318 // cell for the current coarse cell considered
-
1319 CoMMAWeightType min_ar = std::numeric_limits<CoMMAWeightType>::max();
-
1320 const auto neighbours = neighbourhood->get_candidates();
-
1321 CoMMAIndexType arg_max_faces_in_common = neighbours[0];
-
1322
-
1323 for (const auto &i_fc : neighbours) {
-
1324 // we test every possible new cell to chose the one that locally maximizes
-
1325 // the number of shared faces and/or minimizes the Aspect Ratio Compute
-
1326 // features of the CC obtained by adding i_fc
-
1327 CoMMAIntType number_faces_in_common = 0;
-
1328 CoMMAWeightType new_ar = std::numeric_limits<CoMMAWeightType>::min();
-
1329 CoMMAWeightType new_ar_diam = std::numeric_limits<CoMMAWeightType>::min();
-
1330 CoMMAWeightType new_ar_vol = std::numeric_limits<CoMMAWeightType>::min();
-
1331 this->compute_next_cc_features(
-
1332 i_fc, diam_cc, vol_cc, s_of_fc_for_current_cc,
-
1333 // out
-
1334 number_faces_in_common, new_ar, new_ar_diam, new_ar_vol);
-
1335
-
1336 // Neighbourhood order of i_fc wrt to original seed of CC
-
1337 // [i_fc] is not const the method at returns the reference to the value of
-
1338 // the key i_fc.
-
1339 const CoMMAIntType &order = d_n_of_seed.at(i_fc);
+
1231 // This formula does not work
+
1232 number_of_external_faces_current_cc +=
+
1233 this->_fc_graph->get_nb_of_neighbours(next_cell)
+
1234 + this->_fc_graph->get_n_boundary_faces(next_cell) - 1
+
1235 - 2 * max_faces_in_common;
+
1236 // we increase the cc
+
1237 size_current_cc++;
+
1238 tmp_cc.insert(next_cell);
+
1239
+
1240 // Update compactness
+
1241 CoMMAIntType argmin_compact{0};
+
1242 for (auto neigh = this->_fc_graph->neighbours_cbegin(next_cell);
+
1243 neigh != this->_fc_graph->neighbours_cend(next_cell);
+
1244 ++neigh) {
+
1245 if (tmp_cc.find(*neigh) != tmp_cc.end()) {
+
1246 ++argmin_compact;
+
1247 ++cur_compact_by_fc[*neigh];
+
1248 }
+
1249 }
+
1250 cur_compact_by_fc[next_cell] = argmin_compact;
+
1251 const CoMMAIntType cur_compact =
+
1252 min_element(
+
1253 cur_compact_by_fc.cbegin(), cur_compact_by_fc.cend(), second_less
+
1254 )
+
1255 ->second;
+
1256 // Equivalent to:
+
1257 // this->_fc_graph->compute_min_fc_compactness_inside_a_cc(tmp_cc);
+
1258
+
1259 // if the constructed cc is eligible, i.e. its size is inside the
+
1260 // permitted range we store it inside dict_cc_in_creation This choice is
+
1261 // based on the idea that the smallest cc (w.r.t. card) is may be not
+
1262 // the one that minimized the number of external faces. If this if is
+
1263 // satisfied it means we have an eligible cell
+
1264 if ((this->_min_card <= size_current_cc)
+
1265 || size_current_cc == max_ind) {
+
1266 if (cur_compact > max_compact) {
+
1267 max_compact = cur_compact;
+
1268 min_external_faces = number_of_external_faces_current_cc;
+
1269 arg_min_card = size_current_cc;
+
1270
+
1271 } else if (cur_compact == max_compact) {
+
1272 if (
+
1273 (number_of_external_faces_current_cc < min_external_faces) ||
+
1274 (number_of_external_faces_current_cc == min_external_faces &&
+
1275 arg_min_card != this->_goal_card)) {
+
1276 min_external_faces = number_of_external_faces_current_cc;
+
1277 arg_min_card = size_current_cc;
+
1278 }
+
1279 }
+
1280
+
1281 // We update the dictionary of eligible coarse cells
+
1282 std::unordered_map<CoMMAIndexType, CoMMAIntType> new_dict;
+
1283 new_dict[next_cell] = d_n_of_seed[next_cell];
+
1284 std::pair<
+
1285 std::unordered_set<CoMMAIndexType>,
+
1286 std::unordered_map<CoMMAIndexType, CoMMAIntType>>
+
1287 tmp_pair = std::make_pair(tmp_cc, new_dict);
+
1288 dict_cc_in_creation[size_current_cc] = tmp_pair;
+
1289 }
+
1290
+
1291 // Update of diam_cc and vol_cc with the new fc added
+
1292 diam_cc = min_ar_diam;
+
1293 vol_cc = min_ar_vol;
+
1294
+
1295 // Remove added fc from the available neighbours
+
1296 d_n_of_seed.erase(next_cell);
+
1297 }
+
1298
+
1299 // Selecting best CC to return
+
1300 s_current_cc = std::move(dict_cc_in_creation[arg_min_card].first);
+
1301
+
1302 // If we do not chose the biggest cc, we put the useless fc back to the
+
1303 // pool
+
1304 for (auto i_s = arg_min_card + 1; i_s < max_ind + 1; i_s++) {
+
1305 // for all size of Cell from arg_min_card+1 to min(max_card,
+
1306 // len(d_n_of_seed) + 1) + 1
+
1307 // d_n_of_seed.
+
1308 for (auto iKV : dict_cc_in_creation[i_s].second) {
+
1309 d_n_of_seed[iKV.first] = iKV.second;
+
1310 }
+
1311 }
+
1312
+
1313 // Updating Seeds Pool with the neighbours of the final CC. Strategy:
+
1314 // - Compute the direct neighbours of the CC (not yet agglomerated)
+
1315 // - Insert in the queue starting with those of lowest neighbourhood order
+
1316 // wrt
+
1317 // to the original seed
+
1318 // - If more than one cell with the same order, use priority weights
+
1319 const auto cc_neighs = this->_fc_graph->get_neighbourhood_of_cc(
+
1320 s_current_cc, this->_cc_graph->_is_fc_agglomerated
+
1321 );
+
1322 // Basically, like d_n_of_seed but with key and value swapped
+
1323 std::map<CoMMAIntType, std::unordered_set<CoMMAIndexType>>
+
1324 neighs_by_order{};
+
1325 // For those that were outside max neighbourhood order
+
1326 std::unordered_set<CoMMAIndexType> neighs_not_found{};
+
1327 for (const auto &neigh : cc_neighs) {
+
1328 if (d_n_of_seed.find(neigh) != d_n_of_seed.end())
+
1329 neighs_by_order[d_n_of_seed.at(neigh)].insert(neigh);
+
1330 else
+
1331 neighs_not_found.insert(neigh);
+
1332 }
+
1333 for (const auto &[o, neighs] : neighs_by_order)
+
1334 if (!neighs.empty())
+
1335 this->_seeds_pool->order_new_seeds_and_update(neighs);
+
1336 if (!neighs_not_found.empty())
+
1337 this->_seeds_pool->order_new_seeds_and_update(neighs_not_found);
+
1338
+
1339 assert(arg_min_card == static_cast<CoMMAIntType>(s_current_cc.size()));
1340
-
1341 // TODO This version seems good but refactorisation to do: perhaps it is
-
1342 // not needed to update every new possible coarse cell aspect ratio?
-
1343 // TODO also need to remove the list of min_ar, argmin_ar, etc.
-
1344 if (
-
1345 number_faces_in_common >= max_faces_in_common
-
1346 or is_order_primary) { // if is_order_primary is True the order of
-
1347 // neighbourhood is primary
-
1348 if (number_faces_in_common == max_faces_in_common or is_order_primary) {
-
1349 // If the number of faces in common is the same, let's see whether
-
1350 // it's worth to update or not
-
1351
-
1352 if (order <= d_n_of_seed.at(arg_max_faces_in_common)) {
-
1353 // [arg_max_faces_in_common] is not const.
-
1354 if (order == d_n_of_seed.at(arg_max_faces_in_common)) {
-
1355 if (new_ar < min_ar and number_faces_in_common > 0) {
-
1356 // The second condition asserts the connectivity of the coarse
-
1357 // element.
-
1358 min_ar = new_ar;
-
1359 argmin_ar = i_fc;
-
1360 min_ar_diam = new_ar_diam;
-
1361 min_ar_vol = new_ar_vol;
-
1362
-
1363 arg_max_faces_in_common = i_fc;
-
1364 // The number of face in common is the same no need to touch it
-
1365 }
-
1366 } else {
-
1367 // Case :number_faces_in_common == max_faces_in_common and order <
-
1368 // dict_neighbours_of_seed[arg_max_faces_in_common]:
-
1369 arg_max_faces_in_common = i_fc;
-
1370 min_ar = new_ar;
-
1371 argmin_ar = i_fc;
-
1372 min_ar_diam = new_ar_diam;
-
1373 min_ar_vol = new_ar_vol;
-
1374 // The number of face in common is the same no need to touch it
-
1375 }
-
1376 }
-
1377 } else {
-
1378 // Case number_faces_in_common > max_faces_in_common:
-
1379 // -> Just update and see what comes next
-
1380 max_faces_in_common = number_faces_in_common;
-
1381 arg_max_faces_in_common = i_fc;
-
1382 min_ar = new_ar;
-
1383 argmin_ar = i_fc;
-
1384 min_ar_diam = new_ar_diam;
-
1385 min_ar_vol = new_ar_vol;
-
1386 }
-
1387 }
-
1388 }
-
1389 }
-
1390};
-
1391
-
1399template<
-
1400 typename CoMMAIndexType,
-
1401 typename CoMMAWeightType,
-
1402 typename CoMMAIntType>
-
1403class Agglomerator_Iterative :
-
1404 public Agglomerator_Biconnected<
-
1405 CoMMAIndexType,
-
1406 CoMMAWeightType,
-
1407 CoMMAIntType> {
-
1408public:
-
1423 Agglomerator_Iterative(
-
1424 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1425 graph,
-
1426 std::shared_ptr<
-
1427 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1428 cc_graph,
-
1429 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1430 seeds_pool,
-
1431 CoMMAIntType neighbourhood_type,
-
1432 CoMMAIntType fc_iter,
-
1433 CoMMAIntType dimension = 3) :
-
1434 Agglomerator_Biconnected<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
1435 graph, cc_graph, seeds_pool, neighbourhood_type, fc_iter, dimension) {
-
1436 // no particular constructor
-
1437 }
+
1341 compactness = max_compact;
+
1342 } // end else
+
1343 return s_current_cc;
+
1344 }
+
1345
+
1371 virtual void compute_best_fc_to_add(
+
1372 const CoMMAIntType fc_iter,
+
1373 const std::shared_ptr<
+
1374 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
1375 neighbourhood,
+
1376 const std::unordered_map<CoMMAIndexType, CoMMAIntType> &d_n_of_seed,
+
1377 const bool &is_order_primary,
+
1378 const CoMMAWeightType &diam_cc,
+
1379 const CoMMAWeightType &vol_cc,
+
1380 const std::unordered_set<CoMMAIndexType> &s_of_fc_for_current_cc,
+
1381 CoMMAIndexType &argmin_ar,
+
1382 CoMMAIntType &max_faces_in_common,
+
1383 CoMMAWeightType &min_ar_diam,
+
1384 CoMMAWeightType &min_ar_vol
+
1385 ) const {
+
1386 CoMMAUnused(fc_iter);
+
1387 // this function defines the best fine cells to add to create the coarse
+
1388 // cell for the current coarse cell considered
+
1389 CoMMAWeightType min_ar = std::numeric_limits<CoMMAWeightType>::max();
+
1390 const auto neighbours = neighbourhood->get_candidates();
+
1391 CoMMAIndexType arg_max_faces_in_common = neighbours[0];
+
1392
+
1393 for (const auto &i_fc : neighbours) {
+
1394 // we test every possible new cell to chose the one that locally maximizes
+
1395 // the number of shared faces and/or minimizes the Aspect Ratio Compute
+
1396 // features of the CC obtained by adding i_fc
+
1397 CoMMAIntType number_faces_in_common = 0;
+
1398 CoMMAWeightType new_ar = std::numeric_limits<CoMMAWeightType>::min();
+
1399 CoMMAWeightType new_ar_diam = std::numeric_limits<CoMMAWeightType>::min();
+
1400 CoMMAWeightType new_ar_vol = std::numeric_limits<CoMMAWeightType>::min();
+
1401 this->compute_next_cc_features(
+
1402 i_fc,
+
1403 diam_cc,
+
1404 vol_cc,
+
1405 s_of_fc_for_current_cc,
+
1406 // out
+
1407 number_faces_in_common,
+
1408 new_ar,
+
1409 new_ar_diam,
+
1410 new_ar_vol
+
1411 );
+
1412
+
1413 // Neighbourhood order of i_fc wrt to original seed of CC
+
1414 // [i_fc] is not const the method at returns the reference to the value of
+
1415 // the key i_fc.
+
1416 const CoMMAIntType &order = d_n_of_seed.at(i_fc);
+
1417
+
1418 // TODO This version seems good but refactorisation to do: perhaps it is
+
1419 // not needed to update every new possible coarse cell aspect ratio?
+
1420 // TODO also need to remove the list of min_ar, argmin_ar, etc.
+
1421 if (number_faces_in_common >= max_faces_in_common
+
1422 or is_order_primary) { // if is_order_primary is True the order of
+
1423 // neighbourhood is primary
+
1424 if (number_faces_in_common == max_faces_in_common or is_order_primary) {
+
1425 // If the number of faces in common is the same, let's see whether
+
1426 // it's worth to update or not
+
1427
+
1428 if (order <= d_n_of_seed.at(arg_max_faces_in_common)) {
+
1429 // [arg_max_faces_in_common] is not const.
+
1430 if (order == d_n_of_seed.at(arg_max_faces_in_common)) {
+
1431 if (new_ar < min_ar and number_faces_in_common > 0) {
+
1432 // The second condition asserts the connectivity of the coarse
+
1433 // element.
+
1434 min_ar = new_ar;
+
1435 argmin_ar = i_fc;
+
1436 min_ar_diam = new_ar_diam;
+
1437 min_ar_vol = new_ar_vol;
1438
-
1440 ~Agglomerator_Iterative() override = default;
-
1441
-
1468 void compute_best_fc_to_add(
-
1469 const CoMMAIntType fc_iter,
-
1470 const std::shared_ptr<
-
1471 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1472 neighbourhood,
-
1473 const std::unordered_map<CoMMAIndexType, CoMMAIntType> &d_n_of_seed,
-
1474 const bool &is_order_primary,
-
1475 const CoMMAWeightType &diam_cc,
-
1476 const CoMMAWeightType &vol_cc,
-
1477 const std::unordered_set<CoMMAIndexType> &s_of_fc_for_current_cc,
-
1478 CoMMAIndexType &argmin_ar,
-
1479 CoMMAIntType &max_faces_in_common,
-
1480 CoMMAWeightType &min_ar_diam,
-
1481 CoMMAWeightType &min_ar_vol) const override {
-
1482 CoMMAIndexType outer_argmax_faces{0};
-
1483 CoMMAIntType ref_max_faces = max_faces_in_common;
-
1484 CoMMAWeightType outer_ar = std::numeric_limits<CoMMAWeightType>::max();
-
1485 for (const auto &i_fc : neighbourhood->get_candidates()) {
-
1486 auto cur_neighbourhood = this->_neigh_crtor->clone(neighbourhood);
-
1487 CoMMAWeightType inner_ar{-1.};
-
1488 CoMMAIntType inner_max_faces_in_common{0};
-
1489 CoMMAWeightType inner_min_ar_diam =
-
1490 std::numeric_limits<CoMMAWeightType>::max();
-
1491 CoMMAWeightType inner_min_ar_vol{0.};
-
1492 this->compute_next_cc_features(
-
1493 i_fc, diam_cc, vol_cc, s_of_fc_for_current_cc,
-
1494 inner_max_faces_in_common, inner_ar, inner_min_ar_diam,
-
1495 inner_min_ar_vol);
-
1496 cur_neighbourhood->update(i_fc, this->_fc_graph->get_neighbours(i_fc));
-
1497 std::unordered_set<CoMMAIndexType> cur_fc{
-
1498 s_of_fc_for_current_cc.begin(), s_of_fc_for_current_cc.end()};
-
1499 cur_fc.insert(i_fc);
-
1500 // Store value of mother cell
-
1501 const CoMMAIntType ref_inner_faces = inner_max_faces_in_common;
-
1502
-
1503 if (fc_iter > 1) {
-
1504 CoMMAIndexType cur_argmin{0};
-
1505 CoMMAIntType cur_max_faces_in_common{0};
-
1506 CoMMAWeightType cur_min_ar_diam =
-
1507 std::numeric_limits<CoMMAWeightType>::max();
-
1508 CoMMAWeightType cur_min_ar_vol{0.};
-
1509 CoMMAWeightType cur_min_ar{0.};
-
1510 this->compute_best_fc_to_add(
-
1511 fc_iter - 1, cur_neighbourhood, d_n_of_seed, is_order_primary,
-
1512 inner_min_ar_diam, inner_min_ar_vol, cur_fc,
-
1513 // output
-
1514 cur_argmin, cur_max_faces_in_common, cur_min_ar_diam, cur_min_ar_vol);
-
1515 // We just keep the min AR and the max faces in common
-
1516 if (cur_max_faces_in_common > inner_max_faces_in_common) {
-
1517 inner_max_faces_in_common = cur_max_faces_in_common;
-
1518 } else if (
-
1519 cur_max_faces_in_common == inner_max_faces_in_common
-
1520 && cur_min_ar < inner_ar) {
-
1521 inner_ar = cur_min_ar;
-
1522 }
-
1523 }
-
1524
-
1525 const CoMMAIntType &order = d_n_of_seed.at(i_fc);
-
1526
-
1527 // TODO This version seems good but refactorisation to do: perhaps it is
-
1528 // not needed to update every new possible coarse cell aspect ratio?
-
1529 // TODO also need to remove the list of min_ar, argmin_ar, etc.
-
1530 if (
-
1531 inner_max_faces_in_common >= ref_max_faces
-
1532 or is_order_primary) { // if is_order_primary is True the order of
-
1533 // neighbourhood is primary
-
1534 if (inner_max_faces_in_common == ref_max_faces or is_order_primary) {
-
1535 // If the number of faces in common is the same, let's see whether
-
1536 // it's worth to update or not
-
1537
-
1538 if (order <= d_n_of_seed.at(outer_argmax_faces)) {
-
1539 // [outer_argmax_faces] is not const.
-
1540 if (order == d_n_of_seed.at(outer_argmax_faces)) {
-
1541 if (inner_ar < outer_ar and inner_max_faces_in_common > 0) {
-
1542 // The second condition asserts the connectivity of the coarse
-
1543 // element.
-
1544 argmin_ar = i_fc;
-
1545 // Outer AR is the min AR of the children, but since diameter
-
1546 // and volume are used in the next step, we keep those of the
-
1547 // mother cell...
-
1548 outer_ar = inner_ar;
-
1549 min_ar_diam = inner_min_ar_diam;
-
1550 min_ar_vol = inner_min_ar_vol;
-
1551 // ... same for faces in common
-
1552 max_faces_in_common = ref_inner_faces;
-
1553
-
1554 outer_argmax_faces = i_fc;
-
1555 }
-
1556 } else {
-
1557 // Case :inner_max_faces_in_common == ref_max_faces and order <
-
1558 // dict_neighbours_of_seed[outer_argmax_faces]:
-
1559 outer_argmax_faces = i_fc;
-
1560 argmin_ar = i_fc;
-
1561 // Outer AR is the min AR of the children, but since diameter and
-
1562 // volume are used in the next step, we keep those of the mother
-
1563 // cell...
-
1564 outer_ar = inner_ar;
-
1565 min_ar_diam = inner_min_ar_diam;
-
1566 min_ar_vol = inner_min_ar_vol;
-
1567 // ... same for faces in common
-
1568 max_faces_in_common = ref_inner_faces;
-
1569 }
-
1570 }
-
1571 } else {
-
1572 // Case inner_max_faces_in_common > ref_max_faces:
-
1573 // -> Just update and see what comes next
-
1574 ref_max_faces = inner_max_faces_in_common;
-
1575 outer_argmax_faces = i_fc;
-
1576 argmin_ar = i_fc;
-
1577 // Outer AR is the min AR of the children, but since diameter and
-
1578 // volume are used in the next step, we keep those of the mother
-
1579 // cell...
-
1580 outer_ar = inner_ar;
-
1581 min_ar_diam = inner_min_ar_diam;
-
1582 min_ar_vol = inner_min_ar_vol;
-
1583 // ... same for faces in common
-
1584 max_faces_in_common = ref_inner_faces;
-
1585 }
-
1586 }
-
1587 } // for i_fc
-
1588 }
-
1589};
-
1590
-
1591} // end namespace comma
-
1592
-
1593#endif // COMMA_PROJECT_AGGLOMERATOR_H
+
1439 arg_max_faces_in_common = i_fc;
+
1440 // The number of face in common is the same no need to touch it
+
1441 }
+
1442 } else {
+
1443 // Case :number_faces_in_common == max_faces_in_common and order <
+
1444 // dict_neighbours_of_seed[arg_max_faces_in_common]:
+
1445 arg_max_faces_in_common = i_fc;
+
1446 min_ar = new_ar;
+
1447 argmin_ar = i_fc;
+
1448 min_ar_diam = new_ar_diam;
+
1449 min_ar_vol = new_ar_vol;
+
1450 // The number of face in common is the same no need to touch it
+
1451 }
+
1452 }
+
1453 } else {
+
1454 // Case number_faces_in_common > max_faces_in_common:
+
1455 // -> Just update and see what comes next
+
1456 max_faces_in_common = number_faces_in_common;
+
1457 arg_max_faces_in_common = i_fc;
+
1458 min_ar = new_ar;
+
1459 argmin_ar = i_fc;
+
1460 min_ar_diam = new_ar_diam;
+
1461 min_ar_vol = new_ar_vol;
+
1462 }
+
1463 }
+
1464 }
+
1465 }
+
1466};
+
1467
+
1475template<
+
1476 typename CoMMAIndexType,
+
1477 typename CoMMAWeightType,
+
1478 typename CoMMAIntType>
+
1479class Agglomerator_Iterative :
+
1480 public Agglomerator_Biconnected<
+
1481 CoMMAIndexType,
+
1482 CoMMAWeightType,
+
1483 CoMMAIntType> {
+
1484public:
+
1499 Agglomerator_Iterative(
+
1500 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
1501 graph,
+
1502 std::shared_ptr<
+
1503 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
1504 cc_graph,
+
1505 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
1506 seeds_pool,
+
1507 CoMMAIntType neighbourhood_type,
+
1508 CoMMAIntType fc_iter,
+
1509 CoMMAIntType dimension = 3
+
1510 ) :
+
1511 Agglomerator_Biconnected<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
1512 graph, cc_graph, seeds_pool, neighbourhood_type, fc_iter, dimension
+
1513 ) {
+
1514 // no particular constructor
+
1515 }
+
1516
+
1518 ~Agglomerator_Iterative() override = default;
+
1519
+
1546 void compute_best_fc_to_add(
+
1547 const CoMMAIntType fc_iter,
+
1548 const std::shared_ptr<
+
1549 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
1550 neighbourhood,
+
1551 const std::unordered_map<CoMMAIndexType, CoMMAIntType> &d_n_of_seed,
+
1552 const bool &is_order_primary,
+
1553 const CoMMAWeightType &diam_cc,
+
1554 const CoMMAWeightType &vol_cc,
+
1555 const std::unordered_set<CoMMAIndexType> &s_of_fc_for_current_cc,
+
1556 CoMMAIndexType &argmin_ar,
+
1557 CoMMAIntType &max_faces_in_common,
+
1558 CoMMAWeightType &min_ar_diam,
+
1559 CoMMAWeightType &min_ar_vol
+
1560 ) const override {
+
1561 CoMMAIndexType outer_argmax_faces{0};
+
1562 CoMMAIntType ref_max_faces = max_faces_in_common;
+
1563 CoMMAWeightType outer_ar = std::numeric_limits<CoMMAWeightType>::max();
+
1564 for (const auto &i_fc : neighbourhood->get_candidates()) {
+
1565 auto cur_neighbourhood = this->_neigh_crtor->clone(neighbourhood);
+
1566 CoMMAWeightType inner_ar{-1.};
+
1567 CoMMAIntType inner_max_faces_in_common{0};
+
1568 CoMMAWeightType inner_min_ar_diam =
+
1569 std::numeric_limits<CoMMAWeightType>::max();
+
1570 CoMMAWeightType inner_min_ar_vol{0.};
+
1571 this->compute_next_cc_features(
+
1572 i_fc,
+
1573 diam_cc,
+
1574 vol_cc,
+
1575 s_of_fc_for_current_cc,
+
1576 inner_max_faces_in_common,
+
1577 inner_ar,
+
1578 inner_min_ar_diam,
+
1579 inner_min_ar_vol
+
1580 );
+
1581 cur_neighbourhood->update(i_fc, this->_fc_graph->get_neighbours(i_fc));
+
1582 std::unordered_set<CoMMAIndexType> cur_fc{
+
1583 s_of_fc_for_current_cc.begin(), s_of_fc_for_current_cc.end()
+
1584 };
+
1585 cur_fc.insert(i_fc);
+
1586 // Store value of mother cell
+
1587 const CoMMAIntType ref_inner_faces = inner_max_faces_in_common;
+
1588
+
1589 if (fc_iter > 1) {
+
1590 CoMMAIndexType cur_argmin{0};
+
1591 CoMMAIntType cur_max_faces_in_common{0};
+
1592 CoMMAWeightType cur_min_ar_diam =
+
1593 std::numeric_limits<CoMMAWeightType>::max();
+
1594 CoMMAWeightType cur_min_ar_vol{0.};
+
1595 CoMMAWeightType cur_min_ar{0.};
+
1596 this->compute_best_fc_to_add(
+
1597 fc_iter - 1,
+
1598 cur_neighbourhood,
+
1599 d_n_of_seed,
+
1600 is_order_primary,
+
1601 inner_min_ar_diam,
+
1602 inner_min_ar_vol,
+
1603 cur_fc,
+
1604 // output
+
1605 cur_argmin,
+
1606 cur_max_faces_in_common,
+
1607 cur_min_ar_diam,
+
1608 cur_min_ar_vol
+
1609 );
+
1610 // We just keep the min AR and the max faces in common
+
1611 if (cur_max_faces_in_common > inner_max_faces_in_common) {
+
1612 inner_max_faces_in_common = cur_max_faces_in_common;
+
1613 } else if (cur_max_faces_in_common == inner_max_faces_in_common
+
1614 && cur_min_ar < inner_ar) {
+
1615 inner_ar = cur_min_ar;
+
1616 }
+
1617 }
+
1618
+
1619 const CoMMAIntType &order = d_n_of_seed.at(i_fc);
+
1620
+
1621 // TODO This version seems good but refactorisation to do: perhaps it is
+
1622 // not needed to update every new possible coarse cell aspect ratio?
+
1623 // TODO also need to remove the list of min_ar, argmin_ar, etc.
+
1624 if (inner_max_faces_in_common >= ref_max_faces
+
1625 or is_order_primary) { // if is_order_primary is True the order of
+
1626 // neighbourhood is primary
+
1627 if (inner_max_faces_in_common == ref_max_faces or is_order_primary) {
+
1628 // If the number of faces in common is the same, let's see whether
+
1629 // it's worth to update or not
+
1630
+
1631 if (order <= d_n_of_seed.at(outer_argmax_faces)) {
+
1632 // [outer_argmax_faces] is not const.
+
1633 if (order == d_n_of_seed.at(outer_argmax_faces)) {
+
1634 if (inner_ar < outer_ar and inner_max_faces_in_common > 0) {
+
1635 // The second condition asserts the connectivity of the coarse
+
1636 // element.
+
1637 argmin_ar = i_fc;
+
1638 // Outer AR is the min AR of the children, but since diameter
+
1639 // and volume are used in the next step, we keep those of the
+
1640 // mother cell...
+
1641 outer_ar = inner_ar;
+
1642 min_ar_diam = inner_min_ar_diam;
+
1643 min_ar_vol = inner_min_ar_vol;
+
1644 // ... same for faces in common
+
1645 max_faces_in_common = ref_inner_faces;
+
1646
+
1647 outer_argmax_faces = i_fc;
+
1648 }
+
1649 } else {
+
1650 // Case :inner_max_faces_in_common == ref_max_faces and order <
+
1651 // dict_neighbours_of_seed[outer_argmax_faces]:
+
1652 outer_argmax_faces = i_fc;
+
1653 argmin_ar = i_fc;
+
1654 // Outer AR is the min AR of the children, but since diameter and
+
1655 // volume are used in the next step, we keep those of the mother
+
1656 // cell...
+
1657 outer_ar = inner_ar;
+
1658 min_ar_diam = inner_min_ar_diam;
+
1659 min_ar_vol = inner_min_ar_vol;
+
1660 // ... same for faces in common
+
1661 max_faces_in_common = ref_inner_faces;
+
1662 }
+
1663 }
+
1664 } else {
+
1665 // Case inner_max_faces_in_common > ref_max_faces:
+
1666 // -> Just update and see what comes next
+
1667 ref_max_faces = inner_max_faces_in_common;
+
1668 outer_argmax_faces = i_fc;
+
1669 argmin_ar = i_fc;
+
1670 // Outer AR is the min AR of the children, but since diameter and
+
1671 // volume are used in the next step, we keep those of the mother
+
1672 // cell...
+
1673 outer_ar = inner_ar;
+
1674 min_ar_diam = inner_min_ar_diam;
+
1675 min_ar_vol = inner_min_ar_vol;
+
1676 // ... same for faces in common
+
1677 max_faces_in_common = ref_inner_faces;
+
1678 }
+
1679 }
+
1680 } // for i_fc
+
1681 }
+
1682};
+
1683
+
1684} // end namespace comma
+
1685
+
1686#endif // COMMA_PROJECT_AGGLOMERATOR_H
Coarse_Cell_Container.h
Dual_Graph.h
Neighbourhood.h
Util.h
CoMMAUnused
#define CoMMAUnused(var)
Convenient function to avoid unused warnings.
Definition: Util.h:34
-
comma::Agglomerator_Anisotropic
Agglomerator_Anisotropic class is a child class of the Agglomerator class that specializes the implem...
Definition: Agglomerator.h:181
-
comma::Agglomerator_Anisotropic::build_anisotropic_lines
bool build_anisotropic_lines(const std::vector< CoMMAWeightType > &priority_weights, const CoMMAWeightType threshold_anisotropy)
Build the anisotropic lines at the first level (only called at the first level of agglomeration)....
Definition: Agglomerator.h:517
-
comma::Agglomerator_Anisotropic::export_anisotropic_lines
void export_anisotropic_lines(CoMMAIntType level, std::vector< CoMMAIndexType > &aniso_lines_idx, std::vector< CoMMAIndexType > &aniso_lines) const
Function that prepares the anisotropic lines for output.
Definition: Agglomerator.h:456
-
comma::Agglomerator_Anisotropic::CoMMAPairType
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Agglomerator.h:190
-
comma::Agglomerator_Anisotropic::_odd_line_length
bool _odd_line_length
Whether anisotropic lines with odd length are allowed.
Definition: Agglomerator.h:703
-
comma::Agglomerator_Anisotropic::update_seeds_pool
void update_seeds_pool()
Update the seeds pool with the neighbours of the anisotropic cells agglomerated so far.
Definition: Agglomerator.h:422
-
comma::Agglomerator_Anisotropic::agglomerate_one_level
void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) override
Specialization of the pure virtual function to the class Agglomerator_Anisotropic....
Definition: Agglomerator.h:301
-
comma::Agglomerator_Anisotropic::_should_agglomerate
bool _should_agglomerate
Whether agglomeration is possible: for instance, if anisotropy requested but no anisotropic cells fou...
Definition: Agglomerator.h:503
-
comma::Agglomerator_Anisotropic::_max_cells_in_line
std::optional< CoMMAIndexType > _max_cells_in_line
Maximum number of cells in an anisotropic line; when this value is reached, all reaming cells are dis...
Definition: Agglomerator.h:708
-
comma::Agglomerator_Anisotropic::AnisotropicLine
std::deque< CoMMAIndexType > AnisotropicLine
Container for an anisotropic line.
Definition: Agglomerator.h:184
-
comma::Agglomerator_Anisotropic::AnisotropicLinePtr
std::shared_ptr< AnisotropicLine > AnisotropicLinePtr
(Shared) Pointer to an anisotropic line
Definition: Agglomerator.h:187
-
comma::Agglomerator_Anisotropic::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Agglomerator.h:193
+
comma::Agglomerator_Anisotropic
Agglomerator_Anisotropic class is a child class of the Agglomerator class that specializes the implem...
Definition: Agglomerator.h:185
+
comma::Agglomerator_Anisotropic::build_anisotropic_lines
bool build_anisotropic_lines(const std::vector< CoMMAWeightType > &priority_weights, const CoMMAWeightType threshold_anisotropy)
Build the anisotropic lines at the first level (only called at the first level of agglomeration)....
Definition: Agglomerator.h:533
+
comma::Agglomerator_Anisotropic::export_anisotropic_lines
void export_anisotropic_lines(CoMMAIntType level, std::vector< CoMMAIndexType > &aniso_lines_idx, std::vector< CoMMAIndexType > &aniso_lines) const
Function that prepares the anisotropic lines for output.
Definition: Agglomerator.h:470
+
comma::Agglomerator_Anisotropic::CoMMAPairType
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Agglomerator.h:194
+
comma::Agglomerator_Anisotropic::_odd_line_length
bool _odd_line_length
Whether anisotropic lines with odd length are allowed.
Definition: Agglomerator.h:729
+
comma::Agglomerator_Anisotropic::update_seeds_pool
void update_seeds_pool()
Update the seeds pool with the neighbours of the anisotropic cells agglomerated so far.
Definition: Agglomerator.h:434
+
comma::Agglomerator_Anisotropic::agglomerate_one_level
void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) override
Specialization of the pure virtual function to the class Agglomerator_Anisotropic....
Definition: Agglomerator.h:309
+
comma::Agglomerator_Anisotropic::_should_agglomerate
bool _should_agglomerate
Whether agglomeration is possible: for instance, if anisotropy requested but no anisotropic cells fou...
Definition: Agglomerator.h:519
+
comma::Agglomerator_Anisotropic::_max_cells_in_line
std::optional< CoMMAIndexType > _max_cells_in_line
Maximum number of cells in an anisotropic line; when this value is reached, all reaming cells are dis...
Definition: Agglomerator.h:734
+
comma::Agglomerator_Anisotropic::AnisotropicLine
std::deque< CoMMAIndexType > AnisotropicLine
Container for an anisotropic line.
Definition: Agglomerator.h:188
+
comma::Agglomerator_Anisotropic::AnisotropicLinePtr
std::shared_ptr< AnisotropicLine > AnisotropicLinePtr
(Shared) Pointer to an anisotropic line
Definition: Agglomerator.h:191
+
comma::Agglomerator_Anisotropic::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Agglomerator.h:197
comma::Agglomerator_Anisotropic::~Agglomerator_Anisotropic
~Agglomerator_Anisotropic() override=default
Destructor.
-
comma::Agglomerator_Anisotropic::_v_lines
std::vector< std::vector< AnisotropicLinePtr > > _v_lines
_v_lines : Agglomeration lines structure:
Definition: Agglomerator.h:498
-
comma::Agglomerator_Anisotropic::_aniso_neighbours
std::deque< CoMMAIndexType > _aniso_neighbours
Neighbours of the anisotropic cells agglomerated. They are used to update the seeds pool.
Definition: Agglomerator.h:700
-
comma::Agglomerator_Anisotropic::Agglomerator_Anisotropic
Agglomerator_Anisotropic(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, const CoMMAWeightType threshold_anisotropy, const std::vector< CoMMAIndexType > &agglomerationLines_Idx, const std::vector< CoMMAIndexType > &agglomerationLines, const std::vector< CoMMAWeightType > &priority_weights, const bool build_lines, const bool odd_line_length, const std::optional< CoMMAIndexType > max_cells_in_line, CoMMAIntType dimension=3)
Constructor.
Definition: Agglomerator.h:219
-
comma::Agglomerator_Anisotropic::_nb_lines
std::vector< CoMMAIndexType > _nb_lines
Vector of number of Anisotropic agglomeration lines per level.
Definition: Agglomerator.h:490
-
comma::Agglomerator_Biconnected
Child class of Agglomerator_Isotropic where is implemented a specific biconnected algorithm for the a...
Definition: Agglomerator.h:996
+
comma::Agglomerator_Anisotropic::_v_lines
std::vector< std::vector< AnisotropicLinePtr > > _v_lines
_v_lines : Agglomeration lines structure:
Definition: Agglomerator.h:514
+
comma::Agglomerator_Anisotropic::_aniso_neighbours
std::deque< CoMMAIndexType > _aniso_neighbours
Neighbours of the anisotropic cells agglomerated. They are used to update the seeds pool.
Definition: Agglomerator.h:726
+
comma::Agglomerator_Anisotropic::Agglomerator_Anisotropic
Agglomerator_Anisotropic(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, const CoMMAWeightType threshold_anisotropy, const std::vector< CoMMAIndexType > &agglomerationLines_Idx, const std::vector< CoMMAIndexType > &agglomerationLines, const std::vector< CoMMAWeightType > &priority_weights, const bool build_lines, const bool odd_line_length, const std::optional< CoMMAIndexType > max_cells_in_line, CoMMAIntType dimension=3)
Constructor.
Definition: Agglomerator.h:223
+
comma::Agglomerator_Anisotropic::_nb_lines
std::vector< CoMMAIndexType > _nb_lines
Vector of number of Anisotropic agglomeration lines per level.
Definition: Agglomerator.h:506
+
comma::Agglomerator_Biconnected
Child class of Agglomerator_Isotropic where is implemented a specific biconnected algorithm for the a...
Definition: Agglomerator.h:1044
comma::Agglomerator_Biconnected::~Agglomerator_Biconnected
~Agglomerator_Biconnected() override=default
Destructor.
-
comma::Agglomerator_Biconnected::choose_optimal_cc_and_update_seeds_pool
std::unordered_set< CoMMAIndexType > choose_optimal_cc_and_update_seeds_pool(const CoMMAIndexType seed, const std::vector< CoMMAWeightType > &priority_weights, CoMMAIntType &compactness) override
Specialization of the pure virtual function in the parent class, to be used in couple with the agglom...
Definition: Agglomerator.h:1041
-
comma::Agglomerator_Biconnected::Agglomerator_Biconnected
Agglomerator_Biconnected(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, CoMMAIntType neighbourhood_type, CoMMAIntType fc_iter, CoMMAIntType dimension=3)
Constructor of the class. No specific implementation, it instantiates the base class Agglomerator_Iso...
Definition: Agglomerator.h:1012
-
comma::Agglomerator_Biconnected::compute_best_fc_to_add
virtual void compute_best_fc_to_add(const CoMMAIntType fc_iter, const std::shared_ptr< Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > neighbourhood, const std::unordered_map< CoMMAIndexType, CoMMAIntType > &d_n_of_seed, const bool &is_order_primary, const CoMMAWeightType &diam_cc, const CoMMAWeightType &vol_cc, const std::unordered_set< CoMMAIndexType > &s_of_fc_for_current_cc, CoMMAIndexType &argmin_ar, CoMMAIntType &max_faces_in_common, CoMMAWeightType &min_ar_diam, CoMMAWeightType &min_ar_vol) const
Computes the best fine cell to add to the coarse cell. The choice depends on: the number of shared fa...
Definition: Agglomerator.h:1302
-
comma::Agglomerator_Isotropic
Agglomerator_Isotropic class is a child class of the Agglomerator class that specializes the implemen...
Definition: Agglomerator.h:724
+
comma::Agglomerator_Biconnected::choose_optimal_cc_and_update_seeds_pool
std::unordered_set< CoMMAIndexType > choose_optimal_cc_and_update_seeds_pool(const CoMMAIndexType seed, const std::vector< CoMMAWeightType > &priority_weights, CoMMAIntType &compactness) override
Specialization of the pure virtual function in the parent class, to be used in couple with the agglom...
Definition: Agglomerator.h:1091
+
comma::Agglomerator_Biconnected::Agglomerator_Biconnected
Agglomerator_Biconnected(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, CoMMAIntType neighbourhood_type, CoMMAIntType fc_iter, CoMMAIntType dimension=3)
Constructor of the class. No specific implementation, it instantiates the base class Agglomerator_Iso...
Definition: Agglomerator.h:1060
+
comma::Agglomerator_Biconnected::compute_best_fc_to_add
virtual void compute_best_fc_to_add(const CoMMAIntType fc_iter, const std::shared_ptr< Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > neighbourhood, const std::unordered_map< CoMMAIndexType, CoMMAIntType > &d_n_of_seed, const bool &is_order_primary, const CoMMAWeightType &diam_cc, const CoMMAWeightType &vol_cc, const std::unordered_set< CoMMAIndexType > &s_of_fc_for_current_cc, CoMMAIndexType &argmin_ar, CoMMAIntType &max_faces_in_common, CoMMAWeightType &min_ar_diam, CoMMAWeightType &min_ar_vol) const
Computes the best fine cell to add to the coarse cell. The choice depends on: the number of shared fa...
Definition: Agglomerator.h:1371
+
comma::Agglomerator_Isotropic
Agglomerator_Isotropic class is a child class of the Agglomerator class that specializes the implemen...
Definition: Agglomerator.h:750
comma::Agglomerator_Isotropic::choose_optimal_cc_and_update_seeds_pool
virtual std::unordered_set< CoMMAIndexType > choose_optimal_cc_and_update_seeds_pool(const CoMMAIndexType seed, const std::vector< CoMMAWeightType > &priority_weights, CoMMAIntType &compactness)=0
Pure virtual function that must be implemented in child classes to define the optimal coarse cell.
-
comma::Agglomerator_Isotropic::estimate_boundary_face
CoMMAWeightType estimate_boundary_face(const std::vector< CoMMAWeightType > &int_faces) const
Approximate the value of a boundary face using the known internal faces. It uses a (geometric) averag...
Definition: Agglomerator.h:901
-
comma::Agglomerator_Isotropic::_neigh_crtor
std::shared_ptr< NeighbourhoodCreatorBaseType > _neigh_crtor
Creator responsible for neighborhood objects.
Definition: Agglomerator.h:743
-
comma::Agglomerator_Isotropic::_fc_iter
CoMMAIntType _fc_iter
Number of iterations allowed for the algorithm choosing which fine cell to add next.
Definition: Agglomerator.h:740
-
comma::Agglomerator_Isotropic::set_agglomeration_parameter
void set_agglomeration_parameter(CoMMAIntType goal_card=0, CoMMAIntType min_card=0, CoMMAIntType max_card=0)
The task of the function is to set the parameters of determine the cardinality limits with respect to...
Definition: Agglomerator.h:792
-
comma::Agglomerator_Isotropic::agglomerate_one_level
void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) override
Specialization of the pure virtual function to the class Agglomerator_Isotropic. We add the override ...
Definition: Agglomerator.h:854
-
comma::Agglomerator_Isotropic::Agglomerator_Isotropic
Agglomerator_Isotropic(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, CoMMAIntType neighbourhood_type, CoMMAIntType fc_iter, CoMMAIntType dimension=3)
Constructor. The constructor takes as arguments the same arguments of the father and in this way acti...
Definition: Agglomerator.h:760
-
comma::Agglomerator_Isotropic::compute_next_cc_features
void compute_next_cc_features(const CoMMAIndexType i_fc, const CoMMAWeightType cc_diam, const CoMMAWeightType cc_vol, const std::unordered_set< CoMMAIndexType > &fc_of_cc, CoMMAIntType &shared_faces, CoMMAWeightType &aspect_ratio, CoMMAWeightType &new_diam, CoMMAWeightType &new_vol) const
Computes features of the CC obtained by adding a given fine cell. The features are Aspect-Ratio and n...
Definition: Agglomerator.h:931
+
comma::Agglomerator_Isotropic::estimate_boundary_face
CoMMAWeightType estimate_boundary_face(const std::vector< CoMMAWeightType > &int_faces) const
Approximate the value of a boundary face using the known internal faces. It uses a (geometric) averag...
Definition: Agglomerator.h:940
+
comma::Agglomerator_Isotropic::_neigh_crtor
std::shared_ptr< NeighbourhoodCreatorBaseType > _neigh_crtor
Creator responsible for neighborhood objects.
Definition: Agglomerator.h:769
+
comma::Agglomerator_Isotropic::_fc_iter
CoMMAIntType _fc_iter
Number of iterations allowed for the algorithm choosing which fine cell to add next.
Definition: Agglomerator.h:766
+
comma::Agglomerator_Isotropic::set_agglomeration_parameter
void set_agglomeration_parameter(CoMMAIntType goal_card=0, CoMMAIntType min_card=0, CoMMAIntType max_card=0)
The task of the function is to set the parameters of determine the cardinality limits with respect to...
Definition: Agglomerator.h:820
+
comma::Agglomerator_Isotropic::agglomerate_one_level
void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) override
Specialization of the pure virtual function to the class Agglomerator_Isotropic. We add the override ...
Definition: Agglomerator.h:887
+
comma::Agglomerator_Isotropic::Agglomerator_Isotropic
Agglomerator_Isotropic(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, CoMMAIntType neighbourhood_type, CoMMAIntType fc_iter, CoMMAIntType dimension=3)
Constructor. The constructor takes as arguments the same arguments of the father and in this way acti...
Definition: Agglomerator.h:786
+
comma::Agglomerator_Isotropic::compute_next_cc_features
void compute_next_cc_features(const CoMMAIndexType i_fc, const CoMMAWeightType cc_diam, const CoMMAWeightType cc_vol, const std::unordered_set< CoMMAIndexType > &fc_of_cc, CoMMAIntType &shared_faces, CoMMAWeightType &aspect_ratio, CoMMAWeightType &new_diam, CoMMAWeightType &new_vol) const
Computes features of the CC obtained by adding a given fine cell. The features are Aspect-Ratio and n...
Definition: Agglomerator.h:975
comma::Agglomerator_Isotropic::~Agglomerator_Isotropic
~Agglomerator_Isotropic() override=default
Destructor.
-
comma::Agglomerator_Iterative
Child class of Agglomerator_Isotropic which implements a specialized iterative algorithm for the sear...
Definition: Agglomerator.h:1407
+
comma::Agglomerator_Iterative
Child class of Agglomerator_Isotropic which implements a specialized iterative algorithm for the sear...
Definition: Agglomerator.h:1483
comma::Agglomerator_Iterative::~Agglomerator_Iterative
~Agglomerator_Iterative() override=default
Destructor.
-
comma::Agglomerator_Iterative::Agglomerator_Iterative
Agglomerator_Iterative(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, CoMMAIntType neighbourhood_type, CoMMAIntType fc_iter, CoMMAIntType dimension=3)
Constructor of the class. No specific implementation, it instantiates the base class Agglomerator_Bic...
Definition: Agglomerator.h:1423
-
comma::Agglomerator_Iterative::compute_best_fc_to_add
void compute_best_fc_to_add(const CoMMAIntType fc_iter, const std::shared_ptr< Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > neighbourhood, const std::unordered_map< CoMMAIndexType, CoMMAIntType > &d_n_of_seed, const bool &is_order_primary, const CoMMAWeightType &diam_cc, const CoMMAWeightType &vol_cc, const std::unordered_set< CoMMAIndexType > &s_of_fc_for_current_cc, CoMMAIndexType &argmin_ar, CoMMAIntType &max_faces_in_common, CoMMAWeightType &min_ar_diam, CoMMAWeightType &min_ar_vol) const override
Specialization of the parent function. This is an iterative version. Computes the best fine cell to a...
Definition: Agglomerator.h:1468
+
comma::Agglomerator_Iterative::Agglomerator_Iterative
Agglomerator_Iterative(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, CoMMAIntType neighbourhood_type, CoMMAIntType fc_iter, CoMMAIntType dimension=3)
Constructor of the class. No specific implementation, it instantiates the base class Agglomerator_Bic...
Definition: Agglomerator.h:1499
+
comma::Agglomerator_Iterative::compute_best_fc_to_add
void compute_best_fc_to_add(const CoMMAIntType fc_iter, const std::shared_ptr< Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > neighbourhood, const std::unordered_map< CoMMAIndexType, CoMMAIntType > &d_n_of_seed, const bool &is_order_primary, const CoMMAWeightType &diam_cc, const CoMMAWeightType &vol_cc, const std::unordered_set< CoMMAIndexType > &s_of_fc_for_current_cc, CoMMAIndexType &argmin_ar, CoMMAIntType &max_faces_in_common, CoMMAWeightType &min_ar_diam, CoMMAWeightType &min_ar_vol) const override
Specialization of the parent function. This is an iterative version. Computes the best fine cell to a...
Definition: Agglomerator.h:1546
comma::Agglomerator
A class responsible to do the interface between the different kinds of agglomerator.
Definition: Agglomerator.h:53
-
comma::Agglomerator::_l_nb_of_cells
std::vector< CoMMAIndexType > _l_nb_of_cells
List of number of cells per coarse cell created.
Definition: Agglomerator.h:150
+
comma::Agglomerator::_l_nb_of_cells
std::vector< CoMMAIndexType > _l_nb_of_cells
List of number of cells per coarse cell created.
Definition: Agglomerator.h:154
comma::Agglomerator::~Agglomerator
virtual ~Agglomerator()=default
The destructor of the class.
comma::Agglomerator::Agglomerator
Agglomerator(std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > graph, std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > cc_graph, std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > seeds_pool, CoMMAIntType dimension=3)
The constructor of the interface.
Definition: Agglomerator.h:71
-
comma::Agglomerator::_min_card
CoMMAIntType _min_card
Minimum cardinality (default = 0, meaning, equal to the dimension)
Definition: Agglomerator.h:136
-
comma::Agglomerator::_cc_graph
std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > _cc_graph
pointer to Coarse_Cell_Container element
Definition: Agglomerator.h:160
-
comma::Agglomerator::_fc_graph
std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > _fc_graph
Dual_Graph object determining Fine cells graph and hence the connectivity.
Definition: Agglomerator.h:155
-
comma::Agglomerator::_threshold_card
CoMMAIntType _threshold_card
Threshold cardinality (default = 0, meaning, equal to the dimension)
Definition: Agglomerator.h:148
-
comma::Agglomerator::_min_neighbourhood
CoMMAIntType _min_neighbourhood
Minimum number of neighbourhood we extend to search the neighbourhood in the greedy algorithm....
Definition: Agglomerator.h:133
-
comma::Agglomerator::_dimension
CoMMAIntType _dimension
Dimensionality of the problem (_dimension = 2 -> 2D, _dimension = 3 -> 3D)
Definition: Agglomerator.h:130
+
comma::Agglomerator::_min_card
CoMMAIntType _min_card
Minimum cardinality (default = 0, meaning, equal to the dimension)
Definition: Agglomerator.h:140
+
comma::Agglomerator::_cc_graph
std::shared_ptr< Coarse_Cell_Container< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > _cc_graph
pointer to Coarse_Cell_Container element
Definition: Agglomerator.h:164
+
comma::Agglomerator::_fc_graph
std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > _fc_graph
Dual_Graph object determining Fine cells graph and hence the connectivity.
Definition: Agglomerator.h:159
+
comma::Agglomerator::_threshold_card
CoMMAIntType _threshold_card
Threshold cardinality (default = 0, meaning, equal to the dimension)
Definition: Agglomerator.h:152
+
comma::Agglomerator::_min_neighbourhood
CoMMAIntType _min_neighbourhood
Minimum number of neighbourhood we extend to search the neighbourhood in the greedy algorithm....
Definition: Agglomerator.h:137
+
comma::Agglomerator::_dimension
CoMMAIntType _dimension
Dimensionality of the problem (_dimension = 2 -> 2D, _dimension = 3 -> 3D)
Definition: Agglomerator.h:134
comma::Agglomerator::_compute_AR
std::function< CoMMAWeightType(const CoMMAWeightType, const CoMMAWeightType)> _compute_AR
Function which computes the aspect-ratio from a diameter and a volume In 3D: In 2D: (Recall th...
Definition: Agglomerator.h:61
-
comma::Agglomerator::_max_card
CoMMAIntType _max_card
Maximum cardinality (default = 0, meaning, 5 or 10 for, resp., 2- and 3D.
Definition: Agglomerator.h:140
-
comma::Agglomerator::_seeds_pool
std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > _seeds_pool
Seeds_Pool object giving the order in which the fine cells should be considered when agglomerating.
Definition: Agglomerator.h:165
-
comma::Agglomerator::_goal_card
CoMMAIntType _goal_card
Goal cardinality (default = 0, meaning, 4 or 8 for, resp., 2- and 3D.
Definition: Agglomerator.h:144
-
comma::Agglomerator::get_fc_2_cc
std::vector< CoMMAIndexType > get_fc_2_cc() const
Accessor to retrieve the fine cells to coarse cells from the coarse cell graphs class.
Definition: Agglomerator.h:105
+
comma::Agglomerator::_max_card
CoMMAIntType _max_card
Maximum cardinality (default = 0, meaning, 5 or 10 for, resp., 2- and 3D.
Definition: Agglomerator.h:144
+
comma::Agglomerator::_seeds_pool
std::shared_ptr< Seeds_Pool< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > _seeds_pool
Seeds_Pool object giving the order in which the fine cells should be considered when agglomerating.
Definition: Agglomerator.h:169
+
comma::Agglomerator::_goal_card
CoMMAIntType _goal_card
Goal cardinality (default = 0, meaning, 4 or 8 for, resp., 2- and 3D.
Definition: Agglomerator.h:148
+
comma::Agglomerator::get_fc_2_cc
std::vector< CoMMAIndexType > get_fc_2_cc() const
Accessor to retrieve the fine cells to coarse cells from the coarse cell graphs class.
Definition: Agglomerator.h:108
comma::Agglomerator::agglomerate_one_level
virtual void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps)=0
Pure virtual function which implementation is specified in the related child classes and that defines...
comma::Coarse_Cell_Container
Class implementing a custom container where the coarse cells are stored.
Definition: Coarse_Cell_Container.h:41
-
comma::Dual_Graph
A class implementing the CRS global graph representation of the global mesh.
Definition: Dual_Graph.h:517
-
comma::NeighbourhoodCreator
Pure abstract class for a creator of Neighbourhood objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:381
-
comma::NeighbourhoodExtendedCreator
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:427
+
comma::Dual_Graph
A class implementing the CRS global graph representation of the global mesh.
Definition: Dual_Graph.h:546
+
comma::NeighbourhoodCreator
Pure abstract class for a creator of Neighbourhood objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:393
+
comma::NeighbourhoodExtendedCreator
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:441
comma::Neighbourhood
Class representing the neighbourhood of a given cell in the graph. Mind that no information about the...
Definition: Neighbourhood.h:42
-
comma::NeighbourhoodPureFrontCreator
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:490
-
comma::Seeds_Pool
Class representing the pool of all the seeds for creating a coarse cell.
Definition: Seeds_Pool.h:194
+
comma::NeighbourhoodPureFrontCreator
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:509
+
comma::Seeds_Pool
Class representing the pool of all the seeds for creating a coarse cell.
Definition: Seeds_Pool.h:200
comma
Definition: Agglomerator.h:34
comma::EXTENDED
@ EXTENDED
Extended, all neighbours of the coarse cell.
Definition: CoMMADefs.h:38
diff --git a/_bimap_8h_source.html b/_bimap_8h_source.html index b2b3c55..a54f7ac 100644 --- a/_bimap_8h_source.html +++ b/_bimap_8h_source.html @@ -150,61 +150,65 @@
69 _mapB.insert(std::move(node));
70 }
71 }
-
77 void update_nodeA(const B &b_old, const B &b_new) {
-
78 auto node = _mapA.extract(b_old);
-
79 if (!node.empty()) {
-
80 node.key() = b_new;
-
81 _mapA.insert(std::move(node));
-
82 }
-
83 }
-
88 B get_B(const A &a) {
-
89 // We pass the associated value we want to search to the member
-
90 // variable
-
91 auto it = _mapB.find(a);
-
92 return (*(it->second));
-
93 }
-
94
-
99 A get_A(const B &b) {
-
100 // We pass the associated value we want to search to the member
-
101 // variable
-
102 auto it = _mapA.find(b);
-
103 return (*(it->second));
-
104 }
-
105
-
110 void erase_B(const A &a) {
-
111 // We pass the associated value we want to search to the member
-
112 // variable
-
113 auto itB = _mapB.find(a);
-
114 auto be = *(itB->second);
-
115 auto itA = _mapA.find(be);
-
116 _mapB.erase(itB);
-
117 _mapA.erase(itA);
-
118 }
-
122 inline bool empty() { return (_mapA.empty()); }
-
126 inline size_t lung() { return (_mapB.size()); }
-
127
-
128protected:
-
130 std::map<B, const A *> _mapA;
-
132 std::map<A, const B *> _mapB;
-
133};
-
134
-
135} // end namespace comma
-
136
-
137#endif
+
72
+
78 void update_nodeA(const B &b_old, const B &b_new) {
+
79 auto node = _mapA.extract(b_old);
+
80 if (!node.empty()) {
+
81 node.key() = b_new;
+
82 _mapA.insert(std::move(node));
+
83 }
+
84 }
+
85
+
90 B get_B(const A &a) {
+
91 // We pass the associated value we want to search to the member
+
92 // variable
+
93 auto it = _mapB.find(a);
+
94 return (*(it->second));
+
95 }
+
96
+
101 A get_A(const B &b) {
+
102 // We pass the associated value we want to search to the member
+
103 // variable
+
104 auto it = _mapA.find(b);
+
105 return (*(it->second));
+
106 }
+
107
+
112 void erase_B(const A &a) {
+
113 // We pass the associated value we want to search to the member
+
114 // variable
+
115 auto itB = _mapB.find(a);
+
116 auto be = *(itB->second);
+
117 auto itA = _mapA.find(be);
+
118 _mapB.erase(itB);
+
119 _mapA.erase(itA);
+
120 }
+
121
+
125 inline bool empty() { return (_mapA.empty()); }
+
126
+
130 inline size_t lung() { return (_mapB.size()); }
+
131
+
132protected:
+
134 std::map<B, const A *> _mapA;
+
136 std::map<A, const B *> _mapB;
+
137};
+
138
+
139} // end namespace comma
+
140
+
141#endif
comma::Bimap
An easy and straight forward implementation of a Bimap.
Definition: Bimap.h:28
-
comma::Bimap::update_nodeA
void update_nodeA(const B &b_old, const B &b_new)
Update of the key of the map A and hence the value of the node B.
Definition: Bimap.h:77
-
comma::Bimap::get_B
B get_B(const A &a)
Getter of the B value starting from a A value.
Definition: Bimap.h:88
+
comma::Bimap::update_nodeA
void update_nodeA(const B &b_old, const B &b_new)
Update of the key of the map A and hence the value of the node B.
Definition: Bimap.h:78
+
comma::Bimap::get_B
B get_B(const A &a)
Getter of the B value starting from a A value.
Definition: Bimap.h:90
comma::Bimap::~Bimap
~Bimap()=default
Destructor.
comma::Bimap::Bimap
Bimap()=default
Constructor.
comma::Bimap::insert
void insert(const A &a, const B &b)
Insertion function in the Bimap.
Definition: Bimap.h:44
-
comma::Bimap::empty
bool empty()
Check if the Bimap is empty.
Definition: Bimap.h:122
-
comma::Bimap::erase_B
void erase_B(const A &a)
Eraser of the value starting from a A value.
Definition: Bimap.h:110
-
comma::Bimap::_mapB
std::map< A, const B * > _mapB
Right map.
Definition: Bimap.h:132
-
comma::Bimap::get_A
A get_A(const B &b)
Getter of the A value starting from a B value.
Definition: Bimap.h:99
+
comma::Bimap::empty
bool empty()
Check if the Bimap is empty.
Definition: Bimap.h:125
+
comma::Bimap::erase_B
void erase_B(const A &a)
Eraser of the value starting from a A value.
Definition: Bimap.h:112
+
comma::Bimap::_mapB
std::map< A, const B * > _mapB
Right map.
Definition: Bimap.h:136
+
comma::Bimap::get_A
A get_A(const B &b)
Getter of the A value starting from a B value.
Definition: Bimap.h:101
comma::Bimap::update_nodeB
void update_nodeB(const A &a_old, const A &a_new)
Update of the key of the map B and hence the value of the node A.
Definition: Bimap.h:65
-
comma::Bimap::_mapA
std::map< B, const A * > _mapA
Left map
Definition: Bimap.h:130
+
comma::Bimap::_mapA
std::map< B, const A * > _mapA
Left map
Definition: Bimap.h:134
comma::Bimap::print
void print()
Function to print the map.
Definition: Bimap.h:54
-
comma::Bimap::lung
size_t lung()
Returns the size of the container.
Definition: Bimap.h:126
+
comma::Bimap::lung
size_t lung()
Returns the size of the container.
Definition: Bimap.h:130
comma
Definition: Agglomerator.h:34
diff --git a/_co_m_m_a_8h_source.html b/_co_m_m_a_8h_source.html index 05df7c6..5ef4295 100644 --- a/_co_m_m_a_8h_source.html +++ b/_co_m_m_a_8h_source.html @@ -128,292 +128,336 @@
32
33namespace comma {
34
-
36#define CHECK_INT_TYPE(intT, label) \
-
37 static_assert( \
-
38 std::numeric_limits<intT>::is_integer, \
-
39 "CoMMA works with integer types, but " #intT " (" label ") is not")
-
41
-
45constexpr CoMMAIntT iter_agglo_max_iter = 4;
-
46
-
125template<
-
126 typename CoMMAIndexType,
-
127 typename CoMMAWeightType,
-
128 typename CoMMAIntType>
-
129void agglomerate_one_level(
-
130 // Dual graph:
-
131 const std::vector<CoMMAIndexType> &adjMatrix_row_ptr,
-
132 const std::vector<CoMMAIndexType> &adjMatrix_col_ind,
-
133 const std::vector<CoMMAWeightType> &adjMatrix_areaValues,
-
134 const std::vector<CoMMAWeightType> &volumes,
-
135
-
136 // Additional info about the mesh
-
137 const std::vector<std::vector<CoMMAWeightType>> &centers,
-
138 const std::vector<CoMMAWeightType> &priority_weights,
-
139 const std::vector<CoMMAIndexType> &anisotropicCompliantCells,
-
140 const std::vector<CoMMAIntType> &n_bnd_faces,
-
141
-
142 // Anisotropy related info
-
143 bool build_anisotropic_lines,
-
144 bool is_anisotropic,
-
145 bool odd_line_length,
-
146 CoMMAWeightType threshold_anisotropy,
-
147
-
148 // Seed ordering
-
149 const CoMMAIntType seed_ordering_type,
-
150
-
151 // Outputs
-
152 std::vector<CoMMAIndexType> &fc_to_cc, // Out
-
153 std::vector<CoMMAIndexType> &agglomerationLines_Idx, // In & out
-
154 std::vector<CoMMAIndexType> &agglomerationLines, // In & out
-
155
-
156 // Tuning of the algorithms
-
157 bool correction,
-
158 CoMMAIntType dimension,
-
159 CoMMAIntType goal_card,
-
160 CoMMAIntType min_card,
-
161 CoMMAIntType max_card,
-
162 CoMMAIntType singular_card_thresh = 1,
-
163 std::optional<CoMMAIndexType> max_cells_in_line = std::nullopt,
-
164 CoMMAIntType fc_choice_iter = 1,
-
165 const CoMMAIntType neighbourhood_type = CoMMANeighbourhoodT::EXTENDED) {
-
166 // NOTATION
-
167 //======================================
-
168 // fc = Fine Cell
-
169 // cc = Coarse Cell
-
170
-
171 // USEFUL SHORTCUTS
-
172 //======================================
-
173 using SeedsPoolType =
-
174 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
175 using DualGraphType =
-
176 Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
177 using CCContainerType =
-
178 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
179 using IsotropicPtr = std::unique_ptr<
-
180 Agglomerator_Isotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>;
-
181
-
182 // SANITY CHECKS
-
183 //======================================
-
184 CHECK_INT_TYPE(CoMMAIndexType, "first template argument");
-
185 CHECK_INT_TYPE(CoMMAIntType, "third template argument");
-
186 if (!(dimension == 2 || dimension == 3))
-
187 throw std::invalid_argument("CoMMA - Error: dimension must be 2 or 3");
-
188 if (min_card <= 1 || goal_card <= 1 || max_card <= 1)
-
189 throw std::invalid_argument(
-
190 "CoMMA - Error: Cardinalities must be greater than 1");
-
191 if (!(min_card <= goal_card && goal_card <= max_card))
-
192 throw std::invalid_argument(
-
193 "CoMMA - Error: Cardinalities must be in order (min <= goal <= max)");
-
194 if (fc_choice_iter < 1)
+
36#define CHECK_INT_TYPE(intT, label) \
+
37 static_assert( \
+
38 std::numeric_limits<intT>::is_integer, \
+
39 "CoMMA works with integer types, but " #intT " (" label ") is not" \
+
40 )
+
42
+
46constexpr CoMMAIntT iter_agglo_max_iter = 4;
+
47
+
126template<
+
127 typename CoMMAIndexType,
+
128 typename CoMMAWeightType,
+
129 typename CoMMAIntType>
+
130void agglomerate_one_level(
+
131 // Dual graph:
+
132 const std::vector<CoMMAIndexType> &adjMatrix_row_ptr,
+
133 const std::vector<CoMMAIndexType> &adjMatrix_col_ind,
+
134 const std::vector<CoMMAWeightType> &adjMatrix_areaValues,
+
135 const std::vector<CoMMAWeightType> &volumes,
+
136
+
137 // Additional info about the mesh
+
138 const std::vector<std::vector<CoMMAWeightType>> &centers,
+
139 const std::vector<CoMMAWeightType> &priority_weights,
+
140 const std::vector<CoMMAIndexType> &anisotropicCompliantCells,
+
141 const std::vector<CoMMAIntType> &n_bnd_faces,
+
142
+
143 // Anisotropy related info
+
144 bool build_anisotropic_lines,
+
145 bool is_anisotropic,
+
146 bool odd_line_length,
+
147 CoMMAWeightType threshold_anisotropy,
+
148
+
149 // Seed ordering
+
150 const CoMMAIntType seed_ordering_type,
+
151
+
152 // Outputs
+
153 std::vector<CoMMAIndexType> &fc_to_cc, // Out
+
154 std::vector<CoMMAIndexType> &agglomerationLines_Idx, // In & out
+
155 std::vector<CoMMAIndexType> &agglomerationLines, // In & out
+
156
+
157 // Tuning of the algorithms
+
158 bool correction,
+
159 CoMMAIntType dimension,
+
160 CoMMAIntType goal_card,
+
161 CoMMAIntType min_card,
+
162 CoMMAIntType max_card,
+
163 CoMMAIntType singular_card_thresh = 1,
+
164 std::optional<CoMMAIndexType> max_cells_in_line = std::nullopt,
+
165 CoMMAIntType fc_choice_iter = 1,
+
166 const CoMMAIntType neighbourhood_type = CoMMANeighbourhoodT::EXTENDED
+
167) {
+
168 // NOTATION
+
169 //======================================
+
170 // fc = Fine Cell
+
171 // cc = Coarse Cell
+
172
+
173 // USEFUL SHORTCUTS
+
174 //======================================
+
175 using SeedsPoolType =
+
176 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
177 using DualGraphType =
+
178 Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
179 using CCContainerType =
+
180 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
181 using IsotropicPtr = std::unique_ptr<
+
182 Agglomerator_Isotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>;
+
183
+
184 // SANITY CHECKS
+
185 //======================================
+
186 CHECK_INT_TYPE(CoMMAIndexType, "first template argument");
+
187 CHECK_INT_TYPE(CoMMAIntType, "third template argument");
+
188 if (!(dimension == 2 || dimension == 3))
+
189 throw std::invalid_argument("CoMMA - Error: dimension must be 2 or 3");
+
190 if (min_card <= 1 || goal_card <= 1 || max_card <= 1)
+
191 throw std::invalid_argument(
+
192 "CoMMA - Error: Cardinalities must be greater than 1"
+
193 );
+
194 if (!(min_card <= goal_card && goal_card <= max_card))
195 throw std::invalid_argument(
-
196 "CoMMA - Error: the number of iteration for the choice of the fine "
-
197 "cells must be at least 1");
-
198 if (fc_choice_iter > iter_agglo_max_iter)
+
196 "CoMMA - Error: Cardinalities must be in order (min <= goal <= max)"
+
197 );
+
198 if (fc_choice_iter < 1)
199 throw std::invalid_argument(
200 "CoMMA - Error: the number of iteration for the choice of the fine "
-
201 "cells must be at most "
-
202 + std::to_string(iter_agglo_max_iter));
-
203 if (
-
204 adjMatrix_row_ptr.empty()
-
205 || adjMatrix_row_ptr.back()
-
206 != static_cast<CoMMAIndexType>(adjMatrix_col_ind.size())
-
207 || adjMatrix_row_ptr.back()
-
208 != static_cast<CoMMAIndexType>(adjMatrix_areaValues.size()))
-
209 throw std::invalid_argument(
-
210 "CoMMA - Error: bad CRS graph (sizes do not match)");
-
211 if (is_anisotropic) {
-
212 if (build_anisotropic_lines) {
-
213 if (anisotropicCompliantCells.empty()) {
-
214 std::cout << "CoMMA - Warning: building anisotropic line requested, no "
-
215 "compliant cells provided. Switching off anisotropy."
-
216 << std::endl;
-
217 }
-
218 if (max_cells_in_line.has_value() && max_cells_in_line.value() <= 0) {
-
219 std::cout << "CoMMA - Requested a negative or null maximum number of "
-
220 "cells in line. Dropping the limit."
-
221 << std::endl;
-
222 max_cells_in_line = std::nullopt;
+
201 "cells must be at least 1"
+
202 );
+
203 if (fc_choice_iter > iter_agglo_max_iter)
+
204 throw std::invalid_argument(
+
205 "CoMMA - Error: the number of iteration for the choice of the fine "
+
206 "cells must be at most "
+
207 + std::to_string(iter_agglo_max_iter)
+
208 );
+
209 if (adjMatrix_row_ptr.empty()
+
210 || adjMatrix_row_ptr.back()
+
211 != static_cast<CoMMAIndexType>(adjMatrix_col_ind.size())
+
212 || adjMatrix_row_ptr.back()
+
213 != static_cast<CoMMAIndexType>(adjMatrix_areaValues.size()))
+
214 throw std::invalid_argument(
+
215 "CoMMA - Error: bad CRS graph (sizes do not match)"
+
216 );
+
217 if (is_anisotropic) {
+
218 if (build_anisotropic_lines) {
+
219 if (anisotropicCompliantCells.empty()) {
+
220 std::cout << "CoMMA - Warning: building anisotropic line requested, no "
+
221 "compliant cells provided. Switching off anisotropy."
+
222 << std::endl;
223 }
-
224 } else {
-
225 // Anisotropic lines are provided
-
226 if (agglomerationLines_Idx.size() < 2 || agglomerationLines.empty()) {
-
227 std::cout
-
228 << "CoMMA - Warning: usage of input anisotropic line requested, "
-
229 "but arguments are not enough / invalid to define them. "
-
230 "Switching off anisotropy."
-
231 << std::endl;
-
232 is_anisotropic = false;
-
233 } else if (
-
234 agglomerationLines_Idx.back()
-
235 != static_cast<CoMMAIndexType>(agglomerationLines.size())) {
-
236 throw std::invalid_argument(
-
237 "CoMMA - Error: bad anisotropic lines definition (sizes do not "
-
238 "match)");
-
239 }
-
240 }
-
241 }
-
242 auto sing_thresh = singular_card_thresh;
-
243 if (singular_card_thresh <= 0) {
-
244 throw std::invalid_argument(
-
245 "CoMMA - Error: Threshold cardinality for singular cells should be "
-
246 "greater than zero");
+
224 if (max_cells_in_line.has_value() && max_cells_in_line.value() <= 0) {
+
225 std::cout << "CoMMA - Requested a negative or null maximum number of "
+
226 "cells in line. Dropping the limit."
+
227 << std::endl;
+
228 max_cells_in_line = std::nullopt;
+
229 }
+
230 } else {
+
231 // Anisotropic lines are provided
+
232 if (agglomerationLines_Idx.size() < 2 || agglomerationLines.empty()) {
+
233 std::cout
+
234 << "CoMMA - Warning: usage of input anisotropic line requested, "
+
235 "but arguments are not enough / invalid to define them. "
+
236 "Switching off anisotropy."
+
237 << std::endl;
+
238 is_anisotropic = false;
+
239 } else if (agglomerationLines_Idx.back()
+
240 != static_cast<CoMMAIndexType>(agglomerationLines.size())) {
+
241 throw std::invalid_argument(
+
242 "CoMMA - Error: bad anisotropic lines definition (sizes do not "
+
243 "match)"
+
244 );
+
245 }
+
246 }
247 }
-
248 if (singular_card_thresh >= min_card) {
-
249 std::cout
-
250 << "CoMMA - Warning: Threshold cardinality is equal or larger than "
-
251 "minimum cardinality. Changing it to this latter value."
-
252 << std::endl;
-
253 sing_thresh = min_card - 1;
+
248 auto sing_thresh = singular_card_thresh;
+
249 if (singular_card_thresh <= 0) {
+
250 throw std::invalid_argument(
+
251 "CoMMA - Error: Threshold cardinality for singular cells should be "
+
252 "greater than zero"
+
253 );
254 }
-
255
-
256 // SIZES CAST
-
257 //======================================
-
258 const auto nb_fc = static_cast<CoMMAIndexType>(adjMatrix_row_ptr.size() - 1);
-
259
-
260 // BOUNDARY FACES
-
261 //======================================
-
262 // Sometimes partitioners give a number of boundary faces higher than the
-
263 // physical one. We fix this
-
264 const CoMMAIntType expected_max_n_bnd = dimension;
-
265 std::vector<CoMMAIntType> fixed_n_bnd_faces(n_bnd_faces.size());
-
266 std::replace_copy_if(
-
267 n_bnd_faces.begin(), n_bnd_faces.end(), fixed_n_bnd_faces.begin(),
-
268 [expected_max_n_bnd](auto n) { return n > expected_max_n_bnd; },
-
269 expected_max_n_bnd);
-
270
-
271 // SEED POOL
-
272 //======================================
-
273 // Object providing the order of agglomeration
-
274 std::shared_ptr<SeedsPoolType> seeds_pool = nullptr;
-
275 switch (seed_ordering_type) {
-
276 case CoMMASeedsPoolT::BOUNDARY_PRIORITY:
-
277 seeds_pool = std::make_shared<Seeds_Pool_Boundary_Priority<
-
278 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
279 fixed_n_bnd_faces, priority_weights, false);
-
280 break;
-
281 case CoMMASeedsPoolT::NEIGHBOURHOOD_PRIORITY:
-
282 seeds_pool = std::make_shared<Seeds_Pool_Neighbourhood_Priority<
-
283 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
284 fixed_n_bnd_faces, priority_weights, false);
-
285 break;
-
286 case CoMMASeedsPoolT::BOUNDARY_PRIORITY_ONE_POINT_INIT:
+
255 if (singular_card_thresh >= min_card) {
+
256 std::cout
+
257 << "CoMMA - Warning: Threshold cardinality is equal or larger than "
+
258 "minimum cardinality. Changing it to this latter value."
+
259 << std::endl;
+
260 sing_thresh = min_card - 1;
+
261 }
+
262
+
263 // SIZES CAST
+
264 //======================================
+
265 const auto nb_fc = static_cast<CoMMAIndexType>(adjMatrix_row_ptr.size() - 1);
+
266
+
267 // BOUNDARY FACES
+
268 //======================================
+
269 // Sometimes partitioners give a number of boundary faces higher than the
+
270 // physical one. We fix this
+
271 const CoMMAIntType expected_max_n_bnd = dimension;
+
272 std::vector<CoMMAIntType> fixed_n_bnd_faces(n_bnd_faces.size());
+
273 std::replace_copy_if(
+
274 n_bnd_faces.begin(),
+
275 n_bnd_faces.end(),
+
276 fixed_n_bnd_faces.begin(),
+
277 [expected_max_n_bnd](auto n) { return n > expected_max_n_bnd; },
+
278 expected_max_n_bnd
+
279 );
+
280
+
281 // SEED POOL
+
282 //======================================
+
283 // Object providing the order of agglomeration
+
284 std::shared_ptr<SeedsPoolType> seeds_pool = nullptr;
+
285 switch (seed_ordering_type) {
+
286 case CoMMASeedsPoolT::BOUNDARY_PRIORITY:
287 seeds_pool = std::make_shared<Seeds_Pool_Boundary_Priority<
-
288 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
289 fixed_n_bnd_faces, priority_weights, true);
-
290 break;
-
291 case CoMMASeedsPoolT::NEIGHBOURHOOD_PRIORITY_ONE_POINT_INIT:
-
292 seeds_pool = std::make_shared<Seeds_Pool_Neighbourhood_Priority<
-
293 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
294 fixed_n_bnd_faces, priority_weights, true);
-
295 break;
-
296 default:
-
297 throw std::invalid_argument("CoMMA - Error: Seeds pool type unsupported");
-
298 }
-
299
-
300 // DUAL GRAPH
-
301 //======================================
-
302 // Object containing the graph representation and related info in a convenient
-
303 // structure
-
304 std::shared_ptr<DualGraphType> fc_graph = std::make_shared<DualGraphType>(
-
305 nb_fc, adjMatrix_row_ptr, adjMatrix_col_ind, adjMatrix_areaValues, volumes,
-
306 centers, fixed_n_bnd_faces, dimension, anisotropicCompliantCells);
-
307
-
308 // COARSE CELL CONTAINER
-
309 //======================================
-
310 // Preparing the object that will contain all the coarse cells
-
311 std::shared_ptr<CCContainerType> cc_graph =
-
312 std::make_shared<CCContainerType>(fc_graph, sing_thresh);
+
288 CoMMAIndexType,
+
289 CoMMAWeightType,
+
290 CoMMAIntType>>(fixed_n_bnd_faces, priority_weights, false);
+
291 break;
+
292 case CoMMASeedsPoolT::NEIGHBOURHOOD_PRIORITY:
+
293 seeds_pool = std::make_shared<Seeds_Pool_Neighbourhood_Priority<
+
294 CoMMAIndexType,
+
295 CoMMAWeightType,
+
296 CoMMAIntType>>(fixed_n_bnd_faces, priority_weights, false);
+
297 break;
+
298 case CoMMASeedsPoolT::BOUNDARY_PRIORITY_ONE_POINT_INIT:
+
299 seeds_pool = std::make_shared<Seeds_Pool_Boundary_Priority<
+
300 CoMMAIndexType,
+
301 CoMMAWeightType,
+
302 CoMMAIntType>>(fixed_n_bnd_faces, priority_weights, true);
+
303 break;
+
304 case CoMMASeedsPoolT::NEIGHBOURHOOD_PRIORITY_ONE_POINT_INIT:
+
305 seeds_pool = std::make_shared<Seeds_Pool_Neighbourhood_Priority<
+
306 CoMMAIndexType,
+
307 CoMMAWeightType,
+
308 CoMMAIntType>>(fixed_n_bnd_faces, priority_weights, true);
+
309 break;
+
310 default:
+
311 throw std::invalid_argument("CoMMA - Error: Seeds pool type unsupported");
+
312 }
313
-
314 // AGGLOMERATION OF ANISOTROPIC CELLS
+
314 // DUAL GRAPH
315 //======================================
-
316 // @todo maybe re-refactor the class agglomerator to allow the implicit upcast
-
317 // like the biconnected case
-
318 // The agglomerator anisotropic is not called with the implicit upcasting
-
319 // pointing because of the initialization of
-
320 // the anisotropic lines.
-
321 // for more information look at:
-
322 // https://stackoverflow.com/questions/19682402/initialize-child-object-on-a-pointer-to-parent
-
323 // About constructors when upcasting:
-
324 // https://www.reddit.com/r/learnprogramming/comments/1wopf6/java_which_constructor_is_called_when_upcasting/
-
325 if (is_anisotropic) {
-
326 // Build anisotropic agglomerator
-
327 Agglomerator_Anisotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>
-
328 aniso_agg(
-
329 fc_graph, cc_graph, seeds_pool, threshold_anisotropy,
-
330 agglomerationLines_Idx, agglomerationLines, priority_weights,
-
331 build_anisotropic_lines, odd_line_length, max_cells_in_line, dimension);
-
332
-
333 // Agglomerate anisotropic cells only
-
334 aniso_agg.agglomerate_one_level(
-
335 goal_card, min_card, max_card, priority_weights, false);
-
336
-
337 // Put anisotropic lines into the output parameters
-
338 // (Info about level of the line: WARNING! here 1 it means that we give it
-
339 // back lines in the new global index, 0 the old)
-
340 const CoMMAIntType i_level{1};
-
341 aniso_agg.export_anisotropic_lines(
-
342 i_level, agglomerationLines_Idx, agglomerationLines);
-
343 } else {
-
344 seeds_pool->initialize();
-
345 }
-
346
-
347 // AGGLOMERATION OF ISOTROPIC CELLS
-
348 //======================================
-
349 // We define here the type of Agglomerator
-
350 IsotropicPtr agg = nullptr;
-
351 // TODO: maybe pass to a switch when another agglomerator will be implemented
-
352 if (fc_choice_iter > 1) {
-
353 agg = std::make_unique<
-
354 Agglomerator_Iterative<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
355 fc_graph, cc_graph, seeds_pool, neighbourhood_type, fc_choice_iter,
-
356 dimension);
-
357 } else {
-
358 agg = std::make_unique<
-
359 Agglomerator_Biconnected<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
360 fc_graph, cc_graph, seeds_pool, neighbourhood_type, fc_choice_iter,
-
361 dimension);
-
362 }
-
363 // Agglomerate
-
364 agg->agglomerate_one_level(
-
365 goal_card, min_card, max_card, priority_weights, correction);
-
366 // FILLING FC TO CC (it is a property of the cc_graph but retrieved through an
-
367 // helper of the agglomerator)
-
368 const auto &fccc = cc_graph->_fc_2_cc;
-
369 for (auto i_fc = decltype(nb_fc){0}; i_fc < nb_fc; i_fc++) {
-
370 fc_to_cc[i_fc] = fccc[i_fc].value();
-
371 }
-
372}
-
373
-
374#undef CHECK_INT_TYPE
-
375
-
376} // end namespace comma
-
377
-
378#endif
+
316 // Object containing the graph representation and related info in a convenient
+
317 // structure
+
318 std::shared_ptr<DualGraphType> fc_graph = std::make_shared<DualGraphType>(
+
319 nb_fc,
+
320 adjMatrix_row_ptr,
+
321 adjMatrix_col_ind,
+
322 adjMatrix_areaValues,
+
323 volumes,
+
324 centers,
+
325 fixed_n_bnd_faces,
+
326 dimension,
+
327 anisotropicCompliantCells
+
328 );
+
329
+
330 // COARSE CELL CONTAINER
+
331 //======================================
+
332 // Preparing the object that will contain all the coarse cells
+
333 std::shared_ptr<CCContainerType> cc_graph =
+
334 std::make_shared<CCContainerType>(fc_graph, sing_thresh);
+
335
+
336 // AGGLOMERATION OF ANISOTROPIC CELLS
+
337 //======================================
+
338 // @todo maybe re-refactor the class agglomerator to allow the implicit upcast
+
339 // like the biconnected case
+
340 // The agglomerator anisotropic is not called with the implicit upcasting
+
341 // pointing because of the initialization of
+
342 // the anisotropic lines.
+
343 // for more information look at:
+
344 // https://stackoverflow.com/questions/19682402/initialize-child-object-on-a-pointer-to-parent
+
345 // About constructors when upcasting:
+
346 // https://www.reddit.com/r/learnprogramming/comments/1wopf6/java_which_constructor_is_called_when_upcasting/
+
347 if (is_anisotropic) {
+
348 // Build anisotropic agglomerator
+
349 Agglomerator_Anisotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>
+
350 aniso_agg(
+
351 fc_graph,
+
352 cc_graph,
+
353 seeds_pool,
+
354 threshold_anisotropy,
+
355 agglomerationLines_Idx,
+
356 agglomerationLines,
+
357 priority_weights,
+
358 build_anisotropic_lines,
+
359 odd_line_length,
+
360 max_cells_in_line,
+
361 dimension
+
362 );
+
363
+
364 // Agglomerate anisotropic cells only
+
365 aniso_agg.agglomerate_one_level(
+
366 goal_card, min_card, max_card, priority_weights, false
+
367 );
+
368
+
369 // Put anisotropic lines into the output parameters
+
370 // (Info about level of the line: WARNING! here 1 it means that we give it
+
371 // back lines in the new global index, 0 the old)
+
372 const CoMMAIntType i_level{1};
+
373 aniso_agg.export_anisotropic_lines(
+
374 i_level, agglomerationLines_Idx, agglomerationLines
+
375 );
+
376 } else {
+
377 seeds_pool->initialize();
+
378 }
+
379
+
380 // AGGLOMERATION OF ISOTROPIC CELLS
+
381 //======================================
+
382 // We define here the type of Agglomerator
+
383 IsotropicPtr agg = nullptr;
+
384 // TODO: maybe pass to a switch when another agglomerator will be implemented
+
385 if (fc_choice_iter > 1) {
+
386 agg = std::make_unique<
+
387 Agglomerator_Iterative<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
+
388 fc_graph,
+
389 cc_graph,
+
390 seeds_pool,
+
391 neighbourhood_type,
+
392 fc_choice_iter,
+
393 dimension
+
394 );
+
395 } else {
+
396 agg = std::make_unique<
+
397 Agglomerator_Biconnected<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
+
398 fc_graph,
+
399 cc_graph,
+
400 seeds_pool,
+
401 neighbourhood_type,
+
402 fc_choice_iter,
+
403 dimension
+
404 );
+
405 }
+
406 // Agglomerate
+
407 agg->agglomerate_one_level(
+
408 goal_card, min_card, max_card, priority_weights, correction
+
409 );
+
410 // FILLING FC TO CC (it is a property of the cc_graph but retrieved through an
+
411 // helper of the agglomerator)
+
412 const auto &fccc = cc_graph->_fc_2_cc;
+
413 for (auto i_fc = decltype(nb_fc){0}; i_fc < nb_fc; i_fc++) {
+
414 fc_to_cc[i_fc] = fccc[i_fc].value();
+
415 }
+
416}
+
417
+
418#undef CHECK_INT_TYPE
+
419
+
420} // end namespace comma
+
421
+
422#endif
Agglomerator.h
CoMMADefs.h
Coarse_Cell_Container.h
Dual_Graph.h
Seeds_Pool.h
-
comma::Agglomerator_Anisotropic
Agglomerator_Anisotropic class is a child class of the Agglomerator class that specializes the implem...
Definition: Agglomerator.h:181
-
comma::Agglomerator_Anisotropic::export_anisotropic_lines
void export_anisotropic_lines(CoMMAIntType level, std::vector< CoMMAIndexType > &aniso_lines_idx, std::vector< CoMMAIndexType > &aniso_lines) const
Function that prepares the anisotropic lines for output.
Definition: Agglomerator.h:456
-
comma::Agglomerator_Anisotropic::agglomerate_one_level
void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) override
Specialization of the pure virtual function to the class Agglomerator_Anisotropic....
Definition: Agglomerator.h:301
-
comma::Agglomerator_Biconnected
Child class of Agglomerator_Isotropic where is implemented a specific biconnected algorithm for the a...
Definition: Agglomerator.h:996
-
comma::Agglomerator_Isotropic
Agglomerator_Isotropic class is a child class of the Agglomerator class that specializes the implemen...
Definition: Agglomerator.h:724
-
comma::Agglomerator_Isotropic::agglomerate_one_level
void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) override
Specialization of the pure virtual function to the class Agglomerator_Isotropic. We add the override ...
Definition: Agglomerator.h:854
-
comma::Agglomerator_Iterative
Child class of Agglomerator_Isotropic which implements a specialized iterative algorithm for the sear...
Definition: Agglomerator.h:1407
+
comma::Agglomerator_Anisotropic
Agglomerator_Anisotropic class is a child class of the Agglomerator class that specializes the implem...
Definition: Agglomerator.h:185
+
comma::Agglomerator_Anisotropic::export_anisotropic_lines
void export_anisotropic_lines(CoMMAIntType level, std::vector< CoMMAIndexType > &aniso_lines_idx, std::vector< CoMMAIndexType > &aniso_lines) const
Function that prepares the anisotropic lines for output.
Definition: Agglomerator.h:470
+
comma::Agglomerator_Anisotropic::agglomerate_one_level
void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) override
Specialization of the pure virtual function to the class Agglomerator_Anisotropic....
Definition: Agglomerator.h:309
+
comma::Agglomerator_Biconnected
Child class of Agglomerator_Isotropic where is implemented a specific biconnected algorithm for the a...
Definition: Agglomerator.h:1044
+
comma::Agglomerator_Isotropic
Agglomerator_Isotropic class is a child class of the Agglomerator class that specializes the implemen...
Definition: Agglomerator.h:750
+
comma::Agglomerator_Isotropic::agglomerate_one_level
void agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) override
Specialization of the pure virtual function to the class Agglomerator_Isotropic. We add the override ...
Definition: Agglomerator.h:887
+
comma::Agglomerator_Iterative
Child class of Agglomerator_Isotropic which implements a specialized iterative algorithm for the sear...
Definition: Agglomerator.h:1483
comma::Coarse_Cell_Container
Class implementing a custom container where the coarse cells are stored.
Definition: Coarse_Cell_Container.h:41
-
comma::Dual_Graph
A class implementing the CRS global graph representation of the global mesh.
Definition: Dual_Graph.h:517
-
comma::Seeds_Pool_Boundary_Priority
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:430
-
comma::Seeds_Pool_Neighbourhood_Priority
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:583
-
comma::Seeds_Pool
Class representing the pool of all the seeds for creating a coarse cell.
Definition: Seeds_Pool.h:194
+
comma::Dual_Graph
A class implementing the CRS global graph representation of the global mesh.
Definition: Dual_Graph.h:546
+
comma::Seeds_Pool_Boundary_Priority
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:452
+
comma::Seeds_Pool_Neighbourhood_Priority
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:612
+
comma::Seeds_Pool
Class representing the pool of all the seeds for creating a coarse cell.
Definition: Seeds_Pool.h:200
comma
Definition: Agglomerator.h:34
-
comma::agglomerate_one_level
void agglomerate_one_level(const std::vector< CoMMAIndexType > &adjMatrix_row_ptr, const std::vector< CoMMAIndexType > &adjMatrix_col_ind, const std::vector< CoMMAWeightType > &adjMatrix_areaValues, const std::vector< CoMMAWeightType > &volumes, const std::vector< std::vector< CoMMAWeightType > > &centers, const std::vector< CoMMAWeightType > &priority_weights, const std::vector< CoMMAIndexType > &anisotropicCompliantCells, const std::vector< CoMMAIntType > &n_bnd_faces, bool build_anisotropic_lines, bool is_anisotropic, bool odd_line_length, CoMMAWeightType threshold_anisotropy, const CoMMAIntType seed_ordering_type, std::vector< CoMMAIndexType > &fc_to_cc, std::vector< CoMMAIndexType > &agglomerationLines_Idx, std::vector< CoMMAIndexType > &agglomerationLines, bool correction, CoMMAIntType dimension, CoMMAIntType goal_card, CoMMAIntType min_card, CoMMAIntType max_card, CoMMAIntType singular_card_thresh=1, std::optional< CoMMAIndexType > max_cells_in_line=std::nullopt, CoMMAIntType fc_choice_iter=1, const CoMMAIntType neighbourhood_type=CoMMANeighbourhoodT::EXTENDED)
Main function of the agglomerator, it is used as an interface to build up all the agglomeration proce...
Definition: CoMMA.h:129
+
comma::agglomerate_one_level
void agglomerate_one_level(const std::vector< CoMMAIndexType > &adjMatrix_row_ptr, const std::vector< CoMMAIndexType > &adjMatrix_col_ind, const std::vector< CoMMAWeightType > &adjMatrix_areaValues, const std::vector< CoMMAWeightType > &volumes, const std::vector< std::vector< CoMMAWeightType > > &centers, const std::vector< CoMMAWeightType > &priority_weights, const std::vector< CoMMAIndexType > &anisotropicCompliantCells, const std::vector< CoMMAIntType > &n_bnd_faces, bool build_anisotropic_lines, bool is_anisotropic, bool odd_line_length, CoMMAWeightType threshold_anisotropy, const CoMMAIntType seed_ordering_type, std::vector< CoMMAIndexType > &fc_to_cc, std::vector< CoMMAIndexType > &agglomerationLines_Idx, std::vector< CoMMAIndexType > &agglomerationLines, bool correction, CoMMAIntType dimension, CoMMAIntType goal_card, CoMMAIntType min_card, CoMMAIntType max_card, CoMMAIntType singular_card_thresh=1, std::optional< CoMMAIndexType > max_cells_in_line=std::nullopt, CoMMAIntType fc_choice_iter=1, const CoMMAIntType neighbourhood_type=CoMMANeighbourhoodT::EXTENDED)
Main function of the agglomerator, it is used as an interface to build up all the agglomeration proce...
Definition: CoMMA.h:130
comma::EXTENDED
@ EXTENDED
Extended, all neighbours of the coarse cell.
Definition: CoMMADefs.h:38
comma::BOUNDARY_PRIORITY_ONE_POINT_INIT
@ BOUNDARY_PRIORITY_ONE_POINT_INIT
Definition: CoMMADefs.h:53
comma::BOUNDARY_PRIORITY
@ BOUNDARY_PRIORITY
Definition: CoMMADefs.h:45
comma::NEIGHBOURHOOD_PRIORITY_ONE_POINT_INIT
@ NEIGHBOURHOOD_PRIORITY_ONE_POINT_INIT
Definition: CoMMADefs.h:57
comma::NEIGHBOURHOOD_PRIORITY
@ NEIGHBOURHOOD_PRIORITY
Definition: CoMMADefs.h:49
-
comma::iter_agglo_max_iter
constexpr CoMMAIntT iter_agglo_max_iter
Maximum allowed iterations for the iterative algorithm, see Agglomerator_Iterative.
Definition: CoMMA.h:45
+
comma::iter_agglo_max_iter
constexpr CoMMAIntT iter_agglo_max_iter
Maximum allowed iterations for the iterative algorithm, see Agglomerator_Iterative.
Definition: CoMMA.h:46
diff --git a/_coarse___cell_8h_source.html b/_coarse___cell_8h_source.html index 519b69c..808ef46 100644 --- a/_coarse___cell_8h_source.html +++ b/_coarse___cell_8h_source.html @@ -134,188 +134,198 @@
55 CoMMAIndexType i_cc,
56 const std::unordered_set<CoMMAIndexType> &s_fc,
57 CoMMAIntType compactness,
-
58 bool is_isotropic = true) :
-
59 _idx(i_cc),
-
60 _fc_graph(fc_graph),
-
61 _compactness(compactness),
-
62 _cardinality(static_cast<CoMMAIntType>(s_fc.size())),
-
63 _is_isotropic(is_isotropic),
-
64 _s_fc(s_fc) {}
-
65
-
67 virtual ~Coarse_Cell() = default;
-
68
-
71 CoMMAIndexType _idx;
-
72
-
74 DualGraphPtr _fc_graph;
-
75
-
77 CoMMAIntType _compactness;
-
78
-
80 CoMMAIntType _cardinality;
-
81
-
83 bool _is_isotropic;
-
84
-
86 std::unordered_set<CoMMAIndexType> _s_fc;
-
87
-
93 inline bool is_connected() { return _compactness > 0; }
-
94
-
100 virtual void insert_cell(
-
101 const CoMMAIndexType i_fc,
-
102 const std::optional<CoMMAIntType> new_compactness) {
-
103 _s_fc.insert(i_fc);
-
104 ++_cardinality;
-
105 _compactness = new_compactness.has_value()
-
106 ? new_compactness.value()
-
107 : _fc_graph->compute_min_fc_compactness_inside_a_cc(_s_fc);
-
108 }
-
109
-
115 virtual void insert_cells(
-
116 const std::unordered_set<CoMMAIndexType> &fcs,
-
117 const std::optional<CoMMAIntType> new_compactness) {
-
118 _s_fc.insert(fcs.begin(), fcs.end());
-
119 _cardinality += fcs.size();
-
120 _compactness = new_compactness.has_value()
-
121 ? new_compactness.value()
-
122 : _fc_graph->compute_min_fc_compactness_inside_a_cc(_s_fc);
-
123 }
-
124};
-
125
-
134template<
-
135 typename CoMMAIndexType,
-
136 typename CoMMAWeightType,
-
137 typename CoMMAIntType>
-
138class Coarse_Cell_Subgraph :
-
139 Coarse_Cell<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
140public:
-
142 using BaseClass = Coarse_Cell<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
143
-
145 using typename BaseClass::DualGraphPtr;
-
146
-
148 using SubGraphType = Subgraph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
149
-
151 using SubGraphPtr = std::shared_ptr<SubGraphType>;
-
152
-
163 Coarse_Cell_Subgraph(
-
164 DualGraphPtr fc_graph,
-
165 CoMMAIndexType i_cc,
-
166 const std::unordered_set<CoMMAIndexType> &s_fc,
-
167 CoMMAIntType compactness,
-
168 bool is_isotropic = true) :
-
169 BaseClass(fc_graph, i_cc, s_fc, compactness, is_isotropic),
-
170 _is_connected(compactness > 0),
-
171 _is_connectivity_up_to_date(true) {
-
172 // initialization vectors
-
173 CoMMAIndexType position = 0;
-
174 std::vector<CoMMAWeightType> volumes;
-
175 std::vector<CoMMAWeightType> CSR_vals{};
-
176 std::vector<CoMMAIndexType> CSR_row = {0};
-
177 std::vector<CoMMAIndexType> CSR_col{};
-
178 std::vector<CoMMAIndexType> col_ind{};
-
179 std::vector<CoMMAIndexType> mapping{};
-
180 for (const CoMMAIndexType &i_fc : this->_s_fc) {
-
181 // we add to the mapping the i_fc
-
182 mapping.push_back(i_fc);
-
183 // get neighbours and the weights associated
-
184 const std::vector<CoMMAIndexType> neigh =
-
185 this->_fc_graph->get_neighbours(i_fc);
-
186 const std::vector<CoMMAWeightType> area =
-
187 this->_fc_graph->get_weights(i_fc);
-
188 for (auto it = neigh.begin(); it != neigh.end(); ++it) {
-
189 if (
-
190 std::find(this->_s_fc.begin(), this->_s_fc.end(), *it)
-
191 != this->_s_fc.end()) {
-
192 ++position;
-
193 col_ind.push_back(*it);
-
194 CSR_vals.push_back(area[it - neigh.begin()]);
-
195 }
-
196 }
-
197 CSR_row.push_back(position);
-
198 volumes.push_back(this->_fc_graph->_volumes[i_fc]);
-
199 }
-
200
-
201 // Map in the local subgraph
-
202 for (auto it = col_ind.begin(); it != col_ind.end(); ++it) {
-
203 auto indx = std::find(mapping.begin(), mapping.end(), *it);
-
204 CSR_col.push_back(indx - mapping.begin());
-
205 }
-
206
-
207 _cc_graph = std::make_shared<SubGraphType>(
-
208 s_fc.size(), CSR_row, CSR_col, CSR_vals, volumes, mapping, is_isotropic);
-
209 }
-
210
-
216 void insert_cell(
-
217 const CoMMAIndexType i_fc,
-
218 const std::optional<CoMMAIntType> new_compactness) override {
-
219 // As base class...
-
220 this->_s_fc.insert(i_fc);
-
221 ++this->_cardinality;
-
222 this->_compactness =
-
223 new_compactness.has_value()
-
224 ? new_compactness.value()
-
225 : this->_fc_graph->compute_min_fc_compactness_inside_a_cc(this->_s_fc);
-
226 // ...but now add to the subgraph
-
227 _cc_graph->insert_node(
-
228 this->_fc_graph->get_neighbours(i_fc), i_fc,
-
229 this->_fc_graph->_volumes[i_fc], this->_fc_graph->get_weights(i_fc));
-
230 }
-
231
-
237 void insert_cells(
-
238 const std::unordered_set<CoMMAIndexType> &fcs,
-
239 const std::optional<CoMMAIntType> new_compactness) override {
-
240 // As base class...
-
241 this->_s_fc.insert(fcs.begin(), fcs.end());
-
242 this->_cardinality += fcs.size();
-
243 this->_compactness =
-
244 new_compactness.has_value()
-
245 ? new_compactness.value()
-
246 : this->_fc_graph->compute_min_fc_compactness_inside_a_cc(this->_s_fc);
-
247 // ...but now add to the subgraph
-
248 for (const auto &i_fc : fcs) {
-
249 _cc_graph->insert_node(
-
250 this->_fc_graph->get_neighbours(i_fc), i_fc,
-
251 this->_fc_graph->_volumes[i_fc], this->_fc_graph->get_weights(i_fc));
-
252 }
-
253 }
-
254
-
256 inline void update_connectivity() {
-
257 _is_connected = _cc_graph->check_connectivity();
-
258 _is_connectivity_up_to_date = true;
-
259 }
-
260
-
262 SubGraphPtr _cc_graph;
-
263
-
265 bool _is_connected;
-
266
-
268 bool _is_connectivity_up_to_date;
-
269};
+
58 bool is_isotropic = true
+
59 ) :
+
60 _idx(i_cc),
+
61 _fc_graph(fc_graph),
+
62 _compactness(compactness),
+
63 _cardinality(static_cast<CoMMAIntType>(s_fc.size())),
+
64 _is_isotropic(is_isotropic),
+
65 _s_fc(s_fc) {}
+
66
+
68 virtual ~Coarse_Cell() = default;
+
69
+
72 CoMMAIndexType _idx;
+
73
+
75 DualGraphPtr _fc_graph;
+
76
+
78 CoMMAIntType _compactness;
+
79
+
81 CoMMAIntType _cardinality;
+
82
+
84 bool _is_isotropic;
+
85
+
87 std::unordered_set<CoMMAIndexType> _s_fc;
+
88
+
94 inline bool is_connected() { return _compactness > 0; }
+
95
+
101 virtual void insert_cell(
+
102 const CoMMAIndexType i_fc, const std::optional<CoMMAIntType> new_compactness
+
103 ) {
+
104 _s_fc.insert(i_fc);
+
105 ++_cardinality;
+
106 _compactness = new_compactness.has_value()
+
107 ? new_compactness.value()
+
108 : _fc_graph->compute_min_fc_compactness_inside_a_cc(_s_fc);
+
109 }
+
110
+
116 virtual void insert_cells(
+
117 const std::unordered_set<CoMMAIndexType> &fcs,
+
118 const std::optional<CoMMAIntType> new_compactness
+
119 ) {
+
120 _s_fc.insert(fcs.begin(), fcs.end());
+
121 _cardinality += fcs.size();
+
122 _compactness = new_compactness.has_value()
+
123 ? new_compactness.value()
+
124 : _fc_graph->compute_min_fc_compactness_inside_a_cc(_s_fc);
+
125 }
+
126};
+
127
+
136template<
+
137 typename CoMMAIndexType,
+
138 typename CoMMAWeightType,
+
139 typename CoMMAIntType>
+
140class Coarse_Cell_Subgraph :
+
141 Coarse_Cell<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
142public:
+
144 using BaseClass = Coarse_Cell<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
145
+
147 using typename BaseClass::DualGraphPtr;
+
148
+
150 using SubGraphType = Subgraph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
151
+
153 using SubGraphPtr = std::shared_ptr<SubGraphType>;
+
154
+
165 Coarse_Cell_Subgraph(
+
166 DualGraphPtr fc_graph,
+
167 CoMMAIndexType i_cc,
+
168 const std::unordered_set<CoMMAIndexType> &s_fc,
+
169 CoMMAIntType compactness,
+
170 bool is_isotropic = true
+
171 ) :
+
172 BaseClass(fc_graph, i_cc, s_fc, compactness, is_isotropic),
+
173 _is_connected(compactness > 0),
+
174 _is_connectivity_up_to_date(true) {
+
175 // initialization vectors
+
176 CoMMAIndexType position = 0;
+
177 std::vector<CoMMAWeightType> volumes;
+
178 std::vector<CoMMAWeightType> CSR_vals{};
+
179 std::vector<CoMMAIndexType> CSR_row = {0};
+
180 std::vector<CoMMAIndexType> CSR_col{};
+
181 std::vector<CoMMAIndexType> col_ind{};
+
182 std::vector<CoMMAIndexType> mapping{};
+
183 for (const CoMMAIndexType &i_fc : this->_s_fc) {
+
184 // we add to the mapping the i_fc
+
185 mapping.push_back(i_fc);
+
186 // get neighbours and the weights associated
+
187 const std::vector<CoMMAIndexType> neigh =
+
188 this->_fc_graph->get_neighbours(i_fc);
+
189 const std::vector<CoMMAWeightType> area =
+
190 this->_fc_graph->get_weights(i_fc);
+
191 for (auto it = neigh.begin(); it != neigh.end(); ++it) {
+
192 if (std::find(this->_s_fc.begin(), this->_s_fc.end(), *it)
+
193 != this->_s_fc.end()) {
+
194 ++position;
+
195 col_ind.push_back(*it);
+
196 CSR_vals.push_back(area[it - neigh.begin()]);
+
197 }
+
198 }
+
199 CSR_row.push_back(position);
+
200 volumes.push_back(this->_fc_graph->_volumes[i_fc]);
+
201 }
+
202
+
203 // Map in the local subgraph
+
204 for (auto it = col_ind.begin(); it != col_ind.end(); ++it) {
+
205 auto indx = std::find(mapping.begin(), mapping.end(), *it);
+
206 CSR_col.push_back(indx - mapping.begin());
+
207 }
+
208
+
209 _cc_graph = std::make_shared<SubGraphType>(
+
210 s_fc.size(), CSR_row, CSR_col, CSR_vals, volumes, mapping, is_isotropic
+
211 );
+
212 }
+
213
+
219 void insert_cell(
+
220 const CoMMAIndexType i_fc, const std::optional<CoMMAIntType> new_compactness
+
221 ) override {
+
222 // As base class...
+
223 this->_s_fc.insert(i_fc);
+
224 ++this->_cardinality;
+
225 this->_compactness =
+
226 new_compactness.has_value()
+
227 ? new_compactness.value()
+
228 : this->_fc_graph->compute_min_fc_compactness_inside_a_cc(this->_s_fc);
+
229 // ...but now add to the subgraph
+
230 _cc_graph->insert_node(
+
231 this->_fc_graph->get_neighbours(i_fc),
+
232 i_fc,
+
233 this->_fc_graph->_volumes[i_fc],
+
234 this->_fc_graph->get_weights(i_fc)
+
235 );
+
236 }
+
237
+
243 void insert_cells(
+
244 const std::unordered_set<CoMMAIndexType> &fcs,
+
245 const std::optional<CoMMAIntType> new_compactness
+
246 ) override {
+
247 // As base class...
+
248 this->_s_fc.insert(fcs.begin(), fcs.end());
+
249 this->_cardinality += fcs.size();
+
250 this->_compactness =
+
251 new_compactness.has_value()
+
252 ? new_compactness.value()
+
253 : this->_fc_graph->compute_min_fc_compactness_inside_a_cc(this->_s_fc);
+
254 // ...but now add to the subgraph
+
255 for (const auto &i_fc : fcs) {
+
256 _cc_graph->insert_node(
+
257 this->_fc_graph->get_neighbours(i_fc),
+
258 i_fc,
+
259 this->_fc_graph->_volumes[i_fc],
+
260 this->_fc_graph->get_weights(i_fc)
+
261 );
+
262 }
+
263 }
+
264
+
266 inline void update_connectivity() {
+
267 _is_connected = _cc_graph->check_connectivity();
+
268 _is_connectivity_up_to_date = true;
+
269 }
270
-
271} // end namespace comma
-
272
-
273#endif // COMMA_PROJECT_COARSE_CELL_H
+
272 SubGraphPtr _cc_graph;
+
273
+
275 bool _is_connected;
+
276
+
278 bool _is_connectivity_up_to_date;
+
279};
+
280
+
281} // end namespace comma
+
282
+
283#endif // COMMA_PROJECT_COARSE_CELL_H
Dual_Graph.h
-
comma::Coarse_Cell_Subgraph
Class describing a coarse cell with a full description, that is, it also holds a subgraph describing ...
Definition: Coarse_Cell.h:139
-
comma::Coarse_Cell_Subgraph::_cc_graph
SubGraphPtr _cc_graph
Shared pointer of the subgraph structure (CSR representation)
Definition: Coarse_Cell.h:262
-
comma::Coarse_Cell_Subgraph::insert_cell
void insert_cell(const CoMMAIndexType i_fc, const std::optional< CoMMAIntType > new_compactness) override
Insert a FC in the CC (and update sub-graph if necessary)
Definition: Coarse_Cell.h:216
-
comma::Coarse_Cell_Subgraph::update_connectivity
void update_connectivity()
Analyse subgraph and update the connectivity.
Definition: Coarse_Cell.h:256
+
comma::Coarse_Cell_Subgraph
Class describing a coarse cell with a full description, that is, it also holds a subgraph describing ...
Definition: Coarse_Cell.h:141
+
comma::Coarse_Cell_Subgraph::_cc_graph
SubGraphPtr _cc_graph
Shared pointer of the subgraph structure (CSR representation)
Definition: Coarse_Cell.h:272
+
comma::Coarse_Cell_Subgraph::insert_cell
void insert_cell(const CoMMAIndexType i_fc, const std::optional< CoMMAIntType > new_compactness) override
Insert a FC in the CC (and update sub-graph if necessary)
Definition: Coarse_Cell.h:219
+
comma::Coarse_Cell_Subgraph::update_connectivity
void update_connectivity()
Analyse subgraph and update the connectivity.
Definition: Coarse_Cell.h:266
comma::Coarse_Cell_Subgraph::DualGraphPtr
std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > DualGraphPtr
Type for a shared pointer to a Dual_Graph object.
Definition: Coarse_Cell.h:41
-
comma::Coarse_Cell_Subgraph::_is_connectivity_up_to_date
bool _is_connectivity_up_to_date
Whether the connectivity has been checked.
Definition: Coarse_Cell.h:268
-
comma::Coarse_Cell_Subgraph::insert_cells
void insert_cells(const std::unordered_set< CoMMAIndexType > &fcs, const std::optional< CoMMAIntType > new_compactness) override
Insert several FC in the CC (and update sub-graph if necessary)
Definition: Coarse_Cell.h:237
-
comma::Coarse_Cell_Subgraph::_is_connected
bool _is_connected
Whether the cell connected.
Definition: Coarse_Cell.h:265
-
comma::Coarse_Cell_Subgraph::SubGraphPtr
std::shared_ptr< SubGraphType > SubGraphPtr
Type for a shared pointer to a Subgraph object.
Definition: Coarse_Cell.h:151
-
comma::Coarse_Cell_Subgraph::Coarse_Cell_Subgraph
Coarse_Cell_Subgraph(DualGraphPtr fc_graph, CoMMAIndexType i_cc, const std::unordered_set< CoMMAIndexType > &s_fc, CoMMAIntType compactness, bool is_isotropic=true)
Constructor of the class.
Definition: Coarse_Cell.h:163
+
comma::Coarse_Cell_Subgraph::_is_connectivity_up_to_date
bool _is_connectivity_up_to_date
Whether the connectivity has been checked.
Definition: Coarse_Cell.h:278
+
comma::Coarse_Cell_Subgraph::insert_cells
void insert_cells(const std::unordered_set< CoMMAIndexType > &fcs, const std::optional< CoMMAIntType > new_compactness) override
Insert several FC in the CC (and update sub-graph if necessary)
Definition: Coarse_Cell.h:243
+
comma::Coarse_Cell_Subgraph::_is_connected
bool _is_connected
Whether the cell connected.
Definition: Coarse_Cell.h:275
+
comma::Coarse_Cell_Subgraph::SubGraphPtr
std::shared_ptr< SubGraphType > SubGraphPtr
Type for a shared pointer to a Subgraph object.
Definition: Coarse_Cell.h:153
+
comma::Coarse_Cell_Subgraph::Coarse_Cell_Subgraph
Coarse_Cell_Subgraph(DualGraphPtr fc_graph, CoMMAIndexType i_cc, const std::unordered_set< CoMMAIndexType > &s_fc, CoMMAIntType compactness, bool is_isotropic=true)
Constructor of the class.
Definition: Coarse_Cell.h:165
comma::Coarse_Cell
Class describing a coarse cell.
Definition: Coarse_Cell.h:37
-
comma::Coarse_Cell::_idx
CoMMAIndexType _idx
Index of the coarse cell (It seems to be unused, but useful to have)
Definition: Coarse_Cell.h:71
-
comma::Coarse_Cell::_cardinality
CoMMAIntType _cardinality
Number of FC in the CC.
Definition: Coarse_Cell.h:80
+
comma::Coarse_Cell::_idx
CoMMAIndexType _idx
Index of the coarse cell (It seems to be unused, but useful to have)
Definition: Coarse_Cell.h:72
+
comma::Coarse_Cell::_cardinality
CoMMAIntType _cardinality
Number of FC in the CC.
Definition: Coarse_Cell.h:81
comma::Coarse_Cell::DualGraphPtr
std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > DualGraphPtr
Type for a shared pointer to a Dual_Graph object.
Definition: Coarse_Cell.h:41
-
comma::Coarse_Cell::_is_isotropic
bool _is_isotropic
Whether the cell isotropic or anisotropic.
Definition: Coarse_Cell.h:83
+
comma::Coarse_Cell::_is_isotropic
bool _is_isotropic
Whether the cell isotropic or anisotropic.
Definition: Coarse_Cell.h:84
comma::Coarse_Cell::Coarse_Cell
Coarse_Cell(DualGraphPtr fc_graph, CoMMAIndexType i_cc, const std::unordered_set< CoMMAIndexType > &s_fc, CoMMAIntType compactness, bool is_isotropic=true)
Constructor of the class.
Definition: Coarse_Cell.h:53
-
comma::Coarse_Cell::insert_cell
virtual void insert_cell(const CoMMAIndexType i_fc, const std::optional< CoMMAIntType > new_compactness)
Insert a FC in the CC (and update sub-graph if necessary)
Definition: Coarse_Cell.h:100
-
comma::Coarse_Cell::_s_fc
std::unordered_set< CoMMAIndexType > _s_fc
Set of fine cells composing the Coarse cell.
Definition: Coarse_Cell.h:86
-
comma::Coarse_Cell::_fc_graph
DualGraphPtr _fc_graph
The global dual graph.
Definition: Coarse_Cell.h:74
-
comma::Coarse_Cell::_compactness
CoMMAIntType _compactness
Compactness degree of the CC.
Definition: Coarse_Cell.h:77
-
comma::Coarse_Cell::is_connected
bool is_connected()
Method that return a boolean determining if the coarse cell is defined by a connected sub-graph or no...
Definition: Coarse_Cell.h:93
+
comma::Coarse_Cell::insert_cell
virtual void insert_cell(const CoMMAIndexType i_fc, const std::optional< CoMMAIntType > new_compactness)
Insert a FC in the CC (and update sub-graph if necessary)
Definition: Coarse_Cell.h:101
+
comma::Coarse_Cell::_s_fc
std::unordered_set< CoMMAIndexType > _s_fc
Set of fine cells composing the Coarse cell.
Definition: Coarse_Cell.h:87
+
comma::Coarse_Cell::_fc_graph
DualGraphPtr _fc_graph
The global dual graph.
Definition: Coarse_Cell.h:75
+
comma::Coarse_Cell::_compactness
CoMMAIntType _compactness
Compactness degree of the CC.
Definition: Coarse_Cell.h:78
+
comma::Coarse_Cell::is_connected
bool is_connected()
Method that return a boolean determining if the coarse cell is defined by a connected sub-graph or no...
Definition: Coarse_Cell.h:94
comma::Coarse_Cell::~Coarse_Cell
virtual ~Coarse_Cell()=default
Destructor of the class.
-
comma::Coarse_Cell::insert_cells
virtual void insert_cells(const std::unordered_set< CoMMAIndexType > &fcs, const std::optional< CoMMAIntType > new_compactness)
Insert several FC in the CC (and update sub-graph if necessary)
Definition: Coarse_Cell.h:115
-
comma::Subgraph
A class implementing the CRS subgraph representation. It is used in the framework of CoMMA for the im...
Definition: Dual_Graph.h:302
+
comma::Coarse_Cell::insert_cells
virtual void insert_cells(const std::unordered_set< CoMMAIndexType > &fcs, const std::optional< CoMMAIntType > new_compactness)
Insert several FC in the CC (and update sub-graph if necessary)
Definition: Coarse_Cell.h:116
+
comma::Subgraph
A class implementing the CRS subgraph representation. It is used in the framework of CoMMA for the im...
Definition: Dual_Graph.h:318
comma
Definition: Agglomerator.h:34
diff --git a/_coarse___cell___container_8h_source.html b/_coarse___cell___container_8h_source.html index 5ae470e..252d447 100644 --- a/_coarse___cell___container_8h_source.html +++ b/_coarse___cell___container_8h_source.html @@ -137,449 +137,459 @@
51 using DualGraphPtr = typename CoarseCellType::DualGraphPtr;
52
59 Coarse_Cell_Container(
-
60 DualGraphPtr &fc_graph, const CoMMAIntType singular_card_thresh) :
-
61 _ccs(),
-
62 _fc_graph(fc_graph),
-
63 _cc_counter(0),
-
64 _fc_2_cc(fc_graph->_number_of_cells, std::nullopt),
-
65 _is_fc_agglomerated(fc_graph->_number_of_cells, false),
-
66 _sing_card_thresh(singular_card_thresh),
-
67 _nb_of_agglomerated_fc(0),
-
68 _delayed_cc(),
-
69 _singular_cc() {}
-
70
-
72 ~Coarse_Cell_Container() = default;
-
73
-
75 std::map<CoMMAIndexType, CoarseCellPtr> _ccs;
-
76
-
78 DualGraphPtr _fc_graph;
-
79
-
81 CoMMAIndexType _cc_counter;
-
82
-
85 std::vector<std::optional<CoMMAIndexType>> _fc_2_cc;
-
86
-
89 std::vector<bool> _is_fc_agglomerated;
-
90
-
92 CoMMAIntType _sing_card_thresh;
-
93
-
98 inline CoMMAIndexType get_number_of_fc_agglomerated() const {
-
99 return (_nb_of_agglomerated_fc);
-
100 }
-
101
-
105 inline CoMMAIndexType get_nb_of_cc() const { return _cc_counter; }
-
106
-
115 inline std::set<CoMMAIndexType> get_neighs_cc(
-
116 const CoMMAIndexType &i_fc, const CoMMAIndexType &i_cc) const {
-
117 std::set<CoMMAIndexType> result;
-
118 for (auto elem = _fc_graph->neighbours_cbegin(i_fc);
-
119 elem != _fc_graph->neighbours_cend(i_fc); ++elem) {
-
120 const auto cc = _fc_2_cc[*elem].value();
-
121 if (cc != i_cc) result.insert(cc);
-
122 }
-
123 return result;
-
124 }
-
125
-
126#if 0
-
127Not used anymore but we leave it for example purposes
+
60 DualGraphPtr &fc_graph, const CoMMAIntType singular_card_thresh
+
61 ) :
+
62 _ccs(),
+
63 _fc_graph(fc_graph),
+
64 _cc_counter(0),
+
65 _fc_2_cc(fc_graph->_number_of_cells, std::nullopt),
+
66 _is_fc_agglomerated(fc_graph->_number_of_cells, false),
+
67 _sing_card_thresh(singular_card_thresh),
+
68 _nb_of_agglomerated_fc(0),
+
69 _delayed_cc(),
+
70 _singular_cc() {}
+
71
+
73 ~Coarse_Cell_Container() = default;
+
74
+
76 std::map<CoMMAIndexType, CoarseCellPtr> _ccs;
+
77
+
79 DualGraphPtr _fc_graph;
+
80
+
82 CoMMAIndexType _cc_counter;
+
83
+
86 std::vector<std::optional<CoMMAIndexType>> _fc_2_cc;
+
87
+
90 std::vector<bool> _is_fc_agglomerated;
+
91
+
93 CoMMAIntType _sing_card_thresh;
+
94
+
99 inline CoMMAIndexType get_number_of_fc_agglomerated() const {
+
100 return (_nb_of_agglomerated_fc);
+
101 }
+
102
+
106 inline CoMMAIndexType get_nb_of_cc() const { return _cc_counter; }
+
107
+
116 inline std::set<CoMMAIndexType> get_neighs_cc(
+
117 const CoMMAIndexType &i_fc, const CoMMAIndexType &i_cc
+
118 ) const {
+
119 std::set<CoMMAIndexType> result;
+
120 for (auto elem = _fc_graph->neighbours_cbegin(i_fc);
+
121 elem != _fc_graph->neighbours_cend(i_fc);
+
122 ++elem) {
+
123 const auto cc = _fc_2_cc[*elem].value();
+
124 if (cc != i_cc) result.insert(cc);
+
125 }
+
126 return result;
+
127 }
128
-
130 using CustomMapItT = typename std::map<CoMMAIndexType, SubGraphPtr>::iterator;
-
135 CustomMapItT remove_cc(CustomMapItT elim) {
-
136 // we delete the element and we obtained the pointer to the next element in
-
137 // memory
-
138 CustomMapItT it = _ccs.erase(elim);
-
139 // update value of the other nodes
-
140 for (auto i = it; i != _ccs.end(); i++) {
-
141 for (auto const &i_fc : i->second->_mapping_l_to_g) {
-
142 _fc_2_cc[i_fc] = (i->first) - 1;
-
143 }
-
144 auto node = _ccs.extract(i);
-
145 if (!node.empty()) {
-
146 node.key() = (i->first) - 1;
-
147 _ccs.insert(std::move(node));
-
148 }
-
149 }
-
150 // return pointer to the next element
-
151 return (it);
-
152 }
-
153#endif
-
154
-
161 void correct(const CoMMAIntType max_card) {
-
162 // We use it to understand if we have succeeded in the correction
-
163 std::set<typename decltype(_singular_cc)::value_type> removed_cc{};
-
164 for (const auto &old_cc : _singular_cc) {
-
165 // It might happen that we agglomerate to a singular cell so that the new
-
166 // cell was singular when it was created but it is not any more
-
167 auto &cur_cc = _ccs.at(old_cc);
-
168 if (cur_cc->_cardinality <= _sing_card_thresh) {
-
169 const auto &fcs = cur_cc->_s_fc;
-
170 bool should_remove = false;
-
171 std::unordered_map<CoMMAIndexType, std::set<CoMMAIndexType>>
-
172 neighs_by_fc{};
-
173 neighs_by_fc.reserve(cur_cc->_cardinality);
-
174 for (const auto &i_fc : fcs) {
-
175 neighs_by_fc.emplace(i_fc, get_neighs_cc(i_fc, old_cc));
-
176 }
-
177 if (cur_cc->_cardinality > 1) {
-
178 // First try: agglomerate the whole coarse cell to another one
-
179 std::set<CoMMAIndexType> glob_neighs = {};
-
180 for (const auto &[i_fc, neighs] : neighs_by_fc) {
-
181 glob_neighs.insert(neighs.begin(), neighs.end());
-
182 }
-
183 if (!glob_neighs.empty()) {
-
184 std::optional<CoMMAIntType> new_compactness = std::nullopt;
-
185 const auto new_cc = select_best_cc_to_agglomerate_whole(
-
186 fcs, glob_neighs, max_card, new_compactness);
-
187 if (new_cc.has_value()) {
-
188 // first we assign to the fc_2_cc the new cc (later it will be
-
189 // renumbered considering the deleted cc)
-
190 for (const auto &i_fc : fcs) {
-
191 _fc_2_cc[i_fc] = new_cc.value();
-
192 }
-
193 _ccs[new_cc.value()]->insert_cells(fcs, new_compactness);
-
194 should_remove = true;
-
195 }
-
196 }
-
197 }
-
198 if (!should_remove) {
-
199 // If here, we could not agglomerate the whole cell, hence we look
-
200 // fine cell by fine cell
-
201 for (const auto &[i_fc, neighs] : neighs_by_fc) {
-
202 if (!neighs.empty()) {
-
203 std::optional<CoMMAIntType> new_compactness = std::nullopt;
-
204 const auto new_cc = select_best_cc_to_agglomerate(
-
205 i_fc, neighs, max_card, new_compactness);
-
206 if (new_cc.has_value()) {
-
207 _fc_2_cc[i_fc] = new_cc.value();
-
208 _ccs[new_cc.value()]->insert_cell(i_fc, new_compactness);
-
209 should_remove = true;
-
210 }
-
211 }
-
212 // If the cell has no neighbour (this could happen when the
-
213 // partitioning does not give a connected partition), unfortunately,
-
214 // there is nothing that we can do. We just skip it
-
215 }
-
216 }
-
217
-
218 if (should_remove) {
-
219 _ccs.erase(old_cc);
-
220 removed_cc.emplace(old_cc);
+
129#if 0
+
130Not used anymore but we leave it for example purposes
+
131
+
133 using CustomMapItT = typename std::map<CoMMAIndexType, SubGraphPtr>::iterator;
+
138 CustomMapItT remove_cc(CustomMapItT elim) {
+
139 // we delete the element and we obtained the pointer to the next element in
+
140 // memory
+
141 CustomMapItT it = _ccs.erase(elim);
+
142 // update value of the other nodes
+
143 for (auto i = it; i != _ccs.end(); i++) {
+
144 for (auto const &i_fc : i->second->_mapping_l_to_g) {
+
145 _fc_2_cc[i_fc] = (i->first) - 1;
+
146 }
+
147 auto node = _ccs.extract(i);
+
148 if (!node.empty()) {
+
149 node.key() = (i->first) - 1;
+
150 _ccs.insert(std::move(node));
+
151 }
+
152 }
+
153 // return pointer to the next element
+
154 return (it);
+
155 }
+
156#endif
+
157
+
164 void correct(const CoMMAIntType max_card) {
+
165 // We use it to understand if we have succeeded in the correction
+
166 std::set<typename decltype(_singular_cc)::value_type> removed_cc{};
+
167 for (const auto &old_cc : _singular_cc) {
+
168 // It might happen that we agglomerate to a singular cell so that the new
+
169 // cell was singular when it was created but it is not any more
+
170 auto &cur_cc = _ccs.at(old_cc);
+
171 if (cur_cc->_cardinality <= _sing_card_thresh) {
+
172 const auto &fcs = cur_cc->_s_fc;
+
173 bool should_remove = false;
+
174 std::unordered_map<CoMMAIndexType, std::set<CoMMAIndexType>>
+
175 neighs_by_fc{};
+
176 neighs_by_fc.reserve(cur_cc->_cardinality);
+
177 for (const auto &i_fc : fcs) {
+
178 neighs_by_fc.emplace(i_fc, get_neighs_cc(i_fc, old_cc));
+
179 }
+
180 if (cur_cc->_cardinality > 1) {
+
181 // First try: agglomerate the whole coarse cell to another one
+
182 std::set<CoMMAIndexType> glob_neighs = {};
+
183 for (const auto &[i_fc, neighs] : neighs_by_fc) {
+
184 glob_neighs.insert(neighs.begin(), neighs.end());
+
185 }
+
186 if (!glob_neighs.empty()) {
+
187 std::optional<CoMMAIntType> new_compactness = std::nullopt;
+
188 const auto new_cc = select_best_cc_to_agglomerate_whole(
+
189 fcs, glob_neighs, max_card, new_compactness
+
190 );
+
191 if (new_cc.has_value()) {
+
192 // first we assign to the fc_2_cc the new cc (later it will be
+
193 // renumbered considering the deleted cc)
+
194 for (const auto &i_fc : fcs) {
+
195 _fc_2_cc[i_fc] = new_cc.value();
+
196 }
+
197 _ccs[new_cc.value()]->insert_cells(fcs, new_compactness);
+
198 should_remove = true;
+
199 }
+
200 }
+
201 }
+
202 if (!should_remove) {
+
203 // If here, we could not agglomerate the whole cell, hence we look
+
204 // fine cell by fine cell
+
205 for (const auto &[i_fc, neighs] : neighs_by_fc) {
+
206 if (!neighs.empty()) {
+
207 std::optional<CoMMAIntType> new_compactness = std::nullopt;
+
208 const auto new_cc = select_best_cc_to_agglomerate(
+
209 i_fc, neighs, max_card, new_compactness
+
210 );
+
211 if (new_cc.has_value()) {
+
212 _fc_2_cc[i_fc] = new_cc.value();
+
213 _ccs[new_cc.value()]->insert_cell(i_fc, new_compactness);
+
214 should_remove = true;
+
215 }
+
216 }
+
217 // If the cell has no neighbour (this could happen when the
+
218 // partitioning does not give a connected partition), unfortunately,
+
219 // there is nothing that we can do. We just skip it
+
220 }
221 }
-
222 } // End if still singular
-
223 } // End loop over singular cells
-
224
-
225 // Now update the ID if necessary
-
226 if (!removed_cc.empty()) {
-
227 auto new_ID = *(removed_cc.begin());
-
228 // Starting from the CC just after the first removed singular cell, update
-
229 // all cells. Looking for new_ID-1 than doing ++ avoid case of consecutive
-
230 // singular cells. If the first removed cell was cell 0, then start from
-
231 // the beginning
-
232 auto it_cc = _ccs.begin();
-
233 if (new_ID > 0) {
-
234 it_cc = _ccs.find(new_ID - 1);
-
235 ++it_cc;
-
236 }
-
237 for (; it_cc != _ccs.end(); ++it_cc, ++new_ID) {
-
238 // Update fine cells
-
239 for (auto const &i_fc : it_cc->second->_s_fc) {
-
240 _fc_2_cc[i_fc] = new_ID;
-
241 }
-
242 // Update coarse cell ID
-
243 auto node = _ccs.extract(it_cc);
-
244 if (!node.empty()) {
-
245 node.key() = new_ID;
-
246 _ccs.insert(std::move(node));
-
247 }
-
248 }
-
249 }
-
250 }
-
251
-
266 std::optional<CoMMAIndexType> select_best_cc_to_agglomerate_whole(
-
267 const std::unordered_set<CoMMAIndexType> &fcs,
-
268 const std::set<CoMMAIndexType> &neighs,
-
269 const CoMMAIntType max_card,
-
270 std::optional<CoMMAIntType> &new_compactness) const {
-
271 CoMMAUnused(max_card);
-
272 std::unordered_map<CoMMAIndexType, CoMMAIntType> card{};
-
273 std::unordered_map<CoMMAIndexType, CoMMAIntType> compact{};
-
274 const auto n_neighs = neighs.size();
-
275 card.reserve(n_neighs);
-
276 // Since in the end we sort, wouldn't it be better to just use set instead
-
277 // of deque?
-
278 std::deque<CoMMAIndexType> argtrue_compact{};
-
279 // Loop on neighbours to compute their features
-
280 for (const auto &cc_idx : neighs) {
-
281 const auto n_cc = _ccs.at(cc_idx);
-
282 if (n_cc->_is_isotropic) {
-
283 // NOLINTNEXTLINE(readability-simplify-boolean-expr)
-
284 if (true /* n_cc->_cardinality < max_card */) {
-
285 // On second thought, let us consider also cells with max cardinality
-
286 // since the number of faces could be important to ensure compactness
-
287 // of the coarse cell
-
288 card[cc_idx] = n_cc->_cardinality;
-
289 // Analysing compactness
-
290 auto tmp_cc = n_cc->_s_fc; // OK copy
-
291 tmp_cc.insert(fcs.begin(), fcs.end());
-
292 const auto new_cpt =
-
293 _fc_graph->compute_min_fc_compactness_inside_a_cc(tmp_cc);
-
294 compact[cc_idx] = new_cpt;
-
295 if (new_cpt > n_cc->_compactness) {
-
296 argtrue_compact.push_back(cc_idx);
-
297 }
-
298 } // End compactness and cardinality
-
299 } // End if isotropic
-
300 }
-
301 if (!argtrue_compact.empty()) {
-
302 // Sort so that, in the end, if nothing worked, we rely on ID numbering
-
303 sort(argtrue_compact.begin(), argtrue_compact.end());
-
304 CoMMAIndexType ret_cc{argtrue_compact[0]};
-
305 CoMMAIntType cur_min{card[ret_cc]};
-
306 // If more than one, maximize shared faces and/or minimize cardinality
-
307 for (const auto &idx : argtrue_compact) {
-
308 const auto cur_card = card[idx];
-
309 if (cur_card < cur_min) {
-
310 cur_min = cur_card;
-
311 ret_cc = idx;
-
312 }
-
313 }
-
314 new_compactness = compact.at(ret_cc);
-
315 return ret_cc;
-
316 }
-
317 return std::nullopt;
-
318 }
-
319
-
333 std::optional<CoMMAIndexType> select_best_cc_to_agglomerate(
-
334 const CoMMAIndexType fc,
-
335 const std::set<CoMMAIndexType> &neighs,
-
336 const CoMMAIntType max_card,
-
337 std::optional<CoMMAIntType> &new_compactness) const {
-
338 CoMMAUnused(max_card);
-
339 std::unordered_map<CoMMAIndexType, CoMMAIntType> card{};
-
340 std::unordered_map<CoMMAIndexType, CoMMAIntType> shared_faces{};
-
341 std::unordered_map<CoMMAIndexType, CoMMAIntType> compact{};
-
342 const auto n_neighs = neighs.size();
-
343 card.reserve(n_neighs);
-
344 shared_faces.reserve(n_neighs);
-
345 CoMMAIntType min_card = std::numeric_limits<CoMMAIntType>::max();
-
346 CoMMAIntType max_shared_f{0};
-
347 // Since in the end we sort, wouldn't it be better to just use set instead
-
348 // of deque?
-
349 std::deque<CoMMAIndexType> argmin_card{};
-
350 std::deque<CoMMAIndexType> argmax_shared_f{};
-
351 std::deque<CoMMAIndexType> argtrue_compact{};
-
352 std::deque<CoMMAIndexType> iso_neighs{};
-
353 // Loop on neighbours to compute their features
-
354 for (const auto &cc_idx : neighs) {
-
355 const auto n_cc = _ccs.at(cc_idx);
-
356 if (n_cc->_is_isotropic) {
-
357 iso_neighs.push_back(cc_idx);
-
358 // NOLINTNEXTLINE(readability-simplify-boolean-expr)
-
359 if (true /* n_cc->_cardinality < max_card */) {
-
360 // On second thought, let us consider also cells with max cardinality
-
361 // since the number of faces could be important to ensure compactness
-
362 // of the coarse cell
-
363 const auto cur_card = n_cc->_cardinality;
-
364 card[cc_idx] = cur_card;
-
365 if (cur_card < min_card) {
-
366 min_card = cur_card;
-
367 argmin_card.clear();
-
368 argmin_card.push_back(cc_idx);
-
369 } else if (cur_card == min_card) {
-
370 argmin_card.push_back(cc_idx);
-
371 }
-
372 // @TODO: merge computation of shared faces and compactness?
-
373 const auto cur_sf = get_shared_faces(fc, n_cc);
-
374 shared_faces[cc_idx] = cur_sf;
-
375 if (cur_sf > max_shared_f) {
-
376 max_shared_f = cur_sf;
-
377 argmax_shared_f.clear();
-
378 argmax_shared_f.push_back(cc_idx);
-
379 } else if (cur_sf == max_shared_f) {
-
380 argmax_shared_f.push_back(cc_idx);
-
381 }
-
382 // Analysing compactness
-
383 auto tmp_cc = n_cc->_s_fc; // OK copy
-
384 tmp_cc.insert(fc);
-
385 const auto new_cpt =
-
386 _fc_graph->compute_min_fc_compactness_inside_a_cc(tmp_cc);
-
387 compact[cc_idx] = new_cpt;
-
388 if (new_cpt > n_cc->_compactness) {
-
389 argtrue_compact.push_back(cc_idx);
-
390 }
-
391 } // End compactness and cardinality
-
392 } // End if isotropic
-
393 }
-
394 // Now, it's time to choose the best neighbours. Priority is given to those
-
395 // which: 1 - Increase the degree of compactness
-
396 if (!argtrue_compact.empty()) {
-
397 // Sort so that, in the end, if nothing worked, we rely on ID numbering
-
398 sort(argtrue_compact.begin(), argtrue_compact.end());
-
399 CoMMAIndexType ret_cc{argtrue_compact[0]};
-
400 CoMMAIntType cur_max{shared_faces[ret_cc]};
-
401 // If more than one, maximize shared faces and/or minimize cardinality
-
402 for (const auto &idx : argtrue_compact) {
-
403 const auto cur_shf = shared_faces[idx];
-
404 if (cur_shf > cur_max) {
-
405 cur_max = cur_shf;
-
406 ret_cc = idx;
-
407 } else if (cur_shf == cur_max && card[idx] < card[ret_cc]) {
-
408 ret_cc = idx;
-
409 }
-
410 }
-
411 new_compactness = compact.at(ret_cc);
-
412 return ret_cc;
-
413 }
-
414 // 2 - Maximize the number of shared faces
-
415 if (!argmax_shared_f.empty()) {
-
416 // Sort so that, in the end, if nothing worked, we rely on ID numbering
-
417 sort(argmax_shared_f.begin(), argmax_shared_f.end());
-
418 CoMMAIndexType ret_cc{argmax_shared_f[0]};
-
419 CoMMAIntType cur_min{card[ret_cc]};
-
420 // ..but let's see if among all the cells there is one with smaller
-
421 // cardinality
-
422 for (const auto &idx : argmax_shared_f) {
-
423 if (card[idx] < cur_min) {
-
424 ret_cc = idx;
-
425 cur_min = card[ret_cc];
-
426 }
-
427 }
-
428 new_compactness = compact.at(ret_cc);
-
429 return ret_cc;
-
430 }
-
431 // 3 - Minimize the cardinality
-
432 if (!argmin_card.empty()) {
-
433 // We should never need to come here...
-
434 // @TODO: I'm not sure what I could consider here to decide which cell to
-
435 // return. The aspect-ratio maybe? In the mean time, I return the one with
-
436 // the lowest ID
-
437 const auto ret_cc =
-
438 *(min_element(argmin_card.begin(), argmin_card.end()));
-
439 new_compactness = compact.at(ret_cc);
-
440 return ret_cc;
-
441 }
-
442 // If everything failed, look through the neighbours
-
443 if (!iso_neighs.empty()) return iso_neighs[0];
-
444 // otherwise, there is nothing we can do
-
445 return std::nullopt;
-
446 }
-
447
-
454 inline CoMMAIntType get_shared_faces(
-
455 const CoMMAIndexType fc, const CoarseCellPtr cc) const {
-
456 CoMMAIntType shared_faces{0};
-
457 for (const auto &i_fc : cc->_s_fc) {
-
458 shared_faces += count(
-
459 _fc_graph->neighbours_cbegin(i_fc), _fc_graph->neighbours_cend(i_fc),
-
460 fc);
-
461 }
-
462 return shared_faces;
-
463 }
-
464
-
475 CoMMAIndexType create_cc(
-
476 const std::unordered_set<CoMMAIndexType> &s_fc,
-
477 const CoMMAIntType compactness,
-
478 bool is_anisotropic = false,
-
479 bool is_creation_delayed = false) {
-
480 // Create a course cell from the fine cells and update the fc_2_cc tree.
-
481 assert((!is_anisotropic) || (!is_creation_delayed));
-
482 for (const auto &i_fc : s_fc) {
-
483 assert(!_fc_2_cc[i_fc].has_value());
-
484 if (!_is_fc_agglomerated[i_fc]) {
-
485 // Rq: initialise to False pour chaque niveau dans agglomerate(...)
-
486 _is_fc_agglomerated[i_fc] = true;
-
487 _nb_of_agglomerated_fc++;
-
488 }
-
489 }
-
490 // Anisotropic case
-
491 bool is_mutable = true;
-
492 if (is_anisotropic) {
-
493 // we collect the various cc, where the index in the vector is the i_cc
-
494 _ccs[_cc_counter] = std::make_shared<CoarseCellType>(
-
495 _fc_graph, _cc_counter, s_fc, compactness, !is_anisotropic);
-
496 is_mutable = false;
-
497 }
-
498 if (!is_creation_delayed) {
-
499 // We create the cc right now.
-
500 // Everything is updated:
-
501 if (is_mutable) {
-
502 // the cell can be modified afterwards and is thus defined in dict_cc
-
503 // and dict_card_cc, dict_compactness_2_cc, dict_cc_to_compactness
-
504 // Update of dict_cc:
-
505 //==================
-
506 // we collect the various cc, where the index in the vector is the i_cc
-
507 _ccs[_cc_counter] = std::make_shared<CoarseCellType>(
-
508 _fc_graph, _cc_counter, s_fc, compactness);
-
509 if (
-
510 !is_anisotropic
-
511 && static_cast<decltype(_sing_card_thresh)>(s_fc.size())
-
512 <= _sing_card_thresh)
-
513 _singular_cc.emplace_back(_cc_counter);
-
514 }
-
515 // Update of _associatedCoarseCellNumber the output of the current
-
516 // function agglomerate _fc_2_cc is filled with _cc_counter
-
517 for (const auto &i_fc : s_fc) {
-
518 // Only if not isCreationDelayed:
-
519 assert(!_fc_2_cc[i_fc].has_value());
-
520 _fc_2_cc[i_fc] = _cc_counter;
-
521 }
-
522 // Update of the number of CC
-
523 //####################################
-
524 _cc_counter++; // Only if not isCreationDelayed
-
525 } else {
-
526 // We do not create the coarse cell yet.
-
527 // As this coarse cell will be soon deleted, we want its coarse index to
-
528 // be the greater possible.
-
529 // Only isFineCellAgglomerated_tmp, number_of_fine_agglomerated_cells_tmp
-
530 // and dict_DistributionOfCardinalOfCoarseElements are modified!
-
531 _delayed_cc.emplace_back(s_fc, compactness);
-
532 }
-
533 return (_cc_counter - 1);
-
534 }
-
535
-
539 inline void cc_create_all_delayed_cc() {
-
540 for (const auto &[s_fc, cpt] : _delayed_cc) {
-
541 create_cc(s_fc, cpt);
+
222
+
223 if (should_remove) {
+
224 _ccs.erase(old_cc);
+
225 removed_cc.emplace(old_cc);
+
226 }
+
227 } // End if still singular
+
228 } // End loop over singular cells
+
229
+
230 // Now update the ID if necessary
+
231 if (!removed_cc.empty()) {
+
232 auto new_ID = *(removed_cc.begin());
+
233 // Starting from the CC just after the first removed singular cell, update
+
234 // all cells. Looking for new_ID-1 than doing ++ avoid case of consecutive
+
235 // singular cells. If the first removed cell was cell 0, then start from
+
236 // the beginning
+
237 auto it_cc = _ccs.begin();
+
238 if (new_ID > 0) {
+
239 it_cc = _ccs.find(new_ID - 1);
+
240 ++it_cc;
+
241 }
+
242 for (; it_cc != _ccs.end(); ++it_cc, ++new_ID) {
+
243 // Update fine cells
+
244 for (auto const &i_fc : it_cc->second->_s_fc) {
+
245 _fc_2_cc[i_fc] = new_ID;
+
246 }
+
247 // Update coarse cell ID
+
248 auto node = _ccs.extract(it_cc);
+
249 if (!node.empty()) {
+
250 node.key() = new_ID;
+
251 _ccs.insert(std::move(node));
+
252 }
+
253 }
+
254 }
+
255 }
+
256
+
271 std::optional<CoMMAIndexType> select_best_cc_to_agglomerate_whole(
+
272 const std::unordered_set<CoMMAIndexType> &fcs,
+
273 const std::set<CoMMAIndexType> &neighs,
+
274 const CoMMAIntType max_card,
+
275 std::optional<CoMMAIntType> &new_compactness
+
276 ) const {
+
277 CoMMAUnused(max_card);
+
278 std::unordered_map<CoMMAIndexType, CoMMAIntType> card{};
+
279 std::unordered_map<CoMMAIndexType, CoMMAIntType> compact{};
+
280 const auto n_neighs = neighs.size();
+
281 card.reserve(n_neighs);
+
282 // Since in the end we sort, wouldn't it be better to just use set instead
+
283 // of deque?
+
284 std::deque<CoMMAIndexType> argtrue_compact{};
+
285 // Loop on neighbours to compute their features
+
286 for (const auto &cc_idx : neighs) {
+
287 const auto n_cc = _ccs.at(cc_idx);
+
288 if (n_cc->_is_isotropic) {
+
289 // NOLINTNEXTLINE(readability-simplify-boolean-expr)
+
290 if (true /* n_cc->_cardinality < max_card */) {
+
291 // On second thought, let us consider also cells with max cardinality
+
292 // since the number of faces could be important to ensure compactness
+
293 // of the coarse cell
+
294 card[cc_idx] = n_cc->_cardinality;
+
295 // Analysing compactness
+
296 auto tmp_cc = n_cc->_s_fc; // OK copy
+
297 tmp_cc.insert(fcs.begin(), fcs.end());
+
298 const auto new_cpt =
+
299 _fc_graph->compute_min_fc_compactness_inside_a_cc(tmp_cc);
+
300 compact[cc_idx] = new_cpt;
+
301 if (new_cpt > n_cc->_compactness) {
+
302 argtrue_compact.push_back(cc_idx);
+
303 }
+
304 } // End compactness and cardinality
+
305 } // End if isotropic
+
306 }
+
307 if (!argtrue_compact.empty()) {
+
308 // Sort so that, in the end, if nothing worked, we rely on ID numbering
+
309 sort(argtrue_compact.begin(), argtrue_compact.end());
+
310 CoMMAIndexType ret_cc{argtrue_compact[0]};
+
311 CoMMAIntType cur_min{card[ret_cc]};
+
312 // If more than one, maximize shared faces and/or minimize cardinality
+
313 for (const auto &idx : argtrue_compact) {
+
314 const auto cur_card = card[idx];
+
315 if (cur_card < cur_min) {
+
316 cur_min = cur_card;
+
317 ret_cc = idx;
+
318 }
+
319 }
+
320 new_compactness = compact.at(ret_cc);
+
321 return ret_cc;
+
322 }
+
323 return std::nullopt;
+
324 }
+
325
+
339 std::optional<CoMMAIndexType> select_best_cc_to_agglomerate(
+
340 const CoMMAIndexType fc,
+
341 const std::set<CoMMAIndexType> &neighs,
+
342 const CoMMAIntType max_card,
+
343 std::optional<CoMMAIntType> &new_compactness
+
344 ) const {
+
345 CoMMAUnused(max_card);
+
346 std::unordered_map<CoMMAIndexType, CoMMAIntType> card{};
+
347 std::unordered_map<CoMMAIndexType, CoMMAIntType> shared_faces{};
+
348 std::unordered_map<CoMMAIndexType, CoMMAIntType> compact{};
+
349 const auto n_neighs = neighs.size();
+
350 card.reserve(n_neighs);
+
351 shared_faces.reserve(n_neighs);
+
352 CoMMAIntType min_card = std::numeric_limits<CoMMAIntType>::max();
+
353 CoMMAIntType max_shared_f{0};
+
354 // Since in the end we sort, wouldn't it be better to just use set instead
+
355 // of deque?
+
356 std::deque<CoMMAIndexType> argmin_card{};
+
357 std::deque<CoMMAIndexType> argmax_shared_f{};
+
358 std::deque<CoMMAIndexType> argtrue_compact{};
+
359 std::deque<CoMMAIndexType> iso_neighs{};
+
360 // Loop on neighbours to compute their features
+
361 for (const auto &cc_idx : neighs) {
+
362 const auto n_cc = _ccs.at(cc_idx);
+
363 if (n_cc->_is_isotropic) {
+
364 iso_neighs.push_back(cc_idx);
+
365 // NOLINTNEXTLINE(readability-simplify-boolean-expr)
+
366 if (true /* n_cc->_cardinality < max_card */) {
+
367 // On second thought, let us consider also cells with max cardinality
+
368 // since the number of faces could be important to ensure compactness
+
369 // of the coarse cell
+
370 const auto cur_card = n_cc->_cardinality;
+
371 card[cc_idx] = cur_card;
+
372 if (cur_card < min_card) {
+
373 min_card = cur_card;
+
374 argmin_card.clear();
+
375 argmin_card.push_back(cc_idx);
+
376 } else if (cur_card == min_card) {
+
377 argmin_card.push_back(cc_idx);
+
378 }
+
379 // @TODO: merge computation of shared faces and compactness?
+
380 const auto cur_sf = get_shared_faces(fc, n_cc);
+
381 shared_faces[cc_idx] = cur_sf;
+
382 if (cur_sf > max_shared_f) {
+
383 max_shared_f = cur_sf;
+
384 argmax_shared_f.clear();
+
385 argmax_shared_f.push_back(cc_idx);
+
386 } else if (cur_sf == max_shared_f) {
+
387 argmax_shared_f.push_back(cc_idx);
+
388 }
+
389 // Analysing compactness
+
390 auto tmp_cc = n_cc->_s_fc; // OK copy
+
391 tmp_cc.insert(fc);
+
392 const auto new_cpt =
+
393 _fc_graph->compute_min_fc_compactness_inside_a_cc(tmp_cc);
+
394 compact[cc_idx] = new_cpt;
+
395 if (new_cpt > n_cc->_compactness) {
+
396 argtrue_compact.push_back(cc_idx);
+
397 }
+
398 } // End compactness and cardinality
+
399 } // End if isotropic
+
400 }
+
401 // Now, it's time to choose the best neighbours. Priority is given to those
+
402 // which: 1 - Increase the degree of compactness
+
403 if (!argtrue_compact.empty()) {
+
404 // Sort so that, in the end, if nothing worked, we rely on ID numbering
+
405 sort(argtrue_compact.begin(), argtrue_compact.end());
+
406 CoMMAIndexType ret_cc{argtrue_compact[0]};
+
407 CoMMAIntType cur_max{shared_faces[ret_cc]};
+
408 // If more than one, maximize shared faces and/or minimize cardinality
+
409 for (const auto &idx : argtrue_compact) {
+
410 const auto cur_shf = shared_faces[idx];
+
411 if (cur_shf > cur_max) {
+
412 cur_max = cur_shf;
+
413 ret_cc = idx;
+
414 } else if (cur_shf == cur_max && card[idx] < card[ret_cc]) {
+
415 ret_cc = idx;
+
416 }
+
417 }
+
418 new_compactness = compact.at(ret_cc);
+
419 return ret_cc;
+
420 }
+
421 // 2 - Maximize the number of shared faces
+
422 if (!argmax_shared_f.empty()) {
+
423 // Sort so that, in the end, if nothing worked, we rely on ID numbering
+
424 sort(argmax_shared_f.begin(), argmax_shared_f.end());
+
425 CoMMAIndexType ret_cc{argmax_shared_f[0]};
+
426 CoMMAIntType cur_min{card[ret_cc]};
+
427 // ..but let's see if among all the cells there is one with smaller
+
428 // cardinality
+
429 for (const auto &idx : argmax_shared_f) {
+
430 if (card[idx] < cur_min) {
+
431 ret_cc = idx;
+
432 cur_min = card[ret_cc];
+
433 }
+
434 }
+
435 new_compactness = compact.at(ret_cc);
+
436 return ret_cc;
+
437 }
+
438 // 3 - Minimize the cardinality
+
439 if (!argmin_card.empty()) {
+
440 // We should never need to come here...
+
441 // @TODO: I'm not sure what I could consider here to decide which cell to
+
442 // return. The aspect-ratio maybe? In the mean time, I return the one with
+
443 // the lowest ID
+
444 const auto ret_cc =
+
445 *(min_element(argmin_card.begin(), argmin_card.end()));
+
446 new_compactness = compact.at(ret_cc);
+
447 return ret_cc;
+
448 }
+
449 // If everything failed, look through the neighbours
+
450 if (!iso_neighs.empty()) return iso_neighs[0];
+
451 // otherwise, there is nothing we can do
+
452 return std::nullopt;
+
453 }
+
454
+
461 inline CoMMAIntType get_shared_faces(
+
462 const CoMMAIndexType fc, const CoarseCellPtr cc
+
463 ) const {
+
464 CoMMAIntType shared_faces{0};
+
465 for (const auto &i_fc : cc->_s_fc) {
+
466 shared_faces += count(
+
467 _fc_graph->neighbours_cbegin(i_fc), _fc_graph->neighbours_cend(i_fc), fc
+
468 );
+
469 }
+
470 return shared_faces;
+
471 }
+
472
+
483 CoMMAIndexType create_cc(
+
484 const std::unordered_set<CoMMAIndexType> &s_fc,
+
485 const CoMMAIntType compactness,
+
486 bool is_anisotropic = false,
+
487 bool is_creation_delayed = false
+
488 ) {
+
489 // Create a course cell from the fine cells and update the fc_2_cc tree.
+
490 assert((!is_anisotropic) || (!is_creation_delayed));
+
491 for (const auto &i_fc : s_fc) {
+
492 assert(!_fc_2_cc[i_fc].has_value());
+
493 if (!_is_fc_agglomerated[i_fc]) {
+
494 // Rq: initialise to False pour chaque niveau dans agglomerate(...)
+
495 _is_fc_agglomerated[i_fc] = true;
+
496 _nb_of_agglomerated_fc++;
+
497 }
+
498 }
+
499 // Anisotropic case
+
500 bool is_mutable = true;
+
501 if (is_anisotropic) {
+
502 // we collect the various cc, where the index in the vector is the i_cc
+
503 _ccs[_cc_counter] = std::make_shared<CoarseCellType>(
+
504 _fc_graph, _cc_counter, s_fc, compactness, !is_anisotropic
+
505 );
+
506 is_mutable = false;
+
507 }
+
508 if (!is_creation_delayed) {
+
509 // We create the cc right now.
+
510 // Everything is updated:
+
511 if (is_mutable) {
+
512 // the cell can be modified afterwards and is thus defined in dict_cc
+
513 // and dict_card_cc, dict_compactness_2_cc, dict_cc_to_compactness
+
514 // Update of dict_cc:
+
515 //==================
+
516 // we collect the various cc, where the index in the vector is the i_cc
+
517 _ccs[_cc_counter] = std::make_shared<CoarseCellType>(
+
518 _fc_graph, _cc_counter, s_fc, compactness
+
519 );
+
520 if (!is_anisotropic
+
521 && static_cast<decltype(_sing_card_thresh)>(s_fc.size())
+
522 <= _sing_card_thresh)
+
523 _singular_cc.emplace_back(_cc_counter);
+
524 }
+
525 // Update of _associatedCoarseCellNumber the output of the current
+
526 // function agglomerate _fc_2_cc is filled with _cc_counter
+
527 for (const auto &i_fc : s_fc) {
+
528 // Only if not isCreationDelayed:
+
529 assert(!_fc_2_cc[i_fc].has_value());
+
530 _fc_2_cc[i_fc] = _cc_counter;
+
531 }
+
532 // Update of the number of CC
+
533 // ####################################
+
534 _cc_counter++; // Only if not isCreationDelayed
+
535 } else {
+
536 // We do not create the coarse cell yet.
+
537 // As this coarse cell will be soon deleted, we want its coarse index to
+
538 // be the greater possible.
+
539 // Only isFineCellAgglomerated_tmp, number_of_fine_agglomerated_cells_tmp
+
540 // and dict_DistributionOfCardinalOfCoarseElements are modified!
+
541 _delayed_cc.emplace_back(s_fc, compactness);
542 }
-
543 _delayed_cc.clear();
+
543 return (_cc_counter - 1);
544 }
545
-
546protected:
-
548 CoMMAIndexType _nb_of_agglomerated_fc = 0;
-
549
-
554 std::vector<std::pair<std::unordered_set<CoMMAIndexType>, CoMMAIntType>>
-
555 _delayed_cc;
-
556
-
559 std::deque<CoMMAIndexType> _singular_cc;
-
560};
-
561
-
562} // end namespace comma
-
563
-
564#endif // COMMA_PROJECT_COARSE_CELL_GRAPH_H
+
549 inline void cc_create_all_delayed_cc() {
+
550 for (const auto &[s_fc, cpt] : _delayed_cc) {
+
551 create_cc(s_fc, cpt);
+
552 }
+
553 _delayed_cc.clear();
+
554 }
+
555
+
556protected:
+
558 CoMMAIndexType _nb_of_agglomerated_fc = 0;
+
559
+
564 std::vector<std::pair<std::unordered_set<CoMMAIndexType>, CoMMAIntType>>
+
565 _delayed_cc;
+
566
+
569 std::deque<CoMMAIndexType> _singular_cc;
+
570};
+
571
+
572} // end namespace comma
+
573
+
574#endif // COMMA_PROJECT_COARSE_CELL_GRAPH_H
Coarse_Cell.h
Dual_Graph.h
CoMMAUnused
#define CoMMAUnused(var)
Convenient function to avoid unused warnings.
Definition: Util.h:34
comma::Coarse_Cell_Container
Class implementing a custom container where the coarse cells are stored.
Definition: Coarse_Cell_Container.h:41
-
comma::Coarse_Cell_Container::_ccs
std::map< CoMMAIndexType, CoarseCellPtr > _ccs
Map containing the CC and their ID.
Definition: Coarse_Cell_Container.h:75
-
comma::Coarse_Cell_Container::select_best_cc_to_agglomerate_whole
std::optional< CoMMAIndexType > select_best_cc_to_agglomerate_whole(const std::unordered_set< CoMMAIndexType > &fcs, const std::set< CoMMAIndexType > &neighs, const CoMMAIntType max_card, std::optional< CoMMAIntType > &new_compactness) const
Choose among the neighbouring coarse cells, the one to which a singular coarse cell should be assigne...
Definition: Coarse_Cell_Container.h:266
-
comma::Coarse_Cell_Container::_singular_cc
std::deque< CoMMAIndexType > _singular_cc
Set of singular coarse cells, that is, composed of only one fine cell.
Definition: Coarse_Cell_Container.h:559
-
comma::Coarse_Cell_Container::_nb_of_agglomerated_fc
CoMMAIndexType _nb_of_agglomerated_fc
Number of agglomerated fine cells.
Definition: Coarse_Cell_Container.h:548
-
comma::Coarse_Cell_Container::_sing_card_thresh
CoMMAIntType _sing_card_thresh
Minimum cardinality for receiver CC when correcting.
Definition: Coarse_Cell_Container.h:92
-
comma::Coarse_Cell_Container::_delayed_cc
std::vector< std::pair< std::unordered_set< CoMMAIndexType >, CoMMAIntType > > _delayed_cc
Vector of the set of fine cells composing the too small coarse cells that will be built at the end of...
Definition: Coarse_Cell_Container.h:555
-
comma::Coarse_Cell_Container::_fc_2_cc
std::vector< std::optional< CoMMAIndexType > > _fc_2_cc
Output vector identifying to which coarse cell the fine cell belongs.
Definition: Coarse_Cell_Container.h:85
+
comma::Coarse_Cell_Container::_ccs
std::map< CoMMAIndexType, CoarseCellPtr > _ccs
Map containing the CC and their ID.
Definition: Coarse_Cell_Container.h:76
+
comma::Coarse_Cell_Container::select_best_cc_to_agglomerate_whole
std::optional< CoMMAIndexType > select_best_cc_to_agglomerate_whole(const std::unordered_set< CoMMAIndexType > &fcs, const std::set< CoMMAIndexType > &neighs, const CoMMAIntType max_card, std::optional< CoMMAIntType > &new_compactness) const
Choose among the neighbouring coarse cells, the one to which a singular coarse cell should be assigne...
Definition: Coarse_Cell_Container.h:271
+
comma::Coarse_Cell_Container::_singular_cc
std::deque< CoMMAIndexType > _singular_cc
Set of singular coarse cells, that is, composed of only one fine cell.
Definition: Coarse_Cell_Container.h:569
+
comma::Coarse_Cell_Container::_nb_of_agglomerated_fc
CoMMAIndexType _nb_of_agglomerated_fc
Number of agglomerated fine cells.
Definition: Coarse_Cell_Container.h:558
+
comma::Coarse_Cell_Container::_sing_card_thresh
CoMMAIntType _sing_card_thresh
Minimum cardinality for receiver CC when correcting.
Definition: Coarse_Cell_Container.h:93
+
comma::Coarse_Cell_Container::_delayed_cc
std::vector< std::pair< std::unordered_set< CoMMAIndexType >, CoMMAIntType > > _delayed_cc
Vector of the set of fine cells composing the too small coarse cells that will be built at the end of...
Definition: Coarse_Cell_Container.h:565
+
comma::Coarse_Cell_Container::_fc_2_cc
std::vector< std::optional< CoMMAIndexType > > _fc_2_cc
Output vector identifying to which coarse cell the fine cell belongs.
Definition: Coarse_Cell_Container.h:86
comma::Coarse_Cell_Container::CoarseCellPtr
std::shared_ptr< CoarseCellType > CoarseCellPtr
Type for a shared pointer to a Dual_Graph object.
Definition: Coarse_Cell_Container.h:48
comma::Coarse_Cell_Container::DualGraphPtr
typename CoarseCellType::DualGraphPtr DualGraphPtr
Type for a shared pointer to a Dual_Graph object.
Definition: Coarse_Cell_Container.h:51
-
comma::Coarse_Cell_Container::_cc_counter
CoMMAIndexType _cc_counter
Number of coarse cells.
Definition: Coarse_Cell_Container.h:81
-
comma::Coarse_Cell_Container::select_best_cc_to_agglomerate
std::optional< CoMMAIndexType > select_best_cc_to_agglomerate(const CoMMAIndexType fc, const std::set< CoMMAIndexType > &neighs, const CoMMAIntType max_card, std::optional< CoMMAIntType > &new_compactness) const
Choose among the neighbouring coarse cells, the one to which a fine cell should be assigned to....
Definition: Coarse_Cell_Container.h:333
-
comma::Coarse_Cell_Container::create_cc
CoMMAIndexType create_cc(const std::unordered_set< CoMMAIndexType > &s_fc, const CoMMAIntType compactness, bool is_anisotropic=false, bool is_creation_delayed=false)
It creates a coarse cell based on the set of fine cells given as input.
Definition: Coarse_Cell_Container.h:475
-
comma::Coarse_Cell_Container::get_number_of_fc_agglomerated
CoMMAIndexType get_number_of_fc_agglomerated() const
Helper to get the member variable that defines the number of agglomerated fine cells.
Definition: Coarse_Cell_Container.h:98
-
comma::Coarse_Cell_Container::_is_fc_agglomerated
std::vector< bool > _is_fc_agglomerated
Vector of boolean telling whether a fine cell has been agglomerated.
Definition: Coarse_Cell_Container.h:89
-
comma::Coarse_Cell_Container::get_nb_of_cc
CoMMAIndexType get_nb_of_cc() const
Helper to get the number of coarse cells.
Definition: Coarse_Cell_Container.h:105
-
comma::Coarse_Cell_Container::_fc_graph
DualGraphPtr _fc_graph
Dual graph representation.
Definition: Coarse_Cell_Container.h:78
-
comma::Coarse_Cell_Container::get_shared_faces
CoMMAIntType get_shared_faces(const CoMMAIndexType fc, const CoarseCellPtr cc) const
Compute the number of faces shared between a fine cell and a coarse one.
Definition: Coarse_Cell_Container.h:454
+
comma::Coarse_Cell_Container::_cc_counter
CoMMAIndexType _cc_counter
Number of coarse cells.
Definition: Coarse_Cell_Container.h:82
+
comma::Coarse_Cell_Container::select_best_cc_to_agglomerate
std::optional< CoMMAIndexType > select_best_cc_to_agglomerate(const CoMMAIndexType fc, const std::set< CoMMAIndexType > &neighs, const CoMMAIntType max_card, std::optional< CoMMAIntType > &new_compactness) const
Choose among the neighbouring coarse cells, the one to which a fine cell should be assigned to....
Definition: Coarse_Cell_Container.h:339
+
comma::Coarse_Cell_Container::create_cc
CoMMAIndexType create_cc(const std::unordered_set< CoMMAIndexType > &s_fc, const CoMMAIntType compactness, bool is_anisotropic=false, bool is_creation_delayed=false)
It creates a coarse cell based on the set of fine cells given as input.
Definition: Coarse_Cell_Container.h:483
+
comma::Coarse_Cell_Container::get_number_of_fc_agglomerated
CoMMAIndexType get_number_of_fc_agglomerated() const
Helper to get the member variable that defines the number of agglomerated fine cells.
Definition: Coarse_Cell_Container.h:99
+
comma::Coarse_Cell_Container::_is_fc_agglomerated
std::vector< bool > _is_fc_agglomerated
Vector of boolean telling whether a fine cell has been agglomerated.
Definition: Coarse_Cell_Container.h:90
+
comma::Coarse_Cell_Container::get_nb_of_cc
CoMMAIndexType get_nb_of_cc() const
Helper to get the number of coarse cells.
Definition: Coarse_Cell_Container.h:106
+
comma::Coarse_Cell_Container::_fc_graph
DualGraphPtr _fc_graph
Dual graph representation.
Definition: Coarse_Cell_Container.h:79
+
comma::Coarse_Cell_Container::get_shared_faces
CoMMAIntType get_shared_faces(const CoMMAIndexType fc, const CoarseCellPtr cc) const
Compute the number of faces shared between a fine cell and a coarse one.
Definition: Coarse_Cell_Container.h:461
comma::Coarse_Cell_Container::~Coarse_Cell_Container
~Coarse_Cell_Container()=default
Destructor.
comma::Coarse_Cell_Container::Coarse_Cell_Container
Coarse_Cell_Container(DualGraphPtr &fc_graph, const CoMMAIntType singular_card_thresh)
Create a Coarse_Cell_Container.
Definition: Coarse_Cell_Container.h:59
-
comma::Coarse_Cell_Container::get_neighs_cc
std::set< CoMMAIndexType > get_neighs_cc(const CoMMAIndexType &i_fc, const CoMMAIndexType &i_cc) const
Retrieve the indexes of the neighbouring coarse cells to a given fine cell in a coarse cell (excludin...
Definition: Coarse_Cell_Container.h:115
-
comma::Coarse_Cell_Container::correct
void correct(const CoMMAIntType max_card)
Implementation of the correction. In this version it implements the correction of singular cells (if ...
Definition: Coarse_Cell_Container.h:161
-
comma::Coarse_Cell_Container::cc_create_all_delayed_cc
void cc_create_all_delayed_cc()
Creates all the delayed coarse cell. It works only when the delayed cell flag is activated in the agg...
Definition: Coarse_Cell_Container.h:539
+
comma::Coarse_Cell_Container::get_neighs_cc
std::set< CoMMAIndexType > get_neighs_cc(const CoMMAIndexType &i_fc, const CoMMAIndexType &i_cc) const
Retrieve the indexes of the neighbouring coarse cells to a given fine cell in a coarse cell (excludin...
Definition: Coarse_Cell_Container.h:116
+
comma::Coarse_Cell_Container::correct
void correct(const CoMMAIntType max_card)
Implementation of the correction. In this version it implements the correction of singular cells (if ...
Definition: Coarse_Cell_Container.h:164
+
comma::Coarse_Cell_Container::cc_create_all_delayed_cc
void cc_create_all_delayed_cc()
Creates all the delayed coarse cell. It works only when the delayed cell flag is activated in the agg...
Definition: Coarse_Cell_Container.h:549
comma::Coarse_Cell
Class describing a coarse cell.
Definition: Coarse_Cell.h:37
comma::Coarse_Cell::DualGraphPtr
std::shared_ptr< Dual_Graph< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > DualGraphPtr
Type for a shared pointer to a Dual_Graph object.
Definition: Coarse_Cell.h:41
comma
Definition: Agglomerator.h:34
diff --git a/_dual___graph_8h_source.html b/_dual___graph_8h_source.html index a2f71b3..c70be8e 100644 --- a/_dual___graph_8h_source.html +++ b/_dual___graph_8h_source.html @@ -141,628 +141,668 @@
66 const ContainerIndexType &m_crs_row_ptr,
67 const ContainerIndexType &m_crs_col_ind,
68 const ContainerWeightType &m_crs_values,
-
69 const ContainerWeightType &volumes) :
-
70 _number_of_cells(nb_c),
-
71 _m_CRS_Row_Ptr(m_crs_row_ptr),
-
72 _m_CRS_Col_Ind(m_crs_col_ind),
-
73 _m_CRS_Values(m_crs_values),
-
74 _volumes(volumes) {
-
75 _visited.resize(_number_of_cells);
-
76 fill(_visited.begin(), _visited.end(), false);
-
77 }
-
78
-
80 virtual ~Graph() = default;
-
81
-
84 CoMMAIndexType _number_of_cells;
-
85
-
87 std::vector<bool> _visited;
-
88
-
90 ContainerIndexType _m_CRS_Row_Ptr;
-
91
-
93 ContainerIndexType _m_CRS_Col_Ind;
-
94
-
96 ContainerWeightType _m_CRS_Values;
-
97
-
99 ContainerWeightType _volumes;
-
100
-
104 void DFS(const CoMMAIndexType &i_fc) {
-
105 _visited[i_fc] = true;
-
106 for (auto it = neighbours_cbegin(i_fc); it != neighbours_cend(i_fc); ++it) {
-
107 if (!_visited[*it]) { DFS(*it); }
-
108 }
-
109 }
-
110
-
114 void BFS(const CoMMAIndexType &root) {
-
115 std::deque<CoMMAIndexType> coda;
-
116 ContainerIndexType path;
-
117 coda.push_back(root);
-
118 std::vector<bool> visited(_number_of_cells, false);
-
119 visited[root] = true;
-
120 std::vector<std::optional<CoMMAIndexType>> prev(
-
121 _number_of_cells, std::nullopt);
-
122 while (!coda.empty()) {
-
123 CoMMAIndexType node = coda.front();
-
124 coda.pop_front();
-
125 for (auto it = neighbours_cbegin(node); it != neighbours_cend(node);
-
126 ++it) {
-
127 if (!visited[*it]) {
-
128 coda.push_pack(*it);
-
129 visited[*it] = true;
-
130 prev[it] = node;
-
131 }
-
132 }
-
133 }
-
134 // to print the inverse path
-
135 CoMMAIndexType retro = prev[_number_of_cells - 1];
-
136 while (retro.has_value()) {
-
137 path.push_back(retro);
-
138 retro = prev[retro];
-
139 }
-
140 reverse(path.begin(), path.end());
-
141 // for (CoMMAIntType i = 0; i < _number_of_cells; i++) {
-
142 // std::cout<<"BFS"<<path[i]<<std::endl;
-
143 // }
-
144 }
-
145
-
150 inline CoMMAIntType get_nb_of_neighbours(CoMMAIndexType i_c) const {
-
151 // Return the number of neighbours of the ith cell
-
152 return _m_CRS_Row_Ptr[i_c + 1] - _m_CRS_Row_Ptr[i_c];
-
153 }
-
154
-
160 ContainerIndexType get_neighbours(const CoMMAIndexType &i_c) const {
-
161 // given the index of a cell return the neighbourhoods of this cell
-
162 CoMMAIndexType ind = _m_CRS_Row_Ptr[i_c];
-
163 CoMMAIndexType ind_p_one = _m_CRS_Row_Ptr[i_c + 1];
-
164 // insert the values of the CRS_value from begin+ind (pointed to the face)
-
165 // till the next pointed one, so related to all the connected areas (and
-
166 // hence to the faces)
-
167 ContainerIndexType result(
-
168 _m_CRS_Col_Ind.begin() + ind, _m_CRS_Col_Ind.begin() + ind_p_one);
-
169 return result;
-
170 }
-
171
-
176 inline ContainerIndexConstIt neighbours_cbegin(
-
177 const CoMMAIndexType &i_c) const {
-
178 return _m_CRS_Col_Ind.cbegin() + _m_CRS_Row_Ptr[i_c];
-
179 }
-
180
-
186 inline ContainerIndexConstIt neighbours_cend(
-
187 const CoMMAIndexType &i_c) const {
-
188 return _m_CRS_Col_Ind.cbegin() + _m_CRS_Row_Ptr[i_c + 1];
-
189 }
-
190
-
197 inline ContainerWeightType get_weights(const CoMMAIndexType &i_c) const {
-
198 // Given the index of a cell, return the value of the faces connected
-
199 CoMMAIndexType ind = _m_CRS_Row_Ptr[i_c];
-
200 CoMMAIndexType ind_p_one = _m_CRS_Row_Ptr[i_c + 1];
-
201 // insert the values of the CRS_value from begin+ind (pointed to the face)
-
202 // till the next pointed one, so related to all the connected areas (and
-
203 // hence to the faces)
-
204 ContainerWeightType result(
-
205 _m_CRS_Values.begin() + ind, _m_CRS_Values.begin() + ind_p_one);
-
206 return result;
-
207 }
-
208
-
213 inline ContainerWeightConstIt weights_cbegin(
-
214 const CoMMAIndexType &i_c) const {
-
215 return _m_CRS_Values.cbegin() + _m_CRS_Row_Ptr[i_c];
-
216 }
-
217
-
223 inline ContainerWeightConstIt weights_cend(const CoMMAIndexType &i_c) const {
-
224 return _m_CRS_Values.cbegin() + _m_CRS_Row_Ptr[i_c + 1];
-
225 }
-
226
-
230 bool check_connectivity() {
-
231 for (auto i = decltype(_number_of_cells){0}; i < _number_of_cells; ++i) {
-
232 _visited.push_back(false);
-
233 }
-
234 if (_number_of_cells == 1) { return (true); }
-
235 DFS(_m_CRS_Col_Ind[0]);
-
236 for (auto i = decltype(_number_of_cells){0}; i < _number_of_cells; ++i) {
-
237 if (!_visited[i]) { return (false); }
-
238 }
-
239 return (true);
-
240 }
-
241
-
246 CoMMAIntType compute_min_fc_compactness_inside_a_cc(
-
247 const std::unordered_set<CoMMAIndexType> &s_fc) const {
-
248 // Compute Compactness of a cc
-
249 // Be careful: connectivity is assumed
-
250 if (s_fc.size() > 1) {
-
251 std::unordered_map<CoMMAIndexType, CoMMAIntType> dict_fc_compactness =
-
252 compute_fc_compactness_inside_a_cc(s_fc);
-
253 if (dict_fc_compactness.empty()) { return 0; }
-
254 return min_element(
-
255 dict_fc_compactness.begin(), dict_fc_compactness.end(),
-
256 [](const auto &left, const auto &right) {
-
257 return left.second < right.second;
-
258 })
-
259 ->second;
-
260 }
-
261 return 0;
-
262 }
-
263
-
270 std::unordered_map<CoMMAIndexType, CoMMAIntType>
-
271 compute_fc_compactness_inside_a_cc(
-
272 const std::unordered_set<CoMMAIndexType> &s_fc) const {
-
273 std::unordered_map<CoMMAIndexType, CoMMAIntType> dict_fc_compactness;
-
274 if (!s_fc.empty()) {
-
275 if (s_fc.size() == 1) {
-
276 dict_fc_compactness[*s_fc.begin()] = 0;
-
277 } else {
-
278 for (const CoMMAIndexType &i_fc : s_fc) {
-
279 dict_fc_compactness[i_fc] = count_if(
-
280 this->_m_CRS_Col_Ind.cbegin() + this->_m_CRS_Row_Ptr[i_fc],
-
281 this->_m_CRS_Col_Ind.cbegin() + this->_m_CRS_Row_Ptr[i_fc + 1],
-
282 [&](const auto &neigh) { return s_fc.count(neigh) > 0; });
-
283 }
-
284 }
-
285 }
-
286 return dict_fc_compactness;
-
287 }
-
288};
-
289
-
298template<
-
299 typename CoMMAIndexType,
-
300 typename CoMMAWeightType,
-
301 typename CoMMAIntType>
-
302class Subgraph : public Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
303public:
-
305 using BaseClass = Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
307 using typename BaseClass::ContainerIndexType;
-
309 using typename BaseClass::ContainerWeightType;
-
323 Subgraph(
-
324 const CoMMAIndexType &nb_c,
-
325 const ContainerIndexType &m_crs_row_ptr,
-
326 const ContainerIndexType &m_crs_col_ind,
-
327 const ContainerWeightType &m_crs_values,
-
328 const ContainerWeightType &volumes,
-
329 const ContainerIndexType &mapping_l_to_g,
-
330 const bool &is_isotropic) :
-
331 Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
332 nb_c, m_crs_row_ptr, m_crs_col_ind, m_crs_values, volumes),
-
333 _is_isotropic(is_isotropic),
-
334 _cardinality(static_cast<CoMMAIntType>(nb_c)),
-
335 _mapping_l_to_g(mapping_l_to_g) {
-
336 // Compactness computation
-
337 _compactness = static_cast<CoMMAIntType>(nb_c);
-
338 for (auto c = decltype(nb_c){0}; c < nb_c; ++c) {
-
339 const auto n_neighs =
-
340 static_cast<CoMMAIntType>(m_crs_row_ptr[c + 1] - m_crs_row_ptr[c]);
-
341 if (n_neighs < _compactness) { _compactness = n_neighs; }
-
342 }
-
343 }
-
344
-
346 ~Subgraph() override = default;
-
347
-
349 bool _is_isotropic;
-
350
-
354 CoMMAIntType _cardinality;
-
355
-
359 CoMMAIntType _compactness;
-
360
-
365 ContainerIndexType _mapping_l_to_g;
-
366
-
375 void insert_node(
-
376 const ContainerIndexType &v_neigh,
-
377 const CoMMAIndexType &i_fc,
-
378 const CoMMAWeightType &volume,
-
379 const ContainerWeightType &weight) {
-
380 // Use the mapping
-
381 // local vector of neighbourhood
-
382 ContainerIndexType v_l_neigh{};
-
383 // @todo this solution clearly help in the connection of the subnode BUT can
-
384 // bring to instability and errors.
-
385 for (const auto &elem : v_neigh) {
-
386 const auto low1 =
-
387 std::find(_mapping_l_to_g.begin(), _mapping_l_to_g.end(), elem);
-
388 if (low1 != _mapping_l_to_g.end()) {
-
389 v_l_neigh.push_back(low1 - _mapping_l_to_g.begin());
-
390 }
-
391 }
-
392 // variable to add weight for each face
-
393 CoMMAIntType iter_weight = 0;
-
394 CoMMAIndexType local_index = this->_m_CRS_Row_Ptr.size() - 1;
-
395 // initialization pointers for insertion, pointing to the first element of
-
396 // each
-
397 auto row_end = this->_m_CRS_Row_Ptr.end() - 1;
-
398
-
399 // cycle on the set of neighbours
-
400 for (const auto &elem : v_l_neigh) {
-
401 // insert the node and the weight (we have an iterator for this and
-
402 // remember that at edge is associated one weight) look at here
-
403 // https://stackoverflow.com/questions/71299247/inserting-an-element-in-given-positions-more-than-one-of-a-vector/71299304#71299304
-
404 // to understand why we re-initialize.
-
405 this->_m_CRS_Col_Ind.insert(
-
406 this->_m_CRS_Col_Ind.begin() + this->_m_CRS_Row_Ptr[elem], local_index);
-
407 this->_m_CRS_Values.insert(
-
408 this->_m_CRS_Values.begin() + this->_m_CRS_Row_Ptr[elem],
-
409 weight[iter_weight]);
-
410 // We modify the row pointer as far it is related with what we have done
-
411 // before
-
412 for (auto it = this->_m_CRS_Row_Ptr.begin() + elem;
-
413 it != this->_m_CRS_Row_Ptr.end(); ++it) {
-
414 ++(*it);
-
415 }
-
416 // we do the same.
-
417 this->_m_CRS_Col_Ind.insert(this->_m_CRS_Col_Ind.end(), elem);
-
418 this->_m_CRS_Values.insert(
-
419 this->_m_CRS_Values.end(), weight[iter_weight]);
-
420 // We increment the weight flag iterator
-
421 ++iter_weight;
-
422 }
-
423 this->_m_CRS_Row_Ptr.push_back(*row_end + v_neigh.size());
-
424 this->_volumes.push_back(volume);
-
425 _mapping_l_to_g.push_back(i_fc);
-
426 }
-
427
-
432 void remove_node(const CoMMAIndexType &elemento) {
-
433 // Pass to the local
-
434 auto low =
-
435 std::find(_mapping_l_to_g.begin(), _mapping_l_to_g.end(), elemento);
-
436 const CoMMAIndexType i_fc = low - _mapping_l_to_g.begin();
-
437 // Getting neighbours, store them before erasing
-
438 ContainerIndexType v_neigh = this->get_neighbours(i_fc);
-
439
-
440 // weight iterator for erasing in the weight vector
-
441 auto pos_col = this->_m_CRS_Col_Ind.begin();
-
442 auto pos_Values = this->_m_CRS_Values.begin();
-
443 for (const auto &elem : v_neigh) {
-
444 CoMMAIndexType ind = this->_m_CRS_Row_Ptr[elem];
-
445 CoMMAIndexType ind_p_one = this->_m_CRS_Row_Ptr[elem + 1];
-
446 // Constant to keep track and erase the weight
-
447 for (auto it = pos_col + ind; it != pos_col + ind_p_one; ++it) {
-
448 if (*it == i_fc) {
-
449 this->_m_CRS_Col_Ind.erase(it);
-
450 // define the exact position of the element for the processing of the
-
451 // weight later.
-
452 this->_m_CRS_Values.erase(pos_Values + (it - pos_col));
-
453 // for each found i decrease the successive of 1 for the offset
-
454 for (auto it_bis = this->_m_CRS_Row_Ptr.begin() + elem + 1;
-
455 it_bis != this->_m_CRS_Row_Ptr.end(); ++it_bis) {
-
456 *it_bis = *it_bis - 1;
-
457 }
-
458 }
-
459 }
-
460 }
-
461 // reduce the row ptr value of the deleted value
-
462 // do the same with i_fc
-
463 CoMMAIndexType ind = this->_m_CRS_Row_Ptr[i_fc];
-
464 CoMMAIndexType ind_p_one = this->_m_CRS_Row_Ptr[i_fc + 1];
-
465 for (auto it = pos_col + ind; it != pos_col + ind_p_one; ++it) {
-
466 this->_m_CRS_Col_Ind.erase(it);
-
467 // define the exact position of the element for the processing of the
-
468 // weight later.
-
469 this->_m_CRS_Values.erase(pos_Values + (it - pos_col));
-
470 // for each found i decrease the successive of 1 for the offset
-
471 for (auto it_bis = this->_m_CRS_Row_Ptr.begin() + i_fc + 1;
-
472 it_bis != this->_m_CRS_Row_Ptr.end(); ++it_bis) {
-
473 *it_bis = *it_bis - 1;
-
474 }
-
475 }
-
476 // Get rid of the col element
-
477 auto Col_pointer = this->_m_CRS_Row_Ptr.begin() + i_fc;
-
478 // Modify the mapping
-
479 auto mapping_pointer = _mapping_l_to_g.begin() + i_fc;
-
480 auto volumes_pointer = this->_volumes.begin() + i_fc;
-
481 this->_volumes.erase(volumes_pointer);
-
482 this->_m_CRS_Row_Ptr.erase(Col_pointer);
-
483 _mapping_l_to_g.erase(mapping_pointer);
-
484 // now we do not have nomore our node, but we must create a mapping between
-
485 // the before and now, and translate it in the col_ind and update the
-
486 // mapping with the global graph mapping for the renumbering of the nodes
-
487 std::vector<std::optional<CoMMAIndexType>> internal_mapping;
-
488 internal_mapping.reserve(this->_m_CRS_Row_Ptr.size() + 1);
-
489 CoMMAIndexType indice = 0;
-
490 for (auto ix = decltype(this->_m_CRS_Row_Ptr.size()){0};
-
491 ix < this->_m_CRS_Row_Ptr.size() + 1; ++ix) {
-
492 if (static_cast<decltype(i_fc)>(ix) != i_fc) {
-
493 internal_mapping.push_back(indice);
-
494 indice++;
-
495 } else {
-
496 internal_mapping.push_back(std::nullopt);
-
497 }
-
498 }
-
499 for (auto &actual : this->_m_CRS_Col_Ind) {
-
500 assert(internal_mapping[actual].has_value());
-
501 actual = internal_mapping[actual].value();
-
502 }
-
503 }
-
504};
-
505
-
513template<
-
514 typename CoMMAIndexType,
-
515 typename CoMMAWeightType,
-
516 typename CoMMAIntType>
-
517class Dual_Graph : public Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
518public:
-
520 using BaseClass = Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
522 using typename BaseClass::ContainerIndexType;
-
524 using typename BaseClass::ContainerWeightType;
-
526 using CoMMAPairType = std::pair<CoMMAIndexType, CoMMAWeightType>;
-
528 using CoMMASetOfPairType =
-
529 std::set<CoMMAPairType, CustomPairGreaterFunctor<CoMMAPairType>>;
-
530
-
546 Dual_Graph(
-
547 const CoMMAIndexType &nb_c,
-
548 const ContainerIndexType &m_crs_row_ptr,
-
549 const ContainerIndexType &m_crs_col_ind,
-
550 const ContainerWeightType &m_crs_values,
-
551 const ContainerWeightType &volumes,
-
552 const std::vector<std::vector<CoMMAWeightType>> &centers,
-
553 const std::vector<CoMMAIntType> &n_bnd_faces,
-
554 const CoMMAIntType dimension,
-
555 const ContainerIndexType &anisotropic_compliant_fc) :
-
556 Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
557 nb_c, m_crs_row_ptr, m_crs_col_ind, m_crs_values, volumes),
-
558 _n_bnd_faces(n_bnd_faces),
-
559 _s_anisotropic_compliant_cells(
-
560 anisotropic_compliant_fc.begin(), anisotropic_compliant_fc.end()),
-
561 _centers(centers) {
-
562 // Function to compute the aspect-ratio
-
563 _compute_AR = dimension == 2
-
564 ? [](const CoMMAWeightType min_s, const CoMMAWeightType max_s)
-
565 -> CoMMAWeightType { return max_s / min_s; }
-
566 : [](const CoMMAWeightType min_s, const CoMMAWeightType max_s)
-
567 -> CoMMAWeightType { return sqrt(max_s / min_s); };
-
568 }
-
569
-
571 ~Dual_Graph() override = default;
-
572
-
574 const std::vector<CoMMAIntType> &_n_bnd_faces;
-
575
-
581 const std::unordered_set<CoMMAIndexType> _s_anisotropic_compliant_cells;
-
582
-
584 const std::vector<std::vector<CoMMAWeightType>> &_centers;
-
585
-
591 std::function<CoMMAWeightType(const CoMMAWeightType, const CoMMAWeightType)>
-
592 _compute_AR;
-
593
-
598 inline CoMMAIntType get_n_boundary_faces(const CoMMAIndexType idx_c) const {
-
599 return _n_bnd_faces[idx_c];
-
600 }
-
605 inline bool is_on_boundary(const CoMMAIndexType idx_c) const {
-
606 return _n_bnd_faces[idx_c] > 0;
-
607 }
-
608
-
626 void tag_anisotropic_cells(
-
627 ContainerWeightType &max_weights,
-
628 std::vector<bool> &is_anisotropic,
-
629 std::deque<CoMMAIndexType> &aniso_seeds_pool,
-
630 const CoMMAWeightType threshold_anisotropy,
-
631 const ContainerWeightType &priority_weights,
-
632 const CoMMAIndexType preserving) {
-
633 CoMMASetOfPairType aniso_w_weights{};
-
634 if (threshold_anisotropy < 0) {
-
635 for (const CoMMAIndexType i_fc : _s_anisotropic_compliant_cells) {
-
636 aniso_w_weights.emplace(i_fc, priority_weights[i_fc]);
-
637 max_weights[i_fc] =
-
638 *(max_element(this->weights_cbegin(i_fc), this->weights_cend(i_fc)));
-
639 }
-
640 } else {
-
641 for (const CoMMAIndexType i_fc : _s_anisotropic_compliant_cells) {
-
642 CoMMAWeightType min_weight =
-
643 std::numeric_limits<CoMMAWeightType>::max();
-
644 CoMMAWeightType max_weight = 0.0;
-
645
-
646 // computation of min_weight, max_weight for the current cell
-
647 // Process of every faces/Neighbours and compute for the current cell
-
648 // the neighbourhood and the area associated with the neighbourhood
-
649 // cells
-
650 const ContainerIndexType v_neighbours = this->get_neighbours(i_fc);
-
651 const ContainerWeightType v_weights = this->get_weights(i_fc);
-
652
-
653 assert(v_neighbours.size() == v_weights.size());
-
654 auto nb_neighbours = v_neighbours.size();
-
655
-
656 for (auto i_n = decltype(nb_neighbours){0}; i_n < nb_neighbours;
-
657 i_n++) {
-
658 // to avoid special case where the boundary value are stored
-
659 if (v_neighbours[i_n] != i_fc) {
-
660 const CoMMAWeightType i_w_fc_n = v_weights[i_n];
-
661 if (max_weight < i_w_fc_n) { max_weight = i_w_fc_n; }
-
662 if (min_weight > i_w_fc_n) { min_weight = i_w_fc_n; }
-
663 } else {
-
664 nb_neighbours--;
-
665 }
-
666 }
-
667
-
668 max_weights[i_fc] = max_weight;
-
669 // Compute the aspect-ratio and add cell to list if necessary
-
670 const auto ar = _compute_AR(min_weight, max_weight);
-
671 // Anisotropy criteria for the line Admissibility
-
672 if (ar >= threshold_anisotropy) {
-
673 switch (preserving) {
-
674 case 2:
-
675 if (
-
676 (is_on_boundary(i_fc) > 0 && nb_neighbours == 3)
-
677 || nb_neighbours == 4)
-
678 aniso_w_weights.emplace(i_fc, priority_weights[i_fc]);
-
679 break;
-
680 case 3:
-
681 if (
-
682 (is_on_boundary(i_fc) > 0 && nb_neighbours == 5)
-
683 || nb_neighbours == 6)
-
684 aniso_w_weights.emplace(i_fc, priority_weights[i_fc]);
-
685 case 0:
-
686 default:
-
687 // If the ratio is more than the given threshold of the biggest
-
688 // with the smallest cell, add it
-
689 aniso_w_weights.emplace(i_fc, priority_weights[i_fc]);
-
690 break;
-
691 } // End switch
-
692 } // End if ar
-
693 } // End for compliant cells
-
694 } // End if threshold
-
695
-
696 // Build result
-
697 for (const auto &[i_fc, w] : aniso_w_weights) {
-
698 is_anisotropic[i_fc] = true;
-
699 aniso_seeds_pool.emplace_back(i_fc);
-
700 }
-
701 }
-
702
-
706 inline CoMMAIntType get_nb_cells() const { return this->_number_of_cells; }
+
69 const ContainerWeightType &volumes
+
70 ) :
+
71 _number_of_cells(nb_c),
+
72 _m_CRS_Row_Ptr(m_crs_row_ptr),
+
73 _m_CRS_Col_Ind(m_crs_col_ind),
+
74 _m_CRS_Values(m_crs_values),
+
75 _volumes(volumes) {
+
76 _visited.resize(_number_of_cells);
+
77 fill(_visited.begin(), _visited.end(), false);
+
78 }
+
79
+
81 virtual ~Graph() = default;
+
82
+
85 CoMMAIndexType _number_of_cells;
+
86
+
88 std::vector<bool> _visited;
+
89
+
91 ContainerIndexType _m_CRS_Row_Ptr;
+
92
+
94 ContainerIndexType _m_CRS_Col_Ind;
+
95
+
97 ContainerWeightType _m_CRS_Values;
+
98
+
100 ContainerWeightType _volumes;
+
101
+
105 void DFS(const CoMMAIndexType &i_fc) {
+
106 _visited[i_fc] = true;
+
107 for (auto it = neighbours_cbegin(i_fc); it != neighbours_cend(i_fc); ++it) {
+
108 if (!_visited[*it]) {
+
109 DFS(*it);
+
110 }
+
111 }
+
112 }
+
113
+
117 void BFS(const CoMMAIndexType &root) {
+
118 std::deque<CoMMAIndexType> coda;
+
119 ContainerIndexType path;
+
120 coda.push_back(root);
+
121 std::vector<bool> visited(_number_of_cells, false);
+
122 visited[root] = true;
+
123 std::vector<std::optional<CoMMAIndexType>> prev(
+
124 _number_of_cells, std::nullopt
+
125 );
+
126 while (!coda.empty()) {
+
127 CoMMAIndexType node = coda.front();
+
128 coda.pop_front();
+
129 for (auto it = neighbours_cbegin(node); it != neighbours_cend(node);
+
130 ++it) {
+
131 if (!visited[*it]) {
+
132 coda.push_pack(*it);
+
133 visited[*it] = true;
+
134 prev[it] = node;
+
135 }
+
136 }
+
137 }
+
138 // to print the inverse path
+
139 CoMMAIndexType retro = prev[_number_of_cells - 1];
+
140 while (retro.has_value()) {
+
141 path.push_back(retro);
+
142 retro = prev[retro];
+
143 }
+
144 reverse(path.begin(), path.end());
+
145 // for (CoMMAIntType i = 0; i < _number_of_cells; i++) {
+
146 // std::cout<<"BFS"<<path[i]<<std::endl;
+
147 // }
+
148 }
+
149
+
154 inline CoMMAIntType get_nb_of_neighbours(CoMMAIndexType i_c) const {
+
155 // Return the number of neighbours of the ith cell
+
156 return _m_CRS_Row_Ptr[i_c + 1] - _m_CRS_Row_Ptr[i_c];
+
157 }
+
158
+
164 ContainerIndexType get_neighbours(const CoMMAIndexType &i_c) const {
+
165 // given the index of a cell return the neighbourhoods of this cell
+
166 CoMMAIndexType ind = _m_CRS_Row_Ptr[i_c];
+
167 CoMMAIndexType ind_p_one = _m_CRS_Row_Ptr[i_c + 1];
+
168 // insert the values of the CRS_value from begin+ind (pointed to the face)
+
169 // till the next pointed one, so related to all the connected areas (and
+
170 // hence to the faces)
+
171 ContainerIndexType result(
+
172 _m_CRS_Col_Ind.begin() + ind, _m_CRS_Col_Ind.begin() + ind_p_one
+
173 );
+
174 return result;
+
175 }
+
176
+
181 inline ContainerIndexConstIt neighbours_cbegin(const CoMMAIndexType &i_c
+
182 ) const {
+
183 return _m_CRS_Col_Ind.cbegin() + _m_CRS_Row_Ptr[i_c];
+
184 }
+
185
+
191 inline ContainerIndexConstIt neighbours_cend(const CoMMAIndexType &i_c
+
192 ) const {
+
193 return _m_CRS_Col_Ind.cbegin() + _m_CRS_Row_Ptr[i_c + 1];
+
194 }
+
195
+
202 inline ContainerWeightType get_weights(const CoMMAIndexType &i_c) const {
+
203 // Given the index of a cell, return the value of the faces connected
+
204 CoMMAIndexType ind = _m_CRS_Row_Ptr[i_c];
+
205 CoMMAIndexType ind_p_one = _m_CRS_Row_Ptr[i_c + 1];
+
206 // insert the values of the CRS_value from begin+ind (pointed to the face)
+
207 // till the next pointed one, so related to all the connected areas (and
+
208 // hence to the faces)
+
209 ContainerWeightType result(
+
210 _m_CRS_Values.begin() + ind, _m_CRS_Values.begin() + ind_p_one
+
211 );
+
212 return result;
+
213 }
+
214
+
219 inline ContainerWeightConstIt weights_cbegin(const CoMMAIndexType &i_c
+
220 ) const {
+
221 return _m_CRS_Values.cbegin() + _m_CRS_Row_Ptr[i_c];
+
222 }
+
223
+
229 inline ContainerWeightConstIt weights_cend(const CoMMAIndexType &i_c) const {
+
230 return _m_CRS_Values.cbegin() + _m_CRS_Row_Ptr[i_c + 1];
+
231 }
+
232
+
236 bool check_connectivity() {
+
237 for (auto i = decltype(_number_of_cells){0}; i < _number_of_cells; ++i) {
+
238 _visited.push_back(false);
+
239 }
+
240 if (_number_of_cells == 1) {
+
241 return (true);
+
242 }
+
243 DFS(_m_CRS_Col_Ind[0]);
+
244 for (auto i = decltype(_number_of_cells){0}; i < _number_of_cells; ++i) {
+
245 if (!_visited[i]) {
+
246 return (false);
+
247 }
+
248 }
+
249 return (true);
+
250 }
+
251
+
256 CoMMAIntType compute_min_fc_compactness_inside_a_cc(
+
257 const std::unordered_set<CoMMAIndexType> &s_fc
+
258 ) const {
+
259 // Compute Compactness of a cc
+
260 // Be careful: connectivity is assumed
+
261 if (s_fc.size() > 1) {
+
262 std::unordered_map<CoMMAIndexType, CoMMAIntType> dict_fc_compactness =
+
263 compute_fc_compactness_inside_a_cc(s_fc);
+
264 if (dict_fc_compactness.empty()) {
+
265 return 0;
+
266 }
+
267 return min_element(
+
268 dict_fc_compactness.begin(),
+
269 dict_fc_compactness.end(),
+
270 [](const auto &left, const auto &right) {
+
271 return left.second < right.second;
+
272 }
+
273 )->second;
+
274 }
+
275 return 0;
+
276 }
+
277
+
284 std::unordered_map<CoMMAIndexType, CoMMAIntType>
+
285 compute_fc_compactness_inside_a_cc(
+
286 const std::unordered_set<CoMMAIndexType> &s_fc
+
287 ) const {
+
288 std::unordered_map<CoMMAIndexType, CoMMAIntType> dict_fc_compactness;
+
289 if (!s_fc.empty()) {
+
290 if (s_fc.size() == 1) {
+
291 dict_fc_compactness[*s_fc.begin()] = 0;
+
292 } else {
+
293 for (const CoMMAIndexType &i_fc : s_fc) {
+
294 dict_fc_compactness[i_fc] = count_if(
+
295 this->_m_CRS_Col_Ind.cbegin() + this->_m_CRS_Row_Ptr[i_fc],
+
296 this->_m_CRS_Col_Ind.cbegin() + this->_m_CRS_Row_Ptr[i_fc + 1],
+
297 [&](const auto &neigh) { return s_fc.count(neigh) > 0; }
+
298 );
+
299 }
+
300 }
+
301 }
+
302 return dict_fc_compactness;
+
303 }
+
304};
+
305
+
314template<
+
315 typename CoMMAIndexType,
+
316 typename CoMMAWeightType,
+
317 typename CoMMAIntType>
+
318class Subgraph : public Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
319public:
+
321 using BaseClass = Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
323 using typename BaseClass::ContainerIndexType;
+
325 using typename BaseClass::ContainerWeightType;
+
326
+
340 Subgraph(
+
341 const CoMMAIndexType &nb_c,
+
342 const ContainerIndexType &m_crs_row_ptr,
+
343 const ContainerIndexType &m_crs_col_ind,
+
344 const ContainerWeightType &m_crs_values,
+
345 const ContainerWeightType &volumes,
+
346 const ContainerIndexType &mapping_l_to_g,
+
347 const bool &is_isotropic
+
348 ) :
+
349 Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
350 nb_c, m_crs_row_ptr, m_crs_col_ind, m_crs_values, volumes
+
351 ),
+
352 _is_isotropic(is_isotropic),
+
353 _cardinality(static_cast<CoMMAIntType>(nb_c)),
+
354 _mapping_l_to_g(mapping_l_to_g) {
+
355 // Compactness computation
+
356 _compactness = static_cast<CoMMAIntType>(nb_c);
+
357 for (auto c = decltype(nb_c){0}; c < nb_c; ++c) {
+
358 const auto n_neighs =
+
359 static_cast<CoMMAIntType>(m_crs_row_ptr[c + 1] - m_crs_row_ptr[c]);
+
360 if (n_neighs < _compactness) {
+
361 _compactness = n_neighs;
+
362 }
+
363 }
+
364 }
+
365
+
367 ~Subgraph() override = default;
+
368
+
370 bool _is_isotropic;
+
371
+
375 CoMMAIntType _cardinality;
+
376
+
380 CoMMAIntType _compactness;
+
381
+
386 ContainerIndexType _mapping_l_to_g;
+
387
+
396 void insert_node(
+
397 const ContainerIndexType &v_neigh,
+
398 const CoMMAIndexType &i_fc,
+
399 const CoMMAWeightType &volume,
+
400 const ContainerWeightType &weight
+
401 ) {
+
402 // Use the mapping
+
403 // local vector of neighbourhood
+
404 ContainerIndexType v_l_neigh{};
+
405 // @todo this solution clearly help in the connection of the subnode BUT can
+
406 // bring to instability and errors.
+
407 for (const auto &elem : v_neigh) {
+
408 const auto low1 =
+
409 std::find(_mapping_l_to_g.begin(), _mapping_l_to_g.end(), elem);
+
410 if (low1 != _mapping_l_to_g.end()) {
+
411 v_l_neigh.push_back(low1 - _mapping_l_to_g.begin());
+
412 }
+
413 }
+
414 // variable to add weight for each face
+
415 CoMMAIntType iter_weight = 0;
+
416 CoMMAIndexType local_index = this->_m_CRS_Row_Ptr.size() - 1;
+
417 // initialization pointers for insertion, pointing to the first element of
+
418 // each
+
419 auto row_end = this->_m_CRS_Row_Ptr.end() - 1;
+
420
+
421 // cycle on the set of neighbours
+
422 for (const auto &elem : v_l_neigh) {
+
423 // insert the node and the weight (we have an iterator for this and
+
424 // remember that at edge is associated one weight) look at here
+
425 // https://stackoverflow.com/questions/71299247/inserting-an-element-in-given-positions-more-than-one-of-a-vector/71299304#71299304
+
426 // to understand why we re-initialize.
+
427 this->_m_CRS_Col_Ind.insert(
+
428 this->_m_CRS_Col_Ind.begin() + this->_m_CRS_Row_Ptr[elem], local_index
+
429 );
+
430 this->_m_CRS_Values.insert(
+
431 this->_m_CRS_Values.begin() + this->_m_CRS_Row_Ptr[elem],
+
432 weight[iter_weight]
+
433 );
+
434 // We modify the row pointer as far it is related with what we have done
+
435 // before
+
436 for (auto it = this->_m_CRS_Row_Ptr.begin() + elem;
+
437 it != this->_m_CRS_Row_Ptr.end();
+
438 ++it) {
+
439 ++(*it);
+
440 }
+
441 // we do the same.
+
442 this->_m_CRS_Col_Ind.insert(this->_m_CRS_Col_Ind.end(), elem);
+
443 this->_m_CRS_Values.insert(
+
444 this->_m_CRS_Values.end(), weight[iter_weight]
+
445 );
+
446 // We increment the weight flag iterator
+
447 ++iter_weight;
+
448 }
+
449 this->_m_CRS_Row_Ptr.push_back(*row_end + v_neigh.size());
+
450 this->_volumes.push_back(volume);
+
451 _mapping_l_to_g.push_back(i_fc);
+
452 }
+
453
+
458 void remove_node(const CoMMAIndexType &elemento) {
+
459 // Pass to the local
+
460 auto low =
+
461 std::find(_mapping_l_to_g.begin(), _mapping_l_to_g.end(), elemento);
+
462 const CoMMAIndexType i_fc = low - _mapping_l_to_g.begin();
+
463 // Getting neighbours, store them before erasing
+
464 ContainerIndexType v_neigh = this->get_neighbours(i_fc);
+
465
+
466 // weight iterator for erasing in the weight vector
+
467 auto pos_col = this->_m_CRS_Col_Ind.begin();
+
468 auto pos_Values = this->_m_CRS_Values.begin();
+
469 for (const auto &elem : v_neigh) {
+
470 CoMMAIndexType ind = this->_m_CRS_Row_Ptr[elem];
+
471 CoMMAIndexType ind_p_one = this->_m_CRS_Row_Ptr[elem + 1];
+
472 // Constant to keep track and erase the weight
+
473 for (auto it = pos_col + ind; it != pos_col + ind_p_one; ++it) {
+
474 if (*it == i_fc) {
+
475 this->_m_CRS_Col_Ind.erase(it);
+
476 // define the exact position of the element for the processing of the
+
477 // weight later.
+
478 this->_m_CRS_Values.erase(pos_Values + (it - pos_col));
+
479 // for each found i decrease the successive of 1 for the offset
+
480 for (auto it_bis = this->_m_CRS_Row_Ptr.begin() + elem + 1;
+
481 it_bis != this->_m_CRS_Row_Ptr.end();
+
482 ++it_bis) {
+
483 *it_bis = *it_bis - 1;
+
484 }
+
485 }
+
486 }
+
487 }
+
488 // reduce the row ptr value of the deleted value
+
489 // do the same with i_fc
+
490 CoMMAIndexType ind = this->_m_CRS_Row_Ptr[i_fc];
+
491 CoMMAIndexType ind_p_one = this->_m_CRS_Row_Ptr[i_fc + 1];
+
492 for (auto it = pos_col + ind; it != pos_col + ind_p_one; ++it) {
+
493 this->_m_CRS_Col_Ind.erase(it);
+
494 // define the exact position of the element for the processing of the
+
495 // weight later.
+
496 this->_m_CRS_Values.erase(pos_Values + (it - pos_col));
+
497 // for each found i decrease the successive of 1 for the offset
+
498 for (auto it_bis = this->_m_CRS_Row_Ptr.begin() + i_fc + 1;
+
499 it_bis != this->_m_CRS_Row_Ptr.end();
+
500 ++it_bis) {
+
501 *it_bis = *it_bis - 1;
+
502 }
+
503 }
+
504 // Get rid of the col element
+
505 auto Col_pointer = this->_m_CRS_Row_Ptr.begin() + i_fc;
+
506 // Modify the mapping
+
507 auto mapping_pointer = _mapping_l_to_g.begin() + i_fc;
+
508 auto volumes_pointer = this->_volumes.begin() + i_fc;
+
509 this->_volumes.erase(volumes_pointer);
+
510 this->_m_CRS_Row_Ptr.erase(Col_pointer);
+
511 _mapping_l_to_g.erase(mapping_pointer);
+
512 // now we do not have nomore our node, but we must create a mapping between
+
513 // the before and now, and translate it in the col_ind and update the
+
514 // mapping with the global graph mapping for the renumbering of the nodes
+
515 std::vector<std::optional<CoMMAIndexType>> internal_mapping;
+
516 internal_mapping.reserve(this->_m_CRS_Row_Ptr.size() + 1);
+
517 CoMMAIndexType indice = 0;
+
518 for (auto ix = decltype(this->_m_CRS_Row_Ptr.size()){0};
+
519 ix < this->_m_CRS_Row_Ptr.size() + 1;
+
520 ++ix) {
+
521 if (static_cast<decltype(i_fc)>(ix) != i_fc) {
+
522 internal_mapping.push_back(indice);
+
523 indice++;
+
524 } else {
+
525 internal_mapping.push_back(std::nullopt);
+
526 }
+
527 }
+
528 for (auto &actual : this->_m_CRS_Col_Ind) {
+
529 assert(internal_mapping[actual].has_value());
+
530 actual = internal_mapping[actual].value();
+
531 }
+
532 }
+
533};
+
534
+
542template<
+
543 typename CoMMAIndexType,
+
544 typename CoMMAWeightType,
+
545 typename CoMMAIntType>
+
546class Dual_Graph : public Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
547public:
+
549 using BaseClass = Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
551 using typename BaseClass::ContainerIndexType;
+
553 using typename BaseClass::ContainerWeightType;
+
555 using CoMMAPairType = std::pair<CoMMAIndexType, CoMMAWeightType>;
+
557 using CoMMASetOfPairType =
+
558 std::set<CoMMAPairType, CustomPairGreaterFunctor<CoMMAPairType>>;
+
559
+
575 Dual_Graph(
+
576 const CoMMAIndexType &nb_c,
+
577 const ContainerIndexType &m_crs_row_ptr,
+
578 const ContainerIndexType &m_crs_col_ind,
+
579 const ContainerWeightType &m_crs_values,
+
580 const ContainerWeightType &volumes,
+
581 const std::vector<std::vector<CoMMAWeightType>> &centers,
+
582 const std::vector<CoMMAIntType> &n_bnd_faces,
+
583 const CoMMAIntType dimension,
+
584 const ContainerIndexType &anisotropic_compliant_fc
+
585 ) :
+
586 Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
587 nb_c, m_crs_row_ptr, m_crs_col_ind, m_crs_values, volumes
+
588 ),
+
589 _n_bnd_faces(n_bnd_faces),
+
590 _s_anisotropic_compliant_cells(
+
591 anisotropic_compliant_fc.begin(), anisotropic_compliant_fc.end()
+
592 ),
+
593 _centers(centers) {
+
594 // Function to compute the aspect-ratio
+
595 _compute_AR = dimension == 2
+
596 ? [](
+
597 const CoMMAWeightType min_s, const CoMMAWeightType max_s
+
598 ) -> CoMMAWeightType { return max_s / min_s; }
+
599 : [](
+
600 const CoMMAWeightType min_s, const CoMMAWeightType max_s
+
601 ) -> CoMMAWeightType { return sqrt(max_s / min_s); };
+
602 }
+
603
+
605 ~Dual_Graph() override = default;
+
606
+
608 const std::vector<CoMMAIntType> &_n_bnd_faces;
+
609
+
615 const std::unordered_set<CoMMAIndexType> _s_anisotropic_compliant_cells;
+
616
+
618 const std::vector<std::vector<CoMMAWeightType>> &_centers;
+
619
+
625 std::function<CoMMAWeightType(const CoMMAWeightType, const CoMMAWeightType)>
+
626 _compute_AR;
+
627
+
632 inline CoMMAIntType get_n_boundary_faces(const CoMMAIndexType idx_c) const {
+
633 return _n_bnd_faces[idx_c];
+
634 }
+
635
+
640 inline bool is_on_boundary(const CoMMAIndexType idx_c) const {
+
641 return _n_bnd_faces[idx_c] > 0;
+
642 }
+
643
+
661 void tag_anisotropic_cells(
+
662 ContainerWeightType &max_weights,
+
663 std::vector<bool> &is_anisotropic,
+
664 std::deque<CoMMAIndexType> &aniso_seeds_pool,
+
665 const CoMMAWeightType threshold_anisotropy,
+
666 const ContainerWeightType &priority_weights,
+
667 const CoMMAIndexType preserving
+
668 ) {
+
669 CoMMASetOfPairType aniso_w_weights{};
+
670 if (threshold_anisotropy < 0) {
+
671 for (const CoMMAIndexType i_fc : _s_anisotropic_compliant_cells) {
+
672 aniso_w_weights.emplace(i_fc, priority_weights[i_fc]);
+
673 max_weights[i_fc] =
+
674 *(max_element(this->weights_cbegin(i_fc), this->weights_cend(i_fc)));
+
675 }
+
676 } else {
+
677 for (const CoMMAIndexType i_fc : _s_anisotropic_compliant_cells) {
+
678 CoMMAWeightType min_weight =
+
679 std::numeric_limits<CoMMAWeightType>::max();
+
680 CoMMAWeightType max_weight = 0.0;
+
681
+
682 // computation of min_weight, max_weight for the current cell
+
683 // Process of every faces/Neighbours and compute for the current cell
+
684 // the neighbourhood and the area associated with the neighbourhood
+
685 // cells
+
686 const ContainerIndexType v_neighbours = this->get_neighbours(i_fc);
+
687 const ContainerWeightType v_weights = this->get_weights(i_fc);
+
688
+
689 assert(v_neighbours.size() == v_weights.size());
+
690 auto nb_neighbours = v_neighbours.size();
+
691
+
692 for (auto i_n = decltype(nb_neighbours){0}; i_n < nb_neighbours;
+
693 i_n++) {
+
694 // to avoid special case where the boundary value are stored
+
695 if (v_neighbours[i_n] != i_fc) {
+
696 const CoMMAWeightType i_w_fc_n = v_weights[i_n];
+
697 if (max_weight < i_w_fc_n) {
+
698 max_weight = i_w_fc_n;
+
699 }
+
700 if (min_weight > i_w_fc_n) {
+
701 min_weight = i_w_fc_n;
+
702 }
+
703 } else {
+
704 nb_neighbours--;
+
705 }
+
706 }
707
-
716 inline std::unordered_set<CoMMAIndexType> get_neighbourhood_of_cc(
-
717 const std::unordered_set<CoMMAIndexType> &s_seeds,
-
718 const std::vector<bool> &is_fc_agglomerated_tmp) const {
-
719 std::unordered_set<CoMMAIndexType> cc_neighs{};
-
720 for (const auto fc : s_seeds)
-
721 for (auto n = this->neighbours_cbegin(fc); n != this->neighbours_cend(fc);
-
722 ++n)
-
723 if (!is_fc_agglomerated_tmp[*n] && s_seeds.find(*n) == s_seeds.end())
-
724 // If not agglomerated and not part of the coarse cell
-
725 cc_neighs.insert(*n);
-
726 return cc_neighs;
-
727 }
-
728
-
743 void compute_neighbourhood_of_cc(
-
744 const std::unordered_set<CoMMAIndexType> &s_seeds,
-
745 CoMMAIntType &nb_of_order_of_neighbourhood,
-
746 std::unordered_map<CoMMAIndexType, CoMMAIntType> &d_n_of_seed,
-
747 const CoMMAIntType max_card,
-
748 const std::vector<bool> &is_fc_agglomerated_tmp) const {
-
749 // Basic checks
-
750 assert(max_card > 1);
-
751 // dict of FC with the order of neighbouring from seed
-
752 std::unordered_map<CoMMAIndexType, CoMMAIntType> d_n_of_order_o_m_one;
-
753 // we initialize for seeds where order is 0
-
754 for (const CoMMAIndexType &i_fc : s_seeds) {
-
755 d_n_of_order_o_m_one[i_fc] = 0;
-
756 }
-
757
-
758 CoMMAIntType i_order = 1;
-
759
-
760 while ((i_order < nb_of_order_of_neighbourhood + 1)
-
761 || static_cast<CoMMAIntType>(
-
762 d_n_of_seed.size() + d_n_of_order_o_m_one.size())
-
763 < max_card) {
-
764 std::unordered_map<CoMMAIndexType, CoMMAIntType> d_n_of_order_o;
-
765
-
766 // If here, add elements of previous elements to output dictionary
-
767 for (auto id_M_one : d_n_of_order_o_m_one) {
-
768 d_n_of_seed[id_M_one.first] = id_M_one.second;
-
769 }
-
770
-
771 for (const auto &i_k_v : d_n_of_order_o_m_one) {
-
772 // For all the cells in the previous neighbourhood order...
-
773
-
774 CoMMAIndexType seed_tmp = i_k_v.first;
-
775
-
776 for (auto i_fc_n = this->neighbours_cbegin(seed_tmp);
-
777 i_fc_n != this->neighbours_cend(seed_tmp); ++i_fc_n) {
-
778 // For all the neighbours of current seed...
-
779
-
780 if (
-
781 (d_n_of_seed.count(*i_fc_n) == 0)
-
782 && ((!is_fc_agglomerated_tmp[*i_fc_n]))) {
-
783 // If not yet in the final dictionary and not yet agglomerated...
-
784
-
785 if (d_n_of_order_o.count(*i_fc_n) == 0) {
-
786 // If not yet in the current neighbourhood order...
-
787 // a fc can be access via multiple ways. We look for the quickest
-
788 if (d_n_of_order_o_m_one.count(*i_fc_n)) {
-
789 // If it was already in the previous neighbourhood order
-
790
-
791 if (i_order < d_n_of_order_o_m_one[*i_fc_n]) {
-
792 // If current order smaller than the previous one
-
793 // ...update the order
-
794 d_n_of_order_o[*i_fc_n] = i_order;
-
795 }
-
796 } else {
-
797 // ...add the neighbour
-
798 d_n_of_order_o[*i_fc_n] = i_order;
-
799 }
-
800 }
-
801 }
-
802 }
-
803 }
-
804
-
805 // Exit condition (while)
-
806 if (d_n_of_order_o.empty()) {
-
807 // No more neighbours available:
-
808 break;
+
708 max_weights[i_fc] = max_weight;
+
709 // Compute the aspect-ratio and add cell to list if necessary
+
710 const auto ar = _compute_AR(min_weight, max_weight);
+
711 // Anisotropy criteria for the line Admissibility
+
712 if (ar >= threshold_anisotropy) {
+
713 switch (preserving) {
+
714 case 2:
+
715 if ((is_on_boundary(i_fc) > 0 && nb_neighbours == 3)
+
716 || nb_neighbours == 4)
+
717 aniso_w_weights.emplace(i_fc, priority_weights[i_fc]);
+
718 break;
+
719 case 3:
+
720 if ((is_on_boundary(i_fc) > 0 && nb_neighbours == 5)
+
721 || nb_neighbours == 6)
+
722 aniso_w_weights.emplace(i_fc, priority_weights[i_fc]);
+
723 case 0:
+
724 default:
+
725 // If the ratio is more than the given threshold of the biggest
+
726 // with the smallest cell, add it
+
727 aniso_w_weights.emplace(i_fc, priority_weights[i_fc]);
+
728 break;
+
729 } // End switch
+
730 } // End if ar
+
731 } // End for compliant cells
+
732 } // End if threshold
+
733
+
734 // Build result
+
735 for (const auto &[i_fc, w] : aniso_w_weights) {
+
736 is_anisotropic[i_fc] = true;
+
737 aniso_seeds_pool.emplace_back(i_fc);
+
738 }
+
739 }
+
740
+
744 inline CoMMAIntType get_nb_cells() const { return this->_number_of_cells; }
+
745
+
754 inline std::unordered_set<CoMMAIndexType> get_neighbourhood_of_cc(
+
755 const std::unordered_set<CoMMAIndexType> &s_seeds,
+
756 const std::vector<bool> &is_fc_agglomerated_tmp
+
757 ) const {
+
758 std::unordered_set<CoMMAIndexType> cc_neighs{};
+
759 for (const auto fc : s_seeds)
+
760 for (auto n = this->neighbours_cbegin(fc); n != this->neighbours_cend(fc);
+
761 ++n)
+
762 if (!is_fc_agglomerated_tmp[*n] && s_seeds.find(*n) == s_seeds.end())
+
763 // If not agglomerated and not part of the coarse cell
+
764 cc_neighs.insert(*n);
+
765 return cc_neighs;
+
766 }
+
767
+
782 void compute_neighbourhood_of_cc(
+
783 const std::unordered_set<CoMMAIndexType> &s_seeds,
+
784 CoMMAIntType &nb_of_order_of_neighbourhood,
+
785 std::unordered_map<CoMMAIndexType, CoMMAIntType> &d_n_of_seed,
+
786 const CoMMAIntType max_card,
+
787 const std::vector<bool> &is_fc_agglomerated_tmp
+
788 ) const {
+
789 // Basic checks
+
790 assert(max_card > 1);
+
791 // dict of FC with the order of neighbouring from seed
+
792 std::unordered_map<CoMMAIndexType, CoMMAIntType> d_n_of_order_o_m_one;
+
793 // we initialize for seeds where order is 0
+
794 for (const CoMMAIndexType &i_fc : s_seeds) {
+
795 d_n_of_order_o_m_one[i_fc] = 0;
+
796 }
+
797
+
798 CoMMAIntType i_order = 1;
+
799
+
800 while ((i_order < nb_of_order_of_neighbourhood + 1)
+
801 || static_cast<CoMMAIntType>(
+
802 d_n_of_seed.size() + d_n_of_order_o_m_one.size()
+
803 ) < max_card) {
+
804 std::unordered_map<CoMMAIndexType, CoMMAIntType> d_n_of_order_o;
+
805
+
806 // If here, add elements of previous elements to output dictionary
+
807 for (auto id_M_one : d_n_of_order_o_m_one) {
+
808 d_n_of_seed[id_M_one.first] = id_M_one.second;
809 }
810
-
811 // Update previous order
-
812 d_n_of_order_o_m_one.clear();
-
813 for (auto id : d_n_of_order_o) {
-
814 d_n_of_order_o_m_one[id.first] = id.second;
-
815 }
-
816 i_order++;
-
817 } // End of while
-
818 // Update of d_n_of_seed
-
819 // d_n_of_seed.update(d_n_of_order_o_m_one)
-
820 for (auto id_M_one : d_n_of_order_o_m_one) {
-
821 d_n_of_seed[id_M_one.first] = id_M_one.second;
-
822 }
-
823
-
824 // We remove the seed from the neighbours of seed
-
825 for (const CoMMAIndexType &i_fc : s_seeds) {
-
826 d_n_of_seed.erase(i_fc);
-
827 }
-
828
-
829 nb_of_order_of_neighbourhood = i_order;
-
830 }
-
831};
-
832
-
833} // end namespace comma
-
834
-
835#endif // COMMA_PROJECT_DUAL_GRAPH_H
+
811 for (const auto &i_k_v : d_n_of_order_o_m_one) {
+
812 // For all the cells in the previous neighbourhood order...
+
813
+
814 CoMMAIndexType seed_tmp = i_k_v.first;
+
815
+
816 for (auto i_fc_n = this->neighbours_cbegin(seed_tmp);
+
817 i_fc_n != this->neighbours_cend(seed_tmp);
+
818 ++i_fc_n) {
+
819 // For all the neighbours of current seed...
+
820
+
821 if ((d_n_of_seed.count(*i_fc_n) == 0)
+
822 && ((!is_fc_agglomerated_tmp[*i_fc_n]))) {
+
823 // If not yet in the final dictionary and not yet agglomerated...
+
824
+
825 if (d_n_of_order_o.count(*i_fc_n) == 0) {
+
826 // If not yet in the current neighbourhood order...
+
827 // a fc can be access via multiple ways. We look for the quickest
+
828 if (d_n_of_order_o_m_one.count(*i_fc_n)) {
+
829 // If it was already in the previous neighbourhood order
+
830
+
831 if (i_order < d_n_of_order_o_m_one[*i_fc_n]) {
+
832 // If current order smaller than the previous one
+
833 // ...update the order
+
834 d_n_of_order_o[*i_fc_n] = i_order;
+
835 }
+
836 } else {
+
837 // ...add the neighbour
+
838 d_n_of_order_o[*i_fc_n] = i_order;
+
839 }
+
840 }
+
841 }
+
842 }
+
843 }
+
844
+
845 // Exit condition (while)
+
846 if (d_n_of_order_o.empty()) {
+
847 // No more neighbours available:
+
848 break;
+
849 }
+
850
+
851 // Update previous order
+
852 d_n_of_order_o_m_one.clear();
+
853 for (auto id : d_n_of_order_o) {
+
854 d_n_of_order_o_m_one[id.first] = id.second;
+
855 }
+
856 i_order++;
+
857 } // End of while
+
858 // Update of d_n_of_seed
+
859 // d_n_of_seed.update(d_n_of_order_o_m_one)
+
860 for (auto id_M_one : d_n_of_order_o_m_one) {
+
861 d_n_of_seed[id_M_one.first] = id_M_one.second;
+
862 }
+
863
+
864 // We remove the seed from the neighbours of seed
+
865 for (const CoMMAIndexType &i_fc : s_seeds) {
+
866 d_n_of_seed.erase(i_fc);
+
867 }
+
868
+
869 nb_of_order_of_neighbourhood = i_order;
+
870 }
+
871};
+
872
+
873} // end namespace comma
+
874
+
875#endif // COMMA_PROJECT_DUAL_GRAPH_H
Seeds_Pool.h
-
comma::Dual_Graph
A class implementing the CRS global graph representation of the global mesh.
Definition: Dual_Graph.h:517
-
comma::Dual_Graph::get_n_boundary_faces
CoMMAIntType get_n_boundary_faces(const CoMMAIndexType idx_c) const
Return how many boundary faces a certain cell has.
Definition: Dual_Graph.h:598
-
comma::Dual_Graph::get_nb_cells
CoMMAIntType get_nb_cells() const
Getter that returns the number of cells.
Definition: Dual_Graph.h:706
-
comma::Dual_Graph::compute_neighbourhood_of_cc
void compute_neighbourhood_of_cc(const std::unordered_set< CoMMAIndexType > &s_seeds, CoMMAIntType &nb_of_order_of_neighbourhood, std::unordered_map< CoMMAIndexType, CoMMAIntType > &d_n_of_seed, const CoMMAIntType max_card, const std::vector< bool > &is_fc_agglomerated_tmp) const
Compute the dictionary of compactness of fine cells inside a coarse cell.
Definition: Dual_Graph.h:743
-
comma::Dual_Graph::is_on_boundary
bool is_on_boundary(const CoMMAIndexType idx_c) const
Whether a cell is on the boundary.
Definition: Dual_Graph.h:605
-
comma::Dual_Graph::_centers
const std::vector< std::vector< CoMMAWeightType > > & _centers
Vector of cell centers.
Definition: Dual_Graph.h:584
-
comma::Dual_Graph::Dual_Graph
Dual_Graph(const CoMMAIndexType &nb_c, const ContainerIndexType &m_crs_row_ptr, const ContainerIndexType &m_crs_col_ind, const ContainerWeightType &m_crs_values, const ContainerWeightType &volumes, const std::vector< std::vector< CoMMAWeightType > > &centers, const std::vector< CoMMAIntType > &n_bnd_faces, const CoMMAIntType dimension, const ContainerIndexType &anisotropic_compliant_fc)
Constructor of the class.
Definition: Dual_Graph.h:546
-
comma::Dual_Graph::get_neighbourhood_of_cc
std::unordered_set< CoMMAIndexType > get_neighbourhood_of_cc(const std::unordered_set< CoMMAIndexType > &s_seeds, const std::vector< bool > &is_fc_agglomerated_tmp) const
Get the fine cells neighbours of a coarse cell.
Definition: Dual_Graph.h:716
-
comma::Dual_Graph::CoMMAPairType
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Dual_Graph.h:526
-
comma::Dual_Graph::_n_bnd_faces
const std::vector< CoMMAIntType > & _n_bnd_faces
Vector telling how many boundary faces each cell has.
Definition: Dual_Graph.h:574
+
comma::Dual_Graph
A class implementing the CRS global graph representation of the global mesh.
Definition: Dual_Graph.h:546
+
comma::Dual_Graph::get_n_boundary_faces
CoMMAIntType get_n_boundary_faces(const CoMMAIndexType idx_c) const
Return how many boundary faces a certain cell has.
Definition: Dual_Graph.h:632
+
comma::Dual_Graph::get_nb_cells
CoMMAIntType get_nb_cells() const
Getter that returns the number of cells.
Definition: Dual_Graph.h:744
+
comma::Dual_Graph::compute_neighbourhood_of_cc
void compute_neighbourhood_of_cc(const std::unordered_set< CoMMAIndexType > &s_seeds, CoMMAIntType &nb_of_order_of_neighbourhood, std::unordered_map< CoMMAIndexType, CoMMAIntType > &d_n_of_seed, const CoMMAIntType max_card, const std::vector< bool > &is_fc_agglomerated_tmp) const
Compute the dictionary of compactness of fine cells inside a coarse cell.
Definition: Dual_Graph.h:782
+
comma::Dual_Graph::is_on_boundary
bool is_on_boundary(const CoMMAIndexType idx_c) const
Whether a cell is on the boundary.
Definition: Dual_Graph.h:640
+
comma::Dual_Graph::_centers
const std::vector< std::vector< CoMMAWeightType > > & _centers
Vector of cell centers.
Definition: Dual_Graph.h:618
+
comma::Dual_Graph::Dual_Graph
Dual_Graph(const CoMMAIndexType &nb_c, const ContainerIndexType &m_crs_row_ptr, const ContainerIndexType &m_crs_col_ind, const ContainerWeightType &m_crs_values, const ContainerWeightType &volumes, const std::vector< std::vector< CoMMAWeightType > > &centers, const std::vector< CoMMAIntType > &n_bnd_faces, const CoMMAIntType dimension, const ContainerIndexType &anisotropic_compliant_fc)
Constructor of the class.
Definition: Dual_Graph.h:575
+
comma::Dual_Graph::get_neighbourhood_of_cc
std::unordered_set< CoMMAIndexType > get_neighbourhood_of_cc(const std::unordered_set< CoMMAIndexType > &s_seeds, const std::vector< bool > &is_fc_agglomerated_tmp) const
Get the fine cells neighbours of a coarse cell.
Definition: Dual_Graph.h:754
+
comma::Dual_Graph::CoMMAPairType
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Dual_Graph.h:555
+
comma::Dual_Graph::_n_bnd_faces
const std::vector< CoMMAIntType > & _n_bnd_faces
Vector telling how many boundary faces each cell has.
Definition: Dual_Graph.h:608
comma::Dual_Graph::ContainerWeightType
std::vector< CoMMAWeightType > ContainerWeightType
Type for containers of weights.
Definition: Dual_Graph.h:49
comma::Dual_Graph::ContainerIndexType
std::vector< CoMMAIndexType > ContainerIndexType
Type for containers of indices.
Definition: Dual_Graph.h:47
-
comma::Dual_Graph::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Dual_Graph.h:529
+
comma::Dual_Graph::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Dual_Graph.h:558
comma::Dual_Graph::~Dual_Graph
~Dual_Graph() override=default
Destructor of the class.
-
comma::Dual_Graph::_compute_AR
std::function< CoMMAWeightType(const CoMMAWeightType, const CoMMAWeightType)> _compute_AR
Function which computes the aspect-ratio from the minimum and maximum faces In 3D: In 2D: (Recal...
Definition: Dual_Graph.h:592
-
comma::Dual_Graph::tag_anisotropic_cells
void tag_anisotropic_cells(ContainerWeightType &max_weights, std::vector< bool > &is_anisotropic, std::deque< CoMMAIndexType > &aniso_seeds_pool, const CoMMAWeightType threshold_anisotropy, const ContainerWeightType &priority_weights, const CoMMAIndexType preserving)
Tag cells as anisotropic if their aspect-ratio is over a given threshold and order them according to ...
Definition: Dual_Graph.h:626
-
comma::Dual_Graph::_s_anisotropic_compliant_cells
const std::unordered_set< CoMMAIndexType > _s_anisotropic_compliant_cells
Elements that are checked if they are anisotropic. If an element satisfies the condition for being an...
Definition: Dual_Graph.h:581
+
comma::Dual_Graph::_compute_AR
std::function< CoMMAWeightType(const CoMMAWeightType, const CoMMAWeightType)> _compute_AR
Function which computes the aspect-ratio from the minimum and maximum faces In 3D: In 2D: (Recal...
Definition: Dual_Graph.h:626
+
comma::Dual_Graph::tag_anisotropic_cells
void tag_anisotropic_cells(ContainerWeightType &max_weights, std::vector< bool > &is_anisotropic, std::deque< CoMMAIndexType > &aniso_seeds_pool, const CoMMAWeightType threshold_anisotropy, const ContainerWeightType &priority_weights, const CoMMAIndexType preserving)
Tag cells as anisotropic if their aspect-ratio is over a given threshold and order them according to ...
Definition: Dual_Graph.h:661
+
comma::Dual_Graph::_s_anisotropic_compliant_cells
const std::unordered_set< CoMMAIndexType > _s_anisotropic_compliant_cells
Elements that are checked if they are anisotropic. If an element satisfies the condition for being an...
Definition: Dual_Graph.h:615
comma::Graph
An interface class responsible of storing the cell centered dual graph and of acting on it (it is an ...
Definition: Dual_Graph.h:44
-
comma::Graph::weights_cbegin
ContainerWeightConstIt weights_cbegin(const CoMMAIndexType &i_c) const
Get constant pointer to the first neighbour of cell i_c.
Definition: Dual_Graph.h:213
-
comma::Graph::_m_CRS_Values
ContainerWeightType _m_CRS_Values
Vector of area weight of CRS representation.
Definition: Dual_Graph.h:96
-
comma::Graph::DFS
void DFS(const CoMMAIndexType &i_fc)
Depth First Search (DFS) recursive function.
Definition: Dual_Graph.h:104
+
comma::Graph::weights_cbegin
ContainerWeightConstIt weights_cbegin(const CoMMAIndexType &i_c) const
Get constant pointer to the first neighbour of cell i_c.
Definition: Dual_Graph.h:219
+
comma::Graph::_m_CRS_Values
ContainerWeightType _m_CRS_Values
Vector of area weight of CRS representation.
Definition: Dual_Graph.h:97
+
comma::Graph::DFS
void DFS(const CoMMAIndexType &i_fc)
Depth First Search (DFS) recursive function.
Definition: Dual_Graph.h:105
comma::Graph::Graph
Graph(const CoMMAIndexType &nb_c, const ContainerIndexType &m_crs_row_ptr, const ContainerIndexType &m_crs_col_ind, const ContainerWeightType &m_crs_values, const ContainerWeightType &volumes)
Constructor of the class.
Definition: Dual_Graph.h:64
-
comma::Graph::get_neighbours
ContainerIndexType get_neighbours(const CoMMAIndexType &i_c) const
Based on the CRS representation retrieves the neighbours of the cell given as an input.
Definition: Dual_Graph.h:160
+
comma::Graph::get_neighbours
ContainerIndexType get_neighbours(const CoMMAIndexType &i_c) const
Based on the CRS representation retrieves the neighbours of the cell given as an input.
Definition: Dual_Graph.h:164
comma::Graph::ContainerWeightConstIt
typename ContainerWeightType::const_iterator ContainerWeightConstIt
Type for constant iterators of containers of weights.
Definition: Dual_Graph.h:53
-
comma::Graph::neighbours_cend
ContainerIndexConstIt neighbours_cend(const CoMMAIndexType &i_c) const
Get constant pointer to the element following the last neighbour of cell i_c.
Definition: Dual_Graph.h:186
-
comma::Graph::compute_min_fc_compactness_inside_a_cc
CoMMAIntType compute_min_fc_compactness_inside_a_cc(const std::unordered_set< CoMMAIndexType > &s_fc) const
Compute the minimum compactness of fine cells inside a coarse cell.
Definition: Dual_Graph.h:246
-
comma::Graph::get_nb_of_neighbours
CoMMAIntType get_nb_of_neighbours(CoMMAIndexType i_c) const
Retrieve the number of neighbours.
Definition: Dual_Graph.h:150
-
comma::Graph::compute_fc_compactness_inside_a_cc
std::unordered_map< CoMMAIndexType, CoMMAIntType > compute_fc_compactness_inside_a_cc(const std::unordered_set< CoMMAIndexType > &s_fc) const
Compute the dictionary of compactness of fine cells inside a coarse cell.
Definition: Dual_Graph.h:271
+
comma::Graph::neighbours_cend
ContainerIndexConstIt neighbours_cend(const CoMMAIndexType &i_c) const
Get constant pointer to the element following the last neighbour of cell i_c.
Definition: Dual_Graph.h:191
+
comma::Graph::compute_min_fc_compactness_inside_a_cc
CoMMAIntType compute_min_fc_compactness_inside_a_cc(const std::unordered_set< CoMMAIndexType > &s_fc) const
Compute the minimum compactness of fine cells inside a coarse cell.
Definition: Dual_Graph.h:256
+
comma::Graph::get_nb_of_neighbours
CoMMAIntType get_nb_of_neighbours(CoMMAIndexType i_c) const
Retrieve the number of neighbours.
Definition: Dual_Graph.h:154
+
comma::Graph::compute_fc_compactness_inside_a_cc
std::unordered_map< CoMMAIndexType, CoMMAIntType > compute_fc_compactness_inside_a_cc(const std::unordered_set< CoMMAIndexType > &s_fc) const
Compute the dictionary of compactness of fine cells inside a coarse cell.
Definition: Dual_Graph.h:285
comma::Graph::ContainerIndexConstIt
typename ContainerIndexType::const_iterator ContainerIndexConstIt
Type for constant iterators of containers of indices.
Definition: Dual_Graph.h:51
-
comma::Graph::_m_CRS_Row_Ptr
ContainerIndexType _m_CRS_Row_Ptr
Vector of row pointer of CRS representation.
Definition: Dual_Graph.h:90
-
comma::Graph::check_connectivity
bool check_connectivity()
Check the connectivity of the graph.
Definition: Dual_Graph.h:230
-
comma::Graph::weights_cend
ContainerWeightConstIt weights_cend(const CoMMAIndexType &i_c) const
Get constant pointer to the element following the last neighbour of cell i_c.
Definition: Dual_Graph.h:223
-
comma::Graph::_m_CRS_Col_Ind
ContainerIndexType _m_CRS_Col_Ind
Vector of column index of CRS representation.
Definition: Dual_Graph.h:93
+
comma::Graph::_m_CRS_Row_Ptr
ContainerIndexType _m_CRS_Row_Ptr
Vector of row pointer of CRS representation.
Definition: Dual_Graph.h:91
+
comma::Graph::check_connectivity
bool check_connectivity()
Check the connectivity of the graph.
Definition: Dual_Graph.h:236
+
comma::Graph::weights_cend
ContainerWeightConstIt weights_cend(const CoMMAIndexType &i_c) const
Get constant pointer to the element following the last neighbour of cell i_c.
Definition: Dual_Graph.h:229
+
comma::Graph::_m_CRS_Col_Ind
ContainerIndexType _m_CRS_Col_Ind
Vector of column index of CRS representation.
Definition: Dual_Graph.h:94
comma::Graph::ContainerWeightType
std::vector< CoMMAWeightType > ContainerWeightType
Type for containers of weights.
Definition: Dual_Graph.h:49
comma::Graph::ContainerIndexType
std::vector< CoMMAIndexType > ContainerIndexType
Type for containers of indices.
Definition: Dual_Graph.h:47
-
comma::Graph::_number_of_cells
CoMMAIndexType _number_of_cells
Number of nodes in the Graph (it corresponds to the number of cells in the subgraph or the dual graph...
Definition: Dual_Graph.h:84
+
comma::Graph::_number_of_cells
CoMMAIndexType _number_of_cells
Number of nodes in the Graph (it corresponds to the number of cells in the subgraph or the dual graph...
Definition: Dual_Graph.h:85
comma::Graph::~Graph
virtual ~Graph()=default
Destructor of the class.
-
comma::Graph::_volumes
ContainerWeightType _volumes
Vector of volumes.
Definition: Dual_Graph.h:99
-
comma::Graph::neighbours_cbegin
ContainerIndexConstIt neighbours_cbegin(const CoMMAIndexType &i_c) const
Get constant pointer to the first neighbour of cell i_c.
Definition: Dual_Graph.h:176
-
comma::Graph::get_weights
ContainerWeightType get_weights(const CoMMAIndexType &i_c) const
Based on the area of the faces composing the cell given as an input, we retrieve the faces connecting...
Definition: Dual_Graph.h:197
-
comma::Graph::_visited
std::vector< bool > _visited
Helper vector for the DFS.
Definition: Dual_Graph.h:87
-
comma::Graph::BFS
void BFS(const CoMMAIndexType &root)
Breadth First Search (BFS) function.
Definition: Dual_Graph.h:114
-
comma::Subgraph
A class implementing the CRS subgraph representation. It is used in the framework of CoMMA for the im...
Definition: Dual_Graph.h:302
-
comma::Subgraph::_is_isotropic
bool _is_isotropic
Whether it originates from an isotropic cell.
Definition: Dual_Graph.h:349
-
comma::Subgraph::_compactness
CoMMAIntType _compactness
Compactness of the given subgraph. The compactness is the minimum number of internal neighbours.
Definition: Dual_Graph.h:359
+
comma::Graph::_volumes
ContainerWeightType _volumes
Vector of volumes.
Definition: Dual_Graph.h:100
+
comma::Graph::neighbours_cbegin
ContainerIndexConstIt neighbours_cbegin(const CoMMAIndexType &i_c) const
Get constant pointer to the first neighbour of cell i_c.
Definition: Dual_Graph.h:181
+
comma::Graph::get_weights
ContainerWeightType get_weights(const CoMMAIndexType &i_c) const
Based on the area of the faces composing the cell given as an input, we retrieve the faces connecting...
Definition: Dual_Graph.h:202
+
comma::Graph::_visited
std::vector< bool > _visited
Helper vector for the DFS.
Definition: Dual_Graph.h:88
+
comma::Graph::BFS
void BFS(const CoMMAIndexType &root)
Breadth First Search (BFS) function.
Definition: Dual_Graph.h:117
+
comma::Subgraph
A class implementing the CRS subgraph representation. It is used in the framework of CoMMA for the im...
Definition: Dual_Graph.h:318
+
comma::Subgraph::_is_isotropic
bool _is_isotropic
Whether it originates from an isotropic cell.
Definition: Dual_Graph.h:370
+
comma::Subgraph::_compactness
CoMMAIntType _compactness
Compactness of the given subgraph. The compactness is the minimum number of internal neighbours.
Definition: Dual_Graph.h:380
comma::Subgraph::~Subgraph
~Subgraph() override=default
Destructor of the class.
-
comma::Subgraph::insert_node
void insert_node(const ContainerIndexType &v_neigh, const CoMMAIndexType &i_fc, const CoMMAWeightType &volume, const ContainerWeightType &weight)
Insert a node in the subgraph and add it to the mapping the.
Definition: Dual_Graph.h:375
-
comma::Subgraph::_mapping_l_to_g
ContainerIndexType _mapping_l_to_g
Mapping from the local number of node to the global. Being a subgraph this variable connect the local...
Definition: Dual_Graph.h:365
-
comma::Subgraph::Subgraph
Subgraph(const CoMMAIndexType &nb_c, const ContainerIndexType &m_crs_row_ptr, const ContainerIndexType &m_crs_col_ind, const ContainerWeightType &m_crs_values, const ContainerWeightType &volumes, const ContainerIndexType &mapping_l_to_g, const bool &is_isotropic)
Constructor of the class.
Definition: Dual_Graph.h:323
-
comma::Subgraph::_cardinality
CoMMAIntType _cardinality
Cardinality of the given subgraph, alias the number of nodes contained.
Definition: Dual_Graph.h:354
+
comma::Subgraph::insert_node
void insert_node(const ContainerIndexType &v_neigh, const CoMMAIndexType &i_fc, const CoMMAWeightType &volume, const ContainerWeightType &weight)
Insert a node in the subgraph and add it to the mapping the.
Definition: Dual_Graph.h:396
+
comma::Subgraph::_mapping_l_to_g
ContainerIndexType _mapping_l_to_g
Mapping from the local number of node to the global. Being a subgraph this variable connect the local...
Definition: Dual_Graph.h:386
+
comma::Subgraph::Subgraph
Subgraph(const CoMMAIndexType &nb_c, const ContainerIndexType &m_crs_row_ptr, const ContainerIndexType &m_crs_col_ind, const ContainerWeightType &m_crs_values, const ContainerWeightType &volumes, const ContainerIndexType &mapping_l_to_g, const bool &is_isotropic)
Constructor of the class.
Definition: Dual_Graph.h:340
+
comma::Subgraph::_cardinality
CoMMAIntType _cardinality
Cardinality of the given subgraph, alias the number of nodes contained.
Definition: Dual_Graph.h:375
comma::Subgraph::ContainerWeightType
std::vector< CoMMAWeightType > ContainerWeightType
Type for containers of weights.
Definition: Dual_Graph.h:49
-
comma::Subgraph::remove_node
void remove_node(const CoMMAIndexType &elemento)
Remove a node from the CRS representation and automatically adjust the mapping.
Definition: Dual_Graph.h:432
+
comma::Subgraph::remove_node
void remove_node(const CoMMAIndexType &elemento)
Remove a node from the CRS representation and automatically adjust the mapping.
Definition: Dual_Graph.h:458
comma::Subgraph::ContainerIndexType
std::vector< CoMMAIndexType > ContainerIndexType
Type for containers of indices.
Definition: Dual_Graph.h:47
comma
Definition: Agglomerator.h:34
diff --git a/_neighbourhood_8h_source.html b/_neighbourhood_8h_source.html index 2ff01f0..3cdfca4 100644 --- a/_neighbourhood_8h_source.html +++ b/_neighbourhood_8h_source.html @@ -149,352 +149,376 @@
66
73 Neighbourhood(
74 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
-
75 const std::vector<CoMMAWeightType> &weights) :
-
76 _s_neighbours_of_seed(std::move(s_neighbours_of_seed)),
-
77 _weights(weights),
-
78 _s_fc(),
-
79 _candidates() {}
-
80
-
82 Neighbourhood(
-
83 const Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> &other) =
-
84 default;
-
85
-
87 virtual ~Neighbourhood() = default;
-
88
-
96 virtual void update(
-
97 const CoMMAIndexType new_fc,
-
98 const std::vector<CoMMAIndexType> &new_neighbours) = 0;
-
99
-
104 inline const CandidatesContainerType &get_candidates() const {
-
105 return this->_candidates;
-
106 }
-
107
-
108protected:
-
113 const std::unordered_set<CoMMAIndexType> _s_neighbours_of_seed;
-
114
-
116 const std::vector<CoMMAWeightType> &_weights;
-
117
-
119 std::unordered_set<CoMMAIndexType> _s_fc;
-
120
-
124 CandidatesContainerType _candidates;
-
125
-
129 inline void extract_and_update_candidates(
-
130 const CoMMASetOfPairType &candidates_w_weights) {
-
131 for (const auto &[idx, w] : candidates_w_weights)
-
132 this->_candidates.push_back(idx);
-
133 }
-
134};
-
135
-
144template<
-
145 typename CoMMAIndexType,
-
146 typename CoMMAWeightType,
-
147 typename CoMMAIntType>
-
148class Neighbourhood_Extended :
-
149 public Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
150public:
-
152 using NeighbourhoodBaseType =
-
153 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
155 using typename NeighbourhoodBaseType::CoMMAPairType;
-
157 using typename NeighbourhoodBaseType::CoMMASetOfPairType;
-
160 using typename NeighbourhoodBaseType::CoMMAPairFindFirstBasedType;
-
161
-
168 Neighbourhood_Extended(
-
169 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
-
170 const std::vector<CoMMAWeightType> &weights) :
-
171 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
172 s_neighbours_of_seed, weights) {}
-
173
-
175 Neighbourhood_Extended(
-
176 const Neighbourhood_Extended<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>
-
177 &other) = default;
+
75 const std::vector<CoMMAWeightType> &weights
+
76 ) :
+
77 _s_neighbours_of_seed(std::move(s_neighbours_of_seed)),
+
78 _weights(weights),
+
79 _s_fc(),
+
80 _candidates() {}
+
81
+
83 Neighbourhood(
+
84 const Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> &other
+
85 ) = default;
+
86
+
88 virtual ~Neighbourhood() = default;
+
89
+
97 virtual void update(
+
98 const CoMMAIndexType new_fc,
+
99 const std::vector<CoMMAIndexType> &new_neighbours
+
100 ) = 0;
+
101
+
106 inline const CandidatesContainerType &get_candidates() const {
+
107 return this->_candidates;
+
108 }
+
109
+
110protected:
+
115 const std::unordered_set<CoMMAIndexType> _s_neighbours_of_seed;
+
116
+
118 const std::vector<CoMMAWeightType> &_weights;
+
119
+
121 std::unordered_set<CoMMAIndexType> _s_fc;
+
122
+
126 CandidatesContainerType _candidates;
+
127
+
131 inline void extract_and_update_candidates(
+
132 const CoMMASetOfPairType &candidates_w_weights
+
133 ) {
+
134 for (const auto &[idx, w] : candidates_w_weights)
+
135 this->_candidates.push_back(idx);
+
136 }
+
137};
+
138
+
147template<
+
148 typename CoMMAIndexType,
+
149 typename CoMMAWeightType,
+
150 typename CoMMAIntType>
+
151class Neighbourhood_Extended :
+
152 public Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
153public:
+
155 using NeighbourhoodBaseType =
+
156 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
158 using typename NeighbourhoodBaseType::CoMMAPairType;
+
160 using typename NeighbourhoodBaseType::CoMMASetOfPairType;
+
163 using typename NeighbourhoodBaseType::CoMMAPairFindFirstBasedType;
+
164
+
171 Neighbourhood_Extended(
+
172 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
+
173 const std::vector<CoMMAWeightType> &weights
+
174 ) :
+
175 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
176 s_neighbours_of_seed, weights
+
177 ) {}
178
-
180 ~Neighbourhood_Extended() override = default;
-
181
-
189 void update(
-
190 const CoMMAIndexType new_fc,
-
191 const std::vector<CoMMAIndexType> &new_neighbours) override {
-
192 // Add new_fc to current CC and remove it from previous neighbourhoods
-
193 this->_s_fc.insert(new_fc);
-
194 auto new_fc_ptr =
-
195 std::find(this->_candidates.begin(), this->_candidates.end(), new_fc);
-
196 if (new_fc_ptr != this->_candidates.end())
-
197 this->_candidates.erase(new_fc_ptr);
-
198
-
199 // Compute the set of direct neighbours allowed by original
-
200 // neighbourhood-order
-
201 CoMMASetOfPairType neighs;
-
202 for (const CoMMAIndexType &i_fc : new_neighbours) {
-
203 if (
-
204 (std::find(this->_candidates.begin(), this->_candidates.end(), i_fc)
-
205 == this->_candidates.end())
-
206 && (this->_s_fc.count(i_fc) == 0)
-
207 && (this->_s_neighbours_of_seed.count(i_fc) > 0)) {
-
208 // If not yet in the FON, not yet in the coarse cell and among the
-
209 // allowed neighbours, insert
-
210 neighs.emplace(i_fc, this->_weights[i_fc]);
-
211 }
-
212 }
-
213 // Just add new candidates at the back. This will leave candidates closer to
-
214 // the original seed at the top, hence giving them a slightly higher
-
215 // priority
-
216 this->extract_and_update_candidates(neighs);
-
217 }
-
218};
-
219
-
229template<
-
230 typename CoMMAIndexType,
-
231 typename CoMMAWeightType,
-
232 typename CoMMAIntType>
-
233class Neighbourhood_Pure_Front :
-
234 public Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
235public:
-
237 using NeighbourhoodBaseType =
-
238 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
240 using typename NeighbourhoodBaseType::CoMMAPairType;
-
242 using typename NeighbourhoodBaseType::CoMMASetOfPairType;
-
245 using typename NeighbourhoodBaseType::CoMMAPairFindFirstBasedType;
-
246
-
254 Neighbourhood_Pure_Front(
-
255 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
-
256 const std::vector<CoMMAWeightType> &weights,
-
257 CoMMAIntType dimension) :
-
258 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
259 s_neighbours_of_seed, weights),
-
260 _q_neighs_w_weights(),
-
261 _dimension(dimension) {}
-
262
-
264 Neighbourhood_Pure_Front(const Neighbourhood_Pure_Front<
-
265 CoMMAIndexType,
-
266 CoMMAWeightType,
-
267 CoMMAIntType> &other) = default;
-
268
-
270 ~Neighbourhood_Pure_Front() override = default;
-
271
-
279 void update(
-
280 const CoMMAIndexType new_fc,
-
281 const std::vector<CoMMAIndexType> &new_neighbours) override {
-
282 this->_candidates.clear();
-
283 // Add new_fc to current CC and remove it from previous neighbourhoods
-
284 this->_s_fc.insert(new_fc);
-
285 for (auto &queue : this->_q_neighs_w_weights) {
-
286 // There is erase_if for sets in C++20
-
287 // erase_if(queue, [&new_fc](const CoMMAPairType &p){return p.first ==
-
288 // new_fc;});
-
289 auto it = std::find_if(
-
290 queue.begin(), queue.end(), CoMMAPairFindFirstBasedType(new_fc));
-
291 //[&new_fc](const CoMMAPairType &p){return p.first == new_fc;});
-
292 if (it != queue.end()) queue.erase(it);
-
293 }
-
294
-
295 // Compute the set of direct neighbours allowed by original
-
296 // neighbourhood-order
-
297 CoMMASetOfPairType curr_set = CoMMASetOfPairType();
-
298 for (const CoMMAIndexType &i_fc : new_neighbours) {
-
299 if (
-
300 (this->_s_fc.count(i_fc) == 0)
-
301 && (this->_s_neighbours_of_seed.count(i_fc) > 0)) {
-
302 // If not yet in coarse cell and among the allowed neighbours, insert
-
303 curr_set.emplace(i_fc, this->_weights[i_fc]);
-
304 }
-
305 }
-
306
-
307 this->_q_neighs_w_weights.push_front(curr_set);
-
308
-
309 // Now, see which neighbours to return. Here is the strategy:
-
310 // If most recent list is not empty, return it. If not, check the oldest
-
311 // list: if not empty return it, otherwise check the previous list. If
-
312 // empty, check the second oldest, and so on... We grant ourselves one
-
313 // exception...
-
314 if (
-
315 this->_q_neighs_w_weights.size()
-
316 <= static_cast<decltype(this->_q_neighs_w_weights.size())>(
-
317 this->_dimension)) {
-
318 // If at the (very) beginning of the agglomeration, still consider every
-
319 // possible neighbour. This will allow to obtain nice quads from quads
-
320 // TODO[RM]: I think this workaround is needed because we are not able to
-
321 // compute exactly the AR; if we ever we will be able we should try to
-
322 // remove it
-
323 for (auto prev_q = this->_q_neighs_w_weights.begin() + 1;
-
324 prev_q != this->_q_neighs_w_weights.end(); ++prev_q)
-
325 curr_set.insert(prev_q->begin(), prev_q->end());
-
326 this->extract_and_update_candidates(curr_set);
-
327 } else {
-
328 auto cur_front = decltype(this->_q_neighs_w_weights.size()){0};
-
329 auto cur_back = decltype(this->_q_neighs_w_weights.size()){
-
330 this->_q_neighs_w_weights.size() - 1};
-
331 while (cur_front <= cur_back) {
-
332 // typename decltype(this->_q_neighs_w_weights)::iterator it =
-
333 auto it = this->_q_neighs_w_weights.begin() + (cur_front++);
-
334 if (!it->empty()) {
-
335 this->extract_and_update_candidates(*it);
-
336 break;
-
337 }
-
338 it = this->_q_neighs_w_weights.begin() + (cur_back--);
-
339 if (!it->empty()) {
-
340 this->extract_and_update_candidates(*it);
-
341 break;
-
342 }
-
343 }
-
344 }
-
345 }
-
346
-
352 inline const CoMMASetOfPairType &get_neighbours_by_level(
-
353 const CoMMAIntType lvl) const {
-
354 assert(
-
355 lvl >= 0
-
356 && lvl < static_cast<CoMMAIntType>(this->_q_neighs_w_weights.size()));
-
357 return this->_q_neighs_w_weights[lvl];
-
358 }
-
359
-
360protected:
-
363 std::deque<CoMMASetOfPairType> _q_neighs_w_weights;
-
364
-
367 CoMMAIntType _dimension;
-
368};
-
369
-
377template<
-
378 typename CoMMAIndexType,
-
379 typename CoMMAWeightType,
-
380 typename CoMMAIntType>
-
381class NeighbourhoodCreator {
-
382public:
-
384 using NeighbourhoodBaseType =
-
385 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
386
-
388 NeighbourhoodCreator() = default;
-
389
-
391 virtual ~NeighbourhoodCreator() = default;
-
392
-
402 virtual std::shared_ptr<NeighbourhoodBaseType> create(
-
403 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
-
404 const std::vector<CoMMAWeightType> &priority_weights,
-
405 const CoMMAIntType dimension) const = 0;
-
406
-
411 virtual std::shared_ptr<NeighbourhoodBaseType> clone(
-
412 std::shared_ptr<NeighbourhoodBaseType> other) const = 0;
-
413};
-
414
-
422template<
-
423 typename CoMMAIndexType,
-
424 typename CoMMAWeightType,
-
425 typename CoMMAIntType>
-
426class NeighbourhoodExtendedCreator :
-
427 public NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
428public:
-
430 using CreatorBaseType =
-
431 NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
433 using typename CreatorBaseType::NeighbourhoodBaseType;
-
437 using NeighbourhoodDerivedType =
-
438 Neighbourhood_Extended<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
439
-
441 NeighbourhoodExtendedCreator() : CreatorBaseType() {}
-
442
-
444 ~NeighbourhoodExtendedCreator() override = default;
-
445
-
456 inline std::shared_ptr<NeighbourhoodBaseType> create(
-
457 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
-
458 const std::vector<CoMMAWeightType> &priority_weights,
-
459 const CoMMAIntType dimension) const override {
-
460 CoMMAUnused(dimension);
-
461 return std::make_shared<NeighbourhoodDerivedType>(
-
462 s_neighbours_of_seed, priority_weights);
-
463 }
-
464
-
470 inline std::shared_ptr<NeighbourhoodBaseType> clone(
-
471 std::shared_ptr<NeighbourhoodBaseType> other) const override {
-
472 // Using copy-constructor
-
473 return std::make_shared<NeighbourhoodDerivedType>(
-
474 *std::dynamic_pointer_cast<NeighbourhoodDerivedType>(other));
-
475 }
-
476};
-
477
-
485template<
-
486 typename CoMMAIndexType,
-
487 typename CoMMAWeightType,
-
488 typename CoMMAIntType>
-
489class NeighbourhoodPureFrontCreator :
-
490 public NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
491public:
-
493 using CreatorBaseType =
-
494 NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
496 using typename CreatorBaseType::NeighbourhoodBaseType;
-
500 using NeighbourhoodDerivedType =
-
501 Neighbourhood_Pure_Front<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
502
-
504 NeighbourhoodPureFrontCreator() : CreatorBaseType() {}
-
505
-
507 ~NeighbourhoodPureFrontCreator() override = default;
-
508
-
519 inline std::shared_ptr<NeighbourhoodBaseType> create(
-
520 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
-
521 const std::vector<CoMMAWeightType> &priority_weights,
-
522 const CoMMAIntType dimension) const override {
-
523 return std::make_shared<NeighbourhoodDerivedType>(
-
524 s_neighbours_of_seed, priority_weights, dimension);
-
525 }
-
526
-
532 inline std::shared_ptr<NeighbourhoodBaseType> clone(
-
533 std::shared_ptr<NeighbourhoodBaseType> other) const override {
-
534 // Using copy-constructor
-
535 return std::make_shared<NeighbourhoodDerivedType>(
-
536 *std::dynamic_pointer_cast<NeighbourhoodDerivedType>(other));
-
537 }
-
538};
-
539
-
540} // end namespace comma
-
541
-
542#endif // COMMA_PROJECT_FIRST_ORDER_NEIGHBOURHOOD_H
+
180 Neighbourhood_Extended(
+
181 const Neighbourhood_Extended<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>
+
182 &other
+
183 ) = default;
+
184
+
186 ~Neighbourhood_Extended() override = default;
+
187
+
195 void update(
+
196 const CoMMAIndexType new_fc,
+
197 const std::vector<CoMMAIndexType> &new_neighbours
+
198 ) override {
+
199 // Add new_fc to current CC and remove it from previous neighbourhoods
+
200 this->_s_fc.insert(new_fc);
+
201 auto new_fc_ptr =
+
202 std::find(this->_candidates.begin(), this->_candidates.end(), new_fc);
+
203 if (new_fc_ptr != this->_candidates.end())
+
204 this->_candidates.erase(new_fc_ptr);
+
205
+
206 // Compute the set of direct neighbours allowed by original
+
207 // neighbourhood-order
+
208 CoMMASetOfPairType neighs;
+
209 for (const CoMMAIndexType &i_fc : new_neighbours) {
+
210 if ((std::find(this->_candidates.begin(), this->_candidates.end(), i_fc)
+
211 == this->_candidates.end())
+
212 && (this->_s_fc.count(i_fc) == 0)
+
213 && (this->_s_neighbours_of_seed.count(i_fc) > 0)) {
+
214 // If not yet in the FON, not yet in the coarse cell and among the
+
215 // allowed neighbours, insert
+
216 neighs.emplace(i_fc, this->_weights[i_fc]);
+
217 }
+
218 }
+
219 // Just add new candidates at the back. This will leave candidates closer to
+
220 // the original seed at the top, hence giving them a slightly higher
+
221 // priority
+
222 this->extract_and_update_candidates(neighs);
+
223 }
+
224};
+
225
+
235template<
+
236 typename CoMMAIndexType,
+
237 typename CoMMAWeightType,
+
238 typename CoMMAIntType>
+
239class Neighbourhood_Pure_Front :
+
240 public Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
241public:
+
243 using NeighbourhoodBaseType =
+
244 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
246 using typename NeighbourhoodBaseType::CoMMAPairType;
+
248 using typename NeighbourhoodBaseType::CoMMASetOfPairType;
+
251 using typename NeighbourhoodBaseType::CoMMAPairFindFirstBasedType;
+
252
+
260 Neighbourhood_Pure_Front(
+
261 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
+
262 const std::vector<CoMMAWeightType> &weights,
+
263 CoMMAIntType dimension
+
264 ) :
+
265 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
266 s_neighbours_of_seed, weights
+
267 ),
+
268 _q_neighs_w_weights(),
+
269 _dimension(dimension) {}
+
270
+
272 Neighbourhood_Pure_Front(const Neighbourhood_Pure_Front<
+
273 CoMMAIndexType,
+
274 CoMMAWeightType,
+
275 CoMMAIntType> &other) = default;
+
276
+
278 ~Neighbourhood_Pure_Front() override = default;
+
279
+
287 void update(
+
288 const CoMMAIndexType new_fc,
+
289 const std::vector<CoMMAIndexType> &new_neighbours
+
290 ) override {
+
291 this->_candidates.clear();
+
292 // Add new_fc to current CC and remove it from previous neighbourhoods
+
293 this->_s_fc.insert(new_fc);
+
294 for (auto &queue : this->_q_neighs_w_weights) {
+
295 // There is erase_if for sets in C++20
+
296 // erase_if(queue, [&new_fc](const CoMMAPairType &p){return p.first ==
+
297 // new_fc;});
+
298 auto it = std::find_if(
+
299 queue.begin(), queue.end(), CoMMAPairFindFirstBasedType(new_fc)
+
300 );
+
301 //[&new_fc](const CoMMAPairType &p){return p.first == new_fc;});
+
302 if (it != queue.end()) queue.erase(it);
+
303 }
+
304
+
305 // Compute the set of direct neighbours allowed by original
+
306 // neighbourhood-order
+
307 CoMMASetOfPairType curr_set = CoMMASetOfPairType();
+
308 for (const CoMMAIndexType &i_fc : new_neighbours) {
+
309 if ((this->_s_fc.count(i_fc) == 0)
+
310 && (this->_s_neighbours_of_seed.count(i_fc) > 0)) {
+
311 // If not yet in coarse cell and among the allowed neighbours, insert
+
312 curr_set.emplace(i_fc, this->_weights[i_fc]);
+
313 }
+
314 }
+
315
+
316 this->_q_neighs_w_weights.push_front(curr_set);
+
317
+
318 // Now, see which neighbours to return. Here is the strategy:
+
319 // If most recent list is not empty, return it. If not, check the oldest
+
320 // list: if not empty return it, otherwise check the previous list. If
+
321 // empty, check the second oldest, and so on... We grant ourselves one
+
322 // exception...
+
323 if (this->_q_neighs_w_weights.size()
+
324 <= static_cast<decltype(this->_q_neighs_w_weights.size())>(
+
325 this->_dimension
+
326 )) {
+
327 // If at the (very) beginning of the agglomeration, still consider every
+
328 // possible neighbour. This will allow to obtain nice quads from quads
+
329 // TODO[RM]: I think this workaround is needed because we are not able to
+
330 // compute exactly the AR; if we ever we will be able we should try to
+
331 // remove it
+
332 for (auto prev_q = this->_q_neighs_w_weights.begin() + 1;
+
333 prev_q != this->_q_neighs_w_weights.end();
+
334 ++prev_q)
+
335 curr_set.insert(prev_q->begin(), prev_q->end());
+
336 this->extract_and_update_candidates(curr_set);
+
337 } else {
+
338 auto cur_front = decltype(this->_q_neighs_w_weights.size()){0};
+
339 auto cur_back = decltype(this->_q_neighs_w_weights.size()
+
340 ){this->_q_neighs_w_weights.size() - 1};
+
341 while (cur_front <= cur_back) {
+
342 // typename decltype(this->_q_neighs_w_weights)::iterator it =
+
343 auto it = this->_q_neighs_w_weights.begin() + (cur_front++);
+
344 if (!it->empty()) {
+
345 this->extract_and_update_candidates(*it);
+
346 break;
+
347 }
+
348 it = this->_q_neighs_w_weights.begin() + (cur_back--);
+
349 if (!it->empty()) {
+
350 this->extract_and_update_candidates(*it);
+
351 break;
+
352 }
+
353 }
+
354 }
+
355 }
+
356
+
362 inline const CoMMASetOfPairType &get_neighbours_by_level(
+
363 const CoMMAIntType lvl
+
364 ) const {
+
365 assert(
+
366 lvl >= 0
+
367 && lvl < static_cast<CoMMAIntType>(this->_q_neighs_w_weights.size())
+
368 );
+
369 return this->_q_neighs_w_weights[lvl];
+
370 }
+
371
+
372protected:
+
375 std::deque<CoMMASetOfPairType> _q_neighs_w_weights;
+
376
+
379 CoMMAIntType _dimension;
+
380};
+
381
+
389template<
+
390 typename CoMMAIndexType,
+
391 typename CoMMAWeightType,
+
392 typename CoMMAIntType>
+
393class NeighbourhoodCreator {
+
394public:
+
396 using NeighbourhoodBaseType =
+
397 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
398
+
400 NeighbourhoodCreator() = default;
+
401
+
403 virtual ~NeighbourhoodCreator() = default;
+
404
+
414 virtual std::shared_ptr<NeighbourhoodBaseType> create(
+
415 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
+
416 const std::vector<CoMMAWeightType> &priority_weights,
+
417 const CoMMAIntType dimension
+
418 ) const = 0;
+
419
+
424 virtual std::shared_ptr<NeighbourhoodBaseType> clone(
+
425 std::shared_ptr<NeighbourhoodBaseType> other
+
426 ) const = 0;
+
427};
+
428
+
436template<
+
437 typename CoMMAIndexType,
+
438 typename CoMMAWeightType,
+
439 typename CoMMAIntType>
+
440class NeighbourhoodExtendedCreator :
+
441 public NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
442public:
+
444 using CreatorBaseType =
+
445 NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
447 using typename CreatorBaseType::NeighbourhoodBaseType;
+
451 using NeighbourhoodDerivedType =
+
452 Neighbourhood_Extended<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
453
+
455 NeighbourhoodExtendedCreator() :
+
456 CreatorBaseType() {}
+
457
+
459 ~NeighbourhoodExtendedCreator() override = default;
+
460
+
471 inline std::shared_ptr<NeighbourhoodBaseType> create(
+
472 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
+
473 const std::vector<CoMMAWeightType> &priority_weights,
+
474 const CoMMAIntType dimension
+
475 ) const override {
+
476 CoMMAUnused(dimension);
+
477 return std::make_shared<NeighbourhoodDerivedType>(
+
478 s_neighbours_of_seed, priority_weights
+
479 );
+
480 }
+
481
+
487 inline std::shared_ptr<NeighbourhoodBaseType> clone(
+
488 std::shared_ptr<NeighbourhoodBaseType> other
+
489 ) const override {
+
490 // Using copy-constructor
+
491 return std::make_shared<NeighbourhoodDerivedType>(
+
492 *std::dynamic_pointer_cast<NeighbourhoodDerivedType>(other)
+
493 );
+
494 }
+
495};
+
496
+
504template<
+
505 typename CoMMAIndexType,
+
506 typename CoMMAWeightType,
+
507 typename CoMMAIntType>
+
508class NeighbourhoodPureFrontCreator :
+
509 public NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
510public:
+
512 using CreatorBaseType =
+
513 NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
515 using typename CreatorBaseType::NeighbourhoodBaseType;
+
519 using NeighbourhoodDerivedType =
+
520 Neighbourhood_Pure_Front<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
521
+
523 NeighbourhoodPureFrontCreator() :
+
524 CreatorBaseType() {}
+
525
+
527 ~NeighbourhoodPureFrontCreator() override = default;
+
528
+
539 inline std::shared_ptr<NeighbourhoodBaseType> create(
+
540 const std::unordered_set<CoMMAIndexType> &s_neighbours_of_seed,
+
541 const std::vector<CoMMAWeightType> &priority_weights,
+
542 const CoMMAIntType dimension
+
543 ) const override {
+
544 return std::make_shared<NeighbourhoodDerivedType>(
+
545 s_neighbours_of_seed, priority_weights, dimension
+
546 );
+
547 }
+
548
+
554 inline std::shared_ptr<NeighbourhoodBaseType> clone(
+
555 std::shared_ptr<NeighbourhoodBaseType> other
+
556 ) const override {
+
557 // Using copy-constructor
+
558 return std::make_shared<NeighbourhoodDerivedType>(
+
559 *std::dynamic_pointer_cast<NeighbourhoodDerivedType>(other)
+
560 );
+
561 }
+
562};
+
563
+
564} // end namespace comma
+
565
+
566#endif // COMMA_PROJECT_FIRST_ORDER_NEIGHBOURHOOD_H
Util.h
CoMMAUnused
#define CoMMAUnused(var)
Convenient function to avoid unused warnings.
Definition: Util.h:34
-
comma::Neighbourhood_Extended
Class representing the neighbourhood of a given cell in the graph. In this derived class the neighbou...
Definition: Neighbourhood.h:149
-
comma::Neighbourhood_Extended::update
void update(const CoMMAIndexType new_fc, const std::vector< CoMMAIndexType > &new_neighbours) override
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
Definition: Neighbourhood.h:189
+
comma::Neighbourhood_Extended
Class representing the neighbourhood of a given cell in the graph. In this derived class the neighbou...
Definition: Neighbourhood.h:152
+
comma::Neighbourhood_Extended::update
void update(const CoMMAIndexType new_fc, const std::vector< CoMMAIndexType > &new_neighbours) override
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
Definition: Neighbourhood.h:195
comma::Neighbourhood_Extended::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Neighbourhood.h:60
-
comma::Neighbourhood_Extended::Neighbourhood_Extended
Neighbourhood_Extended(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &weights)
Constructor.
Definition: Neighbourhood.h:168
+
comma::Neighbourhood_Extended::Neighbourhood_Extended
Neighbourhood_Extended(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &weights)
Constructor.
Definition: Neighbourhood.h:171
comma::Neighbourhood_Extended::~Neighbourhood_Extended
~Neighbourhood_Extended() override=default
Destructor.
comma::Neighbourhood_Extended::Neighbourhood_Extended
Neighbourhood_Extended(const Neighbourhood_Extended< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > &other)=default
Copy constructor.
-
comma::Neighbourhood_Pure_Front
Class representing the neighbourhood of a given cell in the graph. In this derived class,...
Definition: Neighbourhood.h:234
+
comma::Neighbourhood_Pure_Front
Class representing the neighbourhood of a given cell in the graph. In this derived class,...
Definition: Neighbourhood.h:240
comma::Neighbourhood_Pure_Front::~Neighbourhood_Pure_Front
~Neighbourhood_Pure_Front() override=default
Destructor.
comma::Neighbourhood_Pure_Front::Neighbourhood_Pure_Front
Neighbourhood_Pure_Front(const Neighbourhood_Pure_Front< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > &other)=default
Copy constructor.
comma::Neighbourhood_Pure_Front::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Neighbourhood.h:60
-
comma::Neighbourhood_Pure_Front::get_neighbours_by_level
const CoMMASetOfPairType & get_neighbours_by_level(const CoMMAIntType lvl) const
Get the neighbours from a previous stage.
Definition: Neighbourhood.h:352
-
comma::Neighbourhood_Pure_Front::_q_neighs_w_weights
std::deque< CoMMASetOfPairType > _q_neighs_w_weights
History of the first-order-neighbourhoods of the fine cells recently agglomerated.
Definition: Neighbourhood.h:363
-
comma::Neighbourhood_Pure_Front::_dimension
CoMMAIntType _dimension
Dimensionality of the problem (_dimension = 2 -> 2D, _dimension = 3 -> 3D)
Definition: Neighbourhood.h:367
-
comma::Neighbourhood_Pure_Front::update
void update(const CoMMAIndexType new_fc, const std::vector< CoMMAIndexType > &new_neighbours) override
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
Definition: Neighbourhood.h:279
-
comma::Neighbourhood_Pure_Front::Neighbourhood_Pure_Front
Neighbourhood_Pure_Front(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &weights, CoMMAIntType dimension)
Constructor.
Definition: Neighbourhood.h:254
-
comma::NeighbourhoodCreator
Pure abstract class for a creator of Neighbourhood objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:381
+
comma::Neighbourhood_Pure_Front::get_neighbours_by_level
const CoMMASetOfPairType & get_neighbours_by_level(const CoMMAIntType lvl) const
Get the neighbours from a previous stage.
Definition: Neighbourhood.h:362
+
comma::Neighbourhood_Pure_Front::_q_neighs_w_weights
std::deque< CoMMASetOfPairType > _q_neighs_w_weights
History of the first-order-neighbourhoods of the fine cells recently agglomerated.
Definition: Neighbourhood.h:375
+
comma::Neighbourhood_Pure_Front::_dimension
CoMMAIntType _dimension
Dimensionality of the problem (_dimension = 2 -> 2D, _dimension = 3 -> 3D)
Definition: Neighbourhood.h:379
+
comma::Neighbourhood_Pure_Front::update
void update(const CoMMAIndexType new_fc, const std::vector< CoMMAIndexType > &new_neighbours) override
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
Definition: Neighbourhood.h:287
+
comma::Neighbourhood_Pure_Front::Neighbourhood_Pure_Front
Neighbourhood_Pure_Front(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &weights, CoMMAIntType dimension)
Constructor.
Definition: Neighbourhood.h:260
+
comma::NeighbourhoodCreator
Pure abstract class for a creator of Neighbourhood objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:393
comma::NeighbourhoodCreator::clone
virtual std::shared_ptr< NeighbourhoodBaseType > clone(std::shared_ptr< NeighbourhoodBaseType > other) const =0
Create a new Neighbourhood object by copy.
-
comma::NeighbourhoodCreator::NeighbourhoodBaseType
Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > NeighbourhoodBaseType
Shortcut for the Neighborhood object type.
Definition: Neighbourhood.h:385
+
comma::NeighbourhoodCreator::NeighbourhoodBaseType
Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > NeighbourhoodBaseType
Shortcut for the Neighborhood object type.
Definition: Neighbourhood.h:397
comma::NeighbourhoodCreator::~NeighbourhoodCreator
virtual ~NeighbourhoodCreator()=default
Destructor.
comma::NeighbourhoodCreator::NeighbourhoodCreator
NeighbourhoodCreator()=default
Constructor.
comma::NeighbourhoodCreator::create
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.
-
comma::NeighbourhoodExtendedCreator
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:427
+
comma::NeighbourhoodExtendedCreator
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:441
comma::NeighbourhoodExtendedCreator::~NeighbourhoodExtendedCreator
~NeighbourhoodExtendedCreator() override=default
Destructor.
-
comma::NeighbourhoodExtendedCreator::create
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:456
-
comma::NeighbourhoodExtendedCreator::NeighbourhoodExtendedCreator
NeighbourhoodExtendedCreator()
Constructor.
Definition: Neighbourhood.h:441
-
comma::NeighbourhoodExtendedCreator::clone
std::shared_ptr< NeighbourhoodBaseType > clone(std::shared_ptr< NeighbourhoodBaseType > other) const override
Create a new Neighbourhood object by copy.
Definition: Neighbourhood.h:470
+
comma::NeighbourhoodExtendedCreator::create
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:471
+
comma::NeighbourhoodExtendedCreator::NeighbourhoodExtendedCreator
NeighbourhoodExtendedCreator()
Constructor.
Definition: Neighbourhood.h:455
+
comma::NeighbourhoodExtendedCreator::clone
std::shared_ptr< NeighbourhoodBaseType > clone(std::shared_ptr< NeighbourhoodBaseType > other) const override
Create a new Neighbourhood object by copy.
Definition: Neighbourhood.h:487
comma::Neighbourhood
Class representing the neighbourhood of a given cell in the graph. Mind that no information about the...
Definition: Neighbourhood.h:42
-
comma::Neighbourhood::_weights
const std::vector< CoMMAWeightType > & _weights
Priority weights.
Definition: Neighbourhood.h:116
+
comma::Neighbourhood::_weights
const std::vector< CoMMAWeightType > & _weights
Priority weights.
Definition: Neighbourhood.h:118
comma::Neighbourhood::CoMMAPairFindFirstBasedType
PairFindFirstBasedFunctor< CoMMAPairType > CoMMAPairFindFirstBasedType
Functor used if find-like function relying only on first element of the pair.
Definition: Neighbourhood.h:63
comma::Neighbourhood::Neighbourhood
Neighbourhood(const std::unordered_set< CoMMAIndexType > &s_neighbours_of_seed, const std::vector< CoMMAWeightType > &weights)
Constructor.
Definition: Neighbourhood.h:73
comma::Neighbourhood::update
virtual void update(const CoMMAIndexType new_fc, const std::vector< CoMMAIndexType > &new_neighbours)=0
Method that updates the neighbourhood. Given the new_fc, if is in the neighbours, it is deleted....
-
comma::Neighbourhood::_s_neighbours_of_seed
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:113
-
comma::Neighbourhood::get_candidates
const CandidatesContainerType & get_candidates() const
Get candidates that should be consider in the next step of the agglomeration.
Definition: Neighbourhood.h:104
-
comma::Neighbourhood::_candidates
CandidatesContainerType _candidates
Candidates that should be considered when choosing the next fine cell to add to the coarse one.
Definition: Neighbourhood.h:124
+
comma::Neighbourhood::_s_neighbours_of_seed
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:115
+
comma::Neighbourhood::get_candidates
const CandidatesContainerType & get_candidates() const
Get candidates that should be consider in the next step of the agglomeration.
Definition: Neighbourhood.h:106
+
comma::Neighbourhood::_candidates
CandidatesContainerType _candidates
Candidates that should be considered when choosing the next fine cell to add to the coarse one.
Definition: Neighbourhood.h:126
comma::Neighbourhood::CandidatesContainerType
std::deque< CoMMAIndexType > CandidatesContainerType
Type for container of candidates.
Definition: Neighbourhood.h:65
comma::Neighbourhood::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Neighbourhood.h:60
comma::Neighbourhood::Neighbourhood
Neighbourhood(const Neighbourhood< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > &other)=default
Copy constructor.
-
comma::Neighbourhood::_s_fc
std::unordered_set< CoMMAIndexType > _s_fc
Set of the fine cells composing the coarse cell.
Definition: Neighbourhood.h:119
-
comma::Neighbourhood::extract_and_update_candidates
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:129
+
comma::Neighbourhood::_s_fc
std::unordered_set< CoMMAIndexType > _s_fc
Set of the fine cells composing the coarse cell.
Definition: Neighbourhood.h:121
+
comma::Neighbourhood::extract_and_update_candidates
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:131
comma::Neighbourhood::CoMMAPairType
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Neighbourhood.h:57
comma::Neighbourhood::~Neighbourhood
virtual ~Neighbourhood()=default
Destructor.
-
comma::NeighbourhoodPureFrontCreator
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:490
-
comma::NeighbourhoodPureFrontCreator::NeighbourhoodPureFrontCreator
NeighbourhoodPureFrontCreator()
Constructor.
Definition: Neighbourhood.h:504
-
comma::NeighbourhoodPureFrontCreator::clone
std::shared_ptr< NeighbourhoodBaseType > clone(std::shared_ptr< NeighbourhoodBaseType > other) const override
Create a new Neighbourhood object by copy.
Definition: Neighbourhood.h:532
+
comma::NeighbourhoodPureFrontCreator
Creator of Neighbourhood_Extended objects. It can create from scratch or by copy.
Definition: Neighbourhood.h:509
+
comma::NeighbourhoodPureFrontCreator::NeighbourhoodPureFrontCreator
NeighbourhoodPureFrontCreator()
Constructor.
Definition: Neighbourhood.h:523
+
comma::NeighbourhoodPureFrontCreator::clone
std::shared_ptr< NeighbourhoodBaseType > clone(std::shared_ptr< NeighbourhoodBaseType > other) const override
Create a new Neighbourhood object by copy.
Definition: Neighbourhood.h:554
comma::NeighbourhoodPureFrontCreator::~NeighbourhoodPureFrontCreator
~NeighbourhoodPureFrontCreator() override=default
Destructor.
-
comma::NeighbourhoodPureFrontCreator::create
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:519
-
comma::PairFindFirstBasedFunctor
Functor implementing an operator telling if a given value if the first one of pair.
Definition: Util.h:211
+
comma::NeighbourhoodPureFrontCreator::create
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:539
+
comma::PairFindFirstBasedFunctor
Functor implementing an operator telling if a given value if the first one of pair.
Definition: Util.h:213
comma
Definition: Agglomerator.h:34
-
comma::CustomPairGreaterFunctor
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:154
+
comma::CustomPairGreaterFunctor
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:156
diff --git a/_priority___pair_8h_source.html b/_priority___pair_8h_source.html index f1b49ef..43c891b 100644 --- a/_priority___pair_8h_source.html +++ b/_priority___pair_8h_source.html @@ -123,40 +123,42 @@
37 Priority_Pair() = default;
38 ;
39
-
44 Priority_Pair(const A &a, const B &b) : _p(a, b){};
-
45
-
47 ~Priority_Pair() = default;
-
48 ;
-
49
-
53 // We accept to have a copy passed
-
54 A first() const { return _p.first; }
-
55
-
59 B second() const { return _p.second; }
-
60
-
68 inline friend bool operator<(const Priority_Pair &a, const Priority_Pair &b) {
-
69 if (a._p.first > b._p.first) return true;
-
70 if (a._p.first < b._p.first) return false;
-
71 /* a._p.first == b._p.first */
-
72 return a._p.second < b._p.second;
-
73 }
-
74
-
80 inline friend bool operator==(
-
81 const Priority_Pair &a, const Priority_Pair &b) {
-
82 return (a._p.first == b._p.first) && (a._p.second == b._p.second);
-
83 }
-
84};
-
85
-
86} // end namespace comma
+
44 Priority_Pair(const A &a, const B &b) :
+
45 _p(a, b){};
+
46
+
48 ~Priority_Pair() = default;
+
49 ;
+
50
+
54 // We accept to have a copy passed
+
55 A first() const { return _p.first; }
+
56
+
60 B second() const { return _p.second; }
+
61
+
69 inline friend bool operator<(const Priority_Pair &a, const Priority_Pair &b) {
+
70 if (a._p.first > b._p.first) return true;
+
71 if (a._p.first < b._p.first) return false;
+
72 /* a._p.first == b._p.first */
+
73 return a._p.second < b._p.second;
+
74 }
+
75
+
81 inline friend bool operator==(
+
82 const Priority_Pair &a, const Priority_Pair &b
+
83 ) {
+
84 return (a._p.first == b._p.first) && (a._p.second == b._p.second);
+
85 }
+
86};
87
-
88#endif // COMMA_PROJECT_PRIORITY_PAIR_H
+
88} // end namespace comma
+
89
+
90#endif // COMMA_PROJECT_PRIORITY_PAIR_H
comma::Priority_Pair
Wrapper around the STL pair with custom 'less than' operator: as in the standard case,...
Definition: Priority_Pair.h:30
comma::Priority_Pair::~Priority_Pair
~Priority_Pair()=default
Destructor.
comma::Priority_Pair::Priority_Pair
Priority_Pair(const A &a, const B &b)
Constructor.
Definition: Priority_Pair.h:44
-
comma::Priority_Pair::operator==
friend bool operator==(const Priority_Pair &a, const Priority_Pair &b)
Operator 'equal'.
Definition: Priority_Pair.h:80
+
comma::Priority_Pair::operator==
friend bool operator==(const Priority_Pair &a, const Priority_Pair &b)
Operator 'equal'.
Definition: Priority_Pair.h:81
comma::Priority_Pair::Priority_Pair
Priority_Pair()=default
Constructor.
-
comma::Priority_Pair::operator<
friend bool operator<(const Priority_Pair &a, const Priority_Pair &b)
Operator 'less than'. It actually relies on the 'greater than' operator for the first elements and 'l...
Definition: Priority_Pair.h:68
-
comma::Priority_Pair::second
B second() const
Accessor to the first element.
Definition: Priority_Pair.h:59
-
comma::Priority_Pair::first
A first() const
Accessor to the first element.
Definition: Priority_Pair.h:54
+
comma::Priority_Pair::operator<
friend bool operator<(const Priority_Pair &a, const Priority_Pair &b)
Operator 'less than'. It actually relies on the 'greater than' operator for the first elements and 'l...
Definition: Priority_Pair.h:69
+
comma::Priority_Pair::second
B second() const
Accessor to the first element.
Definition: Priority_Pair.h:60
+
comma::Priority_Pair::first
A first() const
Accessor to the first element.
Definition: Priority_Pair.h:55
comma
Definition: Agglomerator.h:34
diff --git a/_queue_8h_source.html b/_queue_8h_source.html index bd65da3..e78980e 100644 --- a/_queue_8h_source.html +++ b/_queue_8h_source.html @@ -125,30 +125,38 @@
34public:
36 Queue() = default;
38 ~Queue() = default;
-
42 void push(T const &elem) { _elems.push_back(elem); }
-
46 T pop() {
-
47 if (_elems.empty()) { return static_cast<T>(-1); }
-
48 T elem = _elems.front(); // Copy last element
-
49 _elems.pop_front(); // remove last element
-
50 return elem;
-
51 }
-
55 T top() const {
-
56 if (_elems.empty()) { return static_cast<T>(-1); }
-
57 return _elems.front();
-
58 }
-
62 inline bool empty() const { return _elems.empty(); }
-
63};
-
64
-
65} // end namespace comma
+
39
+
43 void push(T const &elem) { _elems.push_back(elem); }
+
44
+
48 T pop() {
+
49 if (_elems.empty()) {
+
50 return static_cast<T>(-1);
+
51 }
+
52 T elem = _elems.front(); // Copy last element
+
53 _elems.pop_front(); // remove last element
+
54 return elem;
+
55 }
+
56
+
60 T top() const {
+
61 if (_elems.empty()) {
+
62 return static_cast<T>(-1);
+
63 }
+
64 return _elems.front();
+
65 }
66
-
67#endif
+
70 inline bool empty() const { return _elems.empty(); }
+
71};
+
72
+
73} // end namespace comma
+
74
+
75#endif
comma::Queue
A template class implementing a custom queue data structure.
Definition: Queue.h:29
-
comma::Queue::top
T top() const
Scope to the element on the bottom of the queue.
Definition: Queue.h:55
-
comma::Queue::pop
T pop()
pop an element from the bottom of the queue
Definition: Queue.h:46
+
comma::Queue::top
T top() const
Scope to the element on the bottom of the queue.
Definition: Queue.h:60
+
comma::Queue::pop
T pop()
pop an element from the bottom of the queue
Definition: Queue.h:48
comma::Queue::~Queue
~Queue()=default
Destructor.
-
comma::Queue::empty
bool empty() const
Whether the queue is empty.
Definition: Queue.h:62
+
comma::Queue::empty
bool empty() const
Whether the queue is empty.
Definition: Queue.h:70
comma::Queue::Queue
Queue()=default
Constructor.
-
comma::Queue::push
void push(T const &elem)
Push an element on the top of the queue.
Definition: Queue.h:42
+
comma::Queue::push
void push(T const &elem)
Push an element on the top of the queue.
Definition: Queue.h:43
comma
Definition: Agglomerator.h:34
diff --git a/_seeds___pool_8h_source.html b/_seeds___pool_8h_source.html index 4236277..4bdb148 100644 --- a/_seeds___pool_8h_source.html +++ b/_seeds___pool_8h_source.html @@ -146,500 +146,538 @@
70 const std::vector<CoMMAWeightType> &priority_weights,
71 const std::vector<CoMMAIntType> &n_bnd_faces,
72 const CoMMAIntType max_bnd,
-
73 CoMMAQueueType &queue) = 0;
-
74};
-
75
-
82template<
-
83 typename CoMMAIndexType,
-
84 typename CoMMAWeightType,
-
85 typename CoMMAIntType>
-
86struct SPFullInitializator :
-
87 public SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
89 using BaseClass =
-
90 SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
92 using typename BaseClass::CoMMAQueueType;
-
94 using typename BaseClass::CoMMASetOfPairType;
-
95
-
97 SPFullInitializator() : BaseClass() {}
-
98
-
100 ~SPFullInitializator() override = default;
-
101
-
111 void operator()(
-
112 const std::vector<CoMMAWeightType> &priority_weights,
-
113 const std::vector<CoMMAIntType> &n_bnd_faces,
-
114 const CoMMAIntType max_bnd,
-
115 CoMMAQueueType &queue) override {
-
116 // Similar to function build_queue but without is_agglomerated
-
117 // Using set to force order
-
118 CoMMASetOfPairType tmp_set{};
-
119 for (auto i_fc = decltype(n_bnd_faces.size()){0}; i_fc < n_bnd_faces.size();
-
120 ++i_fc) {
-
121 if (n_bnd_faces[i_fc] >= max_bnd)
-
122 tmp_set.emplace(i_fc, priority_weights[i_fc]);
-
123 }
-
124 for (const auto &idx : tmp_set)
-
125 queue.push_back(idx.first);
-
126 }
-
127};
-
128
-
135template<
-
136 typename CoMMAIndexType,
-
137 typename CoMMAWeightType,
-
138 typename CoMMAIntType>
-
139struct SPOnePointInitializator :
-
140 public SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
142 using BaseClass =
-
143 SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
145 using typename BaseClass::CoMMAPairType;
-
147 using typename BaseClass::CoMMAQueueType;
-
148
-
150 SPOnePointInitializator() : BaseClass() {}
+
73 CoMMAQueueType &queue
+
74 ) = 0;
+
75};
+
76
+
83template<
+
84 typename CoMMAIndexType,
+
85 typename CoMMAWeightType,
+
86 typename CoMMAIntType>
+
87struct SPFullInitializator :
+
88 public SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
90 using BaseClass =
+
91 SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
93 using typename BaseClass::CoMMAQueueType;
+
95 using typename BaseClass::CoMMASetOfPairType;
+
96
+
98 SPFullInitializator() :
+
99 BaseClass() {}
+
100
+
102 ~SPFullInitializator() override = default;
+
103
+
113 void operator()(
+
114 const std::vector<CoMMAWeightType> &priority_weights,
+
115 const std::vector<CoMMAIntType> &n_bnd_faces,
+
116 const CoMMAIntType max_bnd,
+
117 CoMMAQueueType &queue
+
118 ) override {
+
119 // Similar to function build_queue but without is_agglomerated
+
120 // Using set to force order
+
121 CoMMASetOfPairType tmp_set{};
+
122 for (auto i_fc = decltype(n_bnd_faces.size()){0}; i_fc < n_bnd_faces.size();
+
123 ++i_fc) {
+
124 if (n_bnd_faces[i_fc] >= max_bnd)
+
125 tmp_set.emplace(i_fc, priority_weights[i_fc]);
+
126 }
+
127 for (const auto &idx : tmp_set)
+
128 queue.push_back(idx.first);
+
129 }
+
130};
+
131
+
138template<
+
139 typename CoMMAIndexType,
+
140 typename CoMMAWeightType,
+
141 typename CoMMAIntType>
+
142struct SPOnePointInitializator :
+
143 public SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
145 using BaseClass =
+
146 SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
148 using typename BaseClass::CoMMAPairType;
+
150 using typename BaseClass::CoMMAQueueType;
151
-
153 ~SPOnePointInitializator() override = default;
-
154
-
164 void operator()(
-
165 const std::vector<CoMMAWeightType> &priority_weights,
-
166 const std::vector<CoMMAIntType> &n_bnd_faces,
-
167 const CoMMAIntType max_bnd,
-
168 CoMMAQueueType &queue) override {
-
169 CoMMAPairType cur_max{
-
170 std::numeric_limits<CoMMAIndexType>::max(),
-
171 std::numeric_limits<CoMMAWeightType>::min()};
-
172 const CustomPairGreaterFunctor<CoMMAPairType> comp_op{};
-
173 for (auto i_fc = decltype(n_bnd_faces.size()){0}; i_fc < n_bnd_faces.size();
-
174 ++i_fc) {
-
175 const CoMMAPairType cur_pair{i_fc, priority_weights[i_fc]};
-
176 if (n_bnd_faces[i_fc] >= max_bnd && comp_op(cur_pair, cur_max))
-
177 cur_max = std::move(cur_pair);
-
178 }
-
179 queue.push_back(cur_max.first);
-
180 }
-
181};
-
182
-
190template<
-
191 typename CoMMAIndexType,
-
192 typename CoMMAWeightType,
-
193 typename CoMMAIntType>
-
194class Seeds_Pool {
-
195public:
-
197 using CoMMAPairType = std::pair<CoMMAIndexType, CoMMAWeightType>;
-
198#if 0
-
200 // Better to use a deque (rather than the default vector) because it has nice
-
201 // insert / remove performances, and it's more closer to the philosophy we would
-
202 // like to obtain
-
203 using CoMMAContainerPairType = std::deque<CoMMAPairType>;
-
205 // A drawback of priority_queue to be aware of: it cannot be looped through
-
206 // A workaround is explained on https://stackoverflow.com/questions/4484767/how-to-iterate-over-a-priority-queue
-
207 // TODO: Maybe change to the advised make_heap (with vector or deque)
-
208 using CoMMAPriorityQueueType = priority_queue<CoMMAPairType,
-
209 CoMMAContainerPairType,
-
210 CustomPairLessFunctor<CoMMAPairType>>;
-
211#endif
-
213 using CoMMAQueueType = std::deque<CoMMAIndexType>;
-
215 using CoMMASetOfPairType =
-
216 std::set<CoMMAPairType, CustomPairGreaterFunctor<CoMMAPairType>>;
-
217
-
218protected:
-
223 std::vector<CoMMAQueueType> _l_of_seeds;
-
224
-
226 const std::vector<CoMMAWeightType> &_priority_weights;
-
227
-
231 std::optional<CoMMAIntType> _cur_top_queue;
-
232
-
234 std::shared_ptr<
-
235 SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
236 _initializator;
-
237
-
238public:
-
240 const std::vector<CoMMAIntType> &_n_bnd_faces;
-
241
-
250 Seeds_Pool(
-
251 const std::vector<CoMMAIntType> &n_bnd_faces,
-
252 const std::vector<CoMMAWeightType> &priority_weights,
-
253 const bool one_point_init) :
-
254 _priority_weights(priority_weights),
-
255 _cur_top_queue(std::nullopt),
-
256 _n_bnd_faces(n_bnd_faces) {
-
257 // The size 4 corresponds to 0 : interior, 1 : valley, 2 : ridge, 3 : corner
-
258 _l_of_seeds = std::vector<CoMMAQueueType>(CoMMACellT::N_CELL_TYPES);
-
259
-
260 _initializator = nullptr;
-
261 if (one_point_init)
-
262 _initializator = std::make_shared<SPOnePointInitializator<
-
263 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>();
-
264 else
-
265 _initializator = std::make_shared<
-
266 SPFullInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>();
-
267 }
-
268
-
270 virtual ~Seeds_Pool() = default;
-
271
-
278 inline std::optional<CoMMAIndexType> spoil_queue(
-
279 const std::vector<bool> &is_fc_agglomerated, CoMMAQueueType &queue) {
-
280 // If there still is something and it's already agglomerated, then keep on
-
281 // searching
-
282 for (; !queue.empty() && is_fc_agglomerated[queue.front()];
-
283 queue.pop_front()) {}
-
284 if (!queue.empty()) {
-
285 const auto seed = queue.front();
-
286 queue.pop_front();
-
287 return seed;
-
288 }
-
289 return std::nullopt;
-
290 }
-
291
-
297 virtual std::optional<CoMMAIndexType> choose_new_seed(
-
298 const std::vector<bool> &is_agglomerated) = 0;
-
299
-
306 virtual void update(const std::deque<CoMMAIndexType> &new_seeds) = 0;
-
307
-
313 virtual void order_new_seeds_and_update(
-
314 const std::unordered_set<CoMMAIndexType> &new_seeds) = 0;
-
315
-
324 inline void build_queue(
-
325 const std::vector<bool> &is_fc_agglomerated, const CoMMAIntType target) {
-
326 // Using set to force order
-
327 CoMMASetOfPairType tmp_set{};
-
328 for (auto i_fc = decltype(_n_bnd_faces.size()){0};
-
329 i_fc < _n_bnd_faces.size(); ++i_fc) {
-
330 if (!is_fc_agglomerated[i_fc] && _n_bnd_faces[i_fc] == target)
-
331 tmp_set.emplace(i_fc, _priority_weights[i_fc]);
-
332 }
-
333 for (const auto &idx : tmp_set)
-
334 _l_of_seeds[target].push_back(idx.first);
-
335 }
-
336
-
346 inline std::optional<CoMMAIntType> get_highest_n_bnd_yet_to_agglomerate(
-
347 const std::vector<bool> &is_fc_agglomerated,
-
348 const CoMMAIntType expected_max = CoMMACellT::CORNER) const {
-
349 std::optional<CoMMAIntType> max_bnd = std::nullopt;
-
350 for (auto i_fc = decltype(_n_bnd_faces.size()){0};
-
351 i_fc < _n_bnd_faces.size(); ++i_fc) {
-
352 if (!is_fc_agglomerated[i_fc]) {
-
353 const auto i_fc_bnd = _n_bnd_faces[i_fc];
-
354 if (!max_bnd.has_value()) max_bnd = i_fc_bnd;
-
355 if (i_fc_bnd >= expected_max) { return i_fc_bnd; }
-
356 if (i_fc_bnd > max_bnd) { max_bnd = i_fc_bnd; }
-
357 }
-
358 }
-
359 return max_bnd;
-
360 }
-
361
-
366 bool is_empty(CoMMAIntType i_level = CoMMACellT::N_CELL_TYPES) const {
-
367 assert(CoMMACellT::INTERIOR <= i_level);
-
368 assert(i_level <= CoMMACellT::N_CELL_TYPES);
-
369 if (!_l_of_seeds.empty()) {
-
370 switch (i_level) {
-
371 case CoMMACellT::INTERIOR:
-
372 return _l_of_seeds[CoMMACellT::INTERIOR].empty();
-
373 case CoMMACellT::VALLEY:
-
374 return _l_of_seeds[CoMMACellT::VALLEY].empty();
-
375 case CoMMACellT::RIDGE:
-
376 return _l_of_seeds[CoMMACellT::RIDGE].empty();
-
377 case CoMMACellT::CORNER:
-
378 return _l_of_seeds[CoMMACellT::CORNER].empty();
-
379 case CoMMACellT::N_CELL_TYPES:
-
380 default:
-
381 return _l_of_seeds[CoMMACellT::INTERIOR].empty()
-
382 && _l_of_seeds[CoMMACellT::VALLEY].empty()
-
383 && _l_of_seeds[CoMMACellT::RIDGE].empty()
-
384 && _l_of_seeds[CoMMACellT::CORNER].empty();
-
385 } /* Switch */
-
386 }
-
387 return true;
-
388 }
-
389
-
395 virtual bool need_initialization(
-
396 const std::vector<bool> &is_agglomerated) = 0;
-
397
-
399 inline void initialize() {
-
400 if (!_cur_top_queue.has_value())
-
401 // Computing the max number of boundary faces. Only the related seed queue
-
402 // will be filled at this initial stage
-
403 _cur_top_queue = *(max_element(_n_bnd_faces.begin(), _n_bnd_faces.end()));
-
404 (*this->_initializator)(
-
405 this->_priority_weights, this->_n_bnd_faces, this->_cur_top_queue.value(),
-
406 this->_l_of_seeds[this->_cur_top_queue.value()]);
+
153 SPOnePointInitializator() :
+
154 BaseClass() {}
+
155
+
157 ~SPOnePointInitializator() override = default;
+
158
+
168 void operator()(
+
169 const std::vector<CoMMAWeightType> &priority_weights,
+
170 const std::vector<CoMMAIntType> &n_bnd_faces,
+
171 const CoMMAIntType max_bnd,
+
172 CoMMAQueueType &queue
+
173 ) override {
+
174 CoMMAPairType cur_max{
+
175 std::numeric_limits<CoMMAIndexType>::max(),
+
176 std::numeric_limits<CoMMAWeightType>::min()
+
177 };
+
178 const CustomPairGreaterFunctor<CoMMAPairType> comp_op{};
+
179 for (auto i_fc = decltype(n_bnd_faces.size()){0}; i_fc < n_bnd_faces.size();
+
180 ++i_fc) {
+
181 const CoMMAPairType cur_pair{i_fc, priority_weights[i_fc]};
+
182 if (n_bnd_faces[i_fc] >= max_bnd && comp_op(cur_pair, cur_max))
+
183 cur_max = std::move(cur_pair);
+
184 }
+
185 queue.push_back(cur_max.first);
+
186 }
+
187};
+
188
+
196template<
+
197 typename CoMMAIndexType,
+
198 typename CoMMAWeightType,
+
199 typename CoMMAIntType>
+
200class Seeds_Pool {
+
201public:
+
203 using CoMMAPairType = std::pair<CoMMAIndexType, CoMMAWeightType>;
+
204#if 0
+
206 // Better to use a deque (rather than the default vector) because it has nice
+
207 // insert / remove performances, and it's more closer to the philosophy we would
+
208 // like to obtain
+
209 using CoMMAContainerPairType = std::deque<CoMMAPairType>;
+
211 // A drawback of priority_queue to be aware of: it cannot be looped through
+
212 // A workaround is explained on https://stackoverflow.com/questions/4484767/how-to-iterate-over-a-priority-queue
+
213 // TODO: Maybe change to the advised make_heap (with vector or deque)
+
214 using CoMMAPriorityQueueType = priority_queue<CoMMAPairType,
+
215 CoMMAContainerPairType,
+
216 CustomPairLessFunctor<CoMMAPairType>>;
+
217#endif
+
219 using CoMMAQueueType = std::deque<CoMMAIndexType>;
+
221 using CoMMASetOfPairType =
+
222 std::set<CoMMAPairType, CustomPairGreaterFunctor<CoMMAPairType>>;
+
223
+
224protected:
+
229 std::vector<CoMMAQueueType> _l_of_seeds;
+
230
+
232 const std::vector<CoMMAWeightType> &_priority_weights;
+
233
+
237 std::optional<CoMMAIntType> _cur_top_queue;
+
238
+
240 std::shared_ptr<
+
241 SPInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
+
242 _initializator;
+
243
+
244public:
+
246 const std::vector<CoMMAIntType> &_n_bnd_faces;
+
247
+
256 Seeds_Pool(
+
257 const std::vector<CoMMAIntType> &n_bnd_faces,
+
258 const std::vector<CoMMAWeightType> &priority_weights,
+
259 const bool one_point_init
+
260 ) :
+
261 _priority_weights(priority_weights),
+
262 _cur_top_queue(std::nullopt),
+
263 _n_bnd_faces(n_bnd_faces) {
+
264 // The size 4 corresponds to 0 : interior, 1 : valley, 2 : ridge, 3 : corner
+
265 _l_of_seeds = std::vector<CoMMAQueueType>(CoMMACellT::N_CELL_TYPES);
+
266
+
267 _initializator = nullptr;
+
268 if (one_point_init)
+
269 _initializator = std::make_shared<
+
270 SPOnePointInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
+
271 );
+
272 else
+
273 _initializator = std::make_shared<
+
274 SPFullInitializator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>();
+
275 }
+
276
+
278 virtual ~Seeds_Pool() = default;
+
279
+
286 inline std::optional<CoMMAIndexType> spoil_queue(
+
287 const std::vector<bool> &is_fc_agglomerated, CoMMAQueueType &queue
+
288 ) {
+
289 // If there still is something and it's already agglomerated, then keep on
+
290 // searching
+
291 for (; !queue.empty() && is_fc_agglomerated[queue.front()];
+
292 queue.pop_front()) {}
+
293 if (!queue.empty()) {
+
294 const auto seed = queue.front();
+
295 queue.pop_front();
+
296 return seed;
+
297 }
+
298 return std::nullopt;
+
299 }
+
300
+
306 virtual std::optional<CoMMAIndexType> choose_new_seed(
+
307 const std::vector<bool> &is_agglomerated
+
308 ) = 0;
+
309
+
316 virtual void update(const std::deque<CoMMAIndexType> &new_seeds) = 0;
+
317
+
323 virtual void order_new_seeds_and_update(
+
324 const std::unordered_set<CoMMAIndexType> &new_seeds
+
325 ) = 0;
+
326
+
335 inline void build_queue(
+
336 const std::vector<bool> &is_fc_agglomerated, const CoMMAIntType target
+
337 ) {
+
338 // Using set to force order
+
339 CoMMASetOfPairType tmp_set{};
+
340 for (auto i_fc = decltype(_n_bnd_faces.size()){0};
+
341 i_fc < _n_bnd_faces.size();
+
342 ++i_fc) {
+
343 if (!is_fc_agglomerated[i_fc] && _n_bnd_faces[i_fc] == target)
+
344 tmp_set.emplace(i_fc, _priority_weights[i_fc]);
+
345 }
+
346 for (const auto &idx : tmp_set)
+
347 _l_of_seeds[target].push_back(idx.first);
+
348 }
+
349
+
359 inline std::optional<CoMMAIntType> get_highest_n_bnd_yet_to_agglomerate(
+
360 const std::vector<bool> &is_fc_agglomerated,
+
361 const CoMMAIntType expected_max = CoMMACellT::CORNER
+
362 ) const {
+
363 std::optional<CoMMAIntType> max_bnd = std::nullopt;
+
364 for (auto i_fc = decltype(_n_bnd_faces.size()){0};
+
365 i_fc < _n_bnd_faces.size();
+
366 ++i_fc) {
+
367 if (!is_fc_agglomerated[i_fc]) {
+
368 const auto i_fc_bnd = _n_bnd_faces[i_fc];
+
369 if (!max_bnd.has_value()) max_bnd = i_fc_bnd;
+
370 if (i_fc_bnd >= expected_max) {
+
371 return i_fc_bnd;
+
372 }
+
373 if (i_fc_bnd > max_bnd) {
+
374 max_bnd = i_fc_bnd;
+
375 }
+
376 }
+
377 }
+
378 return max_bnd;
+
379 }
+
380
+
385 bool is_empty(CoMMAIntType i_level = CoMMACellT::N_CELL_TYPES) const {
+
386 assert(CoMMACellT::INTERIOR <= i_level);
+
387 assert(i_level <= CoMMACellT::N_CELL_TYPES);
+
388 if (!_l_of_seeds.empty()) {
+
389 switch (i_level) {
+
390 case CoMMACellT::INTERIOR:
+
391 return _l_of_seeds[CoMMACellT::INTERIOR].empty();
+
392 case CoMMACellT::VALLEY:
+
393 return _l_of_seeds[CoMMACellT::VALLEY].empty();
+
394 case CoMMACellT::RIDGE:
+
395 return _l_of_seeds[CoMMACellT::RIDGE].empty();
+
396 case CoMMACellT::CORNER:
+
397 return _l_of_seeds[CoMMACellT::CORNER].empty();
+
398 case CoMMACellT::N_CELL_TYPES:
+
399 default:
+
400 return _l_of_seeds[CoMMACellT::INTERIOR].empty()
+
401 && _l_of_seeds[CoMMACellT::VALLEY].empty()
+
402 && _l_of_seeds[CoMMACellT::RIDGE].empty()
+
403 && _l_of_seeds[CoMMACellT::CORNER].empty();
+
404 } /* Switch */
+
405 }
+
406 return true;
407 }
408
-
412 inline void set_top_queue(const CoMMAIntType q_lvl) {
-
413 this->_cur_top_queue = q_lvl;
-
414 }
-
415};
+
414 virtual bool need_initialization(const std::vector<bool> &is_agglomerated
+
415 ) = 0;
416
-
425template<
-
426 typename CoMMAIndexType,
-
427 typename CoMMAWeightType,
-
428 typename CoMMAIntType>
-
429class Seeds_Pool_Boundary_Priority :
-
430 public Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
431public:
-
433 using SeedsPoolBaseType =
-
434 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
436 using typename SeedsPoolBaseType::CoMMAPairType;
-
438 using typename SeedsPoolBaseType::CoMMASetOfPairType;
-
439
-
448 Seeds_Pool_Boundary_Priority(
-
449 const std::vector<CoMMAIntType> &n_bnd_faces,
-
450 const std::vector<CoMMAWeightType> &priority_weights,
-
451 const bool one_point_init) :
-
452 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
453 n_bnd_faces, priority_weights, one_point_init) {}
-
454
-
456 ~Seeds_Pool_Boundary_Priority() override = default;
-
457
-
463 std::optional<CoMMAIndexType> choose_new_seed(
-
464 const std::vector<bool> &is_agglomerated) override {
-
465 // Choose a correct seed from the fc pool list_of_seeds beyond not
-
466 // agglomerated fc.
-
467 // We choose preferably the corners, then the ridges, then the valley, and
-
468 // finally interior cells:
-
469 // see NIA (Mavriplis uses Wall and farfield only)
-
470 // Exactly the inverse of the order of the list. For this reason we proceed
-
471 // from the back
-
472 if (this->_cur_top_queue.has_value()) {
-
473 auto opt_seed = this->spoil_queue(
-
474 is_agglomerated, this->_l_of_seeds[this->_cur_top_queue.value()]);
-
475 if (opt_seed.has_value()) return opt_seed.value();
-
476 auto opt_top = this->get_highest_n_bnd_yet_to_agglomerate(
-
477 is_agglomerated, this->_cur_top_queue.value());
-
478 if (opt_top.has_value()) {
-
479 const auto cur_queue = opt_top.value();
-
480 this->_cur_top_queue = cur_queue;
-
481 // Could be the same top queue, but that's OK
-
482 opt_seed =
-
483 this->spoil_queue(is_agglomerated, this->_l_of_seeds[cur_queue]);
-
484 if (opt_seed.has_value()) return opt_seed.value();
-
485 // If here, we already used everything that we had in the seeds pool but
-
486 // there are still cells to agglomerate of the same type, hence we need
-
487 // to rebuild the queue from scratch
-
488 this->build_queue(is_agglomerated, cur_queue);
-
489
-
490 const auto seed = this->_l_of_seeds[cur_queue].front();
-
491 this->_l_of_seeds[cur_queue].pop_front();
-
492 return seed;
-
493 }
-
494 // If everything failed, set to null
-
495 this->_cur_top_queue = std::nullopt;
-
496 }
-
497 return std::nullopt;
-
498 }
-
499
-
506 inline void update(const std::deque<CoMMAIndexType> &new_seeds) override {
-
507 if (!new_seeds.empty()) {
-
508 CoMMAIntType max_bnd{0};
-
509 for (const auto &seed : new_seeds) {
-
510 const auto n_bnd = this->_n_bnd_faces[seed];
-
511 if (n_bnd > max_bnd) max_bnd = n_bnd;
-
512 // We add even if already present. Worst case scenario, a check if
-
513 // agglomerated is done when choosing new seed
-
514 this->_l_of_seeds[n_bnd].push_back(seed);
-
515 }
-
516 if (
-
517 !this->_cur_top_queue.has_value()
-
518 || max_bnd > this->_cur_top_queue.value())
-
519 this->_cur_top_queue = max_bnd;
-
520 }
-
521 }
-
522
-
528 inline void order_new_seeds_and_update(
-
529 const std::unordered_set<CoMMAIndexType> &new_seeds) override {
-
530 std::map<CoMMAIntType, CoMMASetOfPairType, std::greater<>> new_seeds_by_bnd;
-
531 if (!new_seeds.empty()) {
-
532 for (const auto seed : new_seeds) {
-
533 new_seeds_by_bnd[this->_n_bnd_faces[seed]].emplace(
-
534 seed, this->_priority_weights[seed]);
-
535 }
-
536 const auto max_bnd = new_seeds_by_bnd.begin()->first;
-
537 if (
-
538 !this->_cur_top_queue.has_value()
-
539 || max_bnd > this->_cur_top_queue.value())
-
540 this->_cur_top_queue = max_bnd;
-
541 for (const auto &[n_bnd, seeds] : new_seeds_by_bnd) {
-
542 // We add even if already present. Worst case scenario, a check if
-
543 // agglomerated is done when choosing new seed
-
544 std::transform(
-
545 seeds.cbegin(), seeds.cend(),
-
546 std::back_inserter(this->_l_of_seeds[n_bnd]),
-
547 [](const auto &pr) { return pr.first; });
-
548 }
-
549 }
-
550 }
-
551
-
558 bool need_initialization(const std::vector<bool> &is_agglomerated) override {
-
559 if (this->is_empty() || (!this->_cur_top_queue.has_value())) return true;
-
560 const auto max_bnd =
-
561 this->get_highest_n_bnd_yet_to_agglomerate(is_agglomerated);
-
562 if (max_bnd.has_value() && max_bnd.value() > this->_cur_top_queue.value()) {
-
563 this->_cur_top_queue = max_bnd.value();
-
564 return true;
-
565 }
-
566 return false;
-
567 }
-
568};
-
569
-
578template<
-
579 typename CoMMAIndexType,
-
580 typename CoMMAWeightType,
-
581 typename CoMMAIntType>
-
582class Seeds_Pool_Neighbourhood_Priority :
-
583 public Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
584public:
-
586 using SeedsPoolBaseType =
-
587 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
589 using typename SeedsPoolBaseType::CoMMAPairType;
-
591 using typename SeedsPoolBaseType::CoMMASetOfPairType;
-
592
-
601 Seeds_Pool_Neighbourhood_Priority(
-
602 const std::vector<CoMMAIntType> &n_bnd_faces,
-
603 const std::vector<CoMMAWeightType> &priority_weights,
-
604 const bool one_point_init) :
-
605 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
606 n_bnd_faces, priority_weights, one_point_init) {}
-
607
-
609 ~Seeds_Pool_Neighbourhood_Priority() override = default;
-
610
-
616 std::optional<CoMMAIndexType> choose_new_seed(
-
617 const std::vector<bool> &is_agglomerated) override {
-
618 // Choose a correct seed from the fc pool list_of_seeds beyond not
-
619 // agglomerated fc.
-
620 // We choose preferably the corners, then the ridges, then the valley, and
-
621 // finally interior cells:
-
622 // see NIA (Mavriplis uses Wall and farfield only)
-
623 // Exactly the inverse of the order of the list. For this reason we proceed
-
624 // from the back
-
625 if (this->_cur_top_queue.has_value()) {
-
626 for (auto queue =
-
627 this->_l_of_seeds.rbegin()
-
628 + (this->_l_of_seeds.size() - (this->_cur_top_queue.value() + 1));
-
629 queue != this->_l_of_seeds.rend(); ++queue) {
-
630 const auto opt_seed = this->spoil_queue(is_agglomerated, *queue);
-
631 if (opt_seed.has_value()) {
-
632 this->_cur_top_queue = distance(queue, this->_l_of_seeds.rend()) - 1;
-
633 return opt_seed.value();
-
634 }
-
635 }
-
636
-
637 // If not found, see which is the highest unfinished level
-
638 const auto opt_top = this->get_highest_n_bnd_yet_to_agglomerate(
-
639 is_agglomerated, this->_cur_top_queue.value());
-
640 if (opt_top.has_value()) {
-
641 const auto cur_queue = opt_top.value();
-
642 this->_cur_top_queue = cur_queue;
-
643 // Could be the same top queue, but that's OK
-
644 const auto opt_seed =
-
645 this->spoil_queue(is_agglomerated, this->_l_of_seeds[cur_queue]);
-
646 if (opt_seed.has_value()) return opt_seed.value();
-
647 // If here, we already used everything that we had in the seeds pool but
-
648 // there are still cells to agglomerate of the same type, hence we need
-
649 // to rebuild the queue from scratch
-
650 this->build_queue(is_agglomerated, cur_queue);
-
651
-
652 const auto seed = this->_l_of_seeds[cur_queue].front();
-
653 this->_l_of_seeds[cur_queue].pop_front();
-
654 return seed;
-
655 }
-
656 // If everything failed, set to null
-
657 this->_cur_top_queue = std::nullopt;
-
658 }
-
659 return std::nullopt;
-
660 }
-
661
-
668 inline void update(const std::deque<CoMMAIndexType> &new_seeds) override {
-
669 for (const auto &seed : new_seeds) {
-
670 // In order to the neighbourhood priority, we choose to append to the
-
671 // current top queue, rather than switching queue
-
672 const auto q_lvl =
-
673 this->_cur_top_queue.has_value()
-
674 ? std::min(this->_n_bnd_faces[seed], this->_cur_top_queue.value())
-
675 : this->_n_bnd_faces[seed];
-
676 // We add even if already present. Worst case scenario, a check if
-
677 // agglomerated is done when choosing new seed
-
678 this->_l_of_seeds[q_lvl].push_back(seed);
-
679 }
-
680 }
-
681
-
687 inline void order_new_seeds_and_update(
-
688 const std::unordered_set<CoMMAIndexType> &new_seeds) override {
-
689 std::map<CoMMAIntType, CoMMASetOfPairType, std::greater<>> new_seeds_by_bnd;
-
690 for (const auto &seed : new_seeds) {
-
691 new_seeds_by_bnd[this->_n_bnd_faces[seed]].emplace(
-
692 seed, this->_priority_weights[seed]);
-
693 }
-
694 for (auto &[n_bnd, seeds] : new_seeds_by_bnd) {
-
695 // In order to the neighbourhood priority, we choose to append to the
-
696 // current top queue, rather than switching queue
-
697 const auto q_lvl = this->_cur_top_queue.has_value()
-
698 ? std::min(n_bnd, this->_cur_top_queue.value())
-
699 : n_bnd;
-
700 // We add even if already present. Worst case scenario, a check if
-
701 // agglomerated is done when choosing new seed
-
702 std::transform(
-
703 seeds.cbegin(), seeds.cend(),
-
704 std::back_inserter(this->_l_of_seeds[q_lvl]),
-
705 [](const auto &pr) { return pr.first; });
-
706 }
-
707 }
-
708
-
713 bool need_initialization(const std::vector<bool> &is_agglomerated) override {
-
714 CoMMAUnused(is_agglomerated);
-
715 return this->is_empty() || (!this->_cur_top_queue.has_value());
-
716 }
-
717};
-
718
-
719} // end namespace comma
-
720
-
721#endif // COMMA_PROJECT_SEEDS_POOL_H
+
418 inline void initialize() {
+
419 if (!_cur_top_queue.has_value())
+
420 // Computing the max number of boundary faces. Only the related seed queue
+
421 // will be filled at this initial stage
+
422 _cur_top_queue = *(max_element(_n_bnd_faces.begin(), _n_bnd_faces.end()));
+
423 (*this->_initializator)(
+
424 this->_priority_weights,
+
425 this->_n_bnd_faces,
+
426 this->_cur_top_queue.value(),
+
427 this->_l_of_seeds[this->_cur_top_queue.value()]
+
428 );
+
429 }
+
430
+
434 inline void set_top_queue(const CoMMAIntType q_lvl) {
+
435 this->_cur_top_queue = q_lvl;
+
436 }
+
437};
+
438
+
447template<
+
448 typename CoMMAIndexType,
+
449 typename CoMMAWeightType,
+
450 typename CoMMAIntType>
+
451class Seeds_Pool_Boundary_Priority :
+
452 public Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
453public:
+
455 using SeedsPoolBaseType =
+
456 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
458 using typename SeedsPoolBaseType::CoMMAPairType;
+
460 using typename SeedsPoolBaseType::CoMMASetOfPairType;
+
461
+
470 Seeds_Pool_Boundary_Priority(
+
471 const std::vector<CoMMAIntType> &n_bnd_faces,
+
472 const std::vector<CoMMAWeightType> &priority_weights,
+
473 const bool one_point_init
+
474 ) :
+
475 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
476 n_bnd_faces, priority_weights, one_point_init
+
477 ) {}
+
478
+
480 ~Seeds_Pool_Boundary_Priority() override = default;
+
481
+
487 std::optional<CoMMAIndexType> choose_new_seed(
+
488 const std::vector<bool> &is_agglomerated
+
489 ) override {
+
490 // Choose a correct seed from the fc pool list_of_seeds beyond not
+
491 // agglomerated fc.
+
492 // We choose preferably the corners, then the ridges, then the valley, and
+
493 // finally interior cells:
+
494 // see NIA (Mavriplis uses Wall and farfield only)
+
495 // Exactly the inverse of the order of the list. For this reason we proceed
+
496 // from the back
+
497 if (this->_cur_top_queue.has_value()) {
+
498 auto opt_seed = this->spoil_queue(
+
499 is_agglomerated, this->_l_of_seeds[this->_cur_top_queue.value()]
+
500 );
+
501 if (opt_seed.has_value()) return opt_seed.value();
+
502 auto opt_top = this->get_highest_n_bnd_yet_to_agglomerate(
+
503 is_agglomerated, this->_cur_top_queue.value()
+
504 );
+
505 if (opt_top.has_value()) {
+
506 const auto cur_queue = opt_top.value();
+
507 this->_cur_top_queue = cur_queue;
+
508 // Could be the same top queue, but that's OK
+
509 opt_seed =
+
510 this->spoil_queue(is_agglomerated, this->_l_of_seeds[cur_queue]);
+
511 if (opt_seed.has_value()) return opt_seed.value();
+
512 // If here, we already used everything that we had in the seeds pool but
+
513 // there are still cells to agglomerate of the same type, hence we need
+
514 // to rebuild the queue from scratch
+
515 this->build_queue(is_agglomerated, cur_queue);
+
516
+
517 const auto seed = this->_l_of_seeds[cur_queue].front();
+
518 this->_l_of_seeds[cur_queue].pop_front();
+
519 return seed;
+
520 }
+
521 // If everything failed, set to null
+
522 this->_cur_top_queue = std::nullopt;
+
523 }
+
524 return std::nullopt;
+
525 }
+
526
+
533 inline void update(const std::deque<CoMMAIndexType> &new_seeds) override {
+
534 if (!new_seeds.empty()) {
+
535 CoMMAIntType max_bnd{0};
+
536 for (const auto &seed : new_seeds) {
+
537 const auto n_bnd = this->_n_bnd_faces[seed];
+
538 if (n_bnd > max_bnd) max_bnd = n_bnd;
+
539 // We add even if already present. Worst case scenario, a check if
+
540 // agglomerated is done when choosing new seed
+
541 this->_l_of_seeds[n_bnd].push_back(seed);
+
542 }
+
543 if (!this->_cur_top_queue.has_value()
+
544 || max_bnd > this->_cur_top_queue.value())
+
545 this->_cur_top_queue = max_bnd;
+
546 }
+
547 }
+
548
+
554 inline void order_new_seeds_and_update(
+
555 const std::unordered_set<CoMMAIndexType> &new_seeds
+
556 ) override {
+
557 std::map<CoMMAIntType, CoMMASetOfPairType, std::greater<>> new_seeds_by_bnd;
+
558 if (!new_seeds.empty()) {
+
559 for (const auto seed : new_seeds) {
+
560 new_seeds_by_bnd[this->_n_bnd_faces[seed]].emplace(
+
561 seed, this->_priority_weights[seed]
+
562 );
+
563 }
+
564 const auto max_bnd = new_seeds_by_bnd.begin()->first;
+
565 if (!this->_cur_top_queue.has_value()
+
566 || max_bnd > this->_cur_top_queue.value())
+
567 this->_cur_top_queue = max_bnd;
+
568 for (const auto &[n_bnd, seeds] : new_seeds_by_bnd) {
+
569 // We add even if already present. Worst case scenario, a check if
+
570 // agglomerated is done when choosing new seed
+
571 std::transform(
+
572 seeds.cbegin(),
+
573 seeds.cend(),
+
574 std::back_inserter(this->_l_of_seeds[n_bnd]),
+
575 [](const auto &pr) { return pr.first; }
+
576 );
+
577 }
+
578 }
+
579 }
+
580
+
587 bool need_initialization(const std::vector<bool> &is_agglomerated) override {
+
588 if (this->is_empty() || (!this->_cur_top_queue.has_value())) return true;
+
589 const auto max_bnd =
+
590 this->get_highest_n_bnd_yet_to_agglomerate(is_agglomerated);
+
591 if (max_bnd.has_value() && max_bnd.value() > this->_cur_top_queue.value()) {
+
592 this->_cur_top_queue = max_bnd.value();
+
593 return true;
+
594 }
+
595 return false;
+
596 }
+
597};
+
598
+
607template<
+
608 typename CoMMAIndexType,
+
609 typename CoMMAWeightType,
+
610 typename CoMMAIntType>
+
611class Seeds_Pool_Neighbourhood_Priority :
+
612 public Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
+
613public:
+
615 using SeedsPoolBaseType =
+
616 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
+
618 using typename SeedsPoolBaseType::CoMMAPairType;
+
620 using typename SeedsPoolBaseType::CoMMASetOfPairType;
+
621
+
630 Seeds_Pool_Neighbourhood_Priority(
+
631 const std::vector<CoMMAIntType> &n_bnd_faces,
+
632 const std::vector<CoMMAWeightType> &priority_weights,
+
633 const bool one_point_init
+
634 ) :
+
635 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
+
636 n_bnd_faces, priority_weights, one_point_init
+
637 ) {}
+
638
+
640 ~Seeds_Pool_Neighbourhood_Priority() override = default;
+
641
+
647 std::optional<CoMMAIndexType> choose_new_seed(
+
648 const std::vector<bool> &is_agglomerated
+
649 ) override {
+
650 // Choose a correct seed from the fc pool list_of_seeds beyond not
+
651 // agglomerated fc.
+
652 // We choose preferably the corners, then the ridges, then the valley, and
+
653 // finally interior cells:
+
654 // see NIA (Mavriplis uses Wall and farfield only)
+
655 // Exactly the inverse of the order of the list. For this reason we proceed
+
656 // from the back
+
657 if (this->_cur_top_queue.has_value()) {
+
658 for (auto queue =
+
659 this->_l_of_seeds.rbegin()
+
660 + (this->_l_of_seeds.size() - (this->_cur_top_queue.value() + 1));
+
661 queue != this->_l_of_seeds.rend();
+
662 ++queue) {
+
663 const auto opt_seed = this->spoil_queue(is_agglomerated, *queue);
+
664 if (opt_seed.has_value()) {
+
665 this->_cur_top_queue = distance(queue, this->_l_of_seeds.rend()) - 1;
+
666 return opt_seed.value();
+
667 }
+
668 }
+
669
+
670 // If not found, see which is the highest unfinished level
+
671 const auto opt_top = this->get_highest_n_bnd_yet_to_agglomerate(
+
672 is_agglomerated, this->_cur_top_queue.value()
+
673 );
+
674 if (opt_top.has_value()) {
+
675 const auto cur_queue = opt_top.value();
+
676 this->_cur_top_queue = cur_queue;
+
677 // Could be the same top queue, but that's OK
+
678 const auto opt_seed =
+
679 this->spoil_queue(is_agglomerated, this->_l_of_seeds[cur_queue]);
+
680 if (opt_seed.has_value()) return opt_seed.value();
+
681 // If here, we already used everything that we had in the seeds pool but
+
682 // there are still cells to agglomerate of the same type, hence we need
+
683 // to rebuild the queue from scratch
+
684 this->build_queue(is_agglomerated, cur_queue);
+
685
+
686 const auto seed = this->_l_of_seeds[cur_queue].front();
+
687 this->_l_of_seeds[cur_queue].pop_front();
+
688 return seed;
+
689 }
+
690 // If everything failed, set to null
+
691 this->_cur_top_queue = std::nullopt;
+
692 }
+
693 return std::nullopt;
+
694 }
+
695
+
702 inline void update(const std::deque<CoMMAIndexType> &new_seeds) override {
+
703 for (const auto &seed : new_seeds) {
+
704 // In order to the neighbourhood priority, we choose to append to the
+
705 // current top queue, rather than switching queue
+
706 const auto q_lvl =
+
707 this->_cur_top_queue.has_value()
+
708 ? std::min(this->_n_bnd_faces[seed], this->_cur_top_queue.value())
+
709 : this->_n_bnd_faces[seed];
+
710 // We add even if already present. Worst case scenario, a check if
+
711 // agglomerated is done when choosing new seed
+
712 this->_l_of_seeds[q_lvl].push_back(seed);
+
713 }
+
714 }
+
715
+
721 inline void order_new_seeds_and_update(
+
722 const std::unordered_set<CoMMAIndexType> &new_seeds
+
723 ) override {
+
724 std::map<CoMMAIntType, CoMMASetOfPairType, std::greater<>> new_seeds_by_bnd;
+
725 for (const auto &seed : new_seeds) {
+
726 new_seeds_by_bnd[this->_n_bnd_faces[seed]].emplace(
+
727 seed, this->_priority_weights[seed]
+
728 );
+
729 }
+
730 for (auto &[n_bnd, seeds] : new_seeds_by_bnd) {
+
731 // In order to the neighbourhood priority, we choose to append to the
+
732 // current top queue, rather than switching queue
+
733 const auto q_lvl = this->_cur_top_queue.has_value()
+
734 ? std::min(n_bnd, this->_cur_top_queue.value())
+
735 : n_bnd;
+
736 // We add even if already present. Worst case scenario, a check if
+
737 // agglomerated is done when choosing new seed
+
738 std::transform(
+
739 seeds.cbegin(),
+
740 seeds.cend(),
+
741 std::back_inserter(this->_l_of_seeds[q_lvl]),
+
742 [](const auto &pr) { return pr.first; }
+
743 );
+
744 }
+
745 }
+
746
+
751 bool need_initialization(const std::vector<bool> &is_agglomerated) override {
+
752 CoMMAUnused(is_agglomerated);
+
753 return this->is_empty() || (!this->_cur_top_queue.has_value());
+
754 }
+
755};
+
756
+
757} // end namespace comma
+
758
+
759#endif // COMMA_PROJECT_SEEDS_POOL_H
CoMMADefs.h
Util.h
CoMMAUnused
#define CoMMAUnused(var)
Convenient function to avoid unused warnings.
Definition: Util.h:34
-
comma::Seeds_Pool_Boundary_Priority
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:430
-
comma::Seeds_Pool_Boundary_Priority::order_new_seeds_and_update
void order_new_seeds_and_update(const std::unordered_set< CoMMAIndexType > &new_seeds) override
Add the provided seeds to a seeds pool queue according to the number of boundary faces....
Definition: Seeds_Pool.h:528
-
comma::Seeds_Pool_Boundary_Priority::need_initialization
bool need_initialization(const std::vector< bool > &is_agglomerated) override
Whether the seeds pool need to be initialized. It updates the top queue if necessary.
Definition: Seeds_Pool.h:558
-
comma::Seeds_Pool_Boundary_Priority::Seeds_Pool_Boundary_Priority
Seeds_Pool_Boundary_Priority(const std::vector< CoMMAIntType > &n_bnd_faces, const std::vector< CoMMAWeightType > &priority_weights, const bool one_point_init)
Constructor.
Definition: Seeds_Pool.h:448
+
comma::Seeds_Pool_Boundary_Priority
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:452
+
comma::Seeds_Pool_Boundary_Priority::order_new_seeds_and_update
void order_new_seeds_and_update(const std::unordered_set< CoMMAIndexType > &new_seeds) override
Add the provided seeds to a seeds pool queue according to the number of boundary faces....
Definition: Seeds_Pool.h:554
+
comma::Seeds_Pool_Boundary_Priority::need_initialization
bool need_initialization(const std::vector< bool > &is_agglomerated) override
Whether the seeds pool need to be initialized. It updates the top queue if necessary.
Definition: Seeds_Pool.h:587
+
comma::Seeds_Pool_Boundary_Priority::Seeds_Pool_Boundary_Priority
Seeds_Pool_Boundary_Priority(const std::vector< CoMMAIntType > &n_bnd_faces, const std::vector< CoMMAWeightType > &priority_weights, const bool one_point_init)
Constructor.
Definition: Seeds_Pool.h:470
comma::Seeds_Pool_Boundary_Priority::~Seeds_Pool_Boundary_Priority
~Seeds_Pool_Boundary_Priority() override=default
Destructor.
-
comma::Seeds_Pool_Boundary_Priority::update
void update(const std::deque< CoMMAIndexType > &new_seeds) override
Add the provided seeds to a seeds pool queue according to the number of boundary faces....
Definition: Seeds_Pool.h:506
-
comma::Seeds_Pool_Boundary_Priority::choose_new_seed
std::optional< CoMMAIndexType > choose_new_seed(const std::vector< bool > &is_agglomerated) override
Choose a new seed in the pool.
Definition: Seeds_Pool.h:463
-
comma::Seeds_Pool_Neighbourhood_Priority
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:583
-
comma::Seeds_Pool_Neighbourhood_Priority::choose_new_seed
std::optional< CoMMAIndexType > choose_new_seed(const std::vector< bool > &is_agglomerated) override
Choose a new seed in the pool.
Definition: Seeds_Pool.h:616
-
comma::Seeds_Pool_Neighbourhood_Priority::need_initialization
bool need_initialization(const std::vector< bool > &is_agglomerated) override
Whether the seeds pool need to be initialized.
Definition: Seeds_Pool.h:713
-
comma::Seeds_Pool_Neighbourhood_Priority::Seeds_Pool_Neighbourhood_Priority
Seeds_Pool_Neighbourhood_Priority(const std::vector< CoMMAIntType > &n_bnd_faces, const std::vector< CoMMAWeightType > &priority_weights, const bool one_point_init)
Constructor.
Definition: Seeds_Pool.h:601
+
comma::Seeds_Pool_Boundary_Priority::update
void update(const std::deque< CoMMAIndexType > &new_seeds) override
Add the provided seeds to a seeds pool queue according to the number of boundary faces....
Definition: Seeds_Pool.h:533
+
comma::Seeds_Pool_Boundary_Priority::choose_new_seed
std::optional< CoMMAIndexType > choose_new_seed(const std::vector< bool > &is_agglomerated) override
Choose a new seed in the pool.
Definition: Seeds_Pool.h:487
+
comma::Seeds_Pool_Neighbourhood_Priority
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:612
+
comma::Seeds_Pool_Neighbourhood_Priority::choose_new_seed
std::optional< CoMMAIndexType > choose_new_seed(const std::vector< bool > &is_agglomerated) override
Choose a new seed in the pool.
Definition: Seeds_Pool.h:647
+
comma::Seeds_Pool_Neighbourhood_Priority::need_initialization
bool need_initialization(const std::vector< bool > &is_agglomerated) override
Whether the seeds pool need to be initialized.
Definition: Seeds_Pool.h:751
+
comma::Seeds_Pool_Neighbourhood_Priority::Seeds_Pool_Neighbourhood_Priority
Seeds_Pool_Neighbourhood_Priority(const std::vector< CoMMAIntType > &n_bnd_faces, const std::vector< CoMMAWeightType > &priority_weights, const bool one_point_init)
Constructor.
Definition: Seeds_Pool.h:630
comma::Seeds_Pool_Neighbourhood_Priority::~Seeds_Pool_Neighbourhood_Priority
~Seeds_Pool_Neighbourhood_Priority() override=default
Destructor.
-
comma::Seeds_Pool_Neighbourhood_Priority::order_new_seeds_and_update
void order_new_seeds_and_update(const std::unordered_set< CoMMAIndexType > &new_seeds) override
Add the provided seeds to a seeds pool queue according to the number of boundary faces....
Definition: Seeds_Pool.h:687
-
comma::Seeds_Pool_Neighbourhood_Priority::update
void update(const std::deque< CoMMAIndexType > &new_seeds) override
Add the provided seeds to a seeds pool queue according to the number of boundary faces.
Definition: Seeds_Pool.h:668
-
comma::Seeds_Pool
Class representing the pool of all the seeds for creating a coarse cell.
Definition: Seeds_Pool.h:194
+
comma::Seeds_Pool_Neighbourhood_Priority::order_new_seeds_and_update
void order_new_seeds_and_update(const std::unordered_set< CoMMAIndexType > &new_seeds) override
Add the provided seeds to a seeds pool queue according to the number of boundary faces....
Definition: Seeds_Pool.h:721
+
comma::Seeds_Pool_Neighbourhood_Priority::update
void update(const std::deque< CoMMAIndexType > &new_seeds) override
Add the provided seeds to a seeds pool queue according to the number of boundary faces.
Definition: Seeds_Pool.h:702
+
comma::Seeds_Pool
Class representing the pool of all the seeds for creating a coarse cell.
Definition: Seeds_Pool.h:200
comma::Seeds_Pool::need_initialization
virtual bool need_initialization(const std::vector< bool > &is_agglomerated)=0
Whether the seeds pool need to be initialized.
-
comma::Seeds_Pool::_l_of_seeds
std::vector< CoMMAQueueType > _l_of_seeds
List of deque of seeds. For each identifier we have the available seeds. We want the seed to be chose...
Definition: Seeds_Pool.h:223
-
comma::Seeds_Pool::get_highest_n_bnd_yet_to_agglomerate
std::optional< CoMMAIntType > get_highest_n_bnd_yet_to_agglomerate(const std::vector< bool > &is_fc_agglomerated, const CoMMAIntType expected_max=CoMMACellT::CORNER) const
Compute the highest number of boundary faces of cells which are not agglomerated yet.
Definition: Seeds_Pool.h:346
-
comma::Seeds_Pool::_priority_weights
const std::vector< CoMMAWeightType > & _priority_weights
Weights used to set the order of the seed to choose.
Definition: Seeds_Pool.h:226
-
comma::Seeds_Pool::Seeds_Pool
Seeds_Pool(const std::vector< CoMMAIntType > &n_bnd_faces, const std::vector< CoMMAWeightType > &priority_weights, const bool one_point_init)
Constructor.
Definition: Seeds_Pool.h:250
+
comma::Seeds_Pool::_l_of_seeds
std::vector< CoMMAQueueType > _l_of_seeds
List of deque of seeds. For each identifier we have the available seeds. We want the seed to be chose...
Definition: Seeds_Pool.h:229
+
comma::Seeds_Pool::get_highest_n_bnd_yet_to_agglomerate
std::optional< CoMMAIntType > get_highest_n_bnd_yet_to_agglomerate(const std::vector< bool > &is_fc_agglomerated, const CoMMAIntType expected_max=CoMMACellT::CORNER) const
Compute the highest number of boundary faces of cells which are not agglomerated yet.
Definition: Seeds_Pool.h:359
+
comma::Seeds_Pool::_priority_weights
const std::vector< CoMMAWeightType > & _priority_weights
Weights used to set the order of the seed to choose.
Definition: Seeds_Pool.h:232
+
comma::Seeds_Pool::Seeds_Pool
Seeds_Pool(const std::vector< CoMMAIntType > &n_bnd_faces, const std::vector< CoMMAWeightType > &priority_weights, const bool one_point_init)
Constructor.
Definition: Seeds_Pool.h:256
comma::Seeds_Pool::choose_new_seed
virtual std::optional< CoMMAIndexType > choose_new_seed(const std::vector< bool > &is_agglomerated)=0
Choose a new seed in the pool.
-
comma::Seeds_Pool::is_empty
bool is_empty(CoMMAIntType i_level=CoMMACellT::N_CELL_TYPES) const
Given the default levels we define if the list of the targeted level is empty.
Definition: Seeds_Pool.h:366
-
comma::Seeds_Pool::CoMMAPairType
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Seeds_Pool.h:197
+
comma::Seeds_Pool::is_empty
bool is_empty(CoMMAIntType i_level=CoMMACellT::N_CELL_TYPES) const
Given the default levels we define if the list of the targeted level is empty.
Definition: Seeds_Pool.h:385
+
comma::Seeds_Pool::CoMMAPairType
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Seeds_Pool.h:203
comma::Seeds_Pool::~Seeds_Pool
virtual ~Seeds_Pool()=default
Destructor.
-
comma::Seeds_Pool::initialize
void initialize()
Initialize the seeds pool via a call to its initializator.
Definition: Seeds_Pool.h:399
+
comma::Seeds_Pool::initialize
void initialize()
Initialize the seeds pool via a call to its initializator.
Definition: Seeds_Pool.h:418
comma::Seeds_Pool::update
virtual void update(const std::deque< CoMMAIndexType > &new_seeds)=0
Add the provided seeds to a seeds pool queue according to the number of boundary faces.
-
comma::Seeds_Pool::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Seeds_Pool.h:216
-
comma::Seeds_Pool::_cur_top_queue
std::optional< CoMMAIntType > _cur_top_queue
Optional possibly containing the level (0,1,2,3, see Seeds_Pool::_l_of_seeds) of the queue currently ...
Definition: Seeds_Pool.h:231
-
comma::Seeds_Pool::spoil_queue
std::optional< CoMMAIndexType > spoil_queue(const std::vector< bool > &is_fc_agglomerated, CoMMAQueueType &queue)
Spoil a queue looking for an not-yet-agglomerated seed.
Definition: Seeds_Pool.h:278
-
comma::Seeds_Pool::set_top_queue
void set_top_queue(const CoMMAIntType q_lvl)
Setter for the top queue member.
Definition: Seeds_Pool.h:412
-
comma::Seeds_Pool::CoMMAQueueType
std::deque< CoMMAIndexType > CoMMAQueueType
Type of queue which holds seeds.
Definition: Seeds_Pool.h:213
-
comma::Seeds_Pool::_initializator
std::shared_ptr< SPInitializator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > _initializator
Pointer to a SPInitializator.
Definition: Seeds_Pool.h:236
+
comma::Seeds_Pool::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Seeds_Pool.h:222
+
comma::Seeds_Pool::_cur_top_queue
std::optional< CoMMAIntType > _cur_top_queue
Optional possibly containing the level (0,1,2,3, see Seeds_Pool::_l_of_seeds) of the queue currently ...
Definition: Seeds_Pool.h:237
+
comma::Seeds_Pool::spoil_queue
std::optional< CoMMAIndexType > spoil_queue(const std::vector< bool > &is_fc_agglomerated, CoMMAQueueType &queue)
Spoil a queue looking for an not-yet-agglomerated seed.
Definition: Seeds_Pool.h:286
+
comma::Seeds_Pool::set_top_queue
void set_top_queue(const CoMMAIntType q_lvl)
Setter for the top queue member.
Definition: Seeds_Pool.h:434
+
comma::Seeds_Pool::CoMMAQueueType
std::deque< CoMMAIndexType > CoMMAQueueType
Type of queue which holds seeds.
Definition: Seeds_Pool.h:219
+
comma::Seeds_Pool::_initializator
std::shared_ptr< SPInitializator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType > > _initializator
Pointer to a SPInitializator.
Definition: Seeds_Pool.h:242
comma::Seeds_Pool::order_new_seeds_and_update
virtual void order_new_seeds_and_update(const std::unordered_set< CoMMAIndexType > &new_seeds)=0
Add the provided seeds to a seeds pool queue according to the number of boundary faces....
-
comma::Seeds_Pool::build_queue
void build_queue(const std::vector< bool > &is_fc_agglomerated, const CoMMAIntType target)
Build the weight-ordered queue of seed for a given target level. A set of (index, weight) pair with s...
Definition: Seeds_Pool.h:324
-
comma::Seeds_Pool::_n_bnd_faces
const std::vector< CoMMAIntType > & _n_bnd_faces
Vector of number of faces on boundary per cell.
Definition: Seeds_Pool.h:240
+
comma::Seeds_Pool::build_queue
void build_queue(const std::vector< bool > &is_fc_agglomerated, const CoMMAIntType target)
Build the weight-ordered queue of seed for a given target level. A set of (index, weight) pair with s...
Definition: Seeds_Pool.h:335
+
comma::Seeds_Pool::_n_bnd_faces
const std::vector< CoMMAIntType > & _n_bnd_faces
Vector of number of faces on boundary per cell.
Definition: Seeds_Pool.h:246
comma
Definition: Agglomerator.h:34
comma::N_CELL_TYPES
@ N_CELL_TYPES
Total number of values.
Definition: CoMMADefs.h:31
comma::CORNER
@ CORNER
Corners, three boundary faces.
Definition: CoMMADefs.h:28
comma::VALLEY
@ VALLEY
Valley, one boundary face.
Definition: CoMMADefs.h:26
comma::RIDGE
@ RIDGE
Ridge, two boundary faces.
Definition: CoMMADefs.h:27
comma::INTERIOR
@ INTERIOR
Interior cell, no boundary faces.
Definition: CoMMADefs.h:25
-
comma::CustomPairGreaterFunctor
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:154
-
comma::CustomPairLessFunctor
Functor for pairs implementing a custom 'less than'. It relies on the 'less than' operator for the se...
Definition: Util.h:131
-
comma::SPFullInitializator
Functor performing the full initialization of a seeds pool.
Definition: Seeds_Pool.h:87
-
comma::SPFullInitializator::SPFullInitializator
SPFullInitializator()
Constructor.
Definition: Seeds_Pool.h:97
+
comma::CustomPairGreaterFunctor
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:156
+
comma::CustomPairLessFunctor
Functor for pairs implementing a custom 'less than'. It relies on the 'less than' operator for the se...
Definition: Util.h:133
+
comma::SPFullInitializator
Functor performing the full initialization of a seeds pool.
Definition: Seeds_Pool.h:88
+
comma::SPFullInitializator::SPFullInitializator
SPFullInitializator()
Constructor.
Definition: Seeds_Pool.h:98
comma::SPFullInitializator::~SPFullInitializator
~SPFullInitializator() override=default
Destructor.
-
comma::SPFullInitializator::operator()
void operator()(const std::vector< CoMMAWeightType > &priority_weights, const std::vector< CoMMAIntType > &n_bnd_faces, const CoMMAIntType max_bnd, CoMMAQueueType &queue) override
Initialize a queue of a seeds pool.
Definition: Seeds_Pool.h:111
+
comma::SPFullInitializator::operator()
void operator()(const std::vector< CoMMAWeightType > &priority_weights, const std::vector< CoMMAIntType > &n_bnd_faces, const CoMMAIntType max_bnd, CoMMAQueueType &queue) override
Initialize a queue of a seeds pool.
Definition: Seeds_Pool.h:113
comma::SPFullInitializator::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Seeds_Pool.h:52
comma::SPFullInitializator::CoMMAQueueType
std::deque< CoMMAIndexType > CoMMAQueueType
Type of queue which holds seeds.
Definition: Seeds_Pool.h:49
comma::SPInitializator
Functor performing the initialization of a seeds pool.
Definition: Seeds_Pool.h:45
@@ -649,11 +687,11 @@
comma::SPInitializator::operator()
virtual void operator()(const std::vector< CoMMAWeightType > &priority_weights, const std::vector< CoMMAIntType > &n_bnd_faces, const CoMMAIntType max_bnd, CoMMAQueueType &queue)=0
Initialize a queue of a seeds pool.
comma::SPInitializator::CoMMASetOfPairType
std::set< CoMMAPairType, CustomPairGreaterFunctor< CoMMAPairType > > CoMMASetOfPairType
Type of set of pairs.
Definition: Seeds_Pool.h:52
comma::SPInitializator::CoMMAQueueType
std::deque< CoMMAIndexType > CoMMAQueueType
Type of queue which holds seeds.
Definition: Seeds_Pool.h:49
-
comma::SPOnePointInitializator
Functor performing the one-point initialization of a seeds pool.
Definition: Seeds_Pool.h:140
+
comma::SPOnePointInitializator
Functor performing the one-point initialization of a seeds pool.
Definition: Seeds_Pool.h:143
comma::SPOnePointInitializator::CoMMAPairType
std::pair< CoMMAIndexType, CoMMAWeightType > CoMMAPairType
Type of pair.
Definition: Seeds_Pool.h:47
-
comma::SPOnePointInitializator::operator()
void operator()(const std::vector< CoMMAWeightType > &priority_weights, const std::vector< CoMMAIntType > &n_bnd_faces, const CoMMAIntType max_bnd, CoMMAQueueType &queue) override
Initialize a queue of a seeds pool.
Definition: Seeds_Pool.h:164
+
comma::SPOnePointInitializator::operator()
void operator()(const std::vector< CoMMAWeightType > &priority_weights, const std::vector< CoMMAIntType > &n_bnd_faces, const CoMMAIntType max_bnd, CoMMAQueueType &queue) override
Initialize a queue of a seeds pool.
Definition: Seeds_Pool.h:168
comma::SPOnePointInitializator::~SPOnePointInitializator
~SPOnePointInitializator() override=default
Destructor.
-
comma::SPOnePointInitializator::SPOnePointInitializator
SPOnePointInitializator()
Constructor.
Definition: Seeds_Pool.h:150
+
comma::SPOnePointInitializator::SPOnePointInitializator
SPOnePointInitializator()
Constructor.
Definition: Seeds_Pool.h:153
comma::SPOnePointInitializator::CoMMAQueueType
std::deque< CoMMAIndexType > CoMMAQueueType
Type of queue which holds seeds.
Definition: Seeds_Pool.h:49
diff --git a/_tree_8h_source.html b/_tree_8h_source.html index a16dc42..80c23e6 100644 --- a/_tree_8h_source.html +++ b/_tree_8h_source.html @@ -143,87 +143,101 @@
69public:
71 using NodeType = Node<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
72
-
76 explicit Tree(std::shared_ptr<NodeType> &root) : _root(root) {}
-
77
-
79 ~Tree() = default;
-
80
-
82 std::shared_ptr<NodeType> _root;
-
83
-
90 void insertSon(
-
91 const CoMMAIndexType &father_index,
-
92 const CoMMAIndexType &index,
-
93 const CoMMAWeightType &volume,
-
94 const CoMMAIntType &root) {
-
95 std::shared_ptr<NodeType> insertion =
-
96 std::make_shared<NodeType>(index, volume);
-
97 auto u_p_father =
-
98 root == 1 ? _root : search(_root->_left_son_idx, father_index);
-
99 assert(u_p_father != nullptr);
-
100 insertion->_father = u_p_father;
-
101 auto left_idx = transverse(u_p_father->_left_son_idx);
-
102 if (left_idx == nullptr) {
-
103 u_p_father->_left_son_idx = insertion;
-
104 } else {
-
105 insertion->_left_idx = left_idx;
-
106 left_idx->_right_idx = insertion;
-
107 }
-
108 u_p_father->_sonc = u_p_father->_sonc + 1;
-
109 // std::cout << u_p_father->_sonc << std::endl;
-
110 }
-
111
-
117 std::shared_ptr<NodeType> search(
-
118 std::shared_ptr<NodeType> &node, const CoMMAIndexType &value) {
-
119 if (node->_index == value && node->_father != nullptr) { return node; }
-
120 if (node == nullptr || node->_right_idx == nullptr) { return nullptr; }
-
121 return (search(node->_right_idx, value));
-
122 }
-
123
-
128 std::shared_ptr<NodeType> transverse(std::shared_ptr<NodeType> &node) {
-
129 if (node == nullptr || node->_right_idx == nullptr) { return node; }
-
130 return (transverse(node->_right_idx));
-
131 }
-
132
-
136 void deleteNode(const CoMMAIndexType &value) {
-
137 delete_node(_root->_left_son_idx, value);
-
138 }
-
139
-
144 void delete_node(
-
145 std::shared_ptr<NodeType> &searched_node, const CoMMAIndexType &value) {
-
146 if (searched_node == nullptr) { return; }
-
147 if (searched_node->_index == value) {
-
148 // case 0: leftest node
-
149 if (searched_node->_left_idx == nullptr) {
-
150 searched_node->_father->_sonc--;
-
151 searched_node->_father->_left_son_idx = searched_node->_right_idx;
-
152 searched_node->_right_idx->_left_idx = nullptr;
-
153 }
-
154 // case 1: rightest node
-
155 else if (searched_node->_right_idx == nullptr) {
-
156 searched_node->_father->_sonc = searched_node->_father->_sonc - 1;
-
157 searched_node->_left_idx->_right_idx.reset();
-
158 } else {
-
159 searched_node->_father->_sonc--;
-
160 searched_node->_left_idx->_right_idx = searched_node->_right_idx;
-
161 searched_node->_right_idx->_left_idx = searched_node->_left_idx;
-
162 }
-
163 return;
-
164 }
-
165 delete_node(searched_node->_right_idx, value);
-
166 }
-
167
-
169 void print() { print_nodes(_root); }
-
170
-
174 void print_nodes(std::shared_ptr<NodeType> &node) {
-
175 if (node == nullptr) { return; }
-
176 // std::cout << "node" << node->_index << std::endl;
-
177 print_nodes(node->_left_son_idx);
-
178 print_nodes(node->_right_idx);
-
179 }
-
180};
-
181
-
182} // end namespace comma
-
183
-
184#endif // COMMA_PROJECT_TREE_H
+
76 explicit Tree(std::shared_ptr<NodeType> &root) :
+
77 _root(root) {}
+
78
+
80 ~Tree() = default;
+
81
+
83 std::shared_ptr<NodeType> _root;
+
84
+
91 void insertSon(
+
92 const CoMMAIndexType &father_index,
+
93 const CoMMAIndexType &index,
+
94 const CoMMAWeightType &volume,
+
95 const CoMMAIntType &root
+
96 ) {
+
97 std::shared_ptr<NodeType> insertion =
+
98 std::make_shared<NodeType>(index, volume);
+
99 auto u_p_father =
+
100 root == 1 ? _root : search(_root->_left_son_idx, father_index);
+
101 assert(u_p_father != nullptr);
+
102 insertion->_father = u_p_father;
+
103 auto left_idx = transverse(u_p_father->_left_son_idx);
+
104 if (left_idx == nullptr) {
+
105 u_p_father->_left_son_idx = insertion;
+
106 } else {
+
107 insertion->_left_idx = left_idx;
+
108 left_idx->_right_idx = insertion;
+
109 }
+
110 u_p_father->_sonc = u_p_father->_sonc + 1;
+
111 // std::cout << u_p_father->_sonc << std::endl;
+
112 }
+
113
+
119 std::shared_ptr<NodeType> search(
+
120 std::shared_ptr<NodeType> &node, const CoMMAIndexType &value
+
121 ) {
+
122 if (node->_index == value && node->_father != nullptr) {
+
123 return node;
+
124 }
+
125 if (node == nullptr || node->_right_idx == nullptr) {
+
126 return nullptr;
+
127 }
+
128 return (search(node->_right_idx, value));
+
129 }
+
130
+
135 std::shared_ptr<NodeType> transverse(std::shared_ptr<NodeType> &node) {
+
136 if (node == nullptr || node->_right_idx == nullptr) {
+
137 return node;
+
138 }
+
139 return (transverse(node->_right_idx));
+
140 }
+
141
+
145 void deleteNode(const CoMMAIndexType &value) {
+
146 delete_node(_root->_left_son_idx, value);
+
147 }
+
148
+
153 void delete_node(
+
154 std::shared_ptr<NodeType> &searched_node, const CoMMAIndexType &value
+
155 ) {
+
156 if (searched_node == nullptr) {
+
157 return;
+
158 }
+
159 if (searched_node->_index == value) {
+
160 // case 0: leftest node
+
161 if (searched_node->_left_idx == nullptr) {
+
162 searched_node->_father->_sonc--;
+
163 searched_node->_father->_left_son_idx = searched_node->_right_idx;
+
164 searched_node->_right_idx->_left_idx = nullptr;
+
165 }
+
166 // case 1: rightest node
+
167 else if (searched_node->_right_idx == nullptr) {
+
168 searched_node->_father->_sonc = searched_node->_father->_sonc - 1;
+
169 searched_node->_left_idx->_right_idx.reset();
+
170 } else {
+
171 searched_node->_father->_sonc--;
+
172 searched_node->_left_idx->_right_idx = searched_node->_right_idx;
+
173 searched_node->_right_idx->_left_idx = searched_node->_left_idx;
+
174 }
+
175 return;
+
176 }
+
177 delete_node(searched_node->_right_idx, value);
+
178 }
+
179
+
181 void print() { print_nodes(_root); }
+
182
+
186 void print_nodes(std::shared_ptr<NodeType> &node) {
+
187 if (node == nullptr) {
+
188 return;
+
189 }
+
190 // std::cout << "node" << node->_index << std::endl;
+
191 print_nodes(node->_left_son_idx);
+
192 print_nodes(node->_right_idx);
+
193 }
+
194};
+
195
+
196} // end namespace comma
+
197
+
198#endif // COMMA_PROJECT_TREE_H
comma::Node
Node data structure that represent a node of the tree.
Definition: Tree.h:36
comma::Node::_right_idx
std::shared_ptr< Node > _right_idx
Shared pointer to the right element.
Definition: Tree.h:51
comma::Node::_left_son_idx
std::shared_ptr< Node > _left_son_idx
Shared pointer to the left element.
Definition: Tree.h:53
@@ -234,14 +248,14 @@
comma::Node::Node
Node(CoMMAIndexType index, CoMMAWeightType volume)
Definition: Tree.h:38
comma::Node::_index
CoMMAIndexType _index
Index of the cell.
Definition: Tree.h:41
comma::Tree
Tree structure that represent a coarse cell, the fine cell and the neighbours to them.
Definition: Tree.h:68
-
comma::Tree::print_nodes
void print_nodes(std::shared_ptr< NodeType > &node)
Print the branches starting from a given node.
Definition: Tree.h:174
-
comma::Tree::_root
std::shared_ptr< NodeType > _root
The Node at the root of the tree.
Definition: Tree.h:82
-
comma::Tree::deleteNode
void deleteNode(const CoMMAIndexType &value)
Delete a node.
Definition: Tree.h:136
-
comma::Tree::insertSon
void insertSon(const CoMMAIndexType &father_index, const CoMMAIndexType &index, const CoMMAWeightType &volume, const CoMMAIntType &root)
Insert a node as child of a given node.
Definition: Tree.h:90
-
comma::Tree::transverse
std::shared_ptr< NodeType > transverse(std::shared_ptr< NodeType > &node)
Traverse the tree.
Definition: Tree.h:128
-
comma::Tree::print
void print()
Print the tree.
Definition: Tree.h:169
-
comma::Tree::search
std::shared_ptr< NodeType > search(std::shared_ptr< NodeType > &node, const CoMMAIndexType &value)
Look for a node.
Definition: Tree.h:117
-
comma::Tree::delete_node
void delete_node(std::shared_ptr< NodeType > &searched_node, const CoMMAIndexType &value)
Delete a node.
Definition: Tree.h:144
+
comma::Tree::print_nodes
void print_nodes(std::shared_ptr< NodeType > &node)
Print the branches starting from a given node.
Definition: Tree.h:186
+
comma::Tree::_root
std::shared_ptr< NodeType > _root
The Node at the root of the tree.
Definition: Tree.h:83
+
comma::Tree::deleteNode
void deleteNode(const CoMMAIndexType &value)
Delete a node.
Definition: Tree.h:145
+
comma::Tree::insertSon
void insertSon(const CoMMAIndexType &father_index, const CoMMAIndexType &index, const CoMMAWeightType &volume, const CoMMAIntType &root)
Insert a node as child of a given node.
Definition: Tree.h:91
+
comma::Tree::transverse
std::shared_ptr< NodeType > transverse(std::shared_ptr< NodeType > &node)
Traverse the tree.
Definition: Tree.h:135
+
comma::Tree::print
void print()
Print the tree.
Definition: Tree.h:181
+
comma::Tree::search
std::shared_ptr< NodeType > search(std::shared_ptr< NodeType > &node, const CoMMAIndexType &value)
Look for a node.
Definition: Tree.h:119
+
comma::Tree::delete_node
void delete_node(std::shared_ptr< NodeType > &searched_node, const CoMMAIndexType &value)
Delete a node.
Definition: Tree.h:153
comma::Tree::~Tree
~Tree()=default
Destructor.
comma::Tree::Tree
Tree(std::shared_ptr< NodeType > &root)
Constructor.
Definition: Tree.h:76
comma
Definition: Agglomerator.h:34
diff --git a/_util_8h_source.html b/_util_8h_source.html index d976995..b01129b 100644 --- a/_util_8h_source.html +++ b/_util_8h_source.html @@ -148,162 +148,170 @@
71
81template<typename T>
82inline T get_direction(
-
83 const std::vector<T> &a, const std::vector<T> &b, std::vector<T> &dir) {
-
84 T norm{0.};
-
85 for (auto i = decltype(a.size()){0}; i < a.size(); ++i) {
-
86 const T di = b[i] - a[i];
-
87 dir[i] = di;
-
88 norm += di * di;
-
89 }
-
90 norm = sqrt(norm);
-
91 const T ov_norm = T{1.} / norm;
-
92 for (auto &di : dir)
-
93 di *= ov_norm;
-
94 return norm;
-
95}
-
96
-
107template<typename T>
-
108inline T squared_euclidean_distance(
-
109 const std::vector<T> &a, const std::vector<T> &b) {
-
110#if 0
-
111 return sqrt(
-
112 transform_reduce(a.cbegin(), a.cend(), b.cbegin(), T{0.},
-
113 [](const auto sum, const auto val){return sum + val*val;},
-
114 minus<T>())
-
115 );
-
116#endif
-
117 T dist{0.};
-
118 for (auto i = decltype(a.size()){0}; i < a.size(); ++i) {
-
119 const auto diff = a[i] - b[i];
-
120 dist += diff * diff;
-
121 }
-
122 return dist;
-
123}
-
124
-
130template<class PairT>
-
131struct CustomPairLessFunctor {
-
140 inline bool operator()(const PairT &left, const PairT &right) const {
-
141 if (left.second < right.second) return true;
-
142 if (left.second > right.second) return false;
-
143 /* left.second == right.second */
-
144 return left.first > right.first;
-
145 }
-
146};
-
147
-
153template<typename PairT>
-
154struct CustomPairGreaterFunctor {
-
163 inline bool operator()(const PairT &left, const PairT &right) const {
-
164 // I tried this: return !CustomPairLessFunctor<PairT>()(left,right);
-
165 // but it didn't work well for equality
-
166 if (left.second > right.second) return true;
-
167 if (left.second < right.second) return false;
-
168 /* left.second == right.second */
-
169 return left.first < right.first;
-
170 }
-
171};
-
172
-
177template<typename PairT>
-
178struct PairSecondBasedLessFunctor {
-
185 inline bool operator()(const PairT &left, const PairT &right) const {
-
186 return left.second < right.second;
-
187 }
-
188};
-
189
-
196template<typename CoMMAContainerPairType>
-
197inline std::vector<typename CoMMAContainerPairType::value_type::first_type>
-
198vector_of_first_elements(const CoMMAContainerPairType &cont) {
-
199 std::vector<typename CoMMAContainerPairType::value_type::first_type> fe;
-
200 fe.reserve(cont.size());
-
201 for (const auto &pr : cont)
-
202 fe.emplace_back(pr.first);
-
203 return fe;
-
204}
-
205
-
210template<typename PairT>
-
211class PairFindFirstBasedFunctor {
-
212public:
-
214 PairFindFirstBasedFunctor() : _target(){};
-
218 // NOLINTNEXTLINE
-
219 PairFindFirstBasedFunctor(const typename PairT::first_type &target) :
-
220 _target(target){};
-
222 ~PairFindFirstBasedFunctor() = default;
-
228 inline bool operator()(const PairT &pr) const { return pr.first == _target; }
-
229
-
230private:
-
232 typename PairT::first_type _target;
-
233};
-
234
-
241template<typename KeyT, typename ValueT>
-
242inline std::unordered_set<KeyT> d_keys_to_set(
-
243 const std::unordered_map<KeyT, ValueT> &dict) {
-
244 std::unordered_set<KeyT> s_neighbours_of_seed = {};
-
245 for (const auto &i_k_v : dict) {
-
246 s_neighbours_of_seed.insert(i_k_v.first);
-
247 }
-
248 return s_neighbours_of_seed;
-
249}
-
250
-
272template<typename IndexT, typename DistT>
-
273void compute_neighbourhood_based_wall_distance(
-
274 const std::vector<IndexT> &neigh_idxs,
-
275 const std::vector<IndexT> &neighs,
-
276 const std::vector<IndexT> &wall,
-
277 std::vector<DistT> &dist) {
-
278 static_assert(
-
279 std::is_signed<DistT>::value,
-
280 "The distance type should be signed to allow flags (negative values)");
-
281 dist.resize(neigh_idxs.size() - 1);
-
282 std::fill(dist.begin(), dist.end(), DistT{-1});
-
283 std::queue<IndexT> to_visit{};
-
284 for (const auto &cell : wall) {
-
285 dist[cell] = DistT{0};
-
286 to_visit.emplace(cell);
-
287 }
-
288 while (!to_visit.empty()) {
-
289 // If you get wrong results, this could might be to the fact that one should
-
290 // consider not specially the first of the queue, but the one with lowest
-
291 // distance visited so far. So, the definition of `cur` below should be
-
292 // changed, and with that, another container should be used instead of a
-
293 // queue, since one might pop from whenever and not only the front (a deque
-
294 // should work).
-
295 const auto cur = to_visit.front();
-
296 to_visit.pop();
-
297 const auto cur_dist = dist[cur] + DistT{1};
-
298 for (auto neigh = neighs.cbegin() + neigh_idxs[cur];
-
299 neigh < neighs.cbegin() + neigh_idxs[cur + 1]; ++neigh) {
-
300 if (dist[*neigh] < DistT{0}) {
-
301 dist[*neigh] = cur_dist;
-
302 to_visit.emplace(*neigh);
-
303 } else if (dist[*neigh] > cur_dist) {
-
304 dist[*neigh] = cur_dist;
-
305 }
-
306 }
-
307 }
-
308}
-
309
-
310} // end namespace comma
-
311
-
312#endif // COMMA_PROJECT_UTIL_H
-
comma::PairFindFirstBasedFunctor
Functor implementing an operator telling if a given value if the first one of pair.
Definition: Util.h:211
-
comma::PairFindFirstBasedFunctor::operator()
bool operator()(const PairT &pr) const
Operator telling if the first value of the given pair is equal to the reference one.
Definition: Util.h:228
+
83 const std::vector<T> &a, const std::vector<T> &b, std::vector<T> &dir
+
84) {
+
85 T norm{0.};
+
86 for (auto i = decltype(a.size()){0}; i < a.size(); ++i) {
+
87 const T di = b[i] - a[i];
+
88 dir[i] = di;
+
89 norm += di * di;
+
90 }
+
91 norm = sqrt(norm);
+
92 const T ov_norm = T{1.} / norm;
+
93 for (auto &di : dir)
+
94 di *= ov_norm;
+
95 return norm;
+
96}
+
97
+
108template<typename T>
+
109inline T squared_euclidean_distance(
+
110 const std::vector<T> &a, const std::vector<T> &b
+
111) {
+
112#if 0
+
113 return sqrt(
+
114 transform_reduce(a.cbegin(), a.cend(), b.cbegin(), T{0.},
+
115 [](const auto sum, const auto val){return sum + val*val;},
+
116 minus<T>())
+
117 );
+
118#endif
+
119 T dist{0.};
+
120 for (auto i = decltype(a.size()){0}; i < a.size(); ++i) {
+
121 const auto diff = a[i] - b[i];
+
122 dist += diff * diff;
+
123 }
+
124 return dist;
+
125}
+
126
+
132template<class PairT>
+
133struct CustomPairLessFunctor {
+
142 inline bool operator()(const PairT &left, const PairT &right) const {
+
143 if (left.second < right.second) return true;
+
144 if (left.second > right.second) return false;
+
145 /* left.second == right.second */
+
146 return left.first > right.first;
+
147 }
+
148};
+
149
+
155template<typename PairT>
+
156struct CustomPairGreaterFunctor {
+
165 inline bool operator()(const PairT &left, const PairT &right) const {
+
166 // I tried this: return !CustomPairLessFunctor<PairT>()(left,right);
+
167 // but it didn't work well for equality
+
168 if (left.second > right.second) return true;
+
169 if (left.second < right.second) return false;
+
170 /* left.second == right.second */
+
171 return left.first < right.first;
+
172 }
+
173};
+
174
+
179template<typename PairT>
+
180struct PairSecondBasedLessFunctor {
+
187 inline bool operator()(const PairT &left, const PairT &right) const {
+
188 return left.second < right.second;
+
189 }
+
190};
+
191
+
198template<typename CoMMAContainerPairType>
+
199inline std::vector<typename CoMMAContainerPairType::value_type::first_type>
+
200vector_of_first_elements(const CoMMAContainerPairType &cont) {
+
201 std::vector<typename CoMMAContainerPairType::value_type::first_type> fe;
+
202 fe.reserve(cont.size());
+
203 for (const auto &pr : cont)
+
204 fe.emplace_back(pr.first);
+
205 return fe;
+
206}
+
207
+
212template<typename PairT>
+
213class PairFindFirstBasedFunctor {
+
214public:
+
216 PairFindFirstBasedFunctor() :
+
217 _target(){};
+
221 // NOLINTNEXTLINE
+
222 PairFindFirstBasedFunctor(const typename PairT::first_type &target) :
+
223 _target(target){};
+
225 ~PairFindFirstBasedFunctor() = default;
+
226
+
232 inline bool operator()(const PairT &pr) const { return pr.first == _target; }
+
233
+
234private:
+
236 typename PairT::first_type _target;
+
237};
+
238
+
245template<typename KeyT, typename ValueT>
+
246inline std::unordered_set<KeyT> d_keys_to_set(
+
247 const std::unordered_map<KeyT, ValueT> &dict
+
248) {
+
249 std::unordered_set<KeyT> s_neighbours_of_seed = {};
+
250 for (const auto &i_k_v : dict) {
+
251 s_neighbours_of_seed.insert(i_k_v.first);
+
252 }
+
253 return s_neighbours_of_seed;
+
254}
+
255
+
277template<typename IndexT, typename DistT>
+
278void compute_neighbourhood_based_wall_distance(
+
279 const std::vector<IndexT> &neigh_idxs,
+
280 const std::vector<IndexT> &neighs,
+
281 const std::vector<IndexT> &wall,
+
282 std::vector<DistT> &dist
+
283) {
+
284 static_assert(
+
285 std::is_signed<DistT>::value,
+
286 "The distance type should be signed to allow flags (negative values)"
+
287 );
+
288 dist.resize(neigh_idxs.size() - 1);
+
289 std::fill(dist.begin(), dist.end(), DistT{-1});
+
290 std::queue<IndexT> to_visit{};
+
291 for (const auto &cell : wall) {
+
292 dist[cell] = DistT{0};
+
293 to_visit.emplace(cell);
+
294 }
+
295 while (!to_visit.empty()) {
+
296 // If you get wrong results, this could might be to the fact that one should
+
297 // consider not specially the first of the queue, but the one with lowest
+
298 // distance visited so far. So, the definition of `cur` below should be
+
299 // changed, and with that, another container should be used instead of a
+
300 // queue, since one might pop from whenever and not only the front (a deque
+
301 // should work).
+
302 const auto cur = to_visit.front();
+
303 to_visit.pop();
+
304 const auto cur_dist = dist[cur] + DistT{1};
+
305 for (auto neigh = neighs.cbegin() + neigh_idxs[cur];
+
306 neigh < neighs.cbegin() + neigh_idxs[cur + 1];
+
307 ++neigh) {
+
308 if (dist[*neigh] < DistT{0}) {
+
309 dist[*neigh] = cur_dist;
+
310 to_visit.emplace(*neigh);
+
311 } else if (dist[*neigh] > cur_dist) {
+
312 dist[*neigh] = cur_dist;
+
313 }
+
314 }
+
315 }
+
316}
+
317
+
318} // end namespace comma
+
319
+
320#endif // COMMA_PROJECT_UTIL_H
+
comma::PairFindFirstBasedFunctor
Functor implementing an operator telling if a given value if the first one of pair.
Definition: Util.h:213
+
comma::PairFindFirstBasedFunctor::operator()
bool operator()(const PairT &pr) const
Operator telling if the first value of the given pair is equal to the reference one.
Definition: Util.h:232
comma::PairFindFirstBasedFunctor::~PairFindFirstBasedFunctor
~PairFindFirstBasedFunctor()=default
Destructor.
-
comma::PairFindFirstBasedFunctor::PairFindFirstBasedFunctor
PairFindFirstBasedFunctor()
Constructor.
Definition: Util.h:214
-
comma::PairFindFirstBasedFunctor::PairFindFirstBasedFunctor
PairFindFirstBasedFunctor(const typename PairT::first_type &target)
Constructor.
Definition: Util.h:219
+
comma::PairFindFirstBasedFunctor::PairFindFirstBasedFunctor
PairFindFirstBasedFunctor()
Constructor.
Definition: Util.h:216
+
comma::PairFindFirstBasedFunctor::PairFindFirstBasedFunctor
PairFindFirstBasedFunctor(const typename PairT::first_type &target)
Constructor.
Definition: Util.h:222
comma
Definition: Agglomerator.h:34
comma::dot_product
T dot_product(const std::vector< T > &a, const std::vector< T > &b)
Compute the dot product between two vectors. No check on size is performed.
Definition: Util.h:60
-
comma::squared_euclidean_distance
T squared_euclidean_distance(const std::vector< T > &a, const std::vector< T > &b)
Compute the squared Euclidean distance between two points seen as vectors. We use vectors because we ...
Definition: Util.h:108
+
comma::squared_euclidean_distance
T squared_euclidean_distance(const std::vector< T > &a, const std::vector< T > &b)
Compute the squared Euclidean distance between two points seen as vectors. We use vectors because we ...
Definition: Util.h:109
comma::get_direction
T get_direction(const std::vector< T > &a, const std::vector< T > &b, std::vector< T > &dir)
Compute the direction from point a to point b and store it as unit vector in dir.
Definition: Util.h:82
comma::deviate_thresh
constexpr double deviate_thresh
Threshold used in combination with a dot product to tell whether two vector deviate....
Definition: Util.h:39
-
comma::d_keys_to_set
std::unordered_set< KeyT > d_keys_to_set(const std::unordered_map< KeyT, ValueT > &dict)
Utility function for creating a set out of the keys of a map.
Definition: Util.h:242
+
comma::d_keys_to_set
std::unordered_set< KeyT > d_keys_to_set(const std::unordered_map< KeyT, ValueT > &dict)
Utility function for creating a set out of the keys of a map.
Definition: Util.h:246
comma::dot_deviate
bool dot_deviate(const T dot)
Tell whether the dot product given as input comes from two parallel vectors. Compared against deviate...
Definition: Util.h:48
-
comma::vector_of_first_elements
std::vector< typename CoMMAContainerPairType::value_type::first_type > vector_of_first_elements(const CoMMAContainerPairType &cont)
Given a container of pairs, return a vector with first elements only.
Definition: Util.h:198
-
comma::compute_neighbourhood_based_wall_distance
void compute_neighbourhood_based_wall_distance(const std::vector< IndexT > &neigh_idxs, const std::vector< IndexT > &neighs, const std::vector< IndexT > &wall, std::vector< DistT > &dist)
Compute a neighbourhood-base wall-distance, that is, the distance of a given cell from a wall is the ...
Definition: Util.h:273
-
comma::CustomPairGreaterFunctor
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:154
-
comma::CustomPairGreaterFunctor::operator()
bool operator()(const PairT &left, const PairT &right) const
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:163
-
comma::CustomPairLessFunctor
Functor for pairs implementing a custom 'less than'. It relies on the 'less than' operator for the se...
Definition: Util.h:131
-
comma::CustomPairLessFunctor::operator()
bool operator()(const PairT &left, const PairT &right) const
Functor for pairs implementing a custom 'less than'. It relies on the 'less than' operator for the se...
Definition: Util.h:140
-
comma::PairSecondBasedLessFunctor
Functor for pairs implementing a less operator based only on the second element of the pair.
Definition: Util.h:178
-
comma::PairSecondBasedLessFunctor::operator()
bool operator()(const PairT &left, const PairT &right) const
Functor for pairs implementing a less operator based only on the second element of the pair.
Definition: Util.h:185
+
comma::vector_of_first_elements
std::vector< typename CoMMAContainerPairType::value_type::first_type > vector_of_first_elements(const CoMMAContainerPairType &cont)
Given a container of pairs, return a vector with first elements only.
Definition: Util.h:200
+
comma::compute_neighbourhood_based_wall_distance
void compute_neighbourhood_based_wall_distance(const std::vector< IndexT > &neigh_idxs, const std::vector< IndexT > &neighs, const std::vector< IndexT > &wall, std::vector< DistT > &dist)
Compute a neighbourhood-base wall-distance, that is, the distance of a given cell from a wall is the ...
Definition: Util.h:278
+
comma::CustomPairGreaterFunctor
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:156
+
comma::CustomPairGreaterFunctor::operator()
bool operator()(const PairT &left, const PairT &right) const
Functor for pairs implementing a custom 'greater than'. It relies on the 'greater than' operator for ...
Definition: Util.h:165
+
comma::CustomPairLessFunctor
Functor for pairs implementing a custom 'less than'. It relies on the 'less than' operator for the se...
Definition: Util.h:133
+
comma::CustomPairLessFunctor::operator()
bool operator()(const PairT &left, const PairT &right) const
Functor for pairs implementing a custom 'less than'. It relies on the 'less than' operator for the se...
Definition: Util.h:142
+
comma::PairSecondBasedLessFunctor
Functor for pairs implementing a less operator based only on the second element of the pair.
Definition: Util.h:180
+
comma::PairSecondBasedLessFunctor::operator()
bool operator()(const PairT &left, const PairT &right) const
Functor for pairs implementing a less operator based only on the second element of the pair.
Definition: Util.h:187
diff --git a/template_helpers_8h_source.html b/template_helpers_8h_source.html index e82a23e..34eda24 100644 --- a/template_helpers_8h_source.html +++ b/template_helpers_8h_source.html @@ -114,12 +114,14 @@
18
29template<bool condition, typename typeA, typename typeB>
30void fill_value(typeA &a, typeB &b) {
-
31 if constexpr (condition) { a = b; }
-
32}
-
33
-
34} // end namespace comma
+
31 if constexpr (condition) {
+
32 a = b;
+
33 }
+
34}
35
-
36#endif
+
36} // end namespace comma
+
37
+
38#endif
comma
Definition: Agglomerator.h:34
comma::fill_value
void fill_value(typeA &a, typeB &b)
Assign from type to another only if a compile-time condition is verified.
Definition: templateHelpers.h:30