Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
CuthillMcKeeReorderer.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* CuthillMcKeeReorderer h (C) 2000-2026 */
9/* */
10/* (Reverse) Cuthill-McKee matrix reorder algorithm. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_CUTHILLMCKEEREORDERER_H
13#define ARCCORE_ALINA_CUTHILLMCKEEREORDERER_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16/*
17 * This file is based on the work on AMGCL library (version march 2026)
18 * which can be found at https://github.com/ddemidov/amgcl.
19 *
20 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
21 * SPDX-License-Identifier: MIT
22 */
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25/*
26The code is adopted from Kratos project http://www.cimne.com/kratos. The
27original code came with the following copyright notice:
28\verbatim
29Kratos Multi-Physics
30
31Copyright (c) 2012, Pooyan Dadvand, Riccardo Rossi, CIMNE (International Center for Numerical Methods in Engineering)
32All rights reserved.
33
34Redistribution and use in source and binary forms, with or without
35modification, are permitted provided that the following conditions are met:
36
37 Redistributions of source code must retain the above copyright notice, this
38 list of conditions and the following disclaimer.
39 Redistributions in binary form must reproduce the above copyright notice,
40 this list of conditions and the following disclaimer in the documentation
41 and/or other materials provided with the distribution.
42 All advertising materials mentioning features or use of this software must
43 display the following acknowledgement:
44 This product includes Kratos Multi-Physics technology.
45 Neither the name of the CIMNE nor the names of its contributors may be used
46 to endorse or promote products derived from this software without specific
47 prior written permission.
48
49THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR
50IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
51MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
52EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
53INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
54LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ANDON ANY THEORY OF
56LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE
57OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THISSOFTWARE, EVEN IF
58ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59\endverbatim
60*/
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
64#include "arccore/alina/BackendInterface.h"
65#include "arccore/alina/AlinaUtils.h"
66
67#include "arccore/accelerator/Atomic.h"
68
69#include <vector>
70#include <algorithm>
71
72/*---------------------------------------------------------------------------*/
73/*---------------------------------------------------------------------------*/
74
75namespace Arcane::Alina
76{
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
83template <bool reverse = false>
85{
86 template <class Matrix, class Vector>
87 static void get(const Matrix& A, Vector& perm)
88 {
89 const ptrdiff_t n = backend::nbRow(A);
90
91 /* The data structure used to sort and traverse the level sets:
92 *
93 * The current level set is currentLevelSet;
94 * In this level set, there are nodes with degrees from 0 (not really
95 * useful) to maxDegreeInCurrentLevelSet.
96 * firstWithDegree[i] points to a node with degree i, or to -1 if it
97 * does not exist. nextSameDegree[firstWithDegree[i]] points to the
98 * second node with that degree, etc.
99 * While the level set is being traversed, the structure for the next
100 * level set is generated; nMDICLS will be the next
101 * maxDegreeInCurrentLevelSet and nFirstWithDegree will be
102 * firstWithDegree.
103 */
104 ptrdiff_t initialNode = 0; // node to start search
105 ptrdiff_t maxDegree = 0;
106
107 std::vector<ptrdiff_t> degree(n);
108 std::vector<ptrdiff_t> levelSet(n, 0);
109 std::vector<ptrdiff_t> nextSameDegree(n, -1);
110
111 arccoreParallelFor(0, n, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
112 ptrdiff_t maxd = 0;
113 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
114 ptrdiff_t row_width = 0;
115 for (auto a = backend::row_begin(A, i); a; ++a, ++row_width)
116 ;
117 degree[i] = row_width;
118 maxd = std::max(maxd, degree[i]);
119 }
121 });
122
123 std::vector<ptrdiff_t> firstWithDegree(maxDegree + 1, -1);
124 std::vector<ptrdiff_t> nFirstWithDegree(maxDegree + 1);
125
126 // Initialize the first level set, made up by initialNode alone
127 perm[0] = initialNode;
128 ptrdiff_t currentLevelSet = 1;
129 levelSet[initialNode] = currentLevelSet;
130 ptrdiff_t maxDegreeInCurrentLevelSet = degree[initialNode];
131 firstWithDegree[maxDegreeInCurrentLevelSet] = initialNode;
132
133 // Main loop
134 for (ptrdiff_t next = 1; next < n;) {
135 ptrdiff_t nMDICLS = 0;
136 std::fill(nFirstWithDegree.begin(), nFirstWithDegree.end(), -1);
137 bool empty = true; // used to detect different connected components
138
139 ptrdiff_t firstVal = reverse ? maxDegreeInCurrentLevelSet : 0;
140 ptrdiff_t finalVal = reverse ? -1 : maxDegreeInCurrentLevelSet + 1;
141 ptrdiff_t increment = reverse ? -1 : 1;
142
143 for (ptrdiff_t soughtDegree = firstVal; soughtDegree != finalVal; soughtDegree += increment) {
144 ptrdiff_t node = firstWithDegree[soughtDegree];
145 while (node > 0) {
146 // Visit neighbors
147 for (auto a = backend::row_begin(A, node); a; ++a) {
148 ptrdiff_t c = a.col();
149 if (levelSet[c] == 0) {
150 levelSet[c] = currentLevelSet + 1;
151 perm[next] = c;
152 ++next;
153 empty = false; // this level set is not empty
154 nextSameDegree[c] = nFirstWithDegree[degree[c]];
155 nFirstWithDegree[degree[c]] = c;
156 nMDICLS = std::max(nMDICLS, degree[c]);
157 }
158 }
159 node = nextSameDegree[node];
160 }
161 }
162
163 ++currentLevelSet;
164 maxDegreeInCurrentLevelSet = nMDICLS;
165 for (ptrdiff_t i = 0; i <= nMDICLS; ++i)
166 firstWithDegree[i] = nFirstWithDegree[i];
167
168 if (empty) {
169 // The graph contains another connected component that we
170 // cannot reach. Search for a node that has not yet been
171 // included in a level set, and start exploring from it.
172 bool found = false;
173 for (ptrdiff_t i = 0; i < n; ++i) {
174 if (levelSet[i] == 0) {
175 perm[next] = i;
176 ++next;
177 levelSet[i] = currentLevelSet;
178 maxDegreeInCurrentLevelSet = degree[i];
179 firstWithDegree[maxDegreeInCurrentLevelSet] = i;
180 found = true;
181 break;
182 }
183 }
184 precondition(found, "Internal consistency error at skyline_lu");
185 }
186 }
187 }
188};
189
190/*---------------------------------------------------------------------------*/
191/*---------------------------------------------------------------------------*/
192
193} // namespace Arcane::Alina
194
195/*---------------------------------------------------------------------------*/
196/*---------------------------------------------------------------------------*/
197
198#endif
Informations d'exécution d'une boucle.
Matrix class, to be used by user.
Vector class, to be used by user.
__host__ __device__ DataType doAtomic(DataType *ptr, ValueType value)
Applique l'opération atomique Operation à la valeur à l'adresse ptr avec la valeur value.
void arccoreParallelFor(const ComplexForLoopRanges< RankValue > &loop_ranges, const ForLoopRunInfo &run_info, const LambdaType &lambda_function, const ReducerArgs &... reducer_args)
Applique en concurrence la fonction lambda lambda_function sur l'intervalle d'itération donné par loo...
Definition ParallelFor.h:85
std::int32_t Int32
Type entier signé sur 32 bits.
(Reverse) Cuthill-McKee matrix reorder algorithm.