CoMMA 1.3.2
A geometric agglomerator for unstructured meshes
Loading...
Searching...
No Matches
CoMMA.h
Go to the documentation of this file.
1#ifndef COMMA_PROJECT_COMMA_H
2#define COMMA_PROJECT_COMMA_H
3
4/*
5 * CoMMA
6 *
7 * Copyright © 2024 ONERA
8 *
9 * Authors: Nicolas Lantos, Alberto Remigi, and Riccardo Milani
10 * Contributors: Karim Anemiche
11 *
12 * This Source Code Form is subject to the terms of the Mozilla Public
13 * License, v. 2.0. If a copy of the MPL was not distributed with this
14 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
15 */
16
17#include <algorithm>
18#include <iostream>
19#include <iterator>
20#include <numeric>
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/Args.h"
29#include "CoMMA/CoMMADefs.h"
31#include "CoMMA/Dual_Graph.h"
32#include "CoMMA/Seeds_Pool.h"
33
34namespace comma {
35
37#define CHECK_INT_TYPE(intT, label) \
38 static_assert( \
39 std::numeric_limits<intT>::is_integer, \
40 "CoMMA works with integer types, but " #intT " (" label ") is not" \
41 )
43
47constexpr CoMMAIntT iter_agglo_max_iter = 4;
48
133template<
134 typename CoMMAIndexType,
135 typename CoMMAWeightType,
136 typename CoMMAIntType>
138 // Dual graph:
139 const std::vector<CoMMAIndexType> &adjMatrix_row_ptr,
140 const std::vector<CoMMAIndexType> &adjMatrix_col_ind,
141 const std::vector<CoMMAWeightType> &adjMatrix_areaValues,
142 const std::vector<CoMMAWeightType> &volumes,
143
144 // Additional info about the mesh
145 const std::vector<std::vector<CoMMAWeightType>> &centers,
146 const std::vector<CoMMAWeightType> &priority_weights,
147 const std::vector<CoMMAIndexType> &anisotropicCompliantCells,
148 const std::vector<CoMMAIntType> &n_bnd_faces,
149
150 // Anisotropy related info
151 bool build_anisotropic_lines,
152 bool is_anisotropic,
153 bool odd_line_length,
154 CoMMAWeightType threshold_anisotropy,
155
156 // Seed ordering
157 CoMMASeedsPoolT seed_ordering_type,
158
159 // Outputs
160 std::vector<CoMMAIndexType> &fc_to_cc, // Out
161 std::vector<CoMMAIndexType> &agglomerationLines_Idx, // In & out
162 std::vector<CoMMAIndexType> &agglomerationLines, // In & out
163
164 // Tuning of the algorithms
165 bool correction,
166 CoMMAIntType dimension,
167 CoMMAIntType goal_card,
168 CoMMAIntType min_card,
169 CoMMAIntType max_card,
171 CoMMAIntType singular_card_thresh = 1,
172 std::optional<CoMMAIndexType> max_cells_in_line = std::nullopt,
174 bool force_line_direction = true,
175 CoMMAIntType fc_choice_iter = 1,
177) {
178 // NOTATION
179 //======================================
180 // fc = Fine Cell
181 // cc = Coarse Cell
182
183 // USEFUL SHORTCUTS
184 //======================================
185 using SeedsPoolType =
187 using DualGraphType =
189 using CCContainerType =
191 using IsotropicPtr = std::unique_ptr<
193
194 // SANITY CHECKS
195 //======================================
196 CHECK_INT_TYPE(CoMMAIndexType, "first template argument");
197 CHECK_INT_TYPE(CoMMAIntType, "third template argument");
198 if (!(dimension == 2 || dimension == 3))
199 throw std::invalid_argument("CoMMA - Error: dimension must be 2 or 3");
200 if (min_card <= 1 || goal_card <= 1 || max_card <= 1)
201 throw std::invalid_argument(
202 "CoMMA - Error: Cardinalities must be greater than 1"
203 );
204 if (!(min_card <= goal_card && goal_card <= max_card))
205 throw std::invalid_argument(
206 "CoMMA - Error: Cardinalities must be in order (min <= goal <= max)"
207 );
208 if (fc_choice_iter < 1)
209 throw std::invalid_argument(
210 "CoMMA - Error: the number of iteration for the choice of the fine "
211 "cells must be at least 1"
212 );
213 if (fc_choice_iter > iter_agglo_max_iter)
214 throw std::invalid_argument(
215 "CoMMA - Error: the number of iteration for the choice of the fine "
216 "cells must be at most "
217 + std::to_string(iter_agglo_max_iter)
218 );
219 if (adjMatrix_row_ptr.empty()
220 || adjMatrix_row_ptr.back()
221 != static_cast<CoMMAIndexType>(adjMatrix_col_ind.size())
222 || adjMatrix_row_ptr.back()
223 != static_cast<CoMMAIndexType>(adjMatrix_areaValues.size()))
224 throw std::invalid_argument(
225 "CoMMA - Error: bad CRS graph (sizes do not match)"
226 );
227 if (is_anisotropic) {
228 if (build_anisotropic_lines) {
229 if (anisotropicCompliantCells.empty()) {
230 std::cout << "CoMMA - Warning: building anisotropic line requested, no "
231 "compliant cells provided. Switching off anisotropy."
232 << std::endl;
233 }
234 if (max_cells_in_line.has_value() && max_cells_in_line.value() <= 0) {
235 std::cout << "CoMMA - Requested a negative or null maximum number of "
236 "cells in line. Dropping the limit."
237 << std::endl;
238 max_cells_in_line = std::nullopt;
239 }
240 switch (aniso_cell_coupling) {
243 // OK
244 break;
245 default:
246 std::cout << "CoMMA - Warning: Unknown anisotropic cell coupling."
247 " Switching it to: max weight."
248 << std::endl;
249 aniso_cell_coupling = CoMMACellCouplingT::MAX_WEIGHT;
250 }
251 } else {
252 // Anisotropic lines are provided
253 if (agglomerationLines_Idx.size() < 2 || agglomerationLines.empty()) {
254 std::cout
255 << "CoMMA - Warning: usage of input anisotropic line requested, "
256 "but arguments are not enough / invalid to define them. "
257 "Switching off anisotropy."
258 << std::endl;
259 is_anisotropic = false;
260 } else if (agglomerationLines_Idx.back()
261 != static_cast<CoMMAIndexType>(agglomerationLines.size())) {
262 throw std::invalid_argument(
263 "CoMMA - Error: bad anisotropic lines definition (sizes do not "
264 "match)"
265 );
266 }
267 }
268 }
269 auto sing_thresh = singular_card_thresh;
270 if (singular_card_thresh <= 0) {
271 throw std::invalid_argument(
272 "CoMMA - Error: Threshold cardinality for singular cells should be "
273 "greater than zero"
274 );
275 }
276 if (singular_card_thresh >= min_card) {
277 std::cout
278 << "CoMMA - Warning: Threshold cardinality is equal or larger than "
279 "minimum cardinality. Changing it to this latter value."
280 << std::endl;
281 sing_thresh = min_card - 1;
282 }
283
284 // SIZES CAST
285 //======================================
286 const auto nb_fc = static_cast<CoMMAIndexType>(adjMatrix_row_ptr.size() - 1);
287
288 // BOUNDARY FACES
289 //======================================
290 // Sometimes partitioners give a number of boundary faces higher than the
291 // physical one. We fix this
292 const CoMMAIntType expected_max_n_bnd = dimension;
293 std::vector<CoMMAIntType> fixed_n_bnd_faces(n_bnd_faces.size());
294 std::replace_copy_if(
295 n_bnd_faces.begin(),
296 n_bnd_faces.end(),
297 fixed_n_bnd_faces.begin(),
298 [expected_max_n_bnd](auto n) { return n > expected_max_n_bnd; },
299 expected_max_n_bnd
300 );
301
302 // SEED POOL
303 //======================================
304 // Object providing the order of agglomeration
305 std::shared_ptr<SeedsPoolType> seeds_pool = nullptr;
306 switch (seed_ordering_type) {
308 seeds_pool = std::make_shared<Seeds_Pool_Boundary_Priority<
309 CoMMAIndexType,
310 CoMMAWeightType,
311 CoMMAIntType>>(fixed_n_bnd_faces, priority_weights, false);
312 break;
314 seeds_pool = std::make_shared<Seeds_Pool_Neighbourhood_Priority<
315 CoMMAIndexType,
316 CoMMAWeightType,
317 CoMMAIntType>>(fixed_n_bnd_faces, priority_weights, false);
318 break;
320 seeds_pool = std::make_shared<Seeds_Pool_Boundary_Priority<
321 CoMMAIndexType,
322 CoMMAWeightType,
323 CoMMAIntType>>(fixed_n_bnd_faces, priority_weights, true);
324 break;
326 seeds_pool = std::make_shared<Seeds_Pool_Neighbourhood_Priority<
327 CoMMAIndexType,
328 CoMMAWeightType,
329 CoMMAIntType>>(fixed_n_bnd_faces, priority_weights, true);
330 break;
331 default:
332 throw std::invalid_argument("CoMMA - Error: Seeds pool type unsupported");
333 }
334
335 // DUAL GRAPH
336 //======================================
337 // Object containing the graph representation and related info in a convenient
338 // structure
339 std::shared_ptr<DualGraphType> fc_graph = std::make_shared<DualGraphType>(
340 nb_fc,
341 adjMatrix_row_ptr,
342 adjMatrix_col_ind,
343 adjMatrix_areaValues,
344 volumes,
345 centers,
346 fixed_n_bnd_faces,
347 dimension,
348 anisotropicCompliantCells
349 );
350
351 // COARSE CELL CONTAINER
352 //======================================
353 // Preparing the object that will contain all the coarse cells
354 std::shared_ptr<CCContainerType> cc_graph =
355 std::make_shared<CCContainerType>(fc_graph, sing_thresh);
356
357 // AGGLOMERATION OF ANISOTROPIC CELLS
358 //======================================
359 // @todo maybe re-refactor the class agglomerator to allow the implicit upcast
360 // like the biconnected case
361 // The agglomerator anisotropic is not called with the implicit upcasting
362 // pointing because of the initialization of
363 // the anisotropic lines.
364 // for more information look at:
365 // https://stackoverflow.com/questions/19682402/initialize-child-object-on-a-pointer-to-parent
366 // About constructors when upcasting:
367 // https://www.reddit.com/r/learnprogramming/comments/1wopf6/java_which_constructor_is_called_when_upcasting/
368 if (is_anisotropic) {
369 // Build anisotropic agglomerator
371 aniso_agg(
372 fc_graph,
373 cc_graph,
374 seeds_pool,
375 dimension,
376 threshold_anisotropy,
377 agglomerationLines_Idx,
378 agglomerationLines,
379 priority_weights,
380 build_anisotropic_lines,
381 odd_line_length,
382 max_cells_in_line,
383 aniso_cell_coupling,
384 force_line_direction
385 );
386
387 // Agglomerate anisotropic cells only
388 aniso_agg.agglomerate_one_level(
389 goal_card, min_card, max_card, priority_weights, false
390 );
391
392 // Put anisotropic lines into the output parameters
393 // (Info about level of the line: WARNING! here 1 it means that we give it
394 // back lines in the new global index, 0 the old)
395 aniso_agg.export_anisotropic_lines(
396 1, agglomerationLines_Idx, agglomerationLines
397 );
398 } else {
399 seeds_pool->initialize();
400 }
401
402 // AGGLOMERATION OF ISOTROPIC CELLS
403 //======================================
404 // We define here the type of Agglomerator
405 IsotropicPtr agg = nullptr;
406 // TODO: maybe pass to a switch when another agglomerator will be implemented
407 if (fc_choice_iter > 1) {
408 agg = std::make_unique<
410 fc_graph,
411 cc_graph,
412 seeds_pool,
413 dimension,
414 aspect_ratio,
415 neighbourhood_type,
416 fc_choice_iter
417 );
418 } else {
419 agg = std::make_unique<
421 fc_graph,
422 cc_graph,
423 seeds_pool,
424 dimension,
425 aspect_ratio,
426 neighbourhood_type,
427 fc_choice_iter
428 );
429 }
430 // Agglomerate
432 goal_card, min_card, max_card, priority_weights, correction
433 );
434 // FILLING FC TO CC (it is a property of the cc_graph but retrieved through an
435 // helper of the agglomerator)
436 fc_to_cc.clear();
437 fc_to_cc.reserve(cc_graph->_fc_2_cc.size());
438 std::transform(
439 cc_graph->_fc_2_cc.begin(),
440 cc_graph->_fc_2_cc.end(),
441 std::back_inserter(fc_to_cc),
442 [](const auto &f2c) { return f2c.value(); }
443 );
444}
445
471template<
472 typename CoMMAIndexType,
473 typename CoMMAWeightType,
474 typename CoMMAIntType>
479 std::vector<CoMMAIndexType> &fc_to_cc, // Out
480 std::vector<CoMMAIndexType> &aniso_lines_indices, // In & out
481 std::vector<CoMMAIndexType> &aniso_lines // In & out
482) {
483 agglomerate_one_level<CoMMAIndexType, CoMMAWeightType, CoMMAIntType>(
485 graph.connectivity,
487 graph.volumes,
488 graph.centers,
489 graph.priority_weights,
491 graph.n_bnd_faces,
492 aniso.build_lines,
493 aniso.is_anisotropic,
494 aniso.odd_line_length,
496 agglo.seed_ordering_type,
497 fc_to_cc,
498 aniso_lines_indices,
499 aniso_lines,
500 agglo.correction,
501 graph.dimension,
502 agglo.goal_card,
503 agglo.min_card,
504 agglo.max_card,
505 agglo.aspect_ratio,
507 aniso.max_cells_in_line,
508 aniso.cell_coupling,
509 aniso.line_direction,
510 agglo.fc_choice_iter,
512 );
513}
514
515#undef CHECK_INT_TYPE
516
517} // end namespace comma
518
519#endif
Convenient class holding arguments for the parametrization of the agglomeration algorithm.
Definition: Args.h:99
CoMMAIntType goal_card
Desired cardinality of the coarse cells.
Definition: Args.h:102
CoMMASeedsPoolT seed_ordering_type
Type of ordering for the seeds of the coarse cells (see CoMMASeedsPoolT)
Definition: Args.h:114
CoMMANeighbourhoodT neighbourhood_type
Type of neighbourhood to use when growing a coarse cell. See CoMMANeighbourhoodT for more details.
Definition: Args.h:127
CoMMAIntType min_card
Minimum cardinality accepted for the coarse cells.
Definition: Args.h:104
CoMMAAspectRatioT aspect_ratio
Type of aspect ratio.
Definition: Args.h:116
bool correction
Whether to apply correction step (avoid isolated cells) after agglomeration.
Definition: Args.h:110
CoMMAIntType singular_card_thresh
Cardinality below which a coarse is considered as singular, hence, compliant for correction.
Definition: Args.h:119
CoMMAIntType fc_choice_iter
Number of iterations allowed for the algorithm choosing which fine cell to add next....
Definition: Args.h:123
CoMMAIntType max_card
Maximum cardinality accepted for the coarse cells.
Definition: Args.h:106
Agglomerator_Anisotropic class is a child class of the Agglomerator class that specializes the implem...
Definition: Agglomerator.h:174
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:469
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:306
Child class of Agglomerator_Isotropic where is implemented a specific biconnected algorithm for the a...
Definition: Agglomerator.h:1169
Agglomerator_Isotropic class is a child class of the Agglomerator class that specializes the implemen...
Definition: Agglomerator.h:852
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:1092
Child class of Agglomerator_Isotropic which implements a specialized iterative algorithm for the sear...
Definition: Agglomerator.h:1602
Convenient class holding arguments for the parametrization of the anisotropic agglomeration algorithm...
Definition: Args.h:184
CoMMACellCouplingT cell_coupling
Type of coupling to consider when building lines.
Definition: Args.h:201
std::optional< CoMMAIndexType > max_cells_in_line
Maximum number of cells in an anisotropic line.
Definition: Args.h:199
bool is_anisotropic
Whether to consider an anisotropic agglomeration.
Definition: Args.h:187
bool build_lines
Whether lines joining the anisotropic cells should be built.
Definition: Args.h:191
bool line_direction
Whether to force the direction of the anisotropic lines to remain straight.
Definition: Args.h:205
CoMMAWeightType threshold_anisotropy
Value of the aspect-ratio above which a cell is considered as anisotropic.
Definition: Args.h:197
bool odd_line_length
Whether anisotropic lines with odd length are allowed.
Definition: Args.h:193
const std::vector< CoMMAIndexType > & anisotropicCompliantCells
List of cells which have to be looked for anisotropy.
Definition: Args.h:189
Class implementing a custom container where the coarse cells are stored.
Definition: Coarse_Cell_Container.h:41
A class implementing the CRS global graph representation of the global mesh.
Definition: Dual_Graph.h:548
Convenient class holding arguments defining the graph.
Definition: Args.h:34
const std::vector< CoMMAWeightType > & priority_weights
Priority weights.
Definition: Args.h:47
const std::vector< CoMMAIndexType > & connectivity_indices
Indices of the CSR representation of the graph.
Definition: Args.h:37
const std::vector< CoMMAIndexType > & connectivity
Values of the CSR representation of the graph.
Definition: Args.h:39
const std::vector< CoMMAIntType > & n_bnd_faces
Number of boundary faces per cell.
Definition: Args.h:49
const std::vector< CoMMAWeightType > & volumes
Volumes of the cells.
Definition: Args.h:43
const std::vector< CoMMAWeightType > & connectivity_weights
Weights of the CSR representation of the graph.
Definition: Args.h:41
const std::vector< std::vector< CoMMAWeightType > > & centers
Centers of the cells.
Definition: Args.h:45
CoMMAIntType dimension
Dimensionality of the problem, 2- or 3D.
Definition: Args.h:51
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:452
Class representing the pool of all the seeds for creating a coarse cell. This derived class gives hig...
Definition: Seeds_Pool.h:612
Class representing the pool of all the seeds for creating a coarse cell.
Definition: Seeds_Pool.h:200
Definition: Agglomerator.h:37
CoMMAAspectRatioT
Type of aspect-ratio. Notation:
Definition: CoMMADefs.h:73
@ DIAMETER_OVER_RADIUS
Definition: CoMMADefs.h:75
CoMMACellCouplingT
Type of coupling between cells in an anisotropic line.
Definition: CoMMADefs.h:103
@ MIN_DISTANCE
Definition: CoMMADefs.h:107
@ MAX_WEIGHT
Definition: CoMMADefs.h:105
CoMMANeighbourhoodT
Type of neighbourhood (of a coarse cell) considered when agglomerating.
Definition: CoMMADefs.h:37
@ EXTENDED
Extended, all neighbours of the coarse cell.
Definition: CoMMADefs.h:38
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, CoMMASeedsPoolT 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, CoMMAAspectRatioT aspect_ratio=CoMMAAspectRatioT::DIAMETER_OVER_RADIUS, CoMMAIntType singular_card_thresh=1, std::optional< CoMMAIndexType > max_cells_in_line=std::nullopt, CoMMACellCouplingT aniso_cell_coupling=CoMMACellCouplingT::MAX_WEIGHT, bool force_line_direction=true, CoMMAIntType fc_choice_iter=1, CoMMANeighbourhoodT 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:137
CoMMASeedsPoolT
Type of seeds pool ordering.
Definition: CoMMADefs.h:43
@ BOUNDARY_PRIORITY_ONE_POINT_INIT
Definition: CoMMADefs.h:53
@ BOUNDARY_PRIORITY
Definition: CoMMADefs.h:45
@ NEIGHBOURHOOD_PRIORITY_ONE_POINT_INIT
Definition: CoMMADefs.h:57
@ NEIGHBOURHOOD_PRIORITY
Definition: CoMMADefs.h:49
constexpr CoMMAIntT iter_agglo_max_iter
Maximum allowed iterations for the iterative algorithm, see Agglomerator_Iterative.
Definition: CoMMA.h:47