diff --git a/_agglomerator_8h_source.html b/_agglomerator_8h_source.html index f440caa..627a030 100644 --- a/_agglomerator_8h_source.html +++ b/_agglomerator_8h_source.html @@ -217,1146 +217,1164 @@
192 using CoMMASetOfPairType =
193 std::set<CoMMAPairType, CustomPairGreaterFunctor<CoMMAPairType>>;
194
-
216 Agglomerator_Anisotropic(
-
217 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
218 graph,
-
219 std::shared_ptr<
-
220 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
221 cc_graph,
-
222 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
223 seeds_pool,
-
224 const CoMMAWeightType threshold_anisotropy,
-
225 const std::vector<CoMMAIndexType> &agglomerationLines_Idx,
-
226 const std::vector<CoMMAIndexType> &agglomerationLines,
-
227 const std::vector<CoMMAWeightType> &priority_weights,
-
228 const bool build_lines,
-
229 const bool odd_line_length,
-
230 CoMMAIntType dimension = 3) :
-
231 Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
232 graph, cc_graph, seeds_pool, dimension),
-
233 _should_agglomerate(true),
-
234 _aniso_neighbours(),
-
235 _odd_line_length(odd_line_length) {
-
236 // for every defined level (1 by default), contains the number of cells
-
237 // e.g. _l_nb_of_cells[0]= number of cells on finest level
-
238 // _l_nb_of_cells[1]= number of cells on the first coarse level
-
239 this->_l_nb_of_cells.push_back(graph->_number_of_cells);
-
240
-
241 this->_nb_lines = std::vector<CoMMAIndexType>(2);
-
242 this->_v_lines = std::vector<std::vector<AnisotropicLinePtr>>(2);
-
243
-
244 if (build_lines) {
-
245 const CoMMAWeightType thr =
-
246 (threshold_anisotropy > 1 || threshold_anisotropy < 0)
-
247 ? threshold_anisotropy
-
248 : static_cast<CoMMAWeightType>(1. / threshold_anisotropy);
-
249 // if the finest agglomeration line is not computed, hence compute it
-
250 // (REMEMBER! We compute the agglomeration lines only on the (original)
-
251 // finest level
-
252 this->_should_agglomerate =
-
253 this->build_anisotropic_lines(priority_weights, thr);
-
254 } else {
-
255 // case in which we have already agglomerated one level and hence we have
-
256 // already agglomeration lines available; no need to recreate them.
-
257 this->_nb_lines[0] = 0;
-
258 for (auto idx_ptr = agglomerationLines_Idx.cbegin() + 1;
-
259 idx_ptr != agglomerationLines_Idx.cend(); ++idx_ptr) {
-
260 const auto ln_sz = *idx_ptr - (*(idx_ptr - 1));
-
261 if (ln_sz > 1) {
-
262 this->_v_lines[0].push_back(std::make_shared<AnisotropicLine>(
-
263 agglomerationLines.cbegin() + (*(idx_ptr - 1)),
-
264 agglomerationLines.cbegin() + (*idx_ptr)));
-
265 this->_nb_lines[0]++;
-
266 }
-
267 }
-
268 this->_should_agglomerate = this->_nb_lines[0] > 0;
-
269 if (!this->_should_agglomerate)
-
270 std::cout
-
271 << "CoMMA - No anisotropic line was built (e.g., only one-cell "
-
272 "lines). Skipping anisotropic agglomeration"
-
273 << std::endl;
-
274 }
-
275 }
-
276
-
278 ~Agglomerator_Anisotropic() override = default;
-
279
-
296 void agglomerate_one_level(
-
297 const CoMMAIntType goal_card,
-
298 const CoMMAIntType min_card,
-
299 const CoMMAIntType max_card,
-
300 const std::vector<CoMMAWeightType> &priority_weights,
-
301 bool correction_steps) override {
-
302 // Unused parameters
-
303 CoMMAUnused(goal_card);
-
304 CoMMAUnused(min_card);
-
305 CoMMAUnused(max_card);
-
306 CoMMAUnused(correction_steps);
-
307
-
308 if (this->_should_agglomerate) {
-
309 // Necessary for the create_cc but maybe we need in
-
310 // some way to change that.
-
311 constexpr bool is_anisotropic = true;
-
312 constexpr CoMMAIntType compactness = 1;
-
313
-
314 // Setting up lambda function that will perform the loop. This is needed
-
315 // since we want to loop forwards or backwards according to some runtime
-
316 // value See, e.g., https://stackoverflow.com/a/56133699/12152457
-
317 auto loop_line = [&](auto begin, auto end) {
-
318 AnisotropicLinePtr line_lvl_p_one = std::make_shared<AnisotropicLine>();
-
319 for (auto line_it = begin; line_it != end; line_it += 2) {
-
320 // we agglomerate cells along the agglomeration line, hence we have to
-
321 // go through the faces and agglomerate two faces together
-
322 // Here we have to consider a special case when we have an odd number
-
323 // of cells: THIS IS FUNDAMENTAL FOR THE CONVERGENCE OF THE MULTIGRID
-
324 // ALGORITHM
-
325 std::unordered_set<CoMMAIndexType> s_fc = {*line_it, *(line_it + 1)};
-
326 // We update the neighbours. At this stage, we do not check if it is
-
327 // or will be agglomerated since there will be a cleaning step after
-
328 // the anisotropic agglomeration
-
329 this->_aniso_neighbours.insert(
-
330 this->_aniso_neighbours.end(),
-
331 this->_fc_graph->neighbours_cbegin(*line_it),
-
332 this->_fc_graph->neighbours_cend(*line_it));
-
333 this->_aniso_neighbours.insert(
-
334 this->_aniso_neighbours.end(),
-
335 this->_fc_graph->neighbours_cbegin(*(line_it + 1)),
-
336 this->_fc_graph->neighbours_cend(*(line_it + 1)));
-
337 if (distance(line_it, end) == 3) {
-
338 if (this->_odd_line_length) {
-
339 // If only three cells left, agglomerate them
-
340 s_fc.insert(*(line_it + 2));
-
341 this->_aniso_neighbours.insert(
-
342 this->_aniso_neighbours.end(),
-
343 this->_fc_graph->neighbours_cbegin(*(line_it + 2)),
-
344 this->_fc_graph->neighbours_cend(*(line_it + 2)));
-
345 }
-
346 line_it++; // Ensure to break the loop after current iteration
-
347 }
-
348 // We create the coarse cell
-
349 const CoMMAIndexType i_cc =
-
350 this->_cc_graph->create_cc(s_fc, compactness, is_anisotropic);
-
351 line_lvl_p_one->push_back(i_cc);
-
352 }
-
353
-
354 this->_v_lines[1].push_back(line_lvl_p_one);
-
355 }; // End lambda def
-
356
-
357 // Process of every agglomeration lines:
-
358 for (auto line_ptr = this->_v_lines[0].begin();
-
359 line_ptr != this->_v_lines[0].end(); line_ptr++) {
-
360 // We iterate on the anisotropic lines of a particular level (the level
-
361 // 1, where they were copied from level 0). We create a pointer to an
-
362 // empty deque for the line + 1, and hence for the next level of
-
363 // agglomeration
-
364 auto line = **line_ptr;
-
365 if (line.size() <= 1) {
-
366 // the agglomeration_line is empty and hence the iterator points again
-
367 // to the empty deque, updating what is pointed by it and hence
-
368 // __v_lines[1] (each time we iterate on the line, a new deque
-
369 // line_lvl_p_one is defined)
-
370 continue;
-
371 }
-
372 // We start agglomerating from the head or the tail of the line
-
373 // according to which of the two has more boundary faces, or priority or
-
374 // ID
-
375 const auto l_fr = line.front(), l_bk = line.back();
-
376 const auto bnd_fr = this->_fc_graph->get_n_boundary_faces(l_fr),
-
377 bnd_bk = this->_fc_graph->get_n_boundary_faces(l_bk);
-
378 const auto w_fr = priority_weights[l_fr], w_bk = priority_weights[l_bk];
-
379 const bool forward_line =
-
380 bnd_fr > bnd_bk // Greater boundaries...
-
381 || (bnd_fr == bnd_bk &&
-
382 (w_fr > w_bk // ...or greater priority...
-
383 || (w_fr == w_bk && l_fr < l_bk) // ..or smaller index
-
384 ));
-
385
-
386 if (forward_line)
-
387 loop_line(line.cbegin(), line.cend());
-
388 else
-
389 loop_line(line.crbegin(), line.crend());
-
390
-
391 } // End loop on lines
-
392
-
393 this->update_seeds_pool();
-
394
-
395 } // End if should agglomerate
-
396 else
-
397 // If it didn't agglomerate, initialize for sure
-
398 this->_seeds_pool->initialize();
-
399 }
-
400
-
404 void update_seeds_pool() {
-
405 if (!this->_aniso_neighbours.empty()) {
-
406 // Example of erase taken from
-
407 // https://en.cppreference.com/w/cpp/container/deque/erase
-
408 for (auto it = this->_aniso_neighbours.begin();
-
409 it != this->_aniso_neighbours.end();) {
-
410 if (this->_cc_graph->_is_fc_agglomerated[*it])
-
411 it = this->_aniso_neighbours.erase(it);
-
412 else
-
413 ++it;
-
414 }
-
415 if (!this->_aniso_neighbours.empty()) {
-
416 // The master queue is the one of the first agglomerated cell:
-
417 // It is important to set it in the case the user asked for
-
418 // neighbourhood priority
-
419 this->_seeds_pool->set_top_queue(this->_fc_graph->get_n_boundary_faces(
-
420 this->_aniso_neighbours.front()));
-
421 this->_seeds_pool->update(this->_aniso_neighbours);
-
422 }
-
423 }
-
424 // Even if we have updated it, the seeds pool might need initialization, for
-
425 // instance, if it was set up with boundary priority
-
426 if (this->_seeds_pool->need_initialization(
-
427 this->_cc_graph->_is_fc_agglomerated))
-
428 this->_seeds_pool->initialize();
-
429 }
-
430
-
438 void export_anisotropic_lines(
-
439 CoMMAIntType level,
-
440 std::vector<CoMMAIndexType> &aniso_lines_idx,
-
441 std::vector<CoMMAIndexType> &aniso_lines) const {
-
442 // Reset lines
-
443 aniso_lines_idx.clear();
-
444 aniso_lines.clear();
-
445 if (this->_should_agglomerate && !this->_v_lines[level].empty()) {
-
446 // If at the level of agglomeration "level" the vector containing the
-
447 // number of lines is empty, hence it means no line has been found at the
-
448 // current level. variable cumulating the number of fine cells in the
-
449 // agglomeration lines of the current level
-
450 CoMMAIndexType number_of_fc_in_agglomeration_lines = 0;
-
451 aniso_lines_idx.push_back(0);
-
452 // We cycle over the line (in _v_lines)
-
453 for (const auto &line_ptr : this->_v_lines[level]) {
-
454 const auto line = *line_ptr; // Convenience
-
455 const CoMMAIndexType size_of_line = line.size();
-
456 // This vector store the end of a line and the start of a new
-
457 // anisotropic line WARNING! We are storing the anisotropic lines in a
-
458 // vector so we need a way to point to the end of a line and the
-
459 // starting of a new one.
-
460 aniso_lines_idx.push_back(
-
461 size_of_line + number_of_fc_in_agglomeration_lines);
-
462 // Here we store the index of the cell.
-
463 for (const auto cell : line) {
-
464 aniso_lines.push_back(cell);
-
465 }
-
466 number_of_fc_in_agglomeration_lines += size_of_line;
-
467 }
-
468 }
-
469 }
-
470
-
472 std::vector<CoMMAIndexType> _nb_lines;
-
473
-
480 std::vector<std::vector<AnisotropicLinePtr>> _v_lines;
-
481
-
485 bool _should_agglomerate;
-
486
-
487protected:
-
499 bool build_anisotropic_lines(
-
500 const std::vector<CoMMAWeightType> &priority_weights,
-
501 const CoMMAWeightType threshold_anisotropy) {
-
502 std::deque<CoMMAIndexType> aniso_seeds_pool;
-
503 // It is the max_weight, hence the maximum area among the faces composing
-
504 // the cell. Used to recognized the face
-
505 std::vector<CoMMAWeightType> max_weights(
-
506 this->_fc_graph->_number_of_cells, 0.0);
-
507 std::vector<bool> to_treat(this->_fc_graph->_number_of_cells, false);
-
508 // Computation of the anisotropic cell, alias of the cells for which the
-
509 // ratio between the face with maximum area and the face with minimum area
-
510 // is more than a given threshold.
-
511 this->_fc_graph->tag_anisotropic_cells(
-
512 max_weights, to_treat, aniso_seeds_pool, threshold_anisotropy,
-
513 priority_weights, 0);
-
514 if (aniso_seeds_pool.empty()) {
-
515 std::cout << "CoMMA - No anisotropic cell found. Skipping anisotropic "
-
516 "agglomeration"
-
517 << std::endl;
-
518 return false;
-
519 }
-
520 // Size might not be the dimension
-
521 const auto pts_dim = this->_fc_graph->_centers[0].size();
-
522 // size of the line
-
523 this->_nb_lines[0] = 0;
-
524 // we cycle on all the anisotropic cells identified before
-
525 for (auto &i_fc : aniso_seeds_pool) {
-
526 // seed from where we start building the line
-
527 if (!to_treat[i_fc]) {
-
528 // If the cell has been already treated, continue to the next
-
529 // anisotropic cell
-
530 continue;
-
531 }
-
532 // we save the primal seed for the opposite direction check that will
-
533 // happen later
-
534 const auto primal_seed = i_fc;
-
535 std::optional<std::vector<CoMMAWeightType>> primal_dir = std::nullopt;
-
536 // seed to be considered to add or not a new cell to the line
-
537 CoMMAIndexType seed = primal_seed;
-
538 // Create the new line
-
539 AnisotropicLinePtr cur_line = std::make_shared<AnisotropicLine>();
-
540 // we add the first seed
-
541 cur_line->push_back(seed);
-
542 to_treat[seed] = false;
-
543 // Flag to determine end of line
-
544 bool end = false;
-
545 // Flag to determine if we arrived at the end of an extreme of a line
-
546 bool opposite_direction_check = false;
-
547 // Info about growth direction
-
548 std::vector<CoMMAWeightType> prev_cen =
-
549 this->_fc_graph->_centers[seed]; // OK copy
-
550 std::vector<CoMMAWeightType> prev_dir(pts_dim);
-
551 bool empty_line = true;
-
552 // Start the check from the seed
-
553 // while the line is not ended
-
554 while (!end) {
-
555 // for the seed (that is updated each time end!= true) we fill the
-
556 // neighbours and the weights
-
557 const std::vector<CoMMAIndexType> v_neighbours =
-
558 this->_fc_graph->get_neighbours(seed);
-
559 const std::vector<CoMMAWeightType> v_w_neighbours =
-
560 this->_fc_graph->get_weights(seed);
-
561 auto n_it = this->_fc_graph->neighbours_cbegin(seed);
-
562 auto w_it = this->_fc_graph->weights_cbegin(seed);
-
563 // std::vector of the candidates to continue the line
-
564 CoMMASetOfPairType candidates;
-
565 // If the line is long enough, we use the direction. Otherwise, we use
-
566 // the weight. Putting a high-level if to reduce the branching inside
-
567 // the loop over the neighbours.
-
568 if (empty_line) {
-
569 for (; n_it != this->_fc_graph->neighbours_cend(seed);
-
570 ++n_it, ++w_it) {
-
571 if (to_treat[*n_it] && *w_it > 0.90 * max_weights[seed]) {
-
572 candidates.emplace(*w_it, *n_it);
-
573 }
-
574 } // end for loop
-
575 } else {
-
576 // If not an empty line, we check the direction, see
-
577 // !dot_deviate below
-
578 for (; n_it != this->_fc_graph->neighbours_cend(seed);
-
579 ++n_it, ++w_it) {
-
580 if (to_treat[*n_it] && *w_it > 0.90 * max_weights[seed]) {
-
581 std::vector<CoMMAWeightType> cur_dir(pts_dim);
-
582 get_direction<CoMMAWeightType>(
-
583 prev_cen, this->_fc_graph->_centers[*n_it], cur_dir);
-
584 const auto dot = dot_product<CoMMAWeightType>(prev_dir, cur_dir);
-
585 if (!dot_deviate<CoMMAWeightType>(dot))
-
586 candidates.emplace(fabs(dot), *n_it);
-
587 }
-
588 } // end for loop
-
589 }
-
590 if (!candidates.empty()) {
-
591 // Even if we have more than one candidate, we choose just one
-
592 // otherwise we risk to add 2 (problematic with primal seed)
-
593 // It is what is done in Mavriplis
-
594 // https://scicomp.stackexchange.com/questions/41830/anisotropic-lines-identification-algorithm
-
598 // update the seed to the actual candidate
-
599 seed = candidates.begin()->second;
-
600 if (!opposite_direction_check) {
-
601 cur_line->push_back(seed);
-
602 } else {
-
603 cur_line->push_front(seed);
-
604 }
-
605 to_treat[seed] = false;
-
606 empty_line = false;
-
607 const auto &cur_cen = this->_fc_graph->_centers[seed];
-
608 get_direction<CoMMAWeightType>(prev_cen, cur_cen, prev_dir);
-
609 prev_cen = cur_cen; // this->_fc_graph->_centers[seed];
-
610 if (!primal_dir.has_value()) primal_dir = prev_dir;
-
611 }
-
612 // 0 candidate, we are at the end of the line or at the end of one
-
613 // direction
-
614 else /*if (candidates.size() == 0)*/ {
-
615 // Before giving up, let's try another thing: Doing the same things as
-
616 // above with the only difference that we allow to move through any
-
617 // faces and not only the maximum one but still checking for direction
-
618 if (!empty_line) {
-
619 // If not an empty line, we check the direction, see is_parallel
-
620 // below
-
621 for (auto it = this->_fc_graph->neighbours_cbegin(seed);
-
622 it != this->_fc_graph->neighbours_cend(seed); ++it) {
-
623 if (to_treat[*it]) {
-
624 std::vector<CoMMAWeightType> cur_dir(pts_dim);
-
625 get_direction<CoMMAWeightType>(
-
626 prev_cen, this->_fc_graph->_centers[*it], cur_dir);
-
627 const auto dot =
-
628 dot_product<CoMMAWeightType>(prev_dir, cur_dir);
-
629 if (!dot_deviate<CoMMAWeightType>(dot))
-
630 candidates.emplace(fabs(dot), *it);
-
631 }
-
632 } // end for loop
-
633 if (!candidates.empty()) {
-
634 // We found one! Keep going!
-
635 seed = candidates.begin()->second;
-
636 if (!opposite_direction_check) {
-
637 cur_line->push_back(seed);
-
638 } else {
-
639 cur_line->push_front(seed);
-
640 }
-
641 to_treat[seed] = false;
-
642 empty_line = false;
-
643 const auto &cur_cen = this->_fc_graph->_centers[seed];
-
644 get_direction<CoMMAWeightType>(prev_cen, cur_cen, prev_dir);
-
645 prev_cen = cur_cen; // this->_fc_graph->_centers[seed];
-
646 if (!primal_dir.has_value()) primal_dir = prev_dir;
-
647 } else {
-
648 if (opposite_direction_check) {
-
649 end = true;
-
650 } else {
-
651 seed = primal_seed;
-
652 prev_dir = primal_dir.value();
-
653 prev_cen = this->_fc_graph->_centers[seed];
-
654 opposite_direction_check = true;
-
655 }
-
656 }
-
657 } // End last step check on neighbours
-
658 else {
-
659 end = true;
-
660 }
-
661 } // End of no candidates case
-
662 } // End of a line
-
663 // we push the deque to the list if are bigger than 1
-
664 if (cur_line->size() > 1) {
-
665 this->_v_lines[0].push_back(cur_line);
-
666 this->_nb_lines[0] += 1;
-
667 }
-
668 } // End of loop over anisotropic cells
-
669
-
670 if (this->_nb_lines[0] == 0) {
-
671 std::cout << "CoMMA - No anisotropic line was built (e.g., only isolated "
-
672 "anisotropic cells). Skipping anisotropic agglomeration"
-
673 << std::endl;
-
674 return false;
-
675 }
-
676 return true;
-
677 }
-
678
-
682 std::deque<CoMMAIndexType> _aniso_neighbours;
-
683
-
685 bool _odd_line_length;
-
686};
+
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;
+
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
-
696template<
-
697 typename CoMMAIndexType,
-
698 typename CoMMAWeightType,
-
699 typename CoMMAIntType>
-
700class Agglomerator_Isotropic :
-
701 public Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType> {
-
702public:
-
704 using NeighbourhoodCreatorBaseType =
-
705 NeighbourhoodCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
707 using NeighbourhoodCreatorExtType =
-
708 NeighbourhoodExtendedCreator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
710 using NeighbourhoodCreatorPFType = NeighbourhoodPureFrontCreator<
-
711 CoMMAIndexType,
-
712 CoMMAWeightType,
-
713 CoMMAIntType>;
-
717 CoMMAIntType _fc_iter;
-
718
-
720 std::shared_ptr<NeighbourhoodCreatorBaseType> _neigh_crtor;
-
721
-
737 Agglomerator_Isotropic(
-
738 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
739 graph,
-
740 std::shared_ptr<
-
741 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
742 cc_graph,
-
743 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
744 seeds_pool,
-
745 CoMMAIntType neighbourhood_type,
-
746 CoMMAIntType fc_iter,
-
747 CoMMAIntType dimension = 3) :
-
748 Agglomerator<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
749 graph, cc_graph, seeds_pool, dimension),
-
750 _fc_iter(fc_iter) {
-
751 if (neighbourhood_type == CoMMANeighbourhoodT::EXTENDED)
-
752 _neigh_crtor = std::make_shared<NeighbourhoodCreatorExtType>();
-
753 else
-
754 _neigh_crtor = std::make_shared<NeighbourhoodCreatorPFType>();
-
755 }
-
756
-
758 ~Agglomerator_Isotropic() override = default;
-
759
-
769 void set_agglomeration_parameter(
-
770 CoMMAIntType goal_card = 0,
-
771 CoMMAIntType min_card = 0,
-
772 CoMMAIntType max_card = 0) {
-
773 // Note[RM]: I tried make the following const static but ended up
-
774 // with some SEGFAULT with Intel possibly linked to the following
-
775 // https://stackoverflow.com/a/36406774
-
776 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_min_card = {
-
777 {2, 3}, {3, 6}};
-
778 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_max_card = {
-
779 {2, 5}, {3, 10}};
-
780 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_goal_card = {
-
781 {2, 4}, {3, 8}};
-
782 std::unordered_map<CoMMAIntType, CoMMAIntType> d_default_threshold_card = {
-
783 {2, 2}, {3, 3}};
-
784 // Definition of _min_card
-
785 if (min_card == 0) {
-
786 this->_min_card = d_default_min_card.at(this->_dimension);
-
787 } else {
-
788 this->_min_card = min_card;
-
789 }
-
790
-
791 // Definition of _max_card
-
792 if (max_card == 0) {
-
793 this->_max_card = d_default_max_card.at(this->_dimension);
-
794 } else {
-
795 this->_max_card = max_card;
-
796 }
-
797 // Definition of _goal_card
-
798 if (goal_card == 0) {
-
799 this->_goal_card = d_default_goal_card.at(this->_dimension);
-
800 } else {
-
801 this->_goal_card = goal_card;
-
802 }
-
803
-
804 // Definition of _threshold_card
-
805 this->_threshold_card = d_default_threshold_card.at(this->_dimension);
-
806 }
-
807
-
831 void agglomerate_one_level(
-
832 const CoMMAIntType goal_card,
-
833 const CoMMAIntType min_card,
-
834 const CoMMAIntType max_card,
-
835 const std::vector<CoMMAWeightType> &priority_weights,
-
836 bool correction_steps) override {
-
837 set_agglomeration_parameter(goal_card, min_card, max_card);
-
838 constexpr bool is_anistropic = false;
-
839 // We define a while for which we control the number of agglomerated cells
-
840 const CoMMAIndexType nb_of_fc = this->_l_nb_of_cells[0];
-
841 while (this->_cc_graph->get_number_of_fc_agglomerated() < nb_of_fc) {
-
842 // 1) Choose a new seed
-
843 const auto seed = this->_seeds_pool->choose_new_seed(
-
844 this->_cc_graph->_is_fc_agglomerated);
-
845 assert(seed.has_value());
-
846 // 2) Choose the set of Coarse Cells with the specification of the
-
847 // algorithm in the children class
-
848 CoMMAIntType compactness = 0;
-
849 const std::unordered_set<CoMMAIndexType> set_current_cc =
-
850 choose_optimal_cc_and_update_seeds_pool(
-
851 seed.value(), priority_weights, compactness);
-
852 // 3) Creation of cc
-
853 // We check that threshold cardinality is reached
-
854 // const bool creation_delayed =
-
855 // (static_cast<CoMMAIntType>(s_current_cc.size()) <=
-
856 // this->_threshold_card);
-
857 // @TODO: We prefer to have coarse cells created right now, it might be
-
858 // interesting to explore if delaying was allowed
-
859 constexpr bool is_creation_delayed = false;
-
860 this->_cc_graph->create_cc(
-
861 set_current_cc, compactness, is_anistropic, is_creation_delayed);
-
862 }
-
863 // When we exit from this process all the cells are agglomerated, apart the
-
864 // delayed ones
-
865 // We proceed in creating the delayed ones
-
866 this->_cc_graph->cc_create_all_delayed_cc();
-
867 // Correct if necessary
-
868 if (correction_steps) { this->_cc_graph->correct(this->_max_card); }
-
869 this->_l_nb_of_cells.push_back(this->_cc_graph->_cc_counter);
-
870 }
-
871
-
878 inline CoMMAWeightType estimate_boundary_face(
-
879 const std::vector<CoMMAWeightType> &int_faces) const {
-
880 // Approximate with an average of the internal faces
-
881 // We could choose many kinds of average, e.g. arithmetic or geometric, I
-
882 // honestly don't know if one is better then the other...
-
883 // Here, we use the geometric one, which should be less sensitive to
-
884 // outliers
-
885 return pow(
-
886 accumulate(
-
887 int_faces.begin(), int_faces.end(), CoMMAWeightType{1.},
-
888 std::multiplies<>()),
-
889 CoMMAWeightType{1.} / int_faces.size());
-
890 }
-
891
-
908 inline void compute_next_cc_features(
-
909 const CoMMAIndexType i_fc,
-
910 const CoMMAWeightType cc_diam,
-
911 const CoMMAWeightType cc_vol,
-
912 const std::unordered_set<CoMMAIndexType> &fc_of_cc,
-
913 // out
-
914 CoMMAIntType &shared_faces,
-
915 CoMMAWeightType &aspect_ratio,
-
916 CoMMAWeightType &new_diam,
-
917 CoMMAWeightType &new_vol) const {
-
918 // Compute shared faces
-
919 shared_faces = 0;
-
920 for (auto it = this->_fc_graph->neighbours_cbegin(i_fc);
-
921 it != this->_fc_graph->neighbours_cend(i_fc); ++it) {
-
922 if (*it != i_fc && (fc_of_cc.count(*it) != 0)) shared_faces++;
-
923 }
-
924
-
925 // Compute new diameter
-
926 const std::vector<CoMMAWeightType> &cen_fc =
-
927 this->_fc_graph->_centers[i_fc];
-
928 CoMMAWeightType max_diam = cc_diam * cc_diam;
-
929 for (const auto i_fc_cc : fc_of_cc) {
-
930 const auto dist = squared_euclidean_distance<CoMMAWeightType>(
-
931 cen_fc, this->_fc_graph->_centers[i_fc_cc]);
-
932 if (dist > max_diam) max_diam = dist;
-
933 } // for i_fc_cc
-
934 new_diam = sqrt(max_diam);
-
935
-
936 new_vol = cc_vol + this->_fc_graph->_volumes[i_fc];
-
937
-
938 aspect_ratio = this->_compute_AR(new_diam, new_vol);
-
939 }
-
940
-
950 virtual std::unordered_set<CoMMAIndexType>
-
951 choose_optimal_cc_and_update_seeds_pool(
-
952 const CoMMAIndexType seed,
-
953 const std::vector<CoMMAWeightType> &priority_weights,
-
954 CoMMAIntType &compactness) = 0;
-
955};
-
956
-
965template<
-
966 typename CoMMAIndexType,
-
967 typename CoMMAWeightType,
-
968 typename CoMMAIntType>
-
969class Agglomerator_Biconnected :
-
970 public Agglomerator_Isotropic<
-
971 CoMMAIndexType,
-
972 CoMMAWeightType,
-
973 CoMMAIntType> {
-
974public:
-
989 Agglomerator_Biconnected(
-
990 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
991 graph,
-
992 std::shared_ptr<
-
993 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
994 cc_graph,
-
995 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
996 seeds_pool,
-
997 CoMMAIntType neighbourhood_type,
-
998 CoMMAIntType fc_iter,
-
999 CoMMAIntType dimension = 3) :
-
1000 Agglomerator_Isotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
1001 graph, cc_graph, seeds_pool, neighbourhood_type, fc_iter, dimension) {
-
1002 // no particular constructor
-
1003 }
-
1004
-
1006 ~Agglomerator_Biconnected() override = default;
-
1007
-
1018 std::unordered_set<CoMMAIndexType> choose_optimal_cc_and_update_seeds_pool(
-
1019 const CoMMAIndexType seed,
-
1020 const std::vector<CoMMAWeightType> &priority_weights,
-
1021 CoMMAIntType &compactness) override {
-
1022 bool is_order_primary = false;
-
1023 // The goal of this function is to choose from a pool of neighbour the
-
1024 // better one to build a compact coarse cell
-
1025 assert(this->_goal_card > 1); // _goal_card has been initialized
-
1026 // OUTPUT: Definition of the current cc, IT WILL BE GIVEN AS AN OUTPUT
-
1027 std::unordered_set<CoMMAIndexType> s_current_cc = {seed};
-
1028 // Dictionary of the neighbourhood of the seed, the key is the global index
-
1029 // of the cell and the value the order of distance from the seed (1 order
-
1030 // direct neighbourhood, 2 order etc.)
-
1031 std::unordered_map<CoMMAIndexType, CoMMAIntType> d_n_of_seed;
-
1032 // Number of fine cells constituting the current coarse cell in
-
1033 // construction.
-
1034 CoMMAIntType size_current_cc = 1; // CC contains only one cell: the seed
-
1035 // set to 3 as default we set to this value the maximum order to which we
-
1036 // search to compose the coarse cell
-
1037 CoMMAIntType max_order_of_neighbourhood =
-
1038 std::max(this->_min_neighbourhood, this->_max_card / this->_dimension);
-
1039
-
1040 // We fill the d_n_of_seeds considering the initial seed passed
-
1041 this->_fc_graph->compute_neighbourhood_of_cc(
-
1042 s_current_cc,
-
1043 max_order_of_neighbourhood, // in and out
-
1044 d_n_of_seed, // output, the function fills the dictionary
-
1045 this->_max_card,
-
1046 // anisotropic cells agglomerated (not to take into account in the
-
1047 // process)
-
1048 this->_cc_graph->_is_fc_agglomerated);
-
1049
-
1050 // If no neighbour is found for seed: this case happened only when isotropic
-
1051 // cell is surrounded by anisotropic cells.
-
1052 if (d_n_of_seed.empty()) {
-
1053 // d_n_of_seed is empty, i.e: the cc is not complete and no neighbour are
-
1054 // available!
-
1055 compactness = 0;
-
1056 } else if (
-
1057 static_cast<CoMMAIntType>(d_n_of_seed.size() + s_current_cc.size())
-
1058 < this->_goal_card) {
-
1059 // Not enough available neighbour, the dictionary of the available cells
-
1060 // size summed with the current cell size is not enough to reach the goal
-
1061 // cardinality: creation of a (too small) coarse cell.
-
1062 // We add ALL the cells of the dictionary to the set of current coarse
-
1063 // cell.
-
1064 for (auto &i_k_v : d_n_of_seed) {
-
1065 s_current_cc.insert(i_k_v.first);
-
1066 }
-
1067 compactness =
-
1068 this->_fc_graph->compute_min_fc_compactness_inside_a_cc(s_current_cc);
-
1069 } else {
-
1070 // If we passed the two previous checks, the minimum size is the goal
-
1071 // cardinality required
-
1072 // TODO: CHECK THAT, if the goal is 2, the minimum size would be 3?
-
1073 // ARGUABLE! Let's think to 3
-
1074 // Computation of the initial aspect ratio
-
1075 CoMMAWeightType diam_cc{-1.};
-
1076 // CC in construction
-
1077 decltype(s_current_cc) tmp_cc = {seed};
-
1078 // volume of cc is at first the volume of the seed.
-
1079 CoMMAWeightType vol_cc = this->_fc_graph->_volumes[seed];
-
1080 // This dictionary is used to store the eligible cc: i.e. its size is
-
1081 // inside the permitted range. This is useful to track back our step if
-
1082 // needed. [size of the current, [cell set, d_n_of seed]]
-
1083 std::unordered_map<
-
1084 CoMMAIntType, std::pair<
-
1085 std::unordered_set<CoMMAIndexType>,
-
1086 std::unordered_map<CoMMAIndexType, CoMMAIntType>>>
-
1087 dict_cc_in_creation;
-
1088 CoMMAIntType min_external_faces =
-
1089 std::numeric_limits<CoMMAIntType>::max();
-
1090 CoMMAIntType max_compact = 0;
-
1091 CoMMAIntType arg_min_card = this->_min_card;
-
1092 // Here we define the exact dimension of the coarse cell as the min
-
1093 // between the max cardinality given as an input (remember the constructor
-
1094 // choice in case of -1) and the dictionary of the boundary cells, it
-
1095 // means the total number of neighbourhood cells until the order we have
-
1096 // given (as default 3, so until the third order)
-
1097 const CoMMAIntType max_ind = std::min(
-
1098 this->_max_card, static_cast<CoMMAIntType>(d_n_of_seed.size() + 1));
-
1099 // This formula does not work
-
1100 CoMMAIntType number_of_external_faces_current_cc =
-
1101 this->_fc_graph->get_nb_of_neighbours(seed)
-
1102 + this->_fc_graph->get_n_boundary_faces(seed) - 1;
-
1103 // d_keys_to_set from Util.h, it takes the keys of the unordered map and
-
1104 // create an unordered set. The unordered set is representing hence all
-
1105 // the neighbours of seed until a given order.
-
1106 const std::unordered_set<CoMMAIndexType> s_neighbours_of_seed =
-
1107 d_keys_to_set<CoMMAIndexType, CoMMAIntType>(d_n_of_seed);
-
1108 // Build the class neighbourhood
-
1109 auto neighbourhood = this->_neigh_crtor->create(
-
1110 s_neighbours_of_seed, priority_weights, this->_dimension);
-
1111 // Compactness is used when choosing the best cell. We compute it
-
1112 // iteratively as the agglomeration advances.
-
1113 std::unordered_map<CoMMAIndexType, CoMMAIntType> cur_compact_by_fc{};
-
1114 cur_compact_by_fc.reserve(max_ind);
-
1115 cur_compact_by_fc[seed] = 0;
-
1116 constexpr auto second_less = [](const auto &left, const auto &right) {
-
1117 return left.second < right.second;
-
1118 };
-
1119 CoMMAIndexType next_cell = seed; // Dummy initialization
-
1120 // Choice of the fine cells to agglomerate we enter in a while, we store
-
1121 // anyways all the possible coarse cells (not only the max dimension one)
-
1122 while (size_current_cc < max_ind) {
-
1123 // Update the neighbourhood and generate the candidates
-
1124 neighbourhood->update(
-
1125 next_cell, this->_fc_graph->get_neighbours(next_cell));
-
1126 next_cell = 0; // Dummy initialization
-
1127 CoMMAWeightType min_ar_diam =
-
1128 std::numeric_limits<CoMMAWeightType>::max();
-
1129 CoMMAWeightType min_ar_vol =
-
1130 std::numeric_limits<CoMMAWeightType>::max();
-
1131 CoMMAIntType max_faces_in_common = 0;
-
1132 // We compute the best fine cell to add, based on the aspect
-
1133 // ratio and is given back in next_cell. It takes account also
-
1134 // the fine cells that has been added until now.
-
1135 // min(max_ind - size_current_cc, this->_fc_iter)
-
1136 this->compute_best_fc_to_add(
-
1137 std::min(max_ind - size_current_cc, this->_fc_iter), neighbourhood,
-
1138 d_n_of_seed, is_order_primary, diam_cc, vol_cc, tmp_cc, next_cell,
-
1139 // output
-
1140 max_faces_in_common, min_ar_diam, min_ar_vol);
-
1141
-
1142 // This formula does not work
-
1143 number_of_external_faces_current_cc +=
-
1144 this->_fc_graph->get_nb_of_neighbours(next_cell)
-
1145 + this->_fc_graph->get_n_boundary_faces(next_cell) - 1
-
1146 - 2 * max_faces_in_common;
-
1147 // we increase the cc
-
1148 size_current_cc++;
-
1149 tmp_cc.insert(next_cell);
-
1150
-
1151 // Update compactness
-
1152 CoMMAIntType argmin_compact{0};
-
1153 for (auto neigh = this->_fc_graph->neighbours_cbegin(next_cell);
-
1154 neigh != this->_fc_graph->neighbours_cend(next_cell); ++neigh) {
-
1155 if (tmp_cc.find(*neigh) != tmp_cc.end()) {
-
1156 ++argmin_compact;
-
1157 ++cur_compact_by_fc[*neigh];
-
1158 }
-
1159 }
-
1160 cur_compact_by_fc[next_cell] = argmin_compact;
-
1161 const CoMMAIntType cur_compact =
-
1162 min_element(
-
1163 cur_compact_by_fc.cbegin(), cur_compact_by_fc.cend(), second_less)
-
1164 ->second;
-
1165 // Equivalent to:
-
1166 // this->_fc_graph->compute_min_fc_compactness_inside_a_cc(tmp_cc);
-
1167
-
1168 // if the constructed cc is eligible, i.e. its size is inside the
-
1169 // permitted range we store it inside dict_cc_in_creation This choice is
-
1170 // based on the idea that the smallest cc (w.r.t. card) is may be not
-
1171 // the one that minimized the number of external faces. If this if is
-
1172 // satisfied it means we have an eligible cell
-
1173 if (
-
1174 (this->_min_card <= size_current_cc) || size_current_cc == max_ind) {
-
1175 if (cur_compact > max_compact) {
-
1176 max_compact = cur_compact;
-
1177 min_external_faces = number_of_external_faces_current_cc;
-
1178 arg_min_card = size_current_cc;
-
1179
-
1180 } else if (cur_compact == max_compact) {
-
1181 if (
-
1182 (number_of_external_faces_current_cc < min_external_faces) ||
-
1183 (number_of_external_faces_current_cc == min_external_faces &&
-
1184 arg_min_card != this->_goal_card)) {
-
1185 min_external_faces = number_of_external_faces_current_cc;
-
1186 arg_min_card = size_current_cc;
-
1187 }
-
1188 }
-
1189
-
1190 // We update the dictionary of eligible coarse cells
-
1191 std::unordered_map<CoMMAIndexType, CoMMAIntType> new_dict;
-
1192 new_dict[next_cell] = d_n_of_seed[next_cell];
-
1193 std::pair<
-
1194 std::unordered_set<CoMMAIndexType>,
-
1195 std::unordered_map<CoMMAIndexType, CoMMAIntType>>
-
1196 tmp_pair = std::make_pair(tmp_cc, new_dict);
-
1197 dict_cc_in_creation[size_current_cc] = tmp_pair;
-
1198 }
-
1199
-
1200 // Update of diam_cc and vol_cc with the new fc added
-
1201 diam_cc = min_ar_diam;
-
1202 vol_cc = min_ar_vol;
-
1203
-
1204 // Remove added fc from the available neighbours
-
1205 d_n_of_seed.erase(next_cell);
-
1206 }
-
1207
-
1208 // Selecting best CC to return
-
1209 s_current_cc = std::move(dict_cc_in_creation[arg_min_card].first);
-
1210
-
1211 // If we do not chose the biggest cc, we put the useless fc back to the
-
1212 // pool
-
1213 for (auto i_s = arg_min_card + 1; i_s < max_ind + 1; i_s++) {
-
1214 // for all size of Cell from arg_min_card+1 to min(max_card,
-
1215 // len(d_n_of_seed) + 1) + 1
-
1216 // d_n_of_seed.
-
1217 for (auto iKV : dict_cc_in_creation[i_s].second) {
-
1218 d_n_of_seed[iKV.first] = iKV.second;
-
1219 }
-
1220 }
-
1221
-
1222 // Updating Seeds Pool with the neighbours of the final CC. Strategy:
-
1223 // - Compute the direct neighbours of the CC (not yet agglomerated)
-
1224 // - Insert in the queue starting with those of lowest neighbourhood order
-
1225 // wrt
-
1226 // to the original seed
-
1227 // - If more than one cell with the same order, use priority weights
-
1228 const auto cc_neighs = this->_fc_graph->get_neighbourhood_of_cc(
-
1229 s_current_cc, this->_cc_graph->_is_fc_agglomerated);
-
1230 // Basically, like d_n_of_seed but with key and value swapped
-
1231 std::map<CoMMAIntType, std::unordered_set<CoMMAIndexType>>
-
1232 neighs_by_order{};
-
1233 // For those that were outside max neighbourhood order
-
1234 std::unordered_set<CoMMAIndexType> neighs_not_found{};
-
1235 for (const auto &neigh : cc_neighs) {
-
1236 if (d_n_of_seed.find(neigh) != d_n_of_seed.end())
-
1237 neighs_by_order[d_n_of_seed.at(neigh)].insert(neigh);
-
1238 else
-
1239 neighs_not_found.insert(neigh);
-
1240 }
-
1241 for (const auto &[o, neighs] : neighs_by_order)
-
1242 if (!neighs.empty())
-
1243 this->_seeds_pool->order_new_seeds_and_update(neighs);
-
1244 if (!neighs_not_found.empty())
-
1245 this->_seeds_pool->order_new_seeds_and_update(neighs_not_found);
-
1246
-
1247 assert(arg_min_card == static_cast<CoMMAIntType>(s_current_cc.size()));
-
1248
-
1249 compactness = max_compact;
-
1250 } // end else
-
1251 return s_current_cc;
-
1252 }
-
1253
-
1279 virtual void compute_best_fc_to_add(
-
1280 const CoMMAIntType fc_iter,
-
1281 const std::shared_ptr<
-
1282 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1283 neighbourhood,
-
1284 const std::unordered_map<CoMMAIndexType, CoMMAIntType> &d_n_of_seed,
-
1285 const bool &is_order_primary,
-
1286 const CoMMAWeightType &diam_cc,
-
1287 const CoMMAWeightType &vol_cc,
-
1288 const std::unordered_set<CoMMAIndexType> &s_of_fc_for_current_cc,
-
1289 CoMMAIndexType &argmin_ar,
-
1290 CoMMAIntType &max_faces_in_common,
-
1291 CoMMAWeightType &min_ar_diam,
-
1292 CoMMAWeightType &min_ar_vol) const {
-
1293 CoMMAUnused(fc_iter);
-
1294 // this function defines the best fine cells to add to create the coarse
-
1295 // cell for the current coarse cell considered
-
1296 CoMMAWeightType min_ar = std::numeric_limits<CoMMAWeightType>::max();
-
1297 const auto neighbours = neighbourhood->get_candidates();
-
1298 CoMMAIndexType arg_max_faces_in_common = neighbours[0];
-
1299
-
1300 for (const auto &i_fc : neighbours) {
-
1301 // we test every possible new cell to chose the one that locally maximizes
-
1302 // the number of shared faces and/or minimizes the Aspect Ratio Compute
-
1303 // features of the CC obtained by adding i_fc
-
1304 CoMMAIntType number_faces_in_common = 0;
-
1305 CoMMAWeightType new_ar = std::numeric_limits<CoMMAWeightType>::min();
-
1306 CoMMAWeightType new_ar_diam = std::numeric_limits<CoMMAWeightType>::min();
-
1307 CoMMAWeightType new_ar_vol = std::numeric_limits<CoMMAWeightType>::min();
-
1308 this->compute_next_cc_features(
-
1309 i_fc, diam_cc, vol_cc, s_of_fc_for_current_cc,
-
1310 // out
-
1311 number_faces_in_common, new_ar, new_ar_diam, new_ar_vol);
-
1312
-
1313 // Neighbourhood order of i_fc wrt to original seed of CC
-
1314 // [i_fc] is not const the method at returns the reference to the value of
-
1315 // the key i_fc.
-
1316 const CoMMAIntType &order = d_n_of_seed.at(i_fc);
-
1317
-
1318 // TODO This version seems good but refactorisation to do: perhaps it is
-
1319 // not needed to update every new possible coarse cell aspect ratio?
-
1320 // TODO also need to remove the list of min_ar, argmin_ar, etc.
-
1321 if (
-
1322 number_faces_in_common >= max_faces_in_common
-
1323 or is_order_primary) { // if is_order_primary is True the order of
-
1324 // neighbourhood is primary
-
1325 if (number_faces_in_common == max_faces_in_common or is_order_primary) {
-
1326 // If the number of faces in common is the same, let's see whether
-
1327 // it's worth to update or not
-
1328
-
1329 if (order <= d_n_of_seed.at(arg_max_faces_in_common)) {
-
1330 // [arg_max_faces_in_common] is not const.
-
1331 if (order == d_n_of_seed.at(arg_max_faces_in_common)) {
-
1332 if (new_ar < min_ar and number_faces_in_common > 0) {
-
1333 // The second condition asserts the connectivity of the coarse
-
1334 // element.
-
1335 min_ar = new_ar;
-
1336 argmin_ar = i_fc;
-
1337 min_ar_diam = new_ar_diam;
-
1338 min_ar_vol = new_ar_vol;
-
1339
-
1340 arg_max_faces_in_common = i_fc;
-
1341 // The number of face in common is the same no need to touch it
-
1342 }
-
1343 } else {
-
1344 // Case :number_faces_in_common == max_faces_in_common and order <
-
1345 // dict_neighbours_of_seed[arg_max_faces_in_common]:
-
1346 arg_max_faces_in_common = i_fc;
-
1347 min_ar = new_ar;
-
1348 argmin_ar = i_fc;
-
1349 min_ar_diam = new_ar_diam;
-
1350 min_ar_vol = new_ar_vol;
-
1351 // The number of face in common is the same no need to touch it
-
1352 }
-
1353 }
-
1354 } else {
-
1355 // Case number_faces_in_common > max_faces_in_common:
-
1356 // -> Just update and see what comes next
-
1357 max_faces_in_common = number_faces_in_common;
-
1358 arg_max_faces_in_common = i_fc;
-
1359 min_ar = new_ar;
-
1360 argmin_ar = i_fc;
-
1361 min_ar_diam = new_ar_diam;
-
1362 min_ar_vol = new_ar_vol;
-
1363 }
-
1364 }
-
1365 }
-
1366 }
-
1367};
-
1368
-
1376template<
-
1377 typename CoMMAIndexType,
-
1378 typename CoMMAWeightType,
-
1379 typename CoMMAIntType>
-
1380class Agglomerator_Iterative :
-
1381 public Agglomerator_Biconnected<
-
1382 CoMMAIndexType,
-
1383 CoMMAWeightType,
-
1384 CoMMAIntType> {
-
1385public:
-
1400 Agglomerator_Iterative(
-
1401 std::shared_ptr<Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1402 graph,
-
1403 std::shared_ptr<
-
1404 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1405 cc_graph,
-
1406 std::shared_ptr<Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1407 seeds_pool,
-
1408 CoMMAIntType neighbourhood_type,
-
1409 CoMMAIntType fc_iter,
-
1410 CoMMAIntType dimension = 3) :
-
1411 Agglomerator_Biconnected<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
-
1412 graph, cc_graph, seeds_pool, neighbourhood_type, fc_iter, dimension) {
-
1413 // no particular constructor
-
1414 }
-
1415
-
1417 ~Agglomerator_Iterative() override = default;
-
1418
-
1445 void compute_best_fc_to_add(
-
1446 const CoMMAIntType fc_iter,
-
1447 const std::shared_ptr<
-
1448 Neighbourhood<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>
-
1449 neighbourhood,
-
1450 const std::unordered_map<CoMMAIndexType, CoMMAIntType> &d_n_of_seed,
-
1451 const bool &is_order_primary,
-
1452 const CoMMAWeightType &diam_cc,
-
1453 const CoMMAWeightType &vol_cc,
-
1454 const std::unordered_set<CoMMAIndexType> &s_of_fc_for_current_cc,
-
1455 CoMMAIndexType &argmin_ar,
-
1456 CoMMAIntType &max_faces_in_common,
-
1457 CoMMAWeightType &min_ar_diam,
-
1458 CoMMAWeightType &min_ar_vol) const override {
-
1459 CoMMAIndexType outer_argmax_faces{0};
-
1460 CoMMAIntType ref_max_faces = max_faces_in_common;
-
1461 CoMMAWeightType outer_ar = std::numeric_limits<CoMMAWeightType>::max();
-
1462 for (const auto &i_fc : neighbourhood->get_candidates()) {
-
1463 auto cur_neighbourhood = this->_neigh_crtor->clone(neighbourhood);
-
1464 CoMMAWeightType inner_ar{-1.};
-
1465 CoMMAIntType inner_max_faces_in_common{0};
-
1466 CoMMAWeightType inner_min_ar_diam =
-
1467 std::numeric_limits<CoMMAWeightType>::max();
-
1468 CoMMAWeightType inner_min_ar_vol{0.};
-
1469 this->compute_next_cc_features(
-
1470 i_fc, diam_cc, vol_cc, s_of_fc_for_current_cc,
-
1471 inner_max_faces_in_common, inner_ar, inner_min_ar_diam,
-
1472 inner_min_ar_vol);
-
1473 cur_neighbourhood->update(i_fc, this->_fc_graph->get_neighbours(i_fc));
-
1474 std::unordered_set<CoMMAIndexType> cur_fc{
-
1475 s_of_fc_for_current_cc.begin(), s_of_fc_for_current_cc.end()};
-
1476 cur_fc.insert(i_fc);
-
1477 // Store value of mother cell
-
1478 const CoMMAIntType ref_inner_faces = inner_max_faces_in_common;
-
1479
-
1480 if (fc_iter > 1) {
-
1481 CoMMAIndexType cur_argmin{0};
-
1482 CoMMAIntType cur_max_faces_in_common{0};
-
1483 CoMMAWeightType cur_min_ar_diam =
-
1484 std::numeric_limits<CoMMAWeightType>::max();
-
1485 CoMMAWeightType cur_min_ar_vol{0.};
-
1486 CoMMAWeightType cur_min_ar{0.};
-
1487 this->compute_best_fc_to_add(
-
1488 fc_iter - 1, cur_neighbourhood, d_n_of_seed, is_order_primary,
-
1489 inner_min_ar_diam, inner_min_ar_vol, cur_fc,
-
1490 // output
-
1491 cur_argmin, cur_max_faces_in_common, cur_min_ar_diam, cur_min_ar_vol);
-
1492 // We just keep the min AR and the max faces in common
-
1493 if (cur_max_faces_in_common > inner_max_faces_in_common) {
-
1494 inner_max_faces_in_common = cur_max_faces_in_common;
-
1495 } else if (
-
1496 cur_max_faces_in_common == inner_max_faces_in_common
-
1497 && cur_min_ar < inner_ar) {
-
1498 inner_ar = cur_min_ar;
-
1499 }
-
1500 }
-
1501
-
1502 const CoMMAIntType &order = d_n_of_seed.at(i_fc);
-
1503
-
1504 // TODO This version seems good but refactorisation to do: perhaps it is
-
1505 // not needed to update every new possible coarse cell aspect ratio?
-
1506 // TODO also need to remove the list of min_ar, argmin_ar, etc.
-
1507 if (
-
1508 inner_max_faces_in_common >= ref_max_faces
-
1509 or is_order_primary) { // if is_order_primary is True the order of
-
1510 // neighbourhood is primary
-
1511 if (inner_max_faces_in_common == ref_max_faces or is_order_primary) {
-
1512 // If the number of faces in common is the same, let's see whether
-
1513 // it's worth to update or not
-
1514
-
1515 if (order <= d_n_of_seed.at(outer_argmax_faces)) {
-
1516 // [outer_argmax_faces] is not const.
-
1517 if (order == d_n_of_seed.at(outer_argmax_faces)) {
-
1518 if (inner_ar < outer_ar and inner_max_faces_in_common > 0) {
-
1519 // The second condition asserts the connectivity of the coarse
-
1520 // element.
-
1521 argmin_ar = i_fc;
-
1522 // Outer AR is the min AR of the children, but since diameter
-
1523 // and volume are used in the next step, we keep those of the
-
1524 // mother cell...
-
1525 outer_ar = inner_ar;
-
1526 min_ar_diam = inner_min_ar_diam;
-
1527 min_ar_vol = inner_min_ar_vol;
-
1528 // ... same for faces in common
-
1529 max_faces_in_common = ref_inner_faces;
-
1530
-
1531 outer_argmax_faces = i_fc;
-
1532 }
-
1533 } else {
-
1534 // Case :inner_max_faces_in_common == ref_max_faces and order <
-
1535 // dict_neighbours_of_seed[outer_argmax_faces]:
-
1536 outer_argmax_faces = i_fc;
-
1537 argmin_ar = i_fc;
-
1538 // Outer AR is the min AR of the children, but since diameter and
-
1539 // volume are used in the next step, we keep those of the mother
-
1540 // cell...
-
1541 outer_ar = inner_ar;
-
1542 min_ar_diam = inner_min_ar_diam;
-
1543 min_ar_vol = inner_min_ar_vol;
-
1544 // ... same for faces in common
-
1545 max_faces_in_common = ref_inner_faces;
-
1546 }
-
1547 }
-
1548 } else {
-
1549 // Case inner_max_faces_in_common > ref_max_faces:
-
1550 // -> Just update and see what comes next
-
1551 ref_max_faces = inner_max_faces_in_common;
-
1552 outer_argmax_faces = i_fc;
-
1553 argmin_ar = i_fc;
-
1554 // Outer AR is the min AR of the children, but since diameter and
-
1555 // volume are used in the next step, we keep those of the mother
-
1556 // cell...
-
1557 outer_ar = inner_ar;
-
1558 min_ar_diam = inner_min_ar_diam;
-
1559 min_ar_vol = inner_min_ar_vol;
-
1560 // ... same for faces in common
-
1561 max_faces_in_common = ref_inner_faces;
-
1562 }
-
1563 }
-
1564 } // for i_fc
-
1565 }
-
1566};
-
1567
-
1568} // end namespace comma
-
1569
-
1570#endif // COMMA_PROJECT_AGGLOMERATOR_H
+
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);
+
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 }
+
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 }
+
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);
+
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 }
+
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
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:499
-
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:438
+
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:685
-
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:404
-
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, CoMMAIntType dimension=3)
Constructor.
Definition: Agglomerator.h:216
-
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:296
-
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:485
+
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
~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:480
-
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:682
-
comma::Agglomerator_Anisotropic::_nb_lines
std::vector< CoMMAIndexType > _nb_lines
Vector of number of Anisotropic agglomeration lines per level.
Definition: Agglomerator.h:472
-
comma::Agglomerator_Biconnected
Child class of Agglomerator_Isotropic where is implemented a specific biconnected algorithm for the a...
Definition: Agglomerator.h:973
+
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_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:1018
-
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:989
-
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:1279
-
comma::Agglomerator_Isotropic
Agglomerator_Isotropic class is a child class of the Agglomerator class that specializes the implemen...
Definition: Agglomerator.h:701
+
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_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:878
-
comma::Agglomerator_Isotropic::_neigh_crtor
std::shared_ptr< NeighbourhoodCreatorBaseType > _neigh_crtor
Creator responsible for neighborhood objects.
Definition: Agglomerator.h:720
-
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:717
-
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:769
-
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:831
-
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:737
-
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:908
+
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::~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:1384
+
comma::Agglomerator_Iterative
Child class of Agglomerator_Isotropic which implements a specialized iterative algorithm for the sear...
Definition: Agglomerator.h:1407
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:1400
-
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:1445
+
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
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::~Agglomerator
virtual ~Agglomerator()=default
The destructor of the class.
diff --git a/_co_m_m_a_8h.html b/_co_m_m_a_8h.html index be354c6..c62abae 100644 --- a/_co_m_m_a_8h.html +++ b/_co_m_m_a_8h.html @@ -102,6 +102,7 @@ #include <iostream>
#include <iterator>
#include <numeric>
+#include <optional>
#include <stdexcept>
#include <string>
#include <unordered_set>
@@ -121,10 +122,10 @@ - - - - + + + +

Functions

template<typename CoMMAIndexType , typename CoMMAWeightType , typename CoMMAIntType >
void comma::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, 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 process. The result will be the definition of the agglomerated cells fc_to_cc. More...
 
template<typename CoMMAIndexType , typename CoMMAWeightType , typename CoMMAIntType >
void comma::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 process. The result will be the definition of the agglomerated cells fc_to_cc. More...
 
diff --git a/_co_m_m_a_8h.js b/_co_m_m_a_8h.js index 03d6111..f05b0d1 100644 --- a/_co_m_m_a_8h.js +++ b/_co_m_m_a_8h.js @@ -1,5 +1,5 @@ var _co_m_m_a_8h = [ - [ "agglomerate_one_level", "_co_m_m_a_8h.html#aa6987db36673ecd638a9b08dfaac18b1", null ], + [ "agglomerate_one_level", "_co_m_m_a_8h.html#a2d9288bb16f6c211415b0458dafb18a4", null ], [ "iter_agglo_max_iter", "_co_m_m_a_8h.html#ae843c64bc9e371bd460fe8d040c80e2b", null ] ]; \ No newline at end of file diff --git a/_co_m_m_a_8h_source.html b/_co_m_m_a_8h_source.html index 55d257e..05df7c6 100644 --- a/_co_m_m_a_8h_source.html +++ b/_co_m_m_a_8h_source.html @@ -114,298 +114,306 @@
18#include <iostream>
19#include <iterator>
20#include <numeric>
-
21#include <stdexcept>
-
22#include <string>
-
23#include <unordered_set>
-
24#include <vector>
-
25
-
26#include "CoMMA/Agglomerator.h"
-
27#include "CoMMA/CoMMADefs.h"
-
28#include "CoMMA/Coarse_Cell_Container.h"
-
29#include "CoMMA/Dual_Graph.h"
-
30#include "CoMMA/Seeds_Pool.h"
-
31
-
32namespace comma {
-
33
-
35#define CHECK_INT_TYPE(intT, label) \
-
36 static_assert( \
-
37 std::numeric_limits<intT>::is_integer, \
-
38 "CoMMA works with integer types, but " #intT " (" label ") is not")
-
40
-
44constexpr CoMMAIntT iter_agglo_max_iter = 4;
-
45
-
121template<
-
122 typename CoMMAIndexType,
-
123 typename CoMMAWeightType,
-
124 typename CoMMAIntType>
-
125void agglomerate_one_level(
-
126 // Dual graph:
-
127 const std::vector<CoMMAIndexType> &adjMatrix_row_ptr,
-
128 const std::vector<CoMMAIndexType> &adjMatrix_col_ind,
-
129 const std::vector<CoMMAWeightType> &adjMatrix_areaValues,
-
130 const std::vector<CoMMAWeightType> &volumes,
-
131
-
132 // Additional info about the mesh
-
133 const std::vector<std::vector<CoMMAWeightType>> &centers,
-
134 const std::vector<CoMMAWeightType> &priority_weights,
-
135 const std::vector<CoMMAIndexType> &anisotropicCompliantCells,
-
136 const std::vector<CoMMAIntType> &n_bnd_faces,
-
137
-
138 // Anisotropy related info
-
139 bool build_anisotropic_lines,
-
140 bool is_anisotropic,
-
141 bool odd_line_length,
-
142 CoMMAWeightType threshold_anisotropy,
-
143
-
144 // Seed ordering
-
145 const CoMMAIntType seed_ordering_type,
-
146
-
147 // Outputs
-
148 std::vector<CoMMAIndexType> &fc_to_cc, // Out
-
149 std::vector<CoMMAIndexType> &agglomerationLines_Idx, // In & out
-
150 std::vector<CoMMAIndexType> &agglomerationLines, // In & out
-
151
-
152 // Tuning of the algorithms
-
153 bool correction,
-
154 CoMMAIntType dimension,
-
155 CoMMAIntType goal_card,
-
156 CoMMAIntType min_card,
-
157 CoMMAIntType max_card,
-
158 CoMMAIntType singular_card_thresh = 1,
-
159 CoMMAIntType fc_choice_iter = 1,
-
160 const CoMMAIntType neighbourhood_type = CoMMANeighbourhoodT::EXTENDED) {
-
161 // NOTATION
-
162 //======================================
-
163 // fc = Fine Cell
-
164 // cc = Coarse Cell
-
165
-
166 // USEFUL SHORTCUTS
+
21#include <optional>
+
22#include <stdexcept>
+
23#include <string>
+
24#include <unordered_set>
+
25#include <vector>
+
26
+
27#include "CoMMA/Agglomerator.h"
+
28#include "CoMMA/CoMMADefs.h"
+
29#include "CoMMA/Coarse_Cell_Container.h"
+
30#include "CoMMA/Dual_Graph.h"
+
31#include "CoMMA/Seeds_Pool.h"
+
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 using SeedsPoolType =
-
169 Seeds_Pool<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
170 using DualGraphType =
-
171 Dual_Graph<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
172 using CCContainerType =
-
173 Coarse_Cell_Container<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>;
-
174 using IsotropicPtr = std::unique_ptr<
-
175 Agglomerator_Isotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>;
-
176
-
177 // SANITY CHECKS
-
178 //======================================
-
179 CHECK_INT_TYPE(CoMMAIndexType, "first template argument");
-
180 CHECK_INT_TYPE(CoMMAIntType, "third template argument");
-
181 if (!(dimension == 2 || dimension == 3))
-
182 throw std::invalid_argument("CoMMA - Error: dimension must be 2 or 3");
-
183 if (min_card <= 1 || goal_card <= 1 || max_card <= 1)
-
184 throw std::invalid_argument(
-
185 "CoMMA - Error: Cardinalities must be greater than 1");
-
186 if (!(min_card <= goal_card && goal_card <= max_card))
-
187 throw std::invalid_argument(
-
188 "CoMMA - Error: Cardinalities must be in order (min <= goal <= max)");
-
189 if (fc_choice_iter < 1)
-
190 throw std::invalid_argument(
-
191 "CoMMA - Error: the number of iteration for the choice of the fine "
-
192 "cells must be at least 1");
-
193 if (fc_choice_iter > iter_agglo_max_iter)
-
194 throw std::invalid_argument(
-
195 "CoMMA - Error: the number of iteration for the choice of the fine "
-
196 "cells must be at most "
-
197 + std::to_string(iter_agglo_max_iter));
-
198 if (
-
199 adjMatrix_row_ptr.empty()
-
200 || adjMatrix_row_ptr.back()
-
201 != static_cast<CoMMAIndexType>(adjMatrix_col_ind.size())
-
202 || adjMatrix_row_ptr.back()
-
203 != static_cast<CoMMAIndexType>(adjMatrix_areaValues.size()))
-
204 throw std::invalid_argument(
-
205 "CoMMA - Error: bad CRS graph (sizes do not match)");
-
206 if (is_anisotropic) {
-
207 if (build_anisotropic_lines) {
-
208 if (anisotropicCompliantCells.empty()) {
-
209 std::cout << "CoMMA - Warning: building anisotropic line requested, no "
-
210 "compliant cells provided. Switching off anisotropy."
-
211 << std::endl;
-
212 }
-
213 } else {
-
214 // Anisotropic lines are provided
-
215 if (agglomerationLines_Idx.size() < 2 || agglomerationLines.empty()) {
-
216 std::cout
-
217 << "CoMMA - Warning: usage of input anisotropic line requested, "
-
218 "but arguments are not enough / invalid to define them. "
-
219 "Switching off anisotropy."
-
220 << std::endl;
-
221 is_anisotropic = false;
-
222 } else if (
-
223 agglomerationLines_Idx.back()
-
224 != static_cast<CoMMAIndexType>(agglomerationLines.size())) {
-
225 throw std::invalid_argument(
-
226 "CoMMA - Error: bad anisotropic lines definition (sizes do not "
-
227 "match)");
-
228 }
-
229 }
-
230 }
-
231 auto sing_thresh = singular_card_thresh;
-
232 if (singular_card_thresh <= 0) {
-
233 throw std::invalid_argument(
-
234 "CoMMA - Error: Threshold cardinality for singular cells should be "
-
235 "greater than zero");
-
236 }
-
237 if (singular_card_thresh >= min_card) {
-
238 std::cout
-
239 << "CoMMA - Warning: Threshold cardinality is equal or larger than "
-
240 "minimum cardinality. Changing it to this latter value."
-
241 << std::endl;
-
242 sing_thresh = min_card - 1;
-
243 }
-
244
-
245 // SIZES CAST
-
246 //======================================
-
247 const auto nb_fc = static_cast<CoMMAIndexType>(adjMatrix_row_ptr.size() - 1);
-
248
-
249 // BOUNDARY FACES
-
250 //======================================
-
251 // Sometimes partitioners give a number of boundary faces higher than the
-
252 // physical one. We fix this
-
253 const CoMMAIntType expected_max_n_bnd = dimension;
-
254 std::vector<CoMMAIntType> fixed_n_bnd_faces(n_bnd_faces.size());
-
255 std::replace_copy_if(
-
256 n_bnd_faces.begin(), n_bnd_faces.end(), fixed_n_bnd_faces.begin(),
-
257 [expected_max_n_bnd](auto n) { return n > expected_max_n_bnd; },
-
258 expected_max_n_bnd);
+
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)
+
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)
+
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;
+
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");
+
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;
+
254 }
+
255
+
256 // SIZES CAST
+
257 //======================================
+
258 const auto nb_fc = static_cast<CoMMAIndexType>(adjMatrix_row_ptr.size() - 1);
259
-
260 // SEED POOL
+
260 // BOUNDARY FACES
261 //======================================
-
262 // Object providing the order of agglomeration
-
263 std::shared_ptr<SeedsPoolType> seeds_pool = nullptr;
-
264 switch (seed_ordering_type) {
-
265 case CoMMASeedsPoolT::BOUNDARY_PRIORITY:
-
266 seeds_pool = std::make_shared<Seeds_Pool_Boundary_Priority<
-
267 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
268 fixed_n_bnd_faces, priority_weights, false);
-
269 break;
-
270 case CoMMASeedsPoolT::NEIGHBOURHOOD_PRIORITY:
-
271 seeds_pool = std::make_shared<Seeds_Pool_Neighbourhood_Priority<
-
272 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
273 fixed_n_bnd_faces, priority_weights, false);
-
274 break;
-
275 case CoMMASeedsPoolT::BOUNDARY_PRIORITY_ONE_POINT_INIT:
-
276 seeds_pool = std::make_shared<Seeds_Pool_Boundary_Priority<
-
277 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
278 fixed_n_bnd_faces, priority_weights, true);
-
279 break;
-
280 case CoMMASeedsPoolT::NEIGHBOURHOOD_PRIORITY_ONE_POINT_INIT:
-
281 seeds_pool = std::make_shared<Seeds_Pool_Neighbourhood_Priority<
-
282 CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
283 fixed_n_bnd_faces, priority_weights, true);
-
284 break;
-
285 default:
-
286 throw std::invalid_argument("CoMMA - Error: Seeds pool type unsupported");
-
287 }
-
288
-
289 // DUAL GRAPH
-
290 //======================================
-
291 // Object containing the graph representation and related info in a convenient
-
292 // structure
-
293 std::shared_ptr<DualGraphType> fc_graph = std::make_shared<DualGraphType>(
-
294 nb_fc, adjMatrix_row_ptr, adjMatrix_col_ind, adjMatrix_areaValues, volumes,
-
295 centers, fixed_n_bnd_faces, dimension, anisotropicCompliantCells);
-
296
-
297 // COARSE CELL CONTAINER
-
298 //======================================
-
299 // Preparing the object that will contain all the coarse cells
-
300 std::shared_ptr<CCContainerType> cc_graph =
-
301 std::make_shared<CCContainerType>(fc_graph, sing_thresh);
-
302
-
303 // AGGLOMERATION OF ANISOTROPIC CELLS
-
304 //======================================
-
305 // @todo maybe re-refactor the class agglomerator to allow the implicit upcast
-
306 // like the biconnected case
-
307 // The agglomerator anisotropic is not called with the implicit upcasting
-
308 // pointing because of the initialization of
-
309 // the anisotropic lines.
-
310 // for more information look at:
-
311 // https://stackoverflow.com/questions/19682402/initialize-child-object-on-a-pointer-to-parent
-
312 // About constructors when upcasting:
-
313 // https://www.reddit.com/r/learnprogramming/comments/1wopf6/java_which_constructor_is_called_when_upcasting/
-
314 if (is_anisotropic) {
-
315 // Build anisotropic agglomerator
-
316 Agglomerator_Anisotropic<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>
-
317 aniso_agg(
-
318 fc_graph, cc_graph, seeds_pool, threshold_anisotropy,
-
319 agglomerationLines_Idx, agglomerationLines, priority_weights,
-
320 build_anisotropic_lines, odd_line_length, dimension);
-
321
-
322 // Agglomerate anisotropic cells only
-
323 aniso_agg.agglomerate_one_level(
-
324 goal_card, min_card, max_card, priority_weights, false);
-
325
-
326 // Put anisotropic lines into the output parameters
-
327 // (Info about level of the line: WARNING! here 1 it means that we give it
-
328 // back lines in the new global index, 0 the old)
-
329 const CoMMAIntType i_level{1};
-
330 aniso_agg.export_anisotropic_lines(
-
331 i_level, agglomerationLines_Idx, agglomerationLines);
-
332 } else {
-
333 seeds_pool->initialize();
-
334 }
-
335
-
336 // AGGLOMERATION OF ISOTROPIC CELLS
-
337 //======================================
-
338 // We define here the type of Agglomerator
-
339 IsotropicPtr agg = nullptr;
-
340 // TODO: maybe pass to a switch when another agglomerator will be implemented
-
341 if (fc_choice_iter > 1) {
-
342 agg = std::make_unique<
-
343 Agglomerator_Iterative<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
344 fc_graph, cc_graph, seeds_pool, neighbourhood_type, fc_choice_iter,
-
345 dimension);
-
346 } else {
-
347 agg = std::make_unique<
-
348 Agglomerator_Biconnected<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>>(
-
349 fc_graph, cc_graph, seeds_pool, neighbourhood_type, fc_choice_iter,
-
350 dimension);
-
351 }
-
352 // Agglomerate
-
353 agg->agglomerate_one_level(
-
354 goal_card, min_card, max_card, priority_weights, correction);
-
355 // FILLING FC TO CC (it is a property of the cc_graph but retrieved through an
-
356 // helper of the agglomerator)
-
357 const auto &fccc = cc_graph->_fc_2_cc;
-
358 for (auto i_fc = decltype(nb_fc){0}; i_fc < nb_fc; i_fc++) {
-
359 fc_to_cc[i_fc] = fccc[i_fc].value();
-
360 }
-
361}
-
362
-
363#undef CHECK_INT_TYPE
-
364
-
365} // end namespace comma
-
366
-
367#endif
+
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:
+
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);
+
313
+
314 // AGGLOMERATION OF ANISOTROPIC CELLS
+
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
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:438
-
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:296
-
comma::Agglomerator_Biconnected
Child class of Agglomerator_Isotropic where is implemented a specific biconnected algorithm for the a...
Definition: Agglomerator.h:973
-
comma::Agglomerator_Isotropic
Agglomerator_Isotropic class is a child class of the Agglomerator class that specializes the implemen...
Definition: Agglomerator.h:701
-
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:831
-
comma::Agglomerator_Iterative
Child class of Agglomerator_Isotropic which implements a specialized iterative algorithm for the sear...
Definition: Agglomerator.h:1384
+
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::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
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::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::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, 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:125
-
comma::iter_agglo_max_iter
constexpr CoMMAIntT iter_agglo_max_iter
Maximum allowed iterations for the iterative algorithm, see Agglomerator_Iterative.
Definition: CoMMA.h:44
+
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
diff --git a/classcomma_1_1_agglomerator___anisotropic-members.html b/classcomma_1_1_agglomerator___anisotropic-members.html index 7625023..96305a3 100644 --- a/classcomma_1_1_agglomerator___anisotropic-members.html +++ b/classcomma_1_1_agglomerator___anisotropic-members.html @@ -105,27 +105,28 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + +

Variables

_goal_cardcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_l_nb_of_cellscomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_max_cardcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_min_cardcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_min_neighbourhoodcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_nb_linescomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
_odd_line_lengthcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_seeds_poolcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_should_agglomeratecomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
_threshold_cardcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_v_linescomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) overridecomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inlinevirtual
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)comma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
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, CoMMAIntType dimension=3)comma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
AnisotropicLine typedefcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
AnisotropicLinePtr typedefcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
build_anisotropic_lines(const std::vector< CoMMAWeightType > &priority_weights, const CoMMAWeightType threshold_anisotropy)comma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inlineprotected
CoMMAPairType typedefcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
CoMMASetOfPairType typedefcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
export_anisotropic_lines(CoMMAIntType level, std::vector< CoMMAIndexType > &aniso_lines_idx, std::vector< CoMMAIndexType > &aniso_lines) constcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
get_fc_2_cc() constcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
update_seeds_pool()comma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
~Agglomerator()=defaultcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >virtual
~Agglomerator_Anisotropic() override=defaultcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
_max_cells_in_linecomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_min_cardcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_min_neighbourhoodcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_nb_linescomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
_odd_line_lengthcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_seeds_poolcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_should_agglomeratecomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
_threshold_cardcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >protected
_v_linescomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
agglomerate_one_level(const CoMMAIntType goal_card, const CoMMAIntType min_card, const CoMMAIntType max_card, const std::vector< CoMMAWeightType > &priority_weights, bool correction_steps) overridecomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inlinevirtual
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)comma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
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)comma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
AnisotropicLine typedefcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
AnisotropicLinePtr typedefcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
build_anisotropic_lines(const std::vector< CoMMAWeightType > &priority_weights, const CoMMAWeightType threshold_anisotropy)comma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inlineprotected
CoMMAPairType typedefcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
CoMMASetOfPairType typedefcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
export_anisotropic_lines(CoMMAIntType level, std::vector< CoMMAIndexType > &aniso_lines_idx, std::vector< CoMMAIndexType > &aniso_lines) constcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
get_fc_2_cc() constcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
update_seeds_pool()comma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >inline
~Agglomerator()=defaultcomma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >virtual
~Agglomerator_Anisotropic() override=defaultcomma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
diff --git a/classcomma_1_1_agglomerator___anisotropic.html b/classcomma_1_1_agglomerator___anisotropic.html index 4d5a746..ad4e580 100644 --- a/classcomma_1_1_agglomerator___anisotropic.html +++ b/classcomma_1_1_agglomerator___anisotropic.html @@ -133,9 +133,9 @@ - - - + + + @@ -195,6 +195,9 @@ + + + @@ -312,8 +315,8 @@

Constructor & Destructor Documentation

- -

◆ Agglomerator_Anisotropic()

+ +

◆ Agglomerator_Anisotropic()

@@ -377,6 +380,12 @@

const bool 

+ + + + + + @@ -408,6 +417,7 @@

[in]

+

Public Member Functions

 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, CoMMAIntType dimension=3)
 Constructor. More...
 
 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. More...
 
 ~Agglomerator_Anisotropic () override=default
 Destructor. More...
 
bool _odd_line_length
 Whether anisotropic lines with odd length are allowed. More...
 
std::optional< CoMMAIndexType > _max_cells_in_line
 Maximum number of cells in an anisotropic line; when this value is reached, all reaming cells are discarded, hence considered as isotropic. More...
 
- Protected Attributes inherited from comma::Agglomerator< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >
CoMMAIntType _dimension
 Dimensionality of the problem (_dimension = 2 -> 2D, _dimension = 3 -> 3D) More...
odd_line_length,
const std::optional< CoMMAIndexType > max_cells_in_line,
priority_weightsWeights used to set the order telling where to start agglomerating. The higher the weight, the higher the priority
[in]build_linesWhether lines joining the anisotropic cells should be built
[in]odd_line_lengthWhether anisotropic lines with odd length are allowed
[in]max_cells_in_lineMaximum number of cells in an anisotropic line; when this value is reached, all reaming cells are discarded, hence considered as isotropic
[in]dimensionDimension of the problem
@@ -677,6 +687,32 @@

+

◆ _max_cells_in_line

+ +
+
+
+template<typename CoMMAIndexType , typename CoMMAWeightType , typename CoMMAIntType >
+ + + + + +
+ + + + +
std::optional<CoMMAIndexType> comma::Agglomerator_Anisotropic< CoMMAIndexType, CoMMAWeightType, CoMMAIntType >::_max_cells_in_line
+
+protected
+
+ +

Maximum number of cells in an anisotropic line; when this value is reached, all reaming cells are discarded, hence considered as isotropic.

+
diff --git a/classcomma_1_1_agglomerator___anisotropic.js b/classcomma_1_1_agglomerator___anisotropic.js index d4a55d9..9b85ea6 100644 --- a/classcomma_1_1_agglomerator___anisotropic.js +++ b/classcomma_1_1_agglomerator___anisotropic.js @@ -4,13 +4,14 @@ var classcomma_1_1_agglomerator___anisotropic = [ "AnisotropicLinePtr", "classcomma_1_1_agglomerator___anisotropic.html#a9de6a86962a319a3cd058000fade94e0", null ], [ "CoMMAPairType", "classcomma_1_1_agglomerator___anisotropic.html#a221bef52906b0fe45f9957ef52ac85d0", null ], [ "CoMMASetOfPairType", "classcomma_1_1_agglomerator___anisotropic.html#a9f4297614846f54366d4561a6428fa4d", null ], - [ "Agglomerator_Anisotropic", "classcomma_1_1_agglomerator___anisotropic.html#a5c939c5706f8c9c47675e3df657568fb", null ], + [ "Agglomerator_Anisotropic", "classcomma_1_1_agglomerator___anisotropic.html#af168953c042e6db4a008b9ec7cbfa69f", null ], [ "~Agglomerator_Anisotropic", "classcomma_1_1_agglomerator___anisotropic.html#aa9bfcf6f6403c97bff9c9bba8673a377", null ], [ "agglomerate_one_level", "classcomma_1_1_agglomerator___anisotropic.html#a679ba0b3f517db87b18a0707d71a6432", null ], [ "build_anisotropic_lines", "classcomma_1_1_agglomerator___anisotropic.html#a06284c8df3ba73d75790c1b703774b11", null ], [ "export_anisotropic_lines", "classcomma_1_1_agglomerator___anisotropic.html#a117343c20ddb4b72d4c9084a89c3303a", null ], [ "update_seeds_pool", "classcomma_1_1_agglomerator___anisotropic.html#a3ed52576f0b6698a69f388f295a2e1c5", null ], [ "_aniso_neighbours", "classcomma_1_1_agglomerator___anisotropic.html#ac26aae66c211f11a2cbc0d56f3a0a3a4", null ], + [ "_max_cells_in_line", "classcomma_1_1_agglomerator___anisotropic.html#a79aca5e2caedd482930c00a36a024e4a", null ], [ "_nb_lines", "classcomma_1_1_agglomerator___anisotropic.html#af3090efb008f7fd601afcad457be5294", null ], [ "_odd_line_length", "classcomma_1_1_agglomerator___anisotropic.html#a231b51e38cfd45989b02fb7ea383e6a9", null ], [ "_should_agglomerate", "classcomma_1_1_agglomerator___anisotropic.html#a6f8e9378cb1709de43dedd5a1c3c6d5d", null ], diff --git a/functions.html b/functions.html index e648306..c7e24fd 100644 --- a/functions.html +++ b/functions.html @@ -129,6 +129,7 @@

- _ -