Arcane  v4.1.1.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(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(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
97AMRPatchPositionSignature::
98~AMRPatchPositionSignature()
99= default;
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103
104void AMRPatchPositionSignature::
105compress()
106{
107 if (!m_have_cells) {
108 return;
109 }
110
111 Integer reduce_x_min = 0;
112 if (m_sig_x[0] == 0) {
113 for (; reduce_x_min < m_sig_x.size(); ++reduce_x_min) {
114 if (m_sig_x[reduce_x_min] != 0) {
115 break;
116 }
117 }
118 }
119 Integer reduce_y_min = 0;
120 if (m_sig_y[0] == 0) {
121 for (; reduce_y_min < m_sig_y.size(); ++reduce_y_min) {
122 if (m_sig_y[reduce_y_min] != 0) {
123 break;
124 }
125 }
126 }
127 Integer reduce_z_min = 0;
128 if (m_sig_z[0] == 0) {
129 for (; reduce_z_min < m_sig_z.size(); ++reduce_z_min) {
130 if (m_sig_z[reduce_z_min] != 0) {
131 break;
132 }
133 }
134 }
135
136 Integer reduce_x_max = m_sig_x.size()-1;
137 if (m_sig_x[reduce_x_max] == 0) {
138 for (; reduce_x_max >= 0; --reduce_x_max) {
139 if (m_sig_x[reduce_x_max] != 0) {
140 break;
141 }
142 }
143 }
144 Integer reduce_y_max = m_sig_y.size()-1;
145 if (m_sig_y[reduce_y_max] == 0) {
146 for (; reduce_y_max >= 0; --reduce_y_max) {
147 if (m_sig_y[reduce_y_max] != 0) {
148 break;
149 }
150 }
151 }
152 Integer reduce_z_max = m_sig_z.size() - 1;
153 if (m_sig_z[reduce_z_max] == 0) {
154 for (; reduce_z_max >= 0; --reduce_z_max) {
155 if (m_sig_z[reduce_z_max] != 0) {
156 break;
157 }
158 }
159 }
160
161 if (reduce_x_min != 0 || reduce_x_max != m_sig_x.size()-1) {
162 if (reduce_x_max < reduce_x_min) {
163 ARCANE_FATAL("Bad patch X : no refine cell");
164 }
165 reduce_x_max++;
166 UniqueArray tmp = m_sig_x.subView(reduce_x_min, reduce_x_max - reduce_x_min);
167 m_sig_x = tmp;
168 Int64x3 patch_min = m_patch.minPoint();
169 Int64x3 patch_max = m_patch.maxPoint();
170 patch_min.x += reduce_x_min;
171 patch_max.x = patch_min.x + (reduce_x_max - reduce_x_min);
172 m_patch.setMinPoint(patch_min);
173 m_patch.setMaxPoint(patch_max);
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 Int64x3 patch_min = m_patch.minPoint();
183 Int64x3 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 if (m_mesh->mesh()->dimension() == 3 && (reduce_z_min != 0 || reduce_z_max != m_sig_z.size() - 1)) {
190 if (reduce_z_max < reduce_z_min) {
191 ARCANE_FATAL("Bad patch Z : no refine cell");
192 }
193 reduce_z_max++;
194 UniqueArray tmp = m_sig_z.subView(reduce_z_min, reduce_z_max - reduce_z_min);
195 m_sig_z = tmp;
196 Int64x3 patch_min = m_patch.minPoint();
197 Int64x3 patch_max = m_patch.maxPoint();
198 patch_min.z += reduce_z_min;
199 patch_max.z = patch_min.z + (reduce_z_max - reduce_z_min);
200 m_patch.setMinPoint(patch_min);
201 m_patch.setMaxPoint(patch_max);
202 }
203}
204
205/*---------------------------------------------------------------------------*/
206/*---------------------------------------------------------------------------*/
207
208void AMRPatchPositionSignature::
209fillSig()
210{
211 m_sig_x.fill(0);
212 m_sig_y.fill(0);
213 m_sig_z.fill(0);
214 ENUMERATE_ (Cell, icell, m_mesh->mesh()->ownLevelCells(m_patch.level())) {
215 if (!icell->hasFlags(ItemFlags::II_Refine)) {
216 continue;
217 }
218
219 const Int64 pos_x = m_numbering->cellUniqueIdToCoordX(*icell);
220 const Int64 pos_y = m_numbering->cellUniqueIdToCoordY(*icell);
221 const Int64 pos_z = m_numbering->cellUniqueIdToCoordZ(*icell);
222
223 if (
224 pos_x < m_patch.minPoint().x || pos_x >= m_patch.maxPoint().x ||
225 pos_y < m_patch.minPoint().y || pos_y >= m_patch.maxPoint().y ||
226 pos_z < m_patch.minPoint().z || pos_z >= m_patch.maxPoint().z) {
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 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_x);
236 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_y);
237 m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceSum, m_sig_z);
238
239 if (m_all_patches->maxLevel() > m_patch.level()) {
240
241 // Pour que la signature soit valide, il ne faut pas que les patchs de m_all_patches
242 // s'intersectent entre eux (pour un même niveau).
243 for (const auto& elem : m_all_patches->patches(m_patch.level() + 1)) {
244 AMRPatchPosition patch_down = elem.patchDown(m_mesh->mesh()->dimension());
245 if (!m_patch.haveIntersection(patch_down)) {
246 continue;
247 }
248
249 Int64x3 min = patch_down.minPoint() - m_patch.minPoint();
250 Int64x3 max = patch_down.maxPoint() - m_patch.minPoint();
251
252 Int64x3 begin;
253 Int64x3 end;
254
255 begin.x = std::max(min.x, static_cast<Int64>(0));
256 end.x = std::min(max.x, static_cast<Int64>(m_sig_x.size()));
257
258 begin.y = std::max(min.y, static_cast<Int64>(0));
259 end.y = std::min(max.y, static_cast<Int64>(m_sig_y.size()));
260
261 if (m_mesh->mesh()->dimension() == 2) {
262 begin.z = 0;
263 end.z = 1;
264 }
265 else {
266 begin.z = std::max(min.z, static_cast<Int64>(0));
267 end.z = std::min(max.z, static_cast<Int64>(m_sig_z.size()));
268 }
269
270 for (Int64 k = begin.z; k < end.z; ++k) {
271 for (Int64 j = begin.y; j < end.y; ++j) {
272 for (Int64 i = begin.x; i < end.x; ++i) {
273 m_sig_x[i]++;
274 m_sig_y[j]++;
275 m_sig_z[k]++;
276 m_have_cells = true;
277 }
278 }
279 }
280 }
281 }
282
283 m_have_cells = m_mesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceMax, m_have_cells);
284}
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
288
289bool AMRPatchPositionSignature::
290isValid() const
291{
292 if (m_is_null) {
293 return false;
294 }
295 if (m_sig_x.size() < MIN_SIZE || m_sig_y.size() < MIN_SIZE || (m_mesh->mesh()->dimension() == 3 && m_sig_z.size() < MIN_SIZE)) {
296 return false;
297 }
298 return true;
299}
300
301/*---------------------------------------------------------------------------*/
302/*---------------------------------------------------------------------------*/
303
304bool AMRPatchPositionSignature::
305canBeCut() const
306{
307 m_mesh->traceMng()->info() << "canBeCut() -- m_sig_x.size : " << m_sig_x.size()
308 << " -- m_sig_y.size : " << m_sig_y.size()
309 << " -- m_sig_z.size : " << m_sig_z.size()
310 << " -- min = " << m_patch.minPoint()
311 << " -- max = " << m_patch.maxPoint()
312 << " -- length = " << m_patch.length()
313 << " -- isValid : " << isValid()
314 << " -- efficacity : " << efficacity() << " / " << TARGET_EFFICACITY
315 << " -- m_nb_cut : " << m_nb_cut << " / " << MAX_NB_CUT
316 << " -- m_stop_cut : " << m_stop_cut;
317
318 if (!isValid()) {
319 return false;
320 }
321
322 if (m_stop_cut) {
323 return false;
324 }
325
326 if (efficacity() > TARGET_EFFICACITY) {
327 return false;
328 }
329 if (MAX_NB_CUT != -1 && m_nb_cut >= MAX_NB_CUT) {
330 return false;
331 }
332 return true;
333}
334
335/*---------------------------------------------------------------------------*/
336/*---------------------------------------------------------------------------*/
337
338void AMRPatchPositionSignature::
339compute()
340{
341 m_mesh->traceMng()->info() << "Compute() -- Patch before compute : min = " << m_patch.minPoint() << " -- max = " << m_patch.maxPoint() << " -- length = " << m_patch.length();
342 fillSig();
343 //m_mesh->traceMng()->info() << "Compute() -- Signature : x = " << m_sig_x << " -- y = " << m_sig_y ;
344 compress();
345 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;
346 m_mesh->traceMng()->info() << "Compute() -- Patch computed : min = " << m_patch.minPoint() << " -- max = " << m_patch.maxPoint() << " -- length = " << m_patch.length();
347
348 m_is_computed = true;
349}
350
351/*---------------------------------------------------------------------------*/
352/*---------------------------------------------------------------------------*/
353
354Real AMRPatchPositionSignature::
355efficacity() const
356{
357 if (!m_is_computed) {
358 // Sans compression, pas terrible.
359 m_mesh->traceMng()->warning() << "Need to be computed";
360 }
361 Integer sum = 0;
362 for (const Integer elem : m_sig_x) {
363 sum += elem;
364 }
365
366 Real eff = static_cast<Real>(sum) / (m_sig_x.size() * m_sig_y.size() * m_sig_z.size());
367
368 if constexpr (TARGET_SIZE == -1 || TARGET_SIZE_WEIGHT_IN_EFFICACITY == 0) {
369 return eff;
370 }
371
372 Real eff_xy = 0;
373 if (m_sig_x.size() <= TARGET_SIZE) {
374 eff_xy = static_cast<Real>(m_sig_x.size()) / TARGET_SIZE;
375 }
376 else if (m_sig_x.size() < TARGET_SIZE*2) {
377 Real size_x = math::abs(m_sig_x.size() - TARGET_SIZE*2);
378 eff_xy = size_x / TARGET_SIZE;
379 }
380
381 if (m_sig_y.size() <= TARGET_SIZE) {
382 eff_xy += static_cast<Real>(m_sig_y.size()) / TARGET_SIZE;
383 }
384 else if (m_sig_y.size() < TARGET_SIZE * 2) {
385 Real size_y = math::abs(m_sig_y.size() - TARGET_SIZE * 2);
386 eff_xy += size_y / TARGET_SIZE;
387 }
388
389 if (m_mesh->mesh()->dimension() == 2) {
390 eff_xy /= 2;
391 }
392 else {
393 if (m_sig_z.size() <= TARGET_SIZE) {
394 eff_xy = (eff_xy + (static_cast<Real>(m_sig_z.size()) / TARGET_SIZE)) / 3;
395 }
396 else if (m_sig_z.size() < TARGET_SIZE * 2) {
397 Real size_z = math::abs(m_sig_z.size() - TARGET_SIZE * 2);
398 eff_xy = (eff_xy + (size_z / TARGET_SIZE)) / 3;
399 }
400 else {
401 eff_xy /= 3;
402 }
403 }
404 eff_xy *= TARGET_SIZE_WEIGHT_IN_EFFICACITY;
405
406 return (eff+eff_xy)/(1+TARGET_SIZE_WEIGHT_IN_EFFICACITY);
407}
408
409/*---------------------------------------------------------------------------*/
410/*---------------------------------------------------------------------------*/
411
412std::pair<AMRPatchPositionSignature, AMRPatchPositionSignature> AMRPatchPositionSignature::
413cut(Integer dim, Integer cut_point) const
414{
415 auto [fst, snd] = m_patch.cut(cut_point, dim);
416 return {AMRPatchPositionSignature(fst, m_mesh, m_all_patches, m_nb_cut+1), AMRPatchPositionSignature(snd, m_mesh, m_all_patches, m_nb_cut+1)};
417}
418
419/*---------------------------------------------------------------------------*/
420/*---------------------------------------------------------------------------*/
421
422bool AMRPatchPositionSignature::
423isIn(Integer x, Integer y, Integer z) const
424{
425 return m_patch.isIn(x, y, z);
426}
427ConstArrayView<Integer> AMRPatchPositionSignature::sigX() const
428{
429 return m_sig_x;
430}
431ConstArrayView<Integer> AMRPatchPositionSignature::sigY() const
432{
433 return m_sig_y;
434}
435ConstArrayView<Integer> AMRPatchPositionSignature::sigZ() const
436{
437 return m_sig_z;
438}
439AMRPatchPosition AMRPatchPositionSignature::patch() const
440{
441 return m_patch;
442}
443ICartesianMesh* AMRPatchPositionSignature::mesh() const
444{
445 return m_mesh;
446}
447bool AMRPatchPositionSignature::stopCut() const
448{
449 return m_stop_cut;
450}
451void AMRPatchPositionSignature::setStopCut(bool stop_cut)
452{
453 m_stop_cut = stop_cut;
454}
455bool AMRPatchPositionSignature::isComputed() const
456{
457 return m_is_computed;
458}
459
460/*---------------------------------------------------------------------------*/
461/*---------------------------------------------------------------------------*/
462
463} // End namespace Arcane
464
465/*---------------------------------------------------------------------------*/
466/*---------------------------------------------------------------------------*/
#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