Arcane  v4.1.2.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-2025 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-2025 */
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
37namespace
38{
39constexpr Integer MIN_SIZE = 1;
40 constexpr Integer TARGET_SIZE = 8;
41 constexpr Real TARGET_SIZE_WEIGHT_IN_EFFICACITY = 1;
42 constexpr Integer MAX_NB_CUT = 6;
43 constexpr Real TARGET_EFFICACITY = 1.0;
44} // namespace
45
46/*---------------------------------------------------------------------------*/
47/*---------------------------------------------------------------------------*/
48
49AMRPatchPositionSignature::
50AMRPatchPositionSignature()
51: m_is_null(true)
52, m_mesh(nullptr)
53, m_nb_cut(0)
54, m_stop_cut(false)
55, m_numbering(nullptr)
56, m_have_cells(false)
57, m_is_computed(false)
58, m_all_patches(nullptr)
59{
60}
61
62AMRPatchPositionSignature::
63AMRPatchPositionSignature(const AMRPatchPosition& patch, ICartesianMesh* cmesh, AMRPatchPositionLevelGroup* all_patches)
64: m_is_null(false)
65, m_patch(patch)
66, m_mesh(cmesh)
67, m_nb_cut(0)
68, m_stop_cut(false)
69, m_numbering(cmesh->_internalApi()->cartesianMeshNumberingMngInternal().get())
70, m_have_cells(false)
71, m_is_computed(false)
72, m_sig_x(patch.maxPoint().x - patch.minPoint().x, 0)
73, m_sig_y(patch.maxPoint().y - patch.minPoint().y, 0)
74, m_sig_z(patch.maxPoint().z - patch.minPoint().z, 0)
75, m_all_patches(all_patches)
76{}
77
78AMRPatchPositionSignature::
79AMRPatchPositionSignature(const AMRPatchPosition& patch, ICartesianMesh* cmesh, AMRPatchPositionLevelGroup* all_patches, Integer nb_cut)
80: m_is_null(false)
81, m_patch(patch)
82, m_mesh(cmesh)
83, m_nb_cut(nb_cut)
84, m_stop_cut(false)
85, m_numbering(cmesh->_internalApi()->cartesianMeshNumberingMngInternal().get())
86, m_have_cells(false)
87, m_is_computed(false)
88, m_sig_x(patch.maxPoint().x - patch.minPoint().x, 0)
89, m_sig_y(patch.maxPoint().y - patch.minPoint().y, 0)
90, m_sig_z(patch.maxPoint().z - patch.minPoint().z, 0)
91, m_all_patches(all_patches)
92{}
93
94/*---------------------------------------------------------------------------*/
95/*---------------------------------------------------------------------------*/
96
97void AMRPatchPositionSignature::
98compress()
99{
100 if (!m_have_cells) {
101 return;
102 }
103
104 CartCoordType reduce_x_min = 0;
105 if (m_sig_x[0] == 0) {
106 for (; reduce_x_min < m_sig_x.size(); ++reduce_x_min) {
107 if (m_sig_x[reduce_x_min] != 0) {
108 break;
109 }
110 }
111 }
112 CartCoordType reduce_y_min = 0;
113 if (m_sig_y[0] == 0) {
114 for (; reduce_y_min < m_sig_y.size(); ++reduce_y_min) {
115 if (m_sig_y[reduce_y_min] != 0) {
116 break;
117 }
118 }
119 }
120 CartCoordType reduce_z_min = 0;
121 if (m_sig_z[0] == 0) {
122 for (; reduce_z_min < m_sig_z.size(); ++reduce_z_min) {
123 if (m_sig_z[reduce_z_min] != 0) {
124 break;
125 }
126 }
127 }
128
129 CartCoordType reduce_x_max = m_sig_x.size() - 1;
130 if (m_sig_x[reduce_x_max] == 0) {
131 for (; reduce_x_max >= 0; --reduce_x_max) {
132 if (m_sig_x[reduce_x_max] != 0) {
133 break;
134 }
135 }
136 }
137 CartCoordType reduce_y_max = m_sig_y.size() - 1;
138 if (m_sig_y[reduce_y_max] == 0) {
139 for (; reduce_y_max >= 0; --reduce_y_max) {
140 if (m_sig_y[reduce_y_max] != 0) {
141 break;
142 }
143 }
144 }
145 CartCoordType reduce_z_max = m_sig_z.size() - 1;
146 if (m_sig_z[reduce_z_max] == 0) {
147 for (; reduce_z_max >= 0; --reduce_z_max) {
148 if (m_sig_z[reduce_z_max] != 0) {
149 break;
150 }
151 }
152 }
153
154 if (reduce_x_min != 0 || reduce_x_max != m_sig_x.size()-1) {
155 if (reduce_x_max < reduce_x_min) {
156 ARCANE_FATAL("Bad patch X : no refine cell");
157 }
158 reduce_x_max++;
159 UniqueArray tmp = m_sig_x.subView(reduce_x_min, reduce_x_max - reduce_x_min);
160 m_sig_x = tmp;
161 CartCoord3Type patch_min = m_patch.minPoint();
162 CartCoord3Type patch_max = m_patch.maxPoint();
163 patch_min.x += reduce_x_min;
164 patch_max.x = patch_min.x + (reduce_x_max - reduce_x_min);
165 m_patch.setMinPoint(patch_min);
166 m_patch.setMaxPoint(patch_max);
167 }
168 if (reduce_y_min != 0 || reduce_y_max != m_sig_y.size()-1) {
169 if (reduce_y_max < reduce_y_min) {
170 ARCANE_FATAL("Bad patch Y : no refine cell");
171 }
172 reduce_y_max++;
173 UniqueArray tmp = m_sig_y.subView(reduce_y_min, reduce_y_max - reduce_y_min);
174 m_sig_y = tmp;
175 CartCoord3Type patch_min = m_patch.minPoint();
176 CartCoord3Type patch_max = m_patch.maxPoint();
177 patch_min.y += reduce_y_min;
178 patch_max.y = patch_min.y + (reduce_y_max - reduce_y_min);
179 m_patch.setMinPoint(patch_min);
180 m_patch.setMaxPoint(patch_max);
181 }
182 if (m_mesh->mesh()->dimension() == 3 && (reduce_z_min != 0 || reduce_z_max != m_sig_z.size() - 1)) {
183 if (reduce_z_max < reduce_z_min) {
184 ARCANE_FATAL("Bad patch Z : no refine cell");
185 }
186 reduce_z_max++;
187 UniqueArray tmp = m_sig_z.subView(reduce_z_min, reduce_z_max - reduce_z_min);
188 m_sig_z = tmp;
189 CartCoord3Type patch_min = m_patch.minPoint();
190 CartCoord3Type patch_max = m_patch.maxPoint();
191 patch_min.z += reduce_z_min;
192 patch_max.z = patch_min.z + (reduce_z_max - reduce_z_min);
193 m_patch.setMinPoint(patch_min);
194 m_patch.setMaxPoint(patch_max);
195 }
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
201void AMRPatchPositionSignature::
202fillSig()
203{
204 m_sig_x.fill(0);
205 m_sig_y.fill(0);
206 m_sig_z.fill(0);
207 ENUMERATE_ (Cell, icell, m_mesh->mesh()->ownLevelCells(m_patch.level())) {
208 if (!icell->hasFlags(ItemFlags::II_Refine)) {
209 continue;
210 }
211
212 const CartCoord3Type pos = m_numbering->cellUniqueIdToCoord(*icell);
213 if (!m_patch.isIn(pos)) {
214 continue;
215 }
216 m_have_cells = true;
217 m_sig_x[pos.x - m_patch.minPoint().x]++;
218 m_sig_y[pos.y - m_patch.minPoint().y]++;
219 m_sig_z[pos.z - m_patch.minPoint().z]++;
220 }
221
222 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_x);
223 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_y);
224 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_z);
225
226 if (m_all_patches->maxLevel() > m_patch.level()) {
227
228 // Pour que la signature soit valide, il ne faut pas que les patchs de m_all_patches
229 // s'intersectent entre eux (pour un même niveau).
230 for (const auto& elem : m_all_patches->patches(m_patch.level() + 1)) {
231 AMRPatchPosition patch_down = elem.patchDown(m_mesh->mesh()->dimension());
232 if (!m_patch.haveIntersection(patch_down)) {
233 continue;
234 }
235
236 CartCoord3Type min = patch_down.minPoint() - m_patch.minPoint();
237 CartCoord3Type max = patch_down.maxPoint() - m_patch.minPoint();
238
239 CartCoord3Type begin;
240 CartCoord3Type end;
241
242 begin.x = std::max(min.x, 0);
243 end.x = std::min(max.x, m_sig_x.size());
244
245 begin.y = std::max(min.y, 0);
246 end.y = std::min(max.y, m_sig_y.size());
247
248 if (m_mesh->mesh()->dimension() == 2) {
249 begin.z = 0;
250 end.z = 1;
251 }
252 else {
253 begin.z = std::max(min.z, 0);
254 end.z = std::min(max.z, m_sig_z.size());
255 }
256
257 for (CartCoordType k = begin.z; k < end.z; ++k) {
258 for (CartCoordType j = begin.y; j < end.y; ++j) {
259 for (CartCoordType i = begin.x; i < end.x; ++i) {
260 m_sig_x[i]++;
261 m_sig_y[j]++;
262 m_sig_z[k]++;
263 m_have_cells = true;
264 }
265 }
266 }
267 }
268 }
269
270 m_have_cells = m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceMax, m_have_cells);
271}
272
273/*---------------------------------------------------------------------------*/
274/*---------------------------------------------------------------------------*/
275
276bool AMRPatchPositionSignature::
277isValid() const
278{
279 if (m_is_null) {
280 return false;
281 }
282 if (m_sig_x.size() < MIN_SIZE || m_sig_y.size() < MIN_SIZE || (m_mesh->mesh()->dimension() == 3 && m_sig_z.size() < MIN_SIZE)) {
283 return false;
284 }
285 return true;
286}
287
288/*---------------------------------------------------------------------------*/
289/*---------------------------------------------------------------------------*/
290
291bool AMRPatchPositionSignature::
292canBeCut() const
293{
294 m_mesh->traceMng()->info() << "canBeCut() -- m_sig_x.size : " << m_sig_x.size()
295 << " -- m_sig_y.size : " << m_sig_y.size()
296 << " -- m_sig_z.size : " << m_sig_z.size()
297 << " -- min = " << m_patch.minPoint()
298 << " -- max = " << m_patch.maxPoint()
299 << " -- length = " << m_patch.length()
300 << " -- isValid : " << isValid()
301 << " -- efficacity : " << efficacity() << " / " << TARGET_EFFICACITY
302 << " -- m_nb_cut : " << m_nb_cut << " / " << MAX_NB_CUT
303 << " -- m_stop_cut : " << m_stop_cut;
304
305 if (!isValid()) {
306 return false;
307 }
308
309 if (m_stop_cut) {
310 return false;
311 }
312
313 if (efficacity() > TARGET_EFFICACITY) {
314 return false;
315 }
316 if (MAX_NB_CUT != -1 && m_nb_cut >= MAX_NB_CUT) {
317 return false;
318 }
319 return true;
320}
321
322/*---------------------------------------------------------------------------*/
323/*---------------------------------------------------------------------------*/
324
325void AMRPatchPositionSignature::
326compute()
327{
328 m_mesh->traceMng()->info() << "Compute() -- Patch before compute : min = " << m_patch.minPoint() << " -- max = " << m_patch.maxPoint() << " -- length = " << m_patch.length();
329 fillSig();
330 //m_mesh->traceMng()->info() << "Compute() -- Signature : x = " << m_sig_x << " -- y = " << m_sig_y ;
331 compress();
332 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;
333 m_mesh->traceMng()->info() << "Compute() -- Patch computed : min = " << m_patch.minPoint() << " -- max = " << m_patch.maxPoint() << " -- length = " << m_patch.length();
334
335 m_is_computed = true;
336}
337
338/*---------------------------------------------------------------------------*/
339/*---------------------------------------------------------------------------*/
340
341Real AMRPatchPositionSignature::
342efficacity() const
343{
344 if (!m_is_computed) {
345 // Sans compression, pas terrible.
346 m_mesh->traceMng()->warning() << "Need to be computed";
347 }
348 Int32 sum = 0;
349 for (const Int32 elem : m_sig_x) {
350 sum += elem;
351 }
352
353 Real eff = static_cast<Real>(sum) / (m_sig_x.size() * m_sig_y.size() * m_sig_z.size());
354
355 if constexpr (TARGET_SIZE == -1 || TARGET_SIZE_WEIGHT_IN_EFFICACITY == 0) {
356 return eff;
357 }
358
359 Real eff_xy = 0;
360 if (m_sig_x.size() <= TARGET_SIZE) {
361 eff_xy = static_cast<Real>(m_sig_x.size()) / TARGET_SIZE;
362 }
363 else if (m_sig_x.size() < TARGET_SIZE*2) {
364 Real size_x = math::abs(m_sig_x.size() - TARGET_SIZE*2);
365 eff_xy = size_x / TARGET_SIZE;
366 }
367
368 if (m_sig_y.size() <= TARGET_SIZE) {
369 eff_xy += static_cast<Real>(m_sig_y.size()) / TARGET_SIZE;
370 }
371 else if (m_sig_y.size() < TARGET_SIZE * 2) {
372 Real size_y = math::abs(m_sig_y.size() - TARGET_SIZE * 2);
373 eff_xy += size_y / TARGET_SIZE;
374 }
375
376 if (m_mesh->mesh()->dimension() == 2) {
377 eff_xy /= 2;
378 }
379 else {
380 if (m_sig_z.size() <= TARGET_SIZE) {
381 eff_xy = (eff_xy + (static_cast<Real>(m_sig_z.size()) / TARGET_SIZE)) / 3;
382 }
383 else if (m_sig_z.size() < TARGET_SIZE * 2) {
384 Real size_z = math::abs(m_sig_z.size() - TARGET_SIZE * 2);
385 eff_xy = (eff_xy + (size_z / TARGET_SIZE)) / 3;
386 }
387 else {
388 eff_xy /= 3;
389 }
390 }
391 eff_xy *= TARGET_SIZE_WEIGHT_IN_EFFICACITY;
392
393 return (eff+eff_xy)/(1+TARGET_SIZE_WEIGHT_IN_EFFICACITY);
394}
395
396/*---------------------------------------------------------------------------*/
397/*---------------------------------------------------------------------------*/
398
399std::pair<AMRPatchPositionSignature, AMRPatchPositionSignature> AMRPatchPositionSignature::
400cut(Integer dim, CartCoordType cut_point) const
401{
402 auto [fst, snd] = m_patch.cut(cut_point, dim);
403 return {AMRPatchPositionSignature(fst, m_mesh, m_all_patches, m_nb_cut+1), AMRPatchPositionSignature(snd, m_mesh, m_all_patches, m_nb_cut+1)};
404}
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408
409ConstArrayView<CartCoordType> AMRPatchPositionSignature::
410sigX() const
411{
412 return m_sig_x;
413}
414
415/*---------------------------------------------------------------------------*/
416/*---------------------------------------------------------------------------*/
417
418ConstArrayView<CartCoordType> AMRPatchPositionSignature::
419sigY() const
420{
421 return m_sig_y;
422}
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427ConstArrayView<CartCoordType> AMRPatchPositionSignature::
428sigZ() const
429{
430 return m_sig_z;
431}
432
433/*---------------------------------------------------------------------------*/
434/*---------------------------------------------------------------------------*/
435
436AMRPatchPosition AMRPatchPositionSignature::
437patch() const
438{
439 return m_patch;
440}
441
442/*---------------------------------------------------------------------------*/
443/*---------------------------------------------------------------------------*/
444
445ICartesianMesh* AMRPatchPositionSignature::
446mesh() const
447{
448 return m_mesh;
449}
450
451/*---------------------------------------------------------------------------*/
452/*---------------------------------------------------------------------------*/
453
454bool AMRPatchPositionSignature::
455stopCut() const
456{
457 return m_stop_cut;
458}
459
460/*---------------------------------------------------------------------------*/
461/*---------------------------------------------------------------------------*/
462
463void AMRPatchPositionSignature::
464setStopCut(bool stop_cut)
465{
466 m_stop_cut = stop_cut;
467}
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471
472bool AMRPatchPositionSignature::
473isComputed() const
474{
475 return m_is_computed;
476}
477
478/*---------------------------------------------------------------------------*/
479/*---------------------------------------------------------------------------*/
480
481} // End namespace Arcane
482
483/*---------------------------------------------------------------------------*/
484/*---------------------------------------------------------------------------*/
#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é
__host__ __device__ Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
Definition MathUtils.h:336
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:392
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
double Real
Type représentant un réel.
Real y
deuxième composante du couple
Definition Real2.h:35
Real x
première composante du couple
Definition Real2.h:34