Arcane  v4.1.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AMRPatchPositionSignatureCut.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/* AMRPatchPositionSignatureCut.cc (C) 2000-2025 */
9/* */
10/* Méthodes de découpages de patchs selon leurs signatures. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/cartesianmesh/internal/AMRPatchPositionSignatureCut.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/Math.h"
18
19#include "arcane/core/IMesh.h"
20
21#include "arcane/cartesianmesh/ICartesianMesh.h"
22
23#include "arcane/cartesianmesh/internal/AMRPatchPositionSignature.h"
24
25/*---------------------------------------------------------------------------*/
26/*---------------------------------------------------------------------------*/
27
28namespace Arcane
29{
30
31namespace
32{
33 constexpr Integer MIN_SIZE = 1;
34 constexpr Integer TARGET_SIZE = 8;
35 constexpr Real TARGET_SIZE_WEIGHT_IN_EFFICACITY = 1;
36 constexpr Integer MAX_NB_CUT = 6;
37 constexpr Real TARGET_EFFICACITY = 1.0;
38} // namespace
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43AMRPatchPositionSignatureCut::
44AMRPatchPositionSignatureCut()
45{
46}
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
51AMRPatchPositionSignatureCut::
52~AMRPatchPositionSignatureCut() = default;
53
54Integer AMRPatchPositionSignatureCut::
55_cutDim(ConstArrayView<Integer> sig)
56{
57 if (sig.size() < MIN_SIZE * 2) {
58 return -1;
59 }
60
61 Integer cut_point = -1;
62 Integer mid = sig.size() / 2;
63
64 {
65 for (Integer i = 0; i < sig.size(); ++i) {
66 if (sig[i] == 0) {
67 cut_point = i;
68 break;
69 }
70 }
71
72 if (cut_point == 0) {
73 ARCANE_FATAL("Call compress before");
74 }
75 if (cut_point != -1 && cut_point >= MIN_SIZE && sig.size() - cut_point >= MIN_SIZE) {
76 return cut_point;
77 }
78 }
79
80 {
81 UniqueArray<Integer> dsec_sig(sig.size(), 0);
82
83 Integer max = -1;
84 for (Integer i = 1; i < dsec_sig.size() - 1; ++i) {
85 dsec_sig[i] = sig[i + 1] - 2 * sig[i] + sig[i - 1];
86 Integer dif = math::abs(dsec_sig[i - 1] - dsec_sig[i]);
87 if (dif > max) {
88 cut_point = i;
89 max = dif;
90 }
91 else if (dif == max && math::abs(cut_point - mid) > math::abs(i - mid)) {
92 cut_point = i;
93 }
94 }
95
96 if (cut_point != -1 && cut_point >= MIN_SIZE && sig.size() - cut_point >= MIN_SIZE) {
97 return cut_point;
98 }
99 }
100
101 {
102 cut_point = mid;
103
104 if (cut_point != -1 && cut_point >= MIN_SIZE && sig.size() - cut_point >= MIN_SIZE) {
105 return cut_point;
106 }
107 }
108
109 return -1;
110}
111
112std::pair<AMRPatchPositionSignature, AMRPatchPositionSignature> AMRPatchPositionSignatureCut::
113cut(const AMRPatchPositionSignature& sig)
114{
115 Integer cut_point_x = _cutDim(sig.sigX());
116 Integer cut_point_y = _cutDim(sig.sigY());
117 Integer cut_point_z = (sig.mesh()->mesh()->dimension() == 2 ? -1 : _cutDim(sig.sigZ()));
118
119 if (cut_point_x == -1 && cut_point_y == -1 && cut_point_z == -1) {
120 return {};
121 }
122 if (cut_point_x != -1) {
123 cut_point_x += sig.patch().minPoint().x;
124 }
125 if (cut_point_y != -1) {
126 cut_point_y += sig.patch().minPoint().y;
127 }
128 if (cut_point_z != -1) {
129 cut_point_z += sig.patch().minPoint().z;
130 }
131
132 if (cut_point_x != -1 && cut_point_y != -1 && cut_point_z != -1) {
133 Real x_efficacity = 0;
134 auto [fst_x, snd_x] = sig.cut(MD_DirX, cut_point_x);
135 {
136 // sig.mesh()->traceMng()->info() << "Cut() -- Compute X -- Cut Point : " << cut_point_x;
137
138 fst_x.compute();
139 snd_x.compute();
140 if (fst_x.isValid() && snd_x.isValid()) {
141
142 // sig.mesh()->traceMng()->info() << "Cut() -- X.fst_x"
143 // << " -- min = " << fst_x.patch().minPoint()
144 // << " -- max = " << fst_x.patch().maxPoint()
145 // << " -- efficacity : " << fst_x.efficacity();
146 // sig.mesh()->traceMng()->info() << "Cut() -- X.snd_x"
147 // << " -- min = " << snd_x.patch().minPoint()
148 // << " -- max = " << snd_x.patch().maxPoint()
149 // << " -- efficacity : " << snd_x.efficacity();
150
151 x_efficacity = (fst_x.efficacity() + snd_x.efficacity()) / 2;
152 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity X : " << x_efficacity;
153 }
154 // else {
155 // sig.mesh()->traceMng()->info() << "Cut() -- Compute X invalid (too small) -- fst_x.length() : " << fst_x.patch().length() << " -- snd_x.length() : " << snd_x.patch().length();
156 // }
157 }
158
159 Real y_efficacity = 0;
160 auto [fst_y, snd_y] = sig.cut(MD_DirY, cut_point_y);
161 {
162 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Y -- Cut Point : " << cut_point_y;
163
164 fst_y.compute();
165 snd_y.compute();
166 if (fst_y.isValid() && snd_y.isValid()) {
167
168 // sig.mesh()->traceMng()->info() << "Cut() -- Y.fst_y"
169 // << " -- min = " << fst_y.patch().minPoint()
170 // << " -- max = " << fst_y.patch().maxPoint()
171 // << " -- efficacity : " << fst_y.efficacity();
172 // sig.mesh()->traceMng()->info() << "Cut() -- Y.snd_y"
173 // << " -- min = " << snd_y.patch().minPoint()
174 // << " -- max = " << snd_y.patch().maxPoint()
175 // << " -- efficacity : " << snd_y.efficacity();
176
177 y_efficacity = (fst_y.efficacity() + snd_y.efficacity()) / 2;
178 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Y : " << y_efficacity;
179 }
180 // else {
181 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Y invalid (too small) -- fst_y.length() : " << fst_y.patch().length() << " -- snd_y.length() : " << snd_y.patch().length();
182 // }
183 }
184
185 Real z_efficacity = 0;
186 auto [fst_z, snd_z] = sig.cut(MD_DirZ, cut_point_z);
187 {
188 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Z -- Cut Point : " << cut_point_z;
189
190 fst_z.compute();
191 snd_z.compute();
192 if (fst_z.isValid() && snd_z.isValid()) {
193
194 // sig.mesh()->traceMng()->info() << "Cut() -- Z.fst_z"
195 // << " -- min = " << fst_z.patch().minPoint()
196 // << " -- max = " << fst_z.patch().maxPoint()
197 // << " -- efficacity : " << fst_z.efficacity();
198 // sig.mesh()->traceMng()->info() << "Cut() -- Z.snd_z"
199 // << " -- min = " << snd_z.patch().minPoint()
200 // << " -- max = " << snd_z.patch().maxPoint()
201 // << " -- efficacity : " << snd_z.efficacity();
202
203 z_efficacity = (fst_z.efficacity() + snd_z.efficacity()) / 2;
204 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Z : " << z_efficacity;
205 }
206 // else {
207 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Z invalid (too small) -- fst_z.length() : " << fst_z.patch().length() << " -- snd_z.length() : " << snd_z.patch().length();
208 // }
209 }
210
211 if (sig.efficacity() > x_efficacity && sig.efficacity() > y_efficacity && sig.efficacity() > z_efficacity) {
212 return {};
213 }
214
215 if (x_efficacity >= y_efficacity && x_efficacity >= z_efficacity && x_efficacity != 0) {
216 return { fst_x, snd_x };
217 }
218 if (y_efficacity >= x_efficacity && y_efficacity >= z_efficacity && y_efficacity != 0) {
219 return { fst_y, snd_y };
220 }
221 if (z_efficacity == 0) {
222 ARCANE_FATAL("Invalid cut");
223 }
224 return { fst_z, snd_z };
225 }
226
227 if (cut_point_x != -1 && cut_point_y != -1) {
228 Real x_efficacity = 0;
229 auto [fst_x, snd_x] = sig.cut(MD_DirX, cut_point_x);
230 {
231 // sig.mesh()->traceMng()->info() << "Cut() -- Compute X -- Cut Point : " << cut_point_x;
232
233 fst_x.compute();
234 snd_x.compute();
235 if (fst_x.isValid() && snd_x.isValid()) {
236
237 // sig.mesh()->traceMng()->info() << "Cut() -- X.fst_x"
238 // << " -- min = " << fst_x.patch().minPoint()
239 // << " -- max = " << fst_x.patch().maxPoint()
240 // << " -- efficacity : " << fst_x.efficacity();
241 // sig.mesh()->traceMng()->info() << "Cut() -- X.snd_x"
242 // << " -- min = " << snd_x.patch().minPoint()
243 // << " -- max = " << snd_x.patch().maxPoint()
244 // << " -- efficacity : " << snd_x.efficacity();
245
246 x_efficacity = (fst_x.efficacity() + snd_x.efficacity()) / 2;
247 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity X : " << x_efficacity;
248 }
249 // else {
250 // sig.mesh()->traceMng()->info() << "Cut() -- Compute X invalid (too small) -- fst_x.length() : " << fst_x.patch().length() << " -- snd_x.length() : " << snd_x.patch().length();
251 // }
252 }
253
254 Real y_efficacity = 0;
255 auto [fst_y, snd_y] = sig.cut(MD_DirY, cut_point_y);
256 {
257 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Y -- Cut Point : " << cut_point_y;
258
259 fst_y.compute();
260 snd_y.compute();
261 if (fst_y.isValid() && snd_y.isValid()) {
262
263 // sig.mesh()->traceMng()->info() << "Cut() -- Y.fst_y"
264 // << " -- min = " << fst_y.patch().minPoint()
265 // << " -- max = " << fst_y.patch().maxPoint()
266 // << " -- efficacity : " << fst_y.efficacity();
267 // sig.mesh()->traceMng()->info() << "Cut() -- Y.snd_y"
268 // << " -- min = " << snd_y.patch().minPoint()
269 // << " -- max = " << snd_y.patch().maxPoint()
270 // << " -- efficacity : " << snd_y.efficacity();
271
272 y_efficacity = (fst_y.efficacity() + snd_y.efficacity()) / 2;
273 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Y : " << y_efficacity;
274 }
275 // else {
276 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Y invalid (too small) -- fst_y.length() : " << fst_y.patch().length() << " -- snd_y.length() : " << snd_y.patch().length();
277 // }
278 }
279
280 if (sig.efficacity() > x_efficacity && sig.efficacity() > y_efficacity) {
281 return {};
282 }
283
284 if (x_efficacity >= y_efficacity && x_efficacity != 0) {
285 return { fst_x, snd_x };
286 }
287 if (y_efficacity == 0) {
288 ARCANE_FATAL("Invalid cut");
289 }
290 return { fst_y, snd_y };
291 }
292
293 if (cut_point_x != -1) {
294 Real x_efficacity = 0;
295 auto [fst_x, snd_x] = sig.cut(MD_DirX, cut_point_x);
296
297 // sig.mesh()->traceMng()->info() << "Cut() -- Compute X -- Cut Point : " << cut_point_x;
298
299 fst_x.compute();
300 snd_x.compute();
301 if (fst_x.isValid() && snd_x.isValid()) {
302
303 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity X.fst_x : " << fst_x.efficacity();
304 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity X.snd_x : " << snd_x.efficacity();
305 x_efficacity = (fst_x.efficacity() + snd_x.efficacity()) / 2;
306 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity X : " << x_efficacity;
307 }
308 // else {
309 // sig.mesh()->traceMng()->info() << "Cut() -- Compute X invalid (too small) -- fst_x.length() : " << fst_x.patch().length() << " -- snd_x.length() : " << snd_x.patch().length();
310 // }
311 if (sig.efficacity() > x_efficacity) {
312 return {};
313 }
314 return { fst_x, snd_x };
315 }
316
317 if (cut_point_y != -1) {
318 Real y_efficacity = 0;
319 auto [fst_y, snd_y] = sig.cut(MD_DirY, cut_point_y);
320
321 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Y -- Cut Point : " << cut_point_y;
322
323 fst_y.compute();
324 snd_y.compute();
325 if (fst_y.isValid() && snd_y.isValid()) {
326
327 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Y.fst_y : " << fst_y.efficacity();
328 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Y.snd_y : " << snd_y.efficacity();
329 y_efficacity = (fst_y.efficacity() + snd_y.efficacity()) / 2;
330 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Y : " << y_efficacity;
331 }
332 // else {
333 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Y invalid (too small) -- fst_y.length() : " << fst_y.patch().length() << " -- snd_y.length() : " << snd_y.patch().length();
334 // }
335 if (sig.efficacity() > y_efficacity) {
336 return {};
337 }
338 return { fst_y, snd_y };
339 }
340 if (cut_point_z != -1) {
341 Real z_efficacity = 0;
342 auto [fst_z, snd_z] = sig.cut(MD_DirZ, cut_point_z);
343
344 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Z -- Cut Point : " << cut_point_z;
345
346 fst_z.compute();
347 snd_z.compute();
348 if (fst_z.isValid() && snd_z.isValid()) {
349
350 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Z.fst_z : " << fst_z.efficacity();
351 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Z.snd_z : " << snd_z.efficacity();
352 z_efficacity = (fst_z.efficacity() + snd_z.efficacity()) / 2;
353 // sig.mesh()->traceMng()->info() << "Cut() -- efficacity Z : " << z_efficacity;
354 }
355 // else {
356 // sig.mesh()->traceMng()->info() << "Cut() -- Compute Z invalid (too small) -- fst_z.length() : " << fst_z.patch().length() << " -- snd_z.length() : " << snd_z.patch().length();
357 // }
358 if (sig.efficacity() > z_efficacity) {
359 return {};
360 }
361 return { fst_z, snd_z };
362 }
363}
364
365void AMRPatchPositionSignatureCut::
367{
368 UniqueArray<AMRPatchPositionSignature> sig_array_b;
369 bool a_a_b_b = false;
370 bool need_cut = true;
371
372 while (need_cut) {
373 need_cut = false;
374 a_a_b_b = !a_a_b_b;
375
376 UniqueArray<AMRPatchPositionSignature>& array_in = a_a_b_b ? sig_array_a : sig_array_b;
377 UniqueArray<AMRPatchPositionSignature>& array_out = a_a_b_b ? sig_array_b : sig_array_a;
378
379 for (Integer i = 0; i < array_in.size(); ++i) {
380 AMRPatchPositionSignature sig = array_in[i];
381 // sig.mesh()->traceMng()->info() << "Cut() -- i : " << i;
382
383 if (!sig.stopCut()) {
384 if (!sig.isComputed()) {
385 sig.compute();
386 }
387 if (sig.canBeCut()) {
388 auto [fst, snd] = cut(sig);
389
390 if (fst.isValid()) {
391 need_cut = true;
392 array_out.add(fst);
393 array_out.add(snd);
394 // sig.mesh()->traceMng()->info() << "First Signature :";
395 // sig.mesh()->traceMng()->info() << "\tmin = " << fst.patch().minPoint() << " -- max = " << fst.patch().maxPoint() << " -- length = " << fst.patch().length();
396 // sig.mesh()->traceMng()->info() << "Second Signature :";
397 // sig.mesh()->traceMng()->info() << "\tmin = " << snd.patch().minPoint() << " -- max = " << snd.patch().maxPoint() << " -- length = " << snd.patch().length();
398 continue;
399 }
400 // sig.mesh()->traceMng()->info() << "Invalid Signature";
401 sig.setStopCut(true);
402 }
403 else {
404 sig.setStopCut(true);
405 }
406 }
407 // sig.mesh()->traceMng()->info() << "No Update";
408 // sig.mesh()->traceMng()->info() << "\tmin = " << sig.patch().minPoint() << " -- max = " << sig.patch().maxPoint();
409 array_out.add(sig);
410 }
411 array_in.clear();
412 }
413 if (a_a_b_b) {
414 sig_array_a.clear();
415 sig_array_a = sig_array_b;
416 }
417}
418
419/*---------------------------------------------------------------------------*/
420/*---------------------------------------------------------------------------*/
421
422} // End namespace Arcane
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Vue constante d'un tableau de type T.
Vecteur 1D de données avec sémantique par valeur (style STL).
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.
@ MD_DirZ
Direction Z.
@ MD_DirY
Direction Y.
@ MD_DirX
Direction X.
double Real
Type représentant un réel.