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