Arcane  v4.1.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AMRPatchPositionSignature.cc
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/* AMRPatchPositionSignature.cc (C) 2000-2026 */
9/* */
10/* Calcul des signatures d'une position de patch. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/cartesianmesh/internal/AMRPatchPositionSignature.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/ITraceMng.h"
18#include "arcane/utils/Math.h"
19
21#include "arcane/core/IMesh.h"
22#include "arcane/core/IParallelMng.h"
24#include "arcane/core/ItemGroup.h"
25
26#include "arcane/cartesianmesh/ICartesianMesh.h"
27
28#include "arcane/cartesianmesh/internal/ICartesianMeshInternal.h"
29#include "arcane/cartesianmesh/internal/AMRPatchPositionLevelGroup.h"
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34namespace Arcane
35{
36
37// On peut jouer avec ces paramètres pour avoir un meilleur raffinement.
38// TODO : Fixer ça n'est peut-être pas la meilleur façon de faire. Les patchs
39// créés aujourd'hui sont trop nombreux et trop petits mais conviennent
40// dans la majorité des cas de figures.
41namespace
42{
43 constexpr Integer MIN_SIZE = 1;
44 constexpr Integer TARGET_SIZE = 8;
45 constexpr Real TARGET_SIZE_WEIGHT_IN_EFFICACITY = 1;
46 constexpr Integer MAX_NB_CUT = 6;
47 constexpr Real TARGET_EFFICACITY = 1.0;
48} // namespace
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53AMRPatchPositionSignature::
54AMRPatchPositionSignature()
55: m_is_null(true)
56, m_mesh(nullptr)
57, m_nb_cut(0)
58, m_stop_cut(false)
59, m_numbering(nullptr)
60, m_have_cells(false)
61, m_is_computed(false)
62{
63}
64
65AMRPatchPositionSignature::
66AMRPatchPositionSignature(const AMRPatchPosition& patch, ICartesianMesh* cmesh)
67: m_is_null(false)
68, m_patch(patch)
69, m_mesh(cmesh)
70, m_nb_cut(0)
71, m_stop_cut(false)
72, m_numbering(cmesh->_internalApi()->cartesianMeshNumberingMngInternal().get())
73, m_have_cells(false)
74, m_is_computed(false)
75, m_sig_x(patch.maxPoint().x - patch.minPoint().x, 0)
76, m_sig_y(patch.maxPoint().y - patch.minPoint().y, 0)
77, m_sig_z(patch.maxPoint().z - patch.minPoint().z, 0)
78{}
79
80AMRPatchPositionSignature::
81AMRPatchPositionSignature(const AMRPatchPosition& patch, ICartesianMesh* cmesh, Integer nb_cut)
82: m_is_null(false)
83, m_patch(patch)
84, m_mesh(cmesh)
85, m_nb_cut(nb_cut)
86, m_stop_cut(false)
87, m_numbering(cmesh->_internalApi()->cartesianMeshNumberingMngInternal().get())
88, m_have_cells(false)
89, m_is_computed(false)
90, m_sig_x(patch.maxPoint().x - patch.minPoint().x, 0)
91, m_sig_y(patch.maxPoint().y - patch.minPoint().y, 0)
92, m_sig_z(patch.maxPoint().z - patch.minPoint().z, 0)
93{}
94
95/*---------------------------------------------------------------------------*/
96/*---------------------------------------------------------------------------*/
97
98void AMRPatchPositionSignature::
99compress()
100{
101 if (!m_have_cells) {
102 return;
103 }
104
105 // On cherche la première position où il n'y a plus de zéro.
106 CartCoord reduce_x_min = 0;
107 if (m_sig_x[0] == 0) {
108 for (; reduce_x_min < m_sig_x.size(); ++reduce_x_min) {
109 if (m_sig_x[reduce_x_min] != 0) {
110 break;
111 }
112 }
113 }
114 CartCoord reduce_y_min = 0;
115 if (m_sig_y[0] == 0) {
116 for (; reduce_y_min < m_sig_y.size(); ++reduce_y_min) {
117 if (m_sig_y[reduce_y_min] != 0) {
118 break;
119 }
120 }
121 }
122 CartCoord reduce_z_min = 0;
123 if (m_sig_z[0] == 0) {
124 for (; reduce_z_min < m_sig_z.size(); ++reduce_z_min) {
125 if (m_sig_z[reduce_z_min] != 0) {
126 break;
127 }
128 }
129 }
130
131 // On cherche la première position où il n'y a plus de zéro en partant de la
132 // fin.
133 CartCoord reduce_x_max = m_sig_x.size() - 1;
134 if (m_sig_x[reduce_x_max] == 0) {
135 for (; reduce_x_max >= 0; --reduce_x_max) {
136 if (m_sig_x[reduce_x_max] != 0) {
137 break;
138 }
139 }
140 }
141 CartCoord reduce_y_max = m_sig_y.size() - 1;
142 if (m_sig_y[reduce_y_max] == 0) {
143 for (; reduce_y_max >= 0; --reduce_y_max) {
144 if (m_sig_y[reduce_y_max] != 0) {
145 break;
146 }
147 }
148 }
149 CartCoord reduce_z_max = m_sig_z.size() - 1;
150 if (m_sig_z[reduce_z_max] == 0) {
151 for (; reduce_z_max >= 0; --reduce_z_max) {
152 if (m_sig_z[reduce_z_max] != 0) {
153 break;
154 }
155 }
156 }
157
158 // Si une réduction de taille doit avoir lieu en X.
159 if (reduce_x_min != 0 || reduce_x_max != m_sig_x.size()-1) {
160 // Le patch ne peut pas être "plat".
161 if (reduce_x_max < reduce_x_min) {
162 ARCANE_FATAL("Bad patch X : no refine cell");
163 }
164 reduce_x_max++;
165 UniqueArray tmp = m_sig_x.subView(reduce_x_min, reduce_x_max - reduce_x_min);
166 m_sig_x = tmp;
167 CartCoord3 patch_min = m_patch.minPoint();
168 CartCoord3 patch_max = m_patch.maxPoint();
169 patch_min.x += reduce_x_min;
170 patch_max.x = patch_min.x + (reduce_x_max - reduce_x_min);
171 m_patch.setMinPoint(patch_min);
172 m_patch.setMaxPoint(patch_max);
173 }
174
175 if (reduce_y_min != 0 || reduce_y_max != m_sig_y.size()-1) {
176 if (reduce_y_max < reduce_y_min) {
177 ARCANE_FATAL("Bad patch Y : no refine cell");
178 }
179 reduce_y_max++;
180 UniqueArray tmp = m_sig_y.subView(reduce_y_min, reduce_y_max - reduce_y_min);
181 m_sig_y = tmp;
182 CartCoord3 patch_min = m_patch.minPoint();
183 CartCoord3 patch_max = m_patch.maxPoint();
184 patch_min.y += reduce_y_min;
185 patch_max.y = patch_min.y + (reduce_y_max - reduce_y_min);
186 m_patch.setMinPoint(patch_min);
187 m_patch.setMaxPoint(patch_max);
188 }
189
190 if (m_mesh->mesh()->dimension() == 3 && (reduce_z_min != 0 || reduce_z_max != m_sig_z.size() - 1)) {
191 if (reduce_z_max < reduce_z_min) {
192 ARCANE_FATAL("Bad patch Z : no refine cell");
193 }
194 reduce_z_max++;
195 UniqueArray tmp = m_sig_z.subView(reduce_z_min, reduce_z_max - reduce_z_min);
196 m_sig_z = tmp;
197 CartCoord3 patch_min = m_patch.minPoint();
198 CartCoord3 patch_max = m_patch.maxPoint();
199 patch_min.z += reduce_z_min;
200 patch_max.z = patch_min.z + (reduce_z_max - reduce_z_min);
201 m_patch.setMinPoint(patch_min);
202 m_patch.setMaxPoint(patch_max);
203 }
204}
205
206/*---------------------------------------------------------------------------*/
207/*---------------------------------------------------------------------------*/
208
209void AMRPatchPositionSignature::
210fillSig()
211{
212 m_sig_x.fill(0);
213 m_sig_y.fill(0);
214 m_sig_z.fill(0);
215
216 // Le calcul de la signature se fait en deux fois.
217 // D'abord, on calcule la signature avec les flags II_Refine.
218 // Chaque sous-domaine calcule sa signature locale et une réduction est
219 // faite à la fin.
220 ENUMERATE_ (Cell, icell, m_mesh->mesh()->ownLevelCells(m_patch.level())) {
221 if (!icell->hasFlags(ItemFlags::II_Refine)) {
222 continue;
223 }
224
225 const CartCoord3 pos = m_numbering->cellUniqueIdToCoord(*icell);
226 if (!m_patch.isIn(pos)) {
227 continue;
228 }
229 m_have_cells = true;
230 m_sig_x[pos.x - m_patch.minPoint().x]++;
231 m_sig_y[pos.y - m_patch.minPoint().y]++;
232 m_sig_z[pos.z - m_patch.minPoint().z]++;
233 }
234
235 // Compresser un patch vide ne fonctionnera pas.
236 m_have_cells = m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceMax, m_have_cells);
237
238 if (m_have_cells) {
239 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_x);
240 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_y);
241 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_z);
242 }
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248bool AMRPatchPositionSignature::
249isValid() const
250{
251 if (!m_have_cells) {
252 return false;
253 }
254 if (m_is_null) {
255 return false;
256 }
257 if (m_sig_x.size() < MIN_SIZE || m_sig_y.size() < MIN_SIZE || (m_mesh->mesh()->dimension() == 3 && m_sig_z.size() < MIN_SIZE)) {
258 return false;
259 }
260 return true;
261}
262
263/*---------------------------------------------------------------------------*/
264/*---------------------------------------------------------------------------*/
265
266bool AMRPatchPositionSignature::
267canBeCut() const
268{
269 // m_mesh->traceMng()->info() << "canBeCut() -- m_sig_x.size : " << m_sig_x.size()
270 // << " -- m_sig_y.size : " << m_sig_y.size()
271 // << " -- m_sig_z.size : " << m_sig_z.size()
272 // << " -- min = " << m_patch.minPoint()
273 // << " -- max = " << m_patch.maxPoint()
274 // << " -- length = " << m_patch.length()
275 // << " -- isValid : " << isValid()
276 // << " -- efficacity : " << efficacity() << " / " << TARGET_EFFICACITY
277 // << " -- m_nb_cut : " << m_nb_cut << " / " << MAX_NB_CUT
278 // << " -- m_stop_cut : " << m_stop_cut;
279
280 if (!isValid()) {
281 return false;
282 }
283
284 if (m_stop_cut) {
285 return false;
286 }
287
288 if (efficacity() > TARGET_EFFICACITY) {
289 return false;
290 }
291 if (MAX_NB_CUT != -1 && m_nb_cut >= MAX_NB_CUT) {
292 return false;
293 }
294 return true;
295}
296
297/*---------------------------------------------------------------------------*/
298/*---------------------------------------------------------------------------*/
299
300void AMRPatchPositionSignature::
301compute()
302{
303 // m_mesh->traceMng()->info() << "Compute() -- Patch before compute : min = " << m_patch.minPoint() << " -- max = " << m_patch.maxPoint() << " -- length = " << m_patch.length();
304 fillSig();
305 //m_mesh->traceMng()->info() << "Compute() -- Signature : x = " << m_sig_x << " -- y = " << m_sig_y ;
306 compress();
307 // m_mesh->traceMng()->info() << "Compute() -- Compress : min = " << m_patch.minPoint() << " -- max = " << m_patch.maxPoint() << " -- x = " << m_sig_x << " -- y = " << m_sig_y << " -- z = " << m_sig_z;
308 // m_mesh->traceMng()->info() << "Compute() -- Patch computed : min = " << m_patch.minPoint() << " -- max = " << m_patch.maxPoint() << " -- length = " << m_patch.length();
309
310 m_is_computed = true;
311}
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
316Real AMRPatchPositionSignature::
317efficacity() const
318{
319 if (!m_is_computed) {
320 // Sans compression, pas terrible.
321 m_mesh->traceMng()->warning() << "Need to be computed";
322 }
323
324 // On base le calcul de l'efficacité sur deux choses :
325 // - le ratio maille à raffiner dans le patch sur nombre de mailles du patch,
326 // - la taille de chaque dimension par rapport à la taille cible.
327 // TODO : À peaufiner/réécrire.
328
329 Int32 sum = 0;
330 for (const Int32 elem : m_sig_x) {
331 sum += elem;
332 }
333
334 Real eff = static_cast<Real>(sum) / (m_sig_x.size() * m_sig_y.size() * m_sig_z.size());
335
336 if constexpr (TARGET_SIZE == -1 || TARGET_SIZE_WEIGHT_IN_EFFICACITY == 0) {
337 return eff;
338 }
339
340 Real eff_xy = 0;
341 if (m_sig_x.size() <= TARGET_SIZE) {
342 eff_xy = static_cast<Real>(m_sig_x.size()) / TARGET_SIZE;
343 }
344 else if (m_sig_x.size() < TARGET_SIZE*2) {
345 Real size_x = math::abs(m_sig_x.size() - TARGET_SIZE*2);
346 eff_xy = size_x / TARGET_SIZE;
347 }
348
349 if (m_sig_y.size() <= TARGET_SIZE) {
350 eff_xy += static_cast<Real>(m_sig_y.size()) / TARGET_SIZE;
351 }
352 else if (m_sig_y.size() < TARGET_SIZE * 2) {
353 Real size_y = math::abs(m_sig_y.size() - TARGET_SIZE * 2);
354 eff_xy += size_y / TARGET_SIZE;
355 }
356
357 if (m_mesh->mesh()->dimension() == 2) {
358 eff_xy /= 2;
359 }
360 else {
361 if (m_sig_z.size() <= TARGET_SIZE) {
362 eff_xy = (eff_xy + (static_cast<Real>(m_sig_z.size()) / TARGET_SIZE)) / 3;
363 }
364 else if (m_sig_z.size() < TARGET_SIZE * 2) {
365 Real size_z = math::abs(m_sig_z.size() - TARGET_SIZE * 2);
366 eff_xy = (eff_xy + (size_z / TARGET_SIZE)) / 3;
367 }
368 else {
369 eff_xy /= 3;
370 }
371 }
372 eff_xy *= TARGET_SIZE_WEIGHT_IN_EFFICACITY;
373
374 return (eff+eff_xy)/(1+TARGET_SIZE_WEIGHT_IN_EFFICACITY);
375}
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
380std::pair<AMRPatchPositionSignature, AMRPatchPositionSignature> AMRPatchPositionSignature::
381cut(Integer dim, CartCoord cut_point) const
382{
383 auto [fst, snd] = m_patch.cut(cut_point, dim);
384 return { AMRPatchPositionSignature(fst, m_mesh, m_nb_cut + 1), AMRPatchPositionSignature(snd, m_mesh, m_nb_cut + 1) };
385}
386
387/*---------------------------------------------------------------------------*/
388/*---------------------------------------------------------------------------*/
389
390ConstArrayView<CartCoord> AMRPatchPositionSignature::
391sigX() const
392{
393 return m_sig_x;
394}
395
396/*---------------------------------------------------------------------------*/
397/*---------------------------------------------------------------------------*/
398
399ConstArrayView<CartCoord> AMRPatchPositionSignature::
400sigY() const
401{
402 return m_sig_y;
403}
404
405/*---------------------------------------------------------------------------*/
406/*---------------------------------------------------------------------------*/
407
408ConstArrayView<CartCoord> AMRPatchPositionSignature::
409sigZ() const
410{
411 return m_sig_z;
412}
413
414/*---------------------------------------------------------------------------*/
415/*---------------------------------------------------------------------------*/
416
417AMRPatchPosition AMRPatchPositionSignature::
418patch() const
419{
420 return m_patch;
421}
422
423/*---------------------------------------------------------------------------*/
424/*---------------------------------------------------------------------------*/
425
426ICartesianMesh* AMRPatchPositionSignature::
427mesh() const
428{
429 return m_mesh;
430}
431
432/*---------------------------------------------------------------------------*/
433/*---------------------------------------------------------------------------*/
434
435bool AMRPatchPositionSignature::
436stopCut() const
437{
438 return m_stop_cut;
439}
440
441/*---------------------------------------------------------------------------*/
442/*---------------------------------------------------------------------------*/
443
444void AMRPatchPositionSignature::
445setStopCut(bool stop_cut)
446{
447 m_stop_cut = stop_cut;
448}
449
450/*---------------------------------------------------------------------------*/
451/*---------------------------------------------------------------------------*/
452
453bool AMRPatchPositionSignature::
454isComputed() const
455{
456 return m_is_computed;
457}
458
459/*---------------------------------------------------------------------------*/
460/*---------------------------------------------------------------------------*/
461
462} // End namespace Arcane
463
464/*---------------------------------------------------------------------------*/
465/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Déclarations des types généraux de Arcane.
Types et macros pour itérer sur les entités du maillage.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
bool isValid() const
Méthode permettant de savoir si les signatures sont valides.
void compress()
Méthode permettant de retirer les 0 au début et à la fin des signatures.
Real efficacity() const
Méthode permettant de connaitre l'efficacité du patch.
void fillSig()
Méthode permettant de calculer les signatures.
Classe permettant de définir la position d'un patch dans le maillage cartésien.
ArrayView< T > subView(Int64 abegin, Integer asize)
Sous-vue à partir de l'élément abegin et contenant asize éléments.
Maille d'un maillage.
Definition Item.h:1214
Vue constante d'un tableau de type T.
Interface d'un maillage cartésien.
@ II_Refine
L'entité est marquée pour raffinement.
Definition ItemFlags.h:77
Vecteur 1D de données avec sémantique par valeur (style STL).
@ ReduceSum
Somme des valeurs.
@ ReduceMax
Maximum des valeurs.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 CartCoord
Représente une coordonnée d'un élément dans la grille cartésienne (en X ou en Y ou en Z).
Int32 Integer
Type représentant un entier.
double Real
Type représentant un réel.
std::int32_t Int32
Type entier signé sur 32 bits.
Int32x3 CartCoord3
Représente les coordonnées 3D d'un élément dans la grille cartésienne {x, y, z}.