Arcane  v4.1.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AMRCartesianMeshTesterModule.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/* AMRCartesianMeshTesterModule.cc (C) 2000-2025 */
9/* */
10/* Module de test du gestionnaire de maillages cartésiens AMR. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/CheckedConvert.h"
15#include "arcane/utils/PlatformUtils.h"
16#include "arcane/utils/Real2.h"
17#include "arcane/utils/MD5HashAlgorithm.h"
18
20#include "arcane/core/MeshKind.h"
21#include "arcane/core/Directory.h"
22
23#include "arcane/core/ITimeLoopMng.h"
24#include "arcane/core/ITimeLoopService.h"
25#include "arcane/core/ITimeLoop.h"
26#include "arcane/core/TimeLoopEntryPointInfo.h"
27#include "arcane/core/IMesh.h"
28#include "arcane/core/IItemFamily.h"
29#include "arcane/core/ItemPrinter.h"
30#include "arcane/core/IParallelMng.h"
31
32#include "arcane/core/IMesh.h"
33#include "arcane/core/IItemFamily.h"
34#include "arcane/core/IMeshModifier.h"
35#include "arcane/core/IMeshUtilities.h"
36#include "arcane/core/ServiceBuilder.h"
38#include "arcane/core/MeshStats.h"
39#include "arcane/core/IPostProcessorWriter.h"
40#include "arcane/core/IVariableMng.h"
41#include "arcane/core/SimpleSVGMeshExporter.h"
42#include "arcane/core/IGhostLayerMng.h"
43
44#include "arcane/cartesianmesh/ICartesianMesh.h"
45#include "arcane/cartesianmesh/AMRZonePosition.h"
46#include "arcane/cartesianmesh/CellDirectionMng.h"
47#include "arcane/cartesianmesh/FaceDirectionMng.h"
48#include "arcane/cartesianmesh/NodeDirectionMng.h"
49#include "arcane/cartesianmesh/CartesianConnectivity.h"
50#include "arcane/cartesianmesh/CartesianMeshAMRMng.h"
51#include "arcane/cartesianmesh/CartesianMeshRenumberingInfo.h"
52#include "arcane/cartesianmesh/ICartesianMeshPatch.h"
53#include "arcane/cartesianmesh/CartesianMeshUtils.h"
54#include "arcane/cartesianmesh/CartesianMeshCoarsening2.h"
55#include "arcane/cartesianmesh/CartesianMeshPatchListView.h"
56
57#include "arcane/tests/ArcaneTestGlobal.h"
58#include "arcane/tests/AMRCartesianMeshTester_axl.h"
59#include "arcane/tests/CartesianMeshTestUtils.h"
60
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
64namespace ArcaneTest
65{
66
67using namespace Arcane;
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
74class AMRCartesianMeshTesterModule
75: public ArcaneAMRCartesianMeshTesterObject
76{
77 public:
78
79 explicit AMRCartesianMeshTesterModule(const ModuleBuildInfo& mbi);
80 ~AMRCartesianMeshTesterModule();
81
82 public:
83
84 static void staticInitialize(ISubDomain* sd);
85
86 public:
87
88 void buildInit() override;
89 void compute() override;
90 void init() override;
91
92 private:
93
94 VariableCellReal m_density;
95 VariableCellReal m_old_density;
96 VariableCellReal3 m_cell_center;
97 VariableFaceReal3 m_face_center;
98 VariableNodeReal m_node_density;
99 ICartesianMesh* m_cartesian_mesh;
101 UniqueArray<VariableCellReal*> m_cell_patch_variables;
102 Int32 m_nb_expected_patch = 0;
103 bool m_merge_patches = true;
104
105 private:
106
107 void _compute1();
108 void _compute2();
109 void _initAMR();
110 void _coarseZone();
111 void _mergePatches();
112 void _reduceNbGhostLayers();
113 void _computeSubCellDensity(Cell cell);
114 void _computeCenters();
115 void _processPatches();
116 void _writePostProcessing();
117 void _checkUniqueIds();
118 void _testDirections();
119 void _checkDirections();
120 String _checkDirectionUniqueIdsHashCollective(ArrayView<Int64> own_items_uid_around, Integer nb_items_around);
121 Integer _cellsUidAroundCells(UniqueArray<Int64>& own_cells_uid_around_cells);
122 Integer _cellsUidAroundFaces(UniqueArray<Int64>& own_cells_uid_around_faces);
123 Integer _nodesUidAroundNodes(UniqueArray<Int64>& own_nodes_uid_around_nodes);
124 void _checkSync();
125 void _cellsInPatch(Real3 position, Real3 length, bool is_3d, Int32 level, UniqueArray<Int32>& cells_in_patch);
126};
127
128/*---------------------------------------------------------------------------*/
129/*---------------------------------------------------------------------------*/
130
131AMRCartesianMeshTesterModule::
132AMRCartesianMeshTesterModule(const ModuleBuildInfo& mbi)
133: ArcaneAMRCartesianMeshTesterObject(mbi)
134, m_density(VariableBuildInfo(this,"Density"))
135, m_old_density(VariableBuildInfo(this,"OldDensity"))
136, m_cell_center(VariableBuildInfo(this,"CellCenter"))
137, m_face_center(VariableBuildInfo(this,"FaceCenter"))
138, m_node_density(VariableBuildInfo(this,"NodeDensity"))
139, m_cartesian_mesh(nullptr)
140{
141}
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145
146AMRCartesianMeshTesterModule::
147~AMRCartesianMeshTesterModule()
148{
149 for (VariableCellReal* v : m_cell_patch_variables)
150 delete v;
151}
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
156void AMRCartesianMeshTesterModule::
157staticInitialize(ISubDomain* sd)
158{
159 String time_loop_name("AMRCartesianMeshTestLoop");
160
161 ITimeLoopMng* tlm = sd->timeLoopMng();
162 ITimeLoop* time_loop = tlm->createTimeLoop(time_loop_name);
163
164 {
165 List<TimeLoopEntryPointInfo> clist;
166 clist.add(TimeLoopEntryPointInfo("AMRCartesianMeshTester.buildInit"));
167 time_loop->setEntryPoints(ITimeLoop::WBuild,clist);
168 }
169
170 {
171 List<TimeLoopEntryPointInfo> clist;
172 clist.add(TimeLoopEntryPointInfo("AMRCartesianMeshTester.init"));
173 time_loop->setEntryPoints(ITimeLoop::WInit,clist);
174 }
175
176 {
177 List<TimeLoopEntryPointInfo> clist;
178 clist.add(TimeLoopEntryPointInfo("AMRCartesianMeshTester.compute"));
179 time_loop->setEntryPoints(ITimeLoop::WComputeLoop,clist);
180 }
181
182 {
183 StringList clist;
184 clist.add("AMRCartesianMeshTester");
185 time_loop->setRequiredModulesName(clist);
186 clist.clear();
187 clist.add("ArcanePostProcessing");
188 clist.add("ArcaneCheckpoint");
189 clist.add("ArcaneLoadBalance");
190 time_loop->setOptionalModulesName(clist);
191 }
192
193 tlm->registerTimeLoop(time_loop);
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
199void AMRCartesianMeshTesterModule::
200buildInit()
201{
202 if (subDomain()->isContinue())
203 return;
204
205 m_global_deltat.assign(1.0);
206
207 IItemFamily* cell_family = defaultMesh()->cellFamily();
208 cell_family->createGroup("CELL0");
209 cell_family->createGroup("CELL1");
210 cell_family->createGroup("CELL2");
211 cell_family->createGroup("AMRPatchCells0");
212 cell_family->createGroup("AMRPatchCells1");
213 cell_family->createGroup("AMRPatchCells2");
214 cell_family->createGroup("AMRPatchCells3");
215 cell_family->createGroup("AMRPatchCells4");
216 cell_family->createGroup("AMRPatchCells5");
217
218 IItemFamily* face_family = defaultMesh()->faceFamily();
219 face_family->createGroup("FACE0");
220 face_family->createGroup("FACE1");
221 face_family->createGroup("FACE2");
222 face_family->createGroup("FACE3");
223 face_family->createGroup("FACE4");
224 face_family->createGroup("FACE5");
225
226 face_family->createGroup("AllFacesDirection0");
227 face_family->createGroup("AllFacesDirection1");
228}
229
230/*---------------------------------------------------------------------------*/
231/*---------------------------------------------------------------------------*/
232
233void AMRCartesianMeshTesterModule::
234init()
235{
236 info() << "AMR Init";
237
238 IMesh* mesh = defaultMesh();
239
240 IItemFamily* cell_family = mesh->cellFamily();
241 Int32UniqueArray ids(1);
242 ids[0] = 0;
243 cell_family->createGroup("CELL0",ids,true);
244 ids[0] = 1;
245 cell_family->createGroup("CELL1",ids,true);
246 ids[0] = 2;
247 cell_family->createGroup("CELL2",ids,true);
248 IItemFamily* face_family = defaultMesh()->faceFamily();
249 ids[0] = 0;
250 face_family->createGroup("FACE0",ids,true);
251 ids[0] = 1;
252 face_family->createGroup("FACE1",ids,true);
253 ids[0] = 2;
254 face_family->createGroup("FACE2",ids,true);
255 ids[0] = 3;
256 face_family->createGroup("FACE3",ids,true);
257 ids[0] = 4;
258 face_family->createGroup("FACE4",ids,true);
259 ids[0] = 5;
260 face_family->createGroup("FACE5",ids,true);
261
262 m_cartesian_mesh = ICartesianMesh::getReference(mesh);
263 m_utils = makeRef(new CartesianMeshTestUtils(m_cartesian_mesh,acceleratorMng()));
264
265 m_merge_patches = options()->mergePatches();
266
267 if (!subDomain()->isContinue()) {
268 _initAMR();
269 _coarseZone();
270 if (m_merge_patches) {
271 _mergePatches();
272 }
273 _reduceNbGhostLayers();
274 }
275
276 _computeCenters();
277
278
279 const bool do_coarse_at_init = options()->coarseAtInit();
280
281 const Integer dimension = defaultMesh()->dimension();
282 if (dimension==2)
283 m_nb_expected_patch = 1 + options()->refinement2d().size();
284 else if (dimension==3)
285 m_nb_expected_patch = 1 + options()->refinement3d().size();
286
287 // Si on dé-raffine à l'init, on aura un patch de plus
288 if (do_coarse_at_init)
289 ++m_nb_expected_patch;
290
291 if (subDomain()->isContinue())
292 m_cartesian_mesh->recreateFromDump();
293 else{
294 m_cartesian_mesh->computeDirections();
295 CartesianMeshRenumberingInfo renumbering_info;
296 renumbering_info.setRenumberPatchMethod(options()->renumberPatchMethod());
297 renumbering_info.setSortAfterRenumbering(true);
298 if (options()->coarseAtInit())
299 renumbering_info.setParentPatch(m_cartesian_mesh->amrPatch(1));
300 m_cartesian_mesh->renumberItemsUniqueId(renumbering_info);
301 _checkUniqueIds();
302 _processPatches();
303 info() << "MaxUid for mesh=" << MeshUtils::getMaxItemUniqueIdCollective(m_cartesian_mesh->mesh());
304 }
305
306 // Initialise la densité.
307 // On met une densité de 1.0 à l'intérieur
308 // et on ajoute une densité de 5.0 pour chaque direction dans les
309 // mailles de bord.
310 m_density.fill(1.0);
311 for( Integer idir=0, nb_dir=dimension; idir<nb_dir; ++idir){
312 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
313 Integer nb_boundary1 = 0;
314 Integer nb_boundary2 = 0;
315 ENUMERATE_CELL(icell,cdm.innerCells()){
316 DirCell cc(cdm.cell(*icell));
317 Cell next = cc.next();
318 Cell prev = cc.previous();
319 if (next.null() || prev.null()){
320 // Maille au bord. J'ajoute de la densité.
321 // Ne devrait pas arriver car on est sur les innerCells()
322 ++nb_boundary1;
323 m_density[icell] += 5.0;
324 }
325 }
326 // Parcours les mailles frontières pour la direction
327 ENUMERATE_CELL(icell,cdm.outerCells()){
328 DirCell cc(cdm[icell]);
329 if (icell.index()<5)
330 info() << "CELL: cell=" << ItemPrinter(*icell)
331 << " next=" << ItemPrinter(cc.next())
332 << " previous=" << ItemPrinter(cc.previous());
333 // Maille au bord. J'ajoute de la densité.
334 ++nb_boundary2;
335 m_density[icell] += 5.0;
336 }
337
338 info() << "NB_BOUNDARY1=" << nb_boundary1 << " NB_BOUNDARY2=" << nb_boundary2;
339 }
340 bool is_amr = m_nb_expected_patch!=1;
341 if (options()->verbosityLevel()==0)
342 m_utils->setNbPrint(5);
343 m_utils->testAll(is_amr);
344 _writePostProcessing();
345 _testDirections();
346 _checkDirections();
347 _checkSync();
348}
349
350/*---------------------------------------------------------------------------*/
351/*---------------------------------------------------------------------------*/
352
353void AMRCartesianMeshTesterModule::
354_checkUniqueIds()
355{
356 IMesh* mesh = m_cartesian_mesh->mesh();
357 bool print_hash = true;
358 bool with_ghost = options()->hashWithGhost();
359 MD5HashAlgorithm hash_algo;
360 MeshUtils::checkUniqueIdsHashCollective(mesh->nodeFamily(), &hash_algo, options()->nodesUidHash(),
361 print_hash, with_ghost);
362 MeshUtils::checkUniqueIdsHashCollective(mesh->faceFamily(), &hash_algo, options()->facesUidHash(),
363 print_hash, with_ghost);
364 MeshUtils::checkUniqueIdsHashCollective(mesh->cellFamily(), &hash_algo, options()->cellsUidHash(),
365 print_hash, with_ghost);
366}
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
371void AMRCartesianMeshTesterModule::
372_processPatches()
373{
374 const bool do_check = true;
375 const bool is_verbose = options()->verbosityLevel()>=1;
376
377 const Int32 dimension = defaultMesh()->dimension();
378
379 bool without_coarse_zone = true;
380 if (dimension == 2)
381 without_coarse_zone = options()->coarseZone2d().empty();
382 else if (dimension == 3)
383 without_coarse_zone = options()->coarseZone3d().empty();
384
385 // Vérifie qu'il y a autant de patchs que d'options raffinement dans
386 // le jeu de données (en comptant le patch 0 qui est le maillage cartésien).
387 // Cela permet de vérifier que les appels successifs
388 // à computeDirections() n'ajoutent pas de patchs.
389 // Cette vérification ne s'applique que s'il n'y a pas de zone de dé-raffinement.
390 // En effet, dé-raffiner un patch complet le supprime de la liste des patchs.
391 // Elle est aussi désactivée s'il y a fusion possible des patchs.
392 Integer nb_expected_patch = m_nb_expected_patch;
393
394 Integer nb_patch = m_cartesian_mesh->nbPatch();
395 if (without_coarse_zone && nb_expected_patch != nb_patch && !m_merge_patches)
396 ARCANE_FATAL("Bad number of patchs expected={0} value={1}",nb_expected_patch,nb_patch);
397
398 IParallelMng* pm = parallelMng();
399 Int32 comm_rank = pm->commRank();
400 Int32 comm_size = pm->commSize();
401
402 UniqueArray<Int32> nb_cells_expected(options()->expectedNumberOfCellsInPatchs);
403 if (nb_cells_expected.size()!=nb_patch)
404 ARCANE_FATAL("Bad size ({0}, expected={1}) for option '{2}'",
405 nb_cells_expected.size(),nb_patch,options()->expectedNumberOfCellsInPatchs.name());
406
407 // Nombre de mailles fantômes attendu. Utilisé uniquement en parallèle
408 bool has_expected_ghost_cells = options()->expectedNumberOfGhostCellsInPatchs.isPresent();
409 if (!pm->isParallel())
410 has_expected_ghost_cells = false;
411
412 UniqueArray<Int32> nb_ghost_cells_expected(options()->expectedNumberOfGhostCellsInPatchs);
413 if (has_expected_ghost_cells && (nb_ghost_cells_expected.size()!=nb_patch))
414 ARCANE_FATAL("Bad size ({0}, expected={1}) for option '{2}'",
415 nb_ghost_cells_expected.size(), nb_patch, options()->expectedNumberOfGhostCellsInPatchs.name());
416 // Affiche les informations sur les patchs
417 for( Integer i=0; i<nb_patch; ++i ){
418 ICartesianMeshPatch* p = m_cartesian_mesh->patch(i);
419 CellGroup patch_cells(p->cells());
420 info() << "Patch cell_group=" << patch_cells.name() << " nb_cell=" << patch_cells.size();
421 VariableCellReal* cellv = new VariableCellReal(VariableBuildInfo(defaultMesh(),String("CellPatch")+i));
422 m_cell_patch_variables.add(cellv);
423 cellv->fill(0.0);
424 ENUMERATE_CELL(icell,patch_cells){
425 (*cellv)[icell] = 2.0;
426 }
427
428 CellGroup patch_own_cell = patch_cells.own();
429 UniqueArray<Int64> own_cells_uid;
430 ENUMERATE_(Cell,icell,patch_own_cell){
431 Cell cell{*icell};
432 if (is_verbose)
433 info() << "Patch i=" << i << " cell=" << ItemPrinter(*icell);
434 own_cells_uid.add(cell.uniqueId());
435 }
436 // Affiche la liste globales des uniqueId() des mailles.
437 {
438 UniqueArray<Int64> global_cells_uid;
439 pm->allGatherVariable(own_cells_uid,global_cells_uid);
440 std::sort(global_cells_uid.begin(),global_cells_uid.end());
441 Integer nb_global_uid = global_cells_uid.size();
442 info() << "GlobalUids Patch=" << i << " NB=" << nb_global_uid
443 << " expected=" << nb_cells_expected[i];
444 // Vérifie que le nombre de mailles par patch est le bon.
445 if (do_check && nb_cells_expected[i]!=nb_global_uid)
446 ARCANE_FATAL("Bad number of cells for patch I={0} N={1} expected={2}",
447 i,nb_global_uid,nb_cells_expected[i]);
448 if (is_verbose)
449 for( Integer c=0; c<nb_global_uid; ++c )
450 info() << "GlobalUid Patch=" << i << " I=" << c << " cell_uid=" << global_cells_uid[c];
451 }
452 // Teste le nombre de mailles fantômes
453 if (has_expected_ghost_cells){
454 Int32 local_nb_ghost_cell = patch_cells.size() - patch_own_cell.size();
455 Int32 total = pm->reduce(Parallel::ReduceSum,local_nb_ghost_cell);
456 pinfo() << "NbGhostCells my_rank=" << comm_rank << " local=" << local_nb_ghost_cell << " total=" << total;
457 if (total!=nb_ghost_cells_expected[i])
458 ARCANE_FATAL("Bad number of ghost cells for patch I={0} N={1} expected={2}",
459 i,total,nb_ghost_cells_expected[i]);
460 }
461
462 // Exporte le patch au format SVG
463 if (dimension==2 && options()->dumpSvg()){
464 String filename = String::format("Patch{0}-{1}-{2}.svg",i,comm_rank,comm_size);
465 Directory directory = subDomain()->exportDirectory();
466 String full_filename = directory.file(filename);
467 std::ofstream ofile(full_filename.localstr());
468 SimpleSVGMeshExporter exporter(ofile);
469 exporter.write(patch_cells);
470 }
471 }
472}
473
474/*---------------------------------------------------------------------------*/
475/*---------------------------------------------------------------------------*/
476
477void AMRCartesianMeshTesterModule::
478_computeCenters()
479{
480 IMesh* mesh = defaultMesh();
481
482 // Calcule le centre des mailles
483 {
484 VariableNodeReal3& nodes_coord = mesh->nodesCoordinates();
485 ENUMERATE_CELL(icell,allCells()){
486 Cell cell = *icell;
487 Real3 center;
488 for( NodeLocalId inode : cell.nodes() )
489 center += nodes_coord[inode];
490 center /= cell.nbNode();
491 m_cell_center[icell] = center;
492 }
493 }
494
495 // Calcule le centre des faces
496 {
497 VariableNodeReal3& nodes_coord = mesh->nodesCoordinates();
498 ENUMERATE_FACE(iface,allFaces()){
499 Face face = *iface;
500 Real3 center;
501 for( NodeLocalId inode : face.nodes() )
502 center += nodes_coord[inode];
503 center /= face.nbNode();
504 m_face_center[iface] = center;
505 }
506 }
507}
508
509/*---------------------------------------------------------------------------*/
510/*---------------------------------------------------------------------------*/
511
512void AMRCartesianMeshTesterModule::
513_initAMR()
514{
515 CartesianMeshAMRMng amr_mng(m_cartesian_mesh);
516 amr_mng.enableOverlapLayer(false);
517
518 // Regarde si on dé-raffine le maillage initial
519 if (options()->coarseAtInit()){
520 // Il faut que les directions aient été calculées avant d'appeler le dé-raffinement
521 m_cartesian_mesh->computeDirections();
522
523 info() << "Doint initial coarsening";
524 //
525 // if (m_cartesian_mesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::PatchCartesianMeshOnly) {
526 // debug() << "Coarse with specific coarser (for cartesian mesh only)";
527 // Ref<ICartesianMeshAMRPatchMng> coarser = CartesianMeshUtils::cartesianMeshAMRPatchMng(m_cartesian_mesh);
528 // coarser->createSubLevel();
529 // }
530 // else {
531 // Ref<CartesianMeshCoarsening2> coarser = CartesianMeshUtils::createCartesianMeshCoarsening2(m_cartesian_mesh);
532 // coarser->createCoarseCells();
533 // }
534 amr_mng.createSubLevel();
535
536 CartesianMeshPatchListView patches = m_cartesian_mesh->patches();
537 Int32 nb_patch = patches.size();
538 {
539 Int32 index = 0;
540 info() << "NB_PATCH=" << nb_patch;
541 for( CartesianPatch p : patches){
542 info() << "Patch i=" << index << " nb_cell=" << p.cells().size();
543 ++index;
544 }
545 }
546 }
547 // Parcours les mailles actives et ajoute dans la liste des mailles
548 // à raffiner celles qui sont contenues dans le boîte englobante
549 // spécifiée dans le jeu de données.
550 Int32 dim = defaultMesh()->dimension();
551 if (dim == 2) {
552 for (const auto& x : options()->refinement2d()) {
553 amr_mng.refineZone({ x->position(), x->length() });
554 m_cartesian_mesh->computeDirections();
555 }
556 }
557 if (dim == 3) {
558 for (const auto& x : options()->refinement3d()) {
559 amr_mng.refineZone({ x->position(), x->length() });
560 m_cartesian_mesh->computeDirections();
561 }
562 }
563}
564
565/*---------------------------------------------------------------------------*/
566/*---------------------------------------------------------------------------*/
567
568void AMRCartesianMeshTesterModule::
569_coarseZone()
570{
571 Int32 dim = defaultMesh()->dimension();
572 CartesianMeshAMRMng amr_mng(m_cartesian_mesh);
573
574 if (dim == 2) {
575 //UniqueArray<Int32> cells_in_patchs;
576 for (auto& x : options()->coarseZone2d()) {
577 // _cellsInPatch(Real3(x->position()), Real3(x->length()), false, x->level(), cells_in_patchs);
578 // defaultMesh()->modifier()->flagCellToCoarsen(cells_in_patchs);
579 // defaultMesh()->modifier()->coarsenItemsV2(true);
580 // cells_in_patchs.clear();
581 amr_mng.coarseZone({ { x->position() }, { x->length() } });
582 m_cartesian_mesh->computeDirections();
583 }
584 }
585 if (dim == 3) {
586 // UniqueArray<Int32> cells_in_patchs;
587 for (auto& x : options()->coarseZone3d()) {
588 // _cellsInPatch(x->position(), x->length(), true, x->level(), cells_in_patchs);
589 // defaultMesh()->modifier()->flagCellToCoarsen(cells_in_patchs);
590 // defaultMesh()->modifier()->coarsenItemsV2(true);
591 // cells_in_patchs.clear();
592 amr_mng.coarseZone({ { x->position() }, { x->length() } });
593 m_cartesian_mesh->computeDirections();
594 }
595 }
596}
597
598/*---------------------------------------------------------------------------*/
599/*---------------------------------------------------------------------------*/
600
601void AMRCartesianMeshTesterModule::
602_mergePatches()
603{
604 CartesianMeshAMRMng amr_mng(m_cartesian_mesh);
605 amr_mng.mergePatches();
606
607 m_cartesian_mesh->computeDirections();
608}
609
610/*---------------------------------------------------------------------------*/
611/*---------------------------------------------------------------------------*/
612
613void AMRCartesianMeshTesterModule::
614_reduceNbGhostLayers()
615{
616 for (auto& x : options()->reduceNbGhostLayers()) {
617 Integer final_nb_ghost_layer{ m_cartesian_mesh->reduceNbGhostLayers(x->level(), x->nbGhostLayers()) };
618
619 if (parallelMng()->commSize() != 1 && final_nb_ghost_layer != x->nbGhostLayers()) {
620 ARCANE_FATAL("Bad nb ghost layers");
621 }
622 //info() << "Final nb ghost layer : " << final_nb_ghost_layer;
623 }
624}
625
626/*---------------------------------------------------------------------------*/
627/*---------------------------------------------------------------------------*/
628
629void AMRCartesianMeshTesterModule::
630compute()
631{
632 _compute1();
633 // info() << "NbPatch : " << m_cartesian_mesh->nbPatch();
634 // info() << "NbPatch : " << m_cartesian_mesh->patches().size();
635 //
636 // for (Integer i = 0; i < m_cartesian_mesh->patches().size(); ++i) {
637 // auto patch = m_cartesian_mesh->amrPatch(i);
638 // info() << "Patch #" << i;
639 // info() << "\tMin Point : " << patch.patchInterface()->position().minPoint();
640 // info() << "\tMax Point : " << patch.patchInterface()->position().maxPoint();
641 // info() << "\tLevel : " << patch.patchInterface()->position().level();
642 // }
643}
644
645/*---------------------------------------------------------------------------*/
646/*---------------------------------------------------------------------------*/
652{
653 Int32 nb_children = cell.nbHChildren();
654 if (nb_children==0)
655 return;
656 // Pour les mailles AMR, la densité est la moyenne des noeuds qui la compose.
657 for( Int32 j=0; j<nb_children; ++j ) {
658 Real sub_density = 0.0;
659 Cell sub_cell = cell.hChild(j);
660 Integer sub_cell_nb_node = sub_cell.nbNode();
661 for( Integer k=0; k<sub_cell_nb_node; ++k )
662 sub_density += m_node_density[sub_cell.node(k)];
663 sub_density /= (Real)sub_cell_nb_node;
664 m_density[sub_cell] =sub_density;
665 _computeSubCellDensity(sub_cell);
666 }
667}
668
669/*---------------------------------------------------------------------------*/
670/*---------------------------------------------------------------------------*/
671
672void AMRCartesianMeshTesterModule::
673_compute1()
674{
675 // Pour test, on parcours les N directions
676 // et pour chaque maille, on modifie sa densité
677 // par la formule new_density = (density+density_next+density_prev) / 3.0.
678
679 // Effectue l'operation en deux fois. Une premiere sur les
680 // mailles internes, et une deuxieme sur les mailles externes.
681 // Du coup, il faut passer par une variable intermediaire (m_old_density)
682 // mais on evite un test dans la boucle principale
683 IMesh* mesh = defaultMesh();
684 Integer nb_dir = mesh->dimension();
685 for( Integer idir=0; idir<nb_dir; ++idir){
686 m_old_density.copy(m_density);
687 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
688 // Travail sur les mailles internes
689 info() << "Direction=" << idir << " cells=" << cdm.innerCells().name()
690 << " n=" << cdm.innerCells().size();
691 ENUMERATE_CELL(icell,cdm.innerCells()){
692 Cell cell = *icell;
693 DirCell cc(cdm.cell(cell));
694 Cell next = cc.next();
695 Cell prev = cc.previous();
696 Real d = m_old_density[icell] + m_old_density[next] + m_old_density[prev];
697 m_density[icell] = d / 3.0;
699 }
700 // Travail sur les mailles externes
701 // Test si la maille avant ou apres est nulle.
702 ENUMERATE_CELL(icell,cdm.outerCells()){
703 Cell cell = *icell;
704 DirCell cc(cdm[icell]);
705 Cell next = cc.next();
706 Cell prev = cc.previous();
707 Real d = m_old_density[icell];
708 Integer n = 1;
709 if (!next.null()){
710 d += m_old_density[next];
711 ++n;
712 }
713 if (!prev.null()){
714 d += m_old_density[prev];
715 ++n;
716 }
717 m_density[icell] = d / n;
719 }
720 }
721 // Modifie la densité aux noeuds.
722 // Elle sera égale à la moyenne des densités des mailles entourant ce noeud
723 ENUMERATE_NODE(inode,mesh->allNodes()){
724 Node node = *inode;
725 Integer nb_cell = node.nbCell();
726 Real density = 0.0;
727 for( Integer i=0; i<nb_cell; ++i )
728 density += m_density[node.cell(i)];
729 density /= (Real)nb_cell;
730 m_node_density[inode] = density;
731 }
732}
733
734/*---------------------------------------------------------------------------*/
735/*---------------------------------------------------------------------------*/
736
737void AMRCartesianMeshTesterModule::
738_compute2()
739{
740 // Pour test, on parcours les N directions
741 // et pour chaque maille, on modifie sa densité
742 // par la formule new_density = (density+density_next+density_prev) / 3.0.
743
744 // A noter que cette methode ne donne pas le meme comportement que
745 // _compute1() car les mailles de bord et internes sont mises à jour
746 // dans un ordre différent.
747 Integer nb_dir = defaultMesh()->dimension();
748 for( Integer idir=0; idir<nb_dir; ++idir){
749 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
750 // Travail sur toutes les mailles
751 ENUMERATE_CELL(icell,cdm.allCells()){
752 DirCell cc(cdm[icell]);
753 Cell next = cc.next();
754 Cell prev = cc.previous();
755 Real d = m_density[icell];
756 Integer n = 1;
757 if (!next.null()){
758 d += m_density[next];
759 ++n;
760 }
761 if (!prev.null()){
762 d += m_density[prev];
763 ++n;
764 }
765 m_density[icell] = d / n;
766 }
767 }
768}
769
770/*---------------------------------------------------------------------------*/
771/*---------------------------------------------------------------------------*/
772
773void AMRCartesianMeshTesterModule::
774_writePostProcessing()
775{
776 info() << "Post-process AMR";
777 IPostProcessorWriter* post_processor = options()->postProcessor();
778 Directory output_directory = Directory(subDomain()->exportDirectory(),"amrtestpost1");
779 output_directory.createDirectory();
780 info() << "Creating output dir '" << output_directory.path() << "' for export";
781 UniqueArray<Real> times;
782 times.add(m_global_time());
783 post_processor->setTimes(times);
784 post_processor->setMesh(defaultMesh());
785 post_processor->setBaseDirectoryName(output_directory.path());
786
787 VariableList variables;
788 //variables.add(m_density.variable());
789 //variables.add(m_node_density.variable());
790 for( VariableCellReal* v : m_cell_patch_variables )
791 variables.add(v->variable());
792 post_processor->setVariables(variables);
793 ItemGroupList groups;
794 groups.add(allCells());
795 for( CartesianPatch p : m_cartesian_mesh->patches() )
796 groups.add(p.cells());
797 post_processor->setGroups(groups);
798 IVariableMng* vm = subDomain()->variableMng();
799 vm->writePostProcessing(post_processor);
800}
801
802/*---------------------------------------------------------------------------*/
803/*---------------------------------------------------------------------------*/
804
805void AMRCartesianMeshTesterModule::
806_testDirections()
807{
808 Integer nb_patch = m_cartesian_mesh->nbPatch();
809 Integer nb_dir = m_cartesian_mesh->mesh()->dimension();
810 NodeDirectionMng node_dm2;
811 for( Integer ipatch=0; ipatch<nb_patch; ++ipatch ){
812 ICartesianMeshPatch* p = m_cartesian_mesh->patch(ipatch);
813 for( Integer idir=0; idir<nb_dir; ++idir ){
814 NodeDirectionMng node_dm(p->nodeDirection(idir));
815 node_dm2 = p->nodeDirection(idir);
816 NodeGroup dm_all_nodes = node_dm.allNodes();
817 ENUMERATE_NODE(inode,dm_all_nodes){
818 DirNode dir_node(node_dm[inode]);
819 DirNode dir_node2(node_dm2[inode]);
820 Node prev_node = dir_node.previous();
821 Node next_node = dir_node.next();
822 Node prev_node2 = dir_node2.previous();
823 Node next_node2 = dir_node2.next();
824 m_utils->checkSameId(prev_node, prev_node2);
825 m_utils->checkSameId(next_node, next_node2);
826 }
827 }
828 }
829}
830
831void AMRCartesianMeshTesterModule::
832_checkDirections()
833{
834 m_cartesian_mesh->computeDirections();
835 IMesh* mesh = m_cartesian_mesh->mesh();
836 bool print_hash = true;
837
838 auto check_hash = [&](const IItemFamily* item_family, const String& expected_hash, ArrayView<Int64> own_items_uid_around, Integer nb_items_around) {
839 String cell_hash = _checkDirectionUniqueIdsHashCollective(own_items_uid_around, nb_items_around);
840
841 if (print_hash) {
842 info() << "HASH_RESULT direction items of family=" << item_family->name()
843 << " v= " << cell_hash << " expected= " << expected_hash;
844 }
845
846 if (cell_hash != expected_hash)
847 ARCANE_FATAL("Bad hash for uniqueId() for direction items of family '{0}' v='{1}' expected='{2}'",
848 item_family->fullName(), cell_hash, expected_hash);
849 };
850
851 if (!options()->cellsDirectionHash().empty()) {
852 debug() << "Check cells direction hash";
853 UniqueArray<Int64> own_cells_uid_around_cells;
854 Integer nb_items_around = _cellsUidAroundCells(own_cells_uid_around_cells);
855 check_hash(mesh->cellFamily(), options()->cellsDirectionHash(), own_cells_uid_around_cells, nb_items_around);
856 }
857 if (!options()->facesDirectionHash().empty()) {
858 debug() << "Check faces direction hash";
859 UniqueArray<Int64> own_cells_uid_around_faces;
860 Integer nb_items_around = _cellsUidAroundFaces(own_cells_uid_around_faces);
861 check_hash(mesh->faceFamily(), options()->facesDirectionHash(), own_cells_uid_around_faces, nb_items_around);
862 }
863
864 if (!options()->nodesDirectionHash().empty()) {
865 debug() << "Check nodes direction hash";
866 UniqueArray<Int64> own_nodes_uid_around_nodes;
867 Integer nb_items_around = _nodesUidAroundNodes(own_nodes_uid_around_nodes);
868 check_hash(mesh->nodeFamily(), options()->nodesDirectionHash(), own_nodes_uid_around_nodes, nb_items_around);
869 }
870}
871
883_checkDirectionUniqueIdsHashCollective(ArrayView<Int64> own_items_uid_around, Integer nb_items_around)
884{
885 // +1 car on a le uid dedans.
886 Integer size_of_once_case_around = nb_items_around + 1;
887
888 UniqueArray<Int64> final_all_items_uid;
889 {
890 UniqueArray<Int64> global_items_uid_around;
891 parallelMng()->allGatherVariable(own_items_uid_around, global_items_uid_around);
892
893 UniqueArray<Int64*> global_items_uid(global_items_uid_around.size() / size_of_once_case_around);
894 {
895 Int64 index = 0;
896 for (Int64 i = 0; i < global_items_uid_around.size(); i += size_of_once_case_around) {
897 Int64 uid = global_items_uid_around[i];
898 ARCANE_ASSERT((uid != -1), ("Un uid dans le tableau est = -1"));
899 global_items_uid[index++] = &(global_items_uid_around[i]);
900 }
901 }
902
903 std::sort(global_items_uid.begin(), global_items_uid.end(),
904 [](const Int64* a, const Int64* b) {
905 return *a < *b;
906 });
907
908 final_all_items_uid.resize(global_items_uid_around.size());
909
910 Int64 index = 0;
911 Int64 previous_uid = -1;
912
913 for (Int64* ptr_uid : global_items_uid) {
914 if (*ptr_uid == previous_uid) {
915 ARCANE_FATAL("Le uid {0} est dupliqué", *ptr_uid);
916 }
917 previous_uid = *ptr_uid;
918 for (Integer iaround = 0; iaround < size_of_once_case_around; ++iaround) {
919 final_all_items_uid[index++] = ptr_uid[iaround];
920 }
921 }
922 }
923
924 // info() << "final_all_items_uid : " << final_all_items_uid;
925
926 UniqueArray<Byte> hash_result;
927 MD5HashAlgorithm hash_algo;
928 hash_algo.computeHash64(asBytes(final_all_items_uid.constSpan()), hash_result);
929 return Convert::toHexaString(hash_result);
930}
931
942_cellsUidAroundCells(UniqueArray<Int64>& own_cells_uid_around_cells)
943{
944 IParallelMng* pm = parallelMng();
945 IMesh* mesh = m_cartesian_mesh->mesh();
946
947 if (pm->commSize() != 1 && mesh->ghostLayerMng()->nbGhostLayer() == 0) {
948 ARCANE_FATAL("Pas compatible sans ghost");
949 }
950
951 Integer nb_patch = m_cartesian_mesh->nbPatch();
952 Integer nb_dir = mesh->dimension();
953 Integer nb_items = mesh->cellFamily()->allItems().own().size();
954
955 // On a que pred et succ.
956 constexpr Integer nb_items_per_dir = 2;
957 constexpr Integer ipred = 0;
958 constexpr Integer isucc = 1;
959
960 // +1 car on a le uid dedans.
961 Integer size_of_once_case_around = nb_dir * nb_items_per_dir + 1;
962
963 own_cells_uid_around_cells.resize(nb_items * size_of_once_case_around, -1);
964
965 Integer index = 0;
966 ENUMERATE_ (Cell, icell, mesh->cellFamily()->allItems().own()) {
967 own_cells_uid_around_cells[index] = icell->uniqueId();
968 index += size_of_once_case_around;
969 }
970
971 auto set_value = [&](Integer dir, Int64 uid, Int64 uid_pred, Int64 uid_succ) -> void {
972 // debug() << " -- dir : " << dir
973 // << " -- uid : " << uid
974 // << " -- uid_pred : " << uid_pred
975 // << " -- uid_succ : " << uid_succ;
976
977 ARCANE_ASSERT((uid != -1), ("Uid ne peut pas être égal à -1"));
978
979 for (Integer i = 0; i < own_cells_uid_around_cells.size(); i += size_of_once_case_around) {
980 if (own_cells_uid_around_cells[i] == uid) {
981 Integer pos_final = i + 1 + (dir * nb_items_per_dir);
982 Integer pos_pred = pos_final + ipred;
983 Integer pos_succ = pos_final + isucc;
984 if (own_cells_uid_around_cells[pos_pred] != -1 && own_cells_uid_around_cells[pos_pred] != uid_pred) {
985 ARCANE_FATAL("Problème de cohérence entre les patchs (uid={0} -- old_uid_pred={1} -- new_uid_pred={2})", uid, own_cells_uid_around_cells[pos_pred], uid_pred);
986 }
987 if (own_cells_uid_around_cells[pos_succ] != -1 && own_cells_uid_around_cells[pos_succ] != uid_succ) {
988 ARCANE_FATAL("Problème de cohérence entre les patchs (uid={0} -- old_uid_succ={1} -- new_uid_succ={2})", uid, own_cells_uid_around_cells[pos_succ], uid_succ);
989 }
990 own_cells_uid_around_cells[pos_pred] = uid_pred;
991 own_cells_uid_around_cells[pos_succ] = uid_succ;
992 return;
993 }
994 }
995 };
996
997 for (Integer idir = 0; idir < nb_dir; ++idir) {
998 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
999 ENUMERATE_ (Cell, icell, cdm.allCells().own()) {
1000 DirCell cc(cdm.cell(*icell));
1001 Cell next = cc.next();
1002 Cell prev = cc.previous();
1003 set_value(idir, icell->uniqueId(), prev.uniqueId(), next.uniqueId());
1004 }
1005 }
1006
1007 for (Integer ipatch = 0; ipatch < nb_patch; ++ipatch) {
1008 ICartesianMeshPatch* p = m_cartesian_mesh->patch(ipatch);
1009 for (Integer idir = 0; idir < nb_dir; ++idir) {
1010 CellDirectionMng cdm(p->cellDirection(idir));
1011 ENUMERATE_ (Cell, icell, cdm.allCells().own()) {
1012 DirCell cc(cdm.cell(*icell));
1013 Cell next = cc.next();
1014 Cell prev = cc.previous();
1015 set_value(idir, icell->uniqueId(), prev.uniqueId(), next.uniqueId());
1016 }
1017 }
1018 }
1019
1020 return size_of_once_case_around-1;
1021}
1022
1033_cellsUidAroundFaces(UniqueArray<Int64>& own_cells_uid_around_faces)
1034{
1035 IParallelMng* pm = parallelMng();
1036 IMesh* mesh = m_cartesian_mesh->mesh();
1037
1038 if (pm->commSize() != 1 && mesh->ghostLayerMng()->nbGhostLayer() == 0) {
1039 ARCANE_FATAL("Pas compatible sans ghost");
1040 }
1041
1042 Integer nb_patch = m_cartesian_mesh->nbPatch();
1043 Integer nb_dir = mesh->dimension();
1044 Integer nb_items = mesh->faceFamily()->allItems().own().size();
1045
1046 // On a que pred et succ.
1047 constexpr Integer nb_items_per_dir = 2;
1048 constexpr Integer ipred = 0;
1049 constexpr Integer isucc = 1;
1050
1051 // +1 car on a le uid dedans.
1052 Integer size_of_once_case_around = nb_items_per_dir * nb_patch + 1;
1053
1054 own_cells_uid_around_faces.resize(nb_items * size_of_once_case_around, -1);
1055
1056 Integer index = 0;
1057 ENUMERATE_ (Item, iitem, mesh->faceFamily()->allItems().own()) {
1058 own_cells_uid_around_faces[index] = iitem->uniqueId();
1059 index += size_of_once_case_around;
1060 }
1061
1062 auto set_value = [&](Integer ipatch, Int64 uid, Int64 uid_pred, Int64 uid_succ) -> void {
1063 // debug() << " -- uid : " << uid
1064 // << " -- uid_pred : " << uid_pred
1065 // << " -- uid_succ : " << uid_succ;
1066
1067 ARCANE_ASSERT((uid != -1), ("Uid ne peut pas être égal à -1"));
1068
1069 for (Integer i = 0; i < own_cells_uid_around_faces.size(); i += size_of_once_case_around) {
1070 if (own_cells_uid_around_faces[i] == uid) {
1071 Integer pos_final = i + 1 + ipatch * nb_items_per_dir;
1072 Integer pos_pred = pos_final + ipred;
1073 Integer pos_succ = pos_final + isucc;
1074 if (own_cells_uid_around_faces[pos_pred] != -1 && own_cells_uid_around_faces[pos_pred] != uid_pred) {
1075 ARCANE_FATAL("Problème de cohérence entre les patchs (uid={0} -- old_uid_pred={1} -- new_uid_pred={2})", uid, own_cells_uid_around_faces[pos_pred], uid_pred);
1076 }
1077 if (own_cells_uid_around_faces[pos_succ] != -1 && own_cells_uid_around_faces[pos_succ] != uid_succ) {
1078 ARCANE_FATAL("Problème de cohérence entre les patchs (uid={0} -- old_uid_succ={1} -- new_uid_succ={2})", uid, own_cells_uid_around_faces[pos_succ], uid_succ);
1079 }
1080 own_cells_uid_around_faces[pos_pred] = uid_pred;
1081 own_cells_uid_around_faces[pos_succ] = uid_succ;
1082 return;
1083 }
1084 }
1085 };
1086
1087 // // TODO : Il faut pouvoir récupérer le patch correspondant.
1088 // for (Integer idir = 0; idir < nb_dir; ++idir) {
1089 // FaceDirectionMng fdm(m_cartesian_mesh->faceDirection(idir));
1090 // ENUMERATE_ (Face, iface, fdm.allFaces().own()) {
1091 // DirFace cc(fdm.face(*iface));
1092 // Cell next = cc.nextCell();
1093 // Cell prev = cc.previousCell();
1094 // set_value(iface->uniqueId(), prev.uniqueId(), next.uniqueId());
1095 // }
1096 // }
1097
1098 for (Integer ipatch = 0; ipatch < nb_patch; ++ipatch) {
1099 ICartesianMeshPatch* p = m_cartesian_mesh->patch(ipatch);
1100 for (Integer idir = 0; idir < nb_dir; ++idir) {
1101 FaceDirectionMng fdm(p->faceDirection(idir));
1102 ENUMERATE_ (Face, iface, fdm.allFaces().own()) {
1103 DirFace cc(fdm.face(*iface));
1104 Cell next = cc.nextCell();
1105 Cell prev = cc.previousCell();
1106 set_value(ipatch, iface->uniqueId(), prev.uniqueId(), next.uniqueId());
1107 }
1108 }
1109 }
1110
1111 return size_of_once_case_around-1;
1112}
1113
1129_nodesUidAroundNodes(UniqueArray<Int64>& own_nodes_uid_around_nodes)
1130{
1131 IParallelMng* pm = parallelMng();
1132 IMesh* mesh = m_cartesian_mesh->mesh();
1133
1134 if (pm->commSize() != 1 && mesh->ghostLayerMng()->nbGhostLayer() == 0) {
1135 ARCANE_FATAL("Pas compatible sans ghost");
1136 }
1137
1138 Integer nb_patch = m_cartesian_mesh->nbPatch();
1139 Integer nb_dir = mesh->dimension();
1140 Integer nb_items = mesh->nodeFamily()->allItems().own().size();
1141
1142 // On a que pred et succ.
1143 constexpr Integer nb_items_per_dir = 2;
1144 constexpr Integer ipred = 0;
1145 constexpr Integer isucc = 1;
1146
1147 // +1 car on a le uid dedans.
1148 Integer size_of_once_case_around = nb_dir * nb_items_per_dir * nb_patch + 1;
1149
1150 own_nodes_uid_around_nodes.resize(nb_items * size_of_once_case_around, -1);
1151
1152 Integer index = 0;
1153 ENUMERATE_ (Item, iitem, mesh->nodeFamily()->allItems().own()) {
1154 own_nodes_uid_around_nodes[index] = iitem->uniqueId();
1155 index += size_of_once_case_around;
1156 }
1157
1158 auto set_value = [&](Integer dir, Integer ipatch, Int64 uid, Int64 uid_pred, Int64 uid_succ) {
1159 // debug() << " -- dir : " << dir
1160 // << " -- ipatch : " << ipatch
1161 // << " -- uid : " << uid
1162 // << " -- uid_pred : " << uid_pred
1163 // << " -- uid_succ : " << uid_succ;
1164
1165 ARCANE_ASSERT((uid != -1), ("Uid ne peut pas être égal à -1"));
1166
1167 for (Integer i = 0; i < own_nodes_uid_around_nodes.size(); i += size_of_once_case_around) {
1168 if (own_nodes_uid_around_nodes[i] == uid) {
1169 Integer pos_final = i + 1 + ipatch * (nb_items_per_dir * nb_dir) + dir * nb_items_per_dir;
1170 Integer pos_pred = pos_final + ipred;
1171 Integer pos_succ = pos_final + isucc;
1172 if (own_nodes_uid_around_nodes[pos_pred] != -1 && own_nodes_uid_around_nodes[pos_pred] != uid_pred) {
1173 ARCANE_FATAL("Problème de cohérence entre les patchs (uid={0} -- old_uid_pred={1} -- new_uid_pred={2})", uid, own_nodes_uid_around_nodes[pos_pred], uid_pred);
1174 }
1175 if (own_nodes_uid_around_nodes[pos_succ] != -1 && own_nodes_uid_around_nodes[pos_succ] != uid_succ) {
1176 ARCANE_FATAL("Problème de cohérence entre les patchs (uid={0} -- old_uid_succ={1} -- new_uid_succ={2})", uid, own_nodes_uid_around_nodes[pos_succ], uid_succ);
1177 }
1178 own_nodes_uid_around_nodes[pos_pred] = uid_pred;
1179 own_nodes_uid_around_nodes[pos_succ] = uid_succ;
1180 return;
1181 }
1182 }
1183 };
1184
1185 // // TODO : Il faut pouvoir récupérer le patch correspondant.
1186 // for (Integer idir = 0; idir < nb_dir; ++idir) {
1187 // NodeDirectionMng ndm(m_cartesian_mesh->nodeDirection(idir));
1188 // ENUMERATE_ (Node, inode, ndm.allNodes().own()) {
1189 // DirNode cc(ndm.node(*inode));
1190 // Node next = cc.next();
1191 // Node prev = cc.previous();
1192 // set_value(idir, 0, inode->uniqueId(), prev.uniqueId(), next.uniqueId());
1193 // }
1194 // }
1195
1196 for (Integer ipatch = 0; ipatch < nb_patch; ++ipatch) {
1197 ICartesianMeshPatch* p = m_cartesian_mesh->patch(ipatch);
1198 for (Integer idir = 0; idir < nb_dir; ++idir) {
1199 NodeDirectionMng ndm(p->nodeDirection(idir));
1200 ENUMERATE_ (Node, inode, ndm.allNodes().own()) {
1201 DirNode cc(ndm.node(*inode));
1202 Node next = cc.next();
1203 Node prev = cc.previous();
1204 set_value(idir, ipatch, inode->uniqueId(), prev.uniqueId(), next.uniqueId());
1205 }
1206 }
1207 }
1208
1209 return size_of_once_case_around-1;
1210}
1211
1212/*---------------------------------------------------------------------------*/
1213/*---------------------------------------------------------------------------*/
1214
1215void AMRCartesianMeshTesterModule::
1216_checkSync()
1217{
1218 IMesh* mesh = m_cartesian_mesh->mesh();
1219 Integer nb_error = 0;
1220
1221 VariableCellInt32 test_var(VariableBuildInfo(mesh, "ArcaneTestAMRCheckSync"));
1222 test_var.fill(0);
1223 ENUMERATE_ (Cell, icell, mesh->ownCells()) {
1224 test_var[icell] = 1;
1225 }
1226 test_var.synchronize();
1227 ENUMERATE_ (Cell, icell, mesh->allCells()) {
1228 if (test_var[icell] != 1) {
1229 nb_error++;
1230 }
1231 }
1232 if (nb_error > 0) {
1233 ARCANE_FATAL("Bad sync -- Nb error : {0}", nb_error);
1234 }
1235}
1236
1237/*---------------------------------------------------------------------------*/
1238/*---------------------------------------------------------------------------*/
1239
1240void AMRCartesianMeshTesterModule::
1241_cellsInPatch(Real3 position, Real3 length, bool is_3d, Int32 level, UniqueArray<Int32>& cells_in_patch)
1242{
1243 // Parcours les mailles actives et ajoute dans la liste des mailles
1244 // à raffiner celles qui sont contenues dans le boîte englobante
1245 // spécifiée dans le jeu de données.
1246 Real3 min_pos = position;
1247 Real3 max_pos = min_pos + length;
1248 ENUMERATE_ (Cell, icell, mesh()->allCells()) {
1249 if ((icell->level() == level) || (level == -1 && icell->nbHChildren() == 0)) {
1250 Real3 center = m_cell_center[icell];
1251 bool is_inside_x = center.x > min_pos.x && center.x < max_pos.x;
1252 bool is_inside_y = center.y > min_pos.y && center.y < max_pos.y;
1253 bool is_inside_z = (center.z > min_pos.z && center.z < max_pos.z) || !is_3d;
1254 if (is_inside_x && is_inside_y && is_inside_z) {
1255 cells_in_patch.add(icell.itemLocalId());
1256 }
1257 }
1258 }
1259}
1260
1261/*---------------------------------------------------------------------------*/
1262/*---------------------------------------------------------------------------*/
1263
1264ARCANE_REGISTER_MODULE_AMRCARTESIANMESHTESTER(AMRCartesianMeshTesterModule);
1265
1266/*---------------------------------------------------------------------------*/
1267/*---------------------------------------------------------------------------*/
1268
1269} // End namespace ArcaneTest
1270
1271/*---------------------------------------------------------------------------*/
1272/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
Fonctions utilitaires sur le maillage.
Ce fichier contient les différentes fabriques de services et macro pour enregistrer les services.
Module de test pour les infos sur les maillages cartésiens.
Integer _cellsUidAroundFaces(UniqueArray< Int64 > &own_cells_uid_around_faces)
Méthode permettant de récupérer un tableau contenant les mailles autour des faces.
Integer _cellsUidAroundCells(UniqueArray< Int64 > &own_cells_uid_around_cells)
Méthode permettant de récupérer un tableau contenant les mailles autour des mailles.
Integer _nodesUidAroundNodes(UniqueArray< Int64 > &own_nodes_uid_around_nodes)
Méthode permettant de récupérer un tableau contenant les noeuds autour des noeuds.
void _computeSubCellDensity(Cell cell)
Calcule la densité d'une maille AMR.
String _checkDirectionUniqueIdsHashCollective(ArrayView< Int64 > own_items_uid_around, Integer nb_items_around)
Méthode permettant de calculer un hash à partir d'un tableau d'items "autour".
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
iterator end()
Itérateur sur le premier élément après la fin du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
iterator begin()
Itérateur sur le premier élément du tableau.
Span< const T > constSpan() const
Vue constante sur ce tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
void setSortAfterRenumbering(bool v)
Indique si on retrie les entités après renumérotation.
void setParentPatch(CartesianPatch patch)
Numéro du patch parent pour la renumérotation.
void setRenumberPatchMethod(Int32 v)
Méthode pour renuméroter les patchs.
Infos sur les mailles d'une direction spécifique X,Y ou Z d'un maillage structuré.
CellGroup allCells() const
Groupe de toutes les mailles dans la direction.
DirCell cell(Cell c) const
Maille direction correspondant à la maille c.
Maille d'un maillage.
Definition Item.h:1214
Int32 nbHChildren() const
Nombre d'enfants pour l'AMR.
Definition Item.h:1333
Cell hChild(Int32 i) const
i-ème enfant AMR
Definition Item.h:1336
void clear()
Supprime tous les éléments de la collection.
Definition Collection.h:68
Maille avant et après une maille suivant une direction.
Infos sur maille avant et après une face suivant une direction.
Noeud avant et après un noeud suivant une direction.
String file(const String &file_name) const override
Retourne le chemin complet du fichier file_name dans le répertoire.
Definition Directory.cc:120
bool createDirectory() const override
Créé le répertoire.
Definition Directory.cc:102
String path() const override
Retourne le chemin du répertoire.
Definition Directory.cc:111
Infos sur les face d'une direction spécifique X,Y ou Z d'un maillage structuré.
DirFace face(Face f) const
Face direction correspondant à la face f.
FaceGroup allFaces() const
Groupe de toutes les faces dans la direction.
Face d'une maille.
Definition Item.h:964
Interface d'un patch AMR d'un maillage cartésien.
virtual CellGroup cells()=0
Groupe de mailles du patch.
virtual NodeDirectionMng & nodeDirection(eMeshDirection dir)=0
Liste des noeuds dans la direction dir.
virtual FaceDirectionMng & faceDirection(eMeshDirection dir)=0
Liste des faces dans la direction dir.
virtual CellDirectionMng & cellDirection(eMeshDirection dir)=0
Liste des mailles dans la direction dir.
Interface d'un maillage cartésien.
static ICartesianMesh * getReference(const MeshHandleOrMesh &mesh, bool create=true)
Récupère ou créé la référence associée à mesh.
virtual CellDirectionMng cellDirection(eMeshDirection dir)=0
Liste des mailles dans la direction dir.
virtual IMesh * mesh() const =0
Maillage associé à ce maillage cartésien.
virtual ItemGroup createGroup(const String &name, Int32ConstArrayView local_ids, bool do_override=false)=0
Créé un groupe d'entités de nom name contenant les entités local_ids.
virtual String name() const =0
Nom de la famille.
virtual String fullName() const =0
Nom complet de la famille (avec celui du maillage)
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual NodeGroup allNodes()=0
Groupe de tous les noeuds.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
virtual void setVariables(VariableCollection variables)=0
Positionne la liste des variables à sortir.
virtual void setTimes(RealConstArrayView times)=0
Positionne la liste des temps.
virtual void setGroups(ItemGroupCollection groups)=0
Positionne la liste des groupes à sortir.
virtual void setBaseDirectoryName(const String &dirname)=0
Positionne le nom du répertoire de sortie des fichiers. Ce répertoire doit exister.
virtual void setMesh(IMesh *mesh)
Positionne le maillage.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual ITimeLoopMng * timeLoopMng()=0
Retourne le gestionnaire de la boucle en temps.
virtual ITimeLoop * createTimeLoop(const String &name)=0
Crée une boucle en temps de nom name.
virtual void registerTimeLoop(ITimeLoop *time_loop)=0
Enregistrement et choix de la boucle en temps.
virtual void setRequiredModulesName(const StringCollection &)=0
Positionne la liste des des modules obligatoires.
virtual void setOptionalModulesName(const StringCollection &)=0
Positionne la liste des des modules facultatifs.
static const char * WBuild
appelé lors de la lecture du jeu de données
Definition ITimeLoop.h:42
static const char * WComputeLoop
appelé pendant la boucle de calcul
Definition ITimeLoop.h:40
virtual void setEntryPoints(const String &where, const TimeLoopEntryPointInfoCollection &)=0
Positionne la liste des noms des points d'entrée pour le point d'appel where.
static const char * WInit
appelé pendant l'initialisation, l'initialisation d'une reprise ou d'un nouveau cas
Definition ITimeLoop.h:44
virtual void writePostProcessing(IPostProcessorWriter *writer)=0
Ecrit les variables pour un post-traitement.
Integer size() const
Nombre d'éléments du groupe.
Definition ItemGroup.h:88
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:791
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:794
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
Classe de base d'un élément de maillage.
Definition Item.h:83
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Definition Item.h:216
Calcule la fonction de hashage MD5 d'un tableau.
void computeHash64(Span< const Byte > input, ByteArray &output) override
Calcule la valeur du hash pour le tableau input.
Informations pour construire un module.
Infos sur les noeuds d'une direction spécifique X,Y ou Z d'un maillage structuré.
NodeGroup allNodes() const
Groupe de tous les noeuds dans la direction.
DirNode node(Node n) const
Noeud direction correspondant au noeud n.
Noeud d'un maillage.
Definition Item.h:582
Cell cell(Int32 i) const
i-ème maille du noeud
Definition Item.h:1616
Int32 nbCell() const
Nombre de mailles connectées au noeud.
Definition Item.h:665
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Référence à une instance.
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Grandeur au centre des mailles de type réel.
MeshVariableScalarRefT< Cell, Real3 > VariableCellReal3
Grandeur au centre des mailles de type coordonnées.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
MeshVariableScalarRefT< Face, Real3 > VariableFaceReal3
Grandeur aux faces de type coordonnées.
MeshVariableScalarRefT< Node, Real > VariableNodeReal
Grandeur au noeud de type réel.
MeshVariableScalarRefT< Cell, Int32 > VariableCellInt32
Grandeur au centre des mailles de type entier 32 bits.
String toHexaString(ByteConstArrayView input)
Converti un tableau d'octet en sa représentation hexadécimale.
@ ReduceSum
Somme des valeurs.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
List< ItemGroup > ItemGroupList
Tableau de groupes d'éléments du maillage.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:357
List< String > StringList
Tableau de chaînes de caractères unicode.
Definition UtilsTypes.h:525
double Real
Type représentant un réel.
Impl::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converti la vue en un tableau d'octets non modifiables.
Definition Span.h:1022
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52
std::int32_t Int32
Type entier signé sur 32 bits.
Real y
deuxième composante du triplet
Definition Real3.h:36
Real z
troisième composante du triplet
Definition Real3.h:37
Real x
première composante du triplet
Definition Real3.h:35