Arcane  v4.1.3.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-2026 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-2026 */
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#include "arcane/cartesianmesh/SimpleHTMLMeshAMRPatchExporter.h"
57
58#include "arcane/tests/ArcaneTestGlobal.h"
59#include "arcane/tests/AMRCartesianMeshTester_axl.h"
60#include "arcane/tests/CartesianMeshTestUtils.h"
61
62/*---------------------------------------------------------------------------*/
63/*---------------------------------------------------------------------------*/
64
65namespace ArcaneTest
66{
67
68using namespace Arcane;
69
70/*---------------------------------------------------------------------------*/
71/*---------------------------------------------------------------------------*/
75class AMRCartesianMeshTesterModule
76: public ArcaneAMRCartesianMeshTesterObject
77{
78 public:
79
80 explicit AMRCartesianMeshTesterModule(const ModuleBuildInfo& mbi);
81 ~AMRCartesianMeshTesterModule();
82
83 public:
84
85 static void staticInitialize(ISubDomain* sd);
86
87 public:
88
89 void buildInit() override;
90 void compute() override;
91 void init() override;
92
93 private:
94
95 VariableCellReal m_density;
96 VariableCellReal m_old_density;
97 VariableCellReal3 m_cell_center;
98 VariableFaceReal3 m_face_center;
99 VariableNodeReal m_node_density;
100 ICartesianMesh* m_cartesian_mesh;
102 UniqueArray<VariableCellReal*> m_cell_patch_variables;
103 Int32 m_nb_expected_patch = 0;
104 bool m_merge_patches = true;
105
106 private:
107
108 void _compute1();
109 void _compute2();
110 void _initAMR();
111 void _coarseZone();
112 void _mergePatches();
113 void _reduceNbGhostLayers();
114 void _computeSubCellDensity(Cell cell);
115 void _computeCenters();
116 void _processPatches();
117 void _writePostProcessing();
118 void _checkUniqueIds();
119 void _svgOutput();
120 void _testDirections();
121 void _checkDirections();
122 String _checkDirectionUniqueIdsHashCollective(ArrayView<Int64> own_items_uid_around, Integer nb_items_around);
123 Integer _cellsUidAroundCells(UniqueArray<Int64>& own_cells_uid_around_cells);
124 Integer _cellsUidAroundFaces(UniqueArray<Int64>& own_cells_uid_around_faces);
125 Integer _nodesUidAroundNodes(UniqueArray<Int64>& own_nodes_uid_around_nodes);
126 void _checkSync();
127 void _cellsInPatch(Real3 position, Real3 length, bool is_3d, Int32 level, UniqueArray<Int32>& cells_in_patch);
128};
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133AMRCartesianMeshTesterModule::
134AMRCartesianMeshTesterModule(const ModuleBuildInfo& mbi)
135: ArcaneAMRCartesianMeshTesterObject(mbi)
136, m_density(VariableBuildInfo(this,"Density"))
137, m_old_density(VariableBuildInfo(this,"OldDensity"))
138, m_cell_center(VariableBuildInfo(this,"CellCenter"))
139, m_face_center(VariableBuildInfo(this,"FaceCenter"))
140, m_node_density(VariableBuildInfo(this,"NodeDensity"))
141, m_cartesian_mesh(nullptr)
142{
143}
144
145/*---------------------------------------------------------------------------*/
146/*---------------------------------------------------------------------------*/
147
148AMRCartesianMeshTesterModule::
149~AMRCartesianMeshTesterModule()
150{
151 for (VariableCellReal* v : m_cell_patch_variables)
152 delete v;
153}
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157
158void AMRCartesianMeshTesterModule::
159staticInitialize(ISubDomain* sd)
160{
161 String time_loop_name("AMRCartesianMeshTestLoop");
162
163 ITimeLoopMng* tlm = sd->timeLoopMng();
164 ITimeLoop* time_loop = tlm->createTimeLoop(time_loop_name);
165
166 {
167 List<TimeLoopEntryPointInfo> clist;
168 clist.add(TimeLoopEntryPointInfo("AMRCartesianMeshTester.buildInit"));
169 time_loop->setEntryPoints(ITimeLoop::WBuild,clist);
170 }
171
172 {
173 List<TimeLoopEntryPointInfo> clist;
174 clist.add(TimeLoopEntryPointInfo("AMRCartesianMeshTester.init"));
175 time_loop->setEntryPoints(ITimeLoop::WInit,clist);
176 }
177
178 {
179 List<TimeLoopEntryPointInfo> clist;
180 clist.add(TimeLoopEntryPointInfo("AMRCartesianMeshTester.compute"));
181 time_loop->setEntryPoints(ITimeLoop::WComputeLoop,clist);
182 }
183
184 {
185 StringList clist;
186 clist.add("AMRCartesianMeshTester");
187 time_loop->setRequiredModulesName(clist);
188 clist.clear();
189 clist.add("ArcanePostProcessing");
190 clist.add("ArcaneCheckpoint");
191 clist.add("ArcaneLoadBalance");
192 time_loop->setOptionalModulesName(clist);
193 }
194
195 tlm->registerTimeLoop(time_loop);
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
201void AMRCartesianMeshTesterModule::
202buildInit()
203{
204 if (subDomain()->isContinue())
205 return;
206
207 m_global_deltat.assign(1.0);
208
209 IItemFamily* cell_family = defaultMesh()->cellFamily();
210 cell_family->createGroup("CELL0");
211 cell_family->createGroup("CELL1");
212 cell_family->createGroup("CELL2");
213 cell_family->createGroup("AMRPatchCells0");
214 cell_family->createGroup("AMRPatchCells1");
215 cell_family->createGroup("AMRPatchCells2");
216 cell_family->createGroup("AMRPatchCells3");
217 cell_family->createGroup("AMRPatchCells4");
218 cell_family->createGroup("AMRPatchCells5");
219
220 IItemFamily* face_family = defaultMesh()->faceFamily();
221 face_family->createGroup("FACE0");
222 face_family->createGroup("FACE1");
223 face_family->createGroup("FACE2");
224 face_family->createGroup("FACE3");
225 face_family->createGroup("FACE4");
226 face_family->createGroup("FACE5");
227
228 face_family->createGroup("AllFacesDirection0");
229 face_family->createGroup("AllFacesDirection1");
230}
231
232/*---------------------------------------------------------------------------*/
233/*---------------------------------------------------------------------------*/
234
235void AMRCartesianMeshTesterModule::
236init()
237{
238 info() << "AMR Init";
239
240 IMesh* mesh = defaultMesh();
241
242 IItemFamily* cell_family = mesh->cellFamily();
243 Int32UniqueArray ids(1);
244 ids[0] = 0;
245 cell_family->createGroup("CELL0",ids,true);
246 ids[0] = 1;
247 cell_family->createGroup("CELL1",ids,true);
248 ids[0] = 2;
249 cell_family->createGroup("CELL2",ids,true);
250 IItemFamily* face_family = defaultMesh()->faceFamily();
251 ids[0] = 0;
252 face_family->createGroup("FACE0",ids,true);
253 ids[0] = 1;
254 face_family->createGroup("FACE1",ids,true);
255 ids[0] = 2;
256 face_family->createGroup("FACE2",ids,true);
257 ids[0] = 3;
258 face_family->createGroup("FACE3",ids,true);
259 ids[0] = 4;
260 face_family->createGroup("FACE4",ids,true);
261 ids[0] = 5;
262 face_family->createGroup("FACE5",ids,true);
263
264 m_cartesian_mesh = ICartesianMesh::getReference(mesh);
265 m_utils = makeRef(new CartesianMeshTestUtils(m_cartesian_mesh,acceleratorMng()));
266
267 m_merge_patches = options()->mergePatches();
268
269 if (!subDomain()->isContinue()) {
270 _initAMR();
271 _coarseZone();
272 if (m_merge_patches) {
273 _mergePatches();
274 }
275 _reduceNbGhostLayers();
276 }
277
278 _computeCenters();
279
280
281 const bool do_coarse_at_init = options()->coarseAtInit();
282
283 const Integer dimension = defaultMesh()->dimension();
284 if (dimension==2)
285 m_nb_expected_patch = 1 + options()->refinement2d().size();
286 else if (dimension==3)
287 m_nb_expected_patch = 1 + options()->refinement3d().size();
288
289 // Si on dé-raffine à l'init, on aura un patch de plus
290 if (do_coarse_at_init)
291 ++m_nb_expected_patch;
292
293 if (subDomain()->isContinue())
294 m_cartesian_mesh->recreateFromDump();
295 else{
296 m_cartesian_mesh->computeDirections();
297 CartesianMeshRenumberingInfo renumbering_info;
298 renumbering_info.setRenumberPatchMethod(options()->renumberPatchMethod());
299 renumbering_info.setSortAfterRenumbering(true);
300 if (options()->coarseAtInit())
301 renumbering_info.setParentPatch(m_cartesian_mesh->amrPatch(1));
302 m_cartesian_mesh->renumberItemsUniqueId(renumbering_info);
303 _svgOutput();
304 _checkUniqueIds();
305 _processPatches();
306 info() << "MaxUid for mesh=" << MeshUtils::getMaxItemUniqueIdCollective(m_cartesian_mesh->mesh());
307 }
308
309 // Initialise la densité.
310 // On met une densité de 1.0 à l'intérieur
311 // et on ajoute une densité de 5.0 pour chaque direction dans les
312 // mailles de bord.
313 m_density.fill(1.0);
314 for( Integer idir=0, nb_dir=dimension; idir<nb_dir; ++idir){
315 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
316 Integer nb_boundary1 = 0;
317 Integer nb_boundary2 = 0;
318 ENUMERATE_CELL(icell,cdm.innerCells()){
319 DirCell cc(cdm.cell(*icell));
320 Cell next = cc.next();
321 Cell prev = cc.previous();
322 if (next.null() || prev.null()){
323 // Maille au bord. J'ajoute de la densité.
324 // Ne devrait pas arriver car on est sur les innerCells()
325 ++nb_boundary1;
326 m_density[icell] += 5.0;
327 }
328 }
329 // Parcours les mailles frontières pour la direction
330 ENUMERATE_CELL(icell,cdm.outerCells()){
331 DirCell cc(cdm[icell]);
332 if (icell.index()<5)
333 info() << "CELL: cell=" << ItemPrinter(*icell)
334 << " next=" << ItemPrinter(cc.next())
335 << " previous=" << ItemPrinter(cc.previous());
336 // Maille au bord. J'ajoute de la densité.
337 ++nb_boundary2;
338 m_density[icell] += 5.0;
339 }
340
341 info() << "NB_BOUNDARY1=" << nb_boundary1 << " NB_BOUNDARY2=" << nb_boundary2;
342 }
343 bool is_amr = m_nb_expected_patch!=1;
344 if (options()->verbosityLevel()==0)
345 m_utils->setNbPrint(5);
346 m_utils->testAll(is_amr);
347 _writePostProcessing();
348 _testDirections();
349 _checkDirections();
350 _checkSync();
351}
352
353/*---------------------------------------------------------------------------*/
354/*---------------------------------------------------------------------------*/
355
356void AMRCartesianMeshTesterModule::
357_checkUniqueIds()
358{
359 IMesh* mesh = m_cartesian_mesh->mesh();
360 bool print_hash = true;
361 bool with_ghost = options()->hashWithGhost();
362 MD5HashAlgorithm hash_algo;
363 MeshUtils::checkUniqueIdsHashCollective(mesh->nodeFamily(), &hash_algo, options()->nodesUidHash(),
364 print_hash, with_ghost);
365 MeshUtils::checkUniqueIdsHashCollective(mesh->faceFamily(), &hash_algo, options()->facesUidHash(),
366 print_hash, with_ghost);
367 MeshUtils::checkUniqueIdsHashCollective(mesh->cellFamily(), &hash_algo, options()->cellsUidHash(),
368 print_hash, with_ghost);
369}
370
371/*---------------------------------------------------------------------------*/
372/*---------------------------------------------------------------------------*/
373
374void AMRCartesianMeshTesterModule::
375_svgOutput()
376{
377 const Int32 dimension = defaultMesh()->dimension();
378 const Int32 nb_patch = m_cartesian_mesh->nbPatch();
379
380 IParallelMng* pm = parallelMng();
381 Int32 comm_rank = pm->commRank();
382 Int32 comm_size = pm->commSize();
383
384 SimpleHTMLMeshAMRPatchExporter amr_exporter;
385 Directory directory = subDomain()->exportDirectory();
386
387 // Affiche les informations sur les patchs
388 for (Integer i = 0; i < nb_patch; ++i) {
389 ICartesianMeshPatch* p = m_cartesian_mesh->patch(i);
390 CellGroup patch_cells(p->cells());
391
392 // Exporte le patch au format SVG
393 if (dimension == 2 && options()->dumpSvg()) {
394 String filename = String::format("Patch{0}-{1}-{2}.svg", i, comm_rank, comm_size);
395 String full_filename = directory.file(filename);
396 std::ofstream ofile(full_filename.localstr());
397 SimpleSVGMeshExporter exporter(ofile);
398 exporter.write(patch_cells);
399 amr_exporter.addPatch(m_cartesian_mesh->amrPatch(i));
400 }
401 }
402 if (dimension == 2 && options()->dumpSvg()) {
403 String amr_filename = String::format("MeshPatch{0}-{1}.html", comm_rank, comm_size);
404 String amr_full_filename = directory.file(amr_filename);
405 std::ofstream amr_ofile(amr_full_filename.localstr());
406 amr_exporter.write(amr_ofile);
407 }
408}
409
410/*---------------------------------------------------------------------------*/
411/*---------------------------------------------------------------------------*/
412
413void AMRCartesianMeshTesterModule::
414_processPatches()
415{
416 const bool do_check = true;
417 const bool is_verbose = options()->verbosityLevel()>=1;
418
419 const Int32 dimension = defaultMesh()->dimension();
420
421 bool without_coarse_zone = true;
422 if (dimension == 2)
423 without_coarse_zone = options()->coarseZone2d().empty();
424 else if (dimension == 3)
425 without_coarse_zone = options()->coarseZone3d().empty();
426
427 // Vérifie qu'il y a autant de patchs que d'options raffinement dans
428 // le jeu de données (en comptant le patch 0 qui est le maillage cartésien).
429 // Cela permet de vérifier que les appels successifs
430 // à computeDirections() n'ajoutent pas de patchs.
431 // Cette vérification ne s'applique que s'il n'y a pas de zone de dé-raffinement.
432 // En effet, dé-raffiner un patch complet le supprime de la liste des patchs.
433 // Elle est aussi désactivée s'il y a fusion possible des patchs.
434 Integer nb_expected_patch = m_nb_expected_patch;
435
436 Integer nb_patch = m_cartesian_mesh->nbPatch();
437 if (without_coarse_zone && nb_expected_patch != nb_patch && !m_merge_patches)
438 ARCANE_FATAL("Bad number of patchs expected={0} value={1}",nb_expected_patch,nb_patch);
439
440 IParallelMng* pm = parallelMng();
441 Int32 comm_rank = pm->commRank();
442
443 UniqueArray<Int32> nb_cells_expected(options()->expectedNumberOfCellsInPatchs);
444 if (nb_cells_expected.size()!=nb_patch)
445 ARCANE_FATAL("Bad size ({0}, expected={1}) for option '{2}'",
446 nb_cells_expected.size(),nb_patch,options()->expectedNumberOfCellsInPatchs.name());
447
448 // Nombre de mailles fantômes attendu. Utilisé uniquement en parallèle
449 bool has_expected_ghost_cells = options()->expectedNumberOfGhostCellsInPatchs.isPresent();
450 if (!pm->isParallel())
451 has_expected_ghost_cells = false;
452
453 UniqueArray<Int32> nb_ghost_cells_expected(options()->expectedNumberOfGhostCellsInPatchs);
454 if (has_expected_ghost_cells && (nb_ghost_cells_expected.size()!=nb_patch))
455 ARCANE_FATAL("Bad size ({0}, expected={1}) for option '{2}'",
456 nb_ghost_cells_expected.size(), nb_patch, options()->expectedNumberOfGhostCellsInPatchs.name());
457
458 // Affiche les informations sur les patchs
459 for( Integer i=0; i<nb_patch; ++i ){
460 ICartesianMeshPatch* p = m_cartesian_mesh->patch(i);
461 CellGroup patch_cells(p->cells());
462 info() << "Patch cell_group=" << patch_cells.name() << " nb_cell=" << patch_cells.size();
463 VariableCellReal* cellv = new VariableCellReal(VariableBuildInfo(defaultMesh(),String("CellPatch")+i));
464 m_cell_patch_variables.add(cellv);
465 cellv->fill(0.0);
466 ENUMERATE_CELL(icell,patch_cells){
467 (*cellv)[icell] = 2.0;
468 }
469
470 CellGroup patch_own_cell = patch_cells.own();
471 UniqueArray<Int64> own_cells_uid;
472 ENUMERATE_(Cell,icell,patch_own_cell){
473 Cell cell{*icell};
474 if (is_verbose)
475 info() << "Patch i=" << i << " cell=" << ItemPrinter(*icell);
476 own_cells_uid.add(cell.uniqueId());
477 }
478 // Affiche la liste globales des uniqueId() des mailles.
479 {
480 UniqueArray<Int64> global_cells_uid;
481 pm->allGatherVariable(own_cells_uid,global_cells_uid);
482 std::sort(global_cells_uid.begin(),global_cells_uid.end());
483 Integer nb_global_uid = global_cells_uid.size();
484 info() << "GlobalUids Patch=" << i << " NB=" << nb_global_uid
485 << " expected=" << nb_cells_expected[i];
486 // Vérifie que le nombre de mailles par patch est le bon.
487 if (do_check && nb_cells_expected[i]!=nb_global_uid)
488 ARCANE_FATAL("Bad number of cells for patch I={0} N={1} expected={2}",
489 i,nb_global_uid,nb_cells_expected[i]);
490 if (is_verbose)
491 for( Integer c=0; c<nb_global_uid; ++c )
492 info() << "GlobalUid Patch=" << i << " I=" << c << " cell_uid=" << global_cells_uid[c];
493 }
494 // Teste le nombre de mailles fantômes
495 if (has_expected_ghost_cells){
496 Int32 local_nb_ghost_cell = patch_cells.size() - patch_own_cell.size();
497 Int32 total = pm->reduce(Parallel::ReduceSum,local_nb_ghost_cell);
498 pinfo() << "NbGhostCells my_rank=" << comm_rank << " local=" << local_nb_ghost_cell << " total=" << total;
499 if (total!=nb_ghost_cells_expected[i])
500 ARCANE_FATAL("Bad number of ghost cells for patch I={0} N={1} expected={2}",
501 i,total,nb_ghost_cells_expected[i]);
502 }
503 }
504}
505
506/*---------------------------------------------------------------------------*/
507/*---------------------------------------------------------------------------*/
508
509void AMRCartesianMeshTesterModule::
510_computeCenters()
511{
512 IMesh* mesh = defaultMesh();
513
514 // Calcule le centre des mailles
515 {
516 VariableNodeReal3& nodes_coord = mesh->nodesCoordinates();
517 ENUMERATE_CELL(icell,allCells()){
518 Cell cell = *icell;
519 Real3 center;
520 for( NodeLocalId inode : cell.nodes() )
521 center += nodes_coord[inode];
522 center /= cell.nbNode();
523 m_cell_center[icell] = center;
524 }
525 }
526
527 // Calcule le centre des faces
528 {
529 VariableNodeReal3& nodes_coord = mesh->nodesCoordinates();
530 ENUMERATE_FACE(iface,allFaces()){
531 Face face = *iface;
532 Real3 center;
533 for( NodeLocalId inode : face.nodes() )
534 center += nodes_coord[inode];
535 center /= face.nbNode();
536 m_face_center[iface] = center;
537 }
538 }
539}
540
541/*---------------------------------------------------------------------------*/
542/*---------------------------------------------------------------------------*/
543
544void AMRCartesianMeshTesterModule::
545_initAMR()
546{
547 CartesianMeshAMRMng amr_mng(m_cartesian_mesh);
548 amr_mng.setOverlapLayerSizeTopLevel(options()->overlapLayerSizeTopLevel());
549
550 // Regarde si on dé-raffine le maillage initial
551 if (options()->coarseAtInit()){
552 // Il faut que les directions aient été calculées avant d'appeler le dé-raffinement
553 m_cartesian_mesh->computeDirections();
554
555 info() << "Doint initial coarsening";
556 //
557 // if (m_cartesian_mesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::PatchCartesianMeshOnly) {
558 // debug() << "Coarse with specific coarser (for cartesian mesh only)";
559 // Ref<ICartesianMeshAMRPatchMng> coarser = CartesianMeshUtils::cartesianMeshAMRPatchMng(m_cartesian_mesh);
560 // coarser->createSubLevel();
561 // }
562 // else {
563 // Ref<CartesianMeshCoarsening2> coarser = CartesianMeshUtils::createCartesianMeshCoarsening2(m_cartesian_mesh);
564 // coarser->createCoarseCells();
565 // }
566 amr_mng.createSubLevel();
567
568 CartesianMeshPatchListView patches = m_cartesian_mesh->patches();
569 Int32 nb_patch = patches.size();
570 {
571 Int32 index = 0;
572 info() << "NB_PATCH=" << nb_patch;
573 for( CartesianPatch p : patches){
574 info() << "Patch i=" << index << " nb_cell=" << p.cells().size();
575 ++index;
576 }
577 }
578 }
579 // Parcours les mailles actives et ajoute dans la liste des mailles
580 // à raffiner celles qui sont contenues dans le boîte englobante
581 // spécifiée dans le jeu de données.
582 Int32 dim = defaultMesh()->dimension();
583 if (dim == 2) {
584 for (const auto& x : options()->refinement2d()) {
585 amr_mng.refineZone({ x->position(), x->length() });
586 m_cartesian_mesh->computeDirections();
587 }
588 }
589 if (dim == 3) {
590 for (const auto& x : options()->refinement3d()) {
591 amr_mng.refineZone({ x->position(), x->length() });
592 m_cartesian_mesh->computeDirections();
593 }
594 }
595}
596
597/*---------------------------------------------------------------------------*/
598/*---------------------------------------------------------------------------*/
599
600void AMRCartesianMeshTesterModule::
601_coarseZone()
602{
603 Int32 dim = defaultMesh()->dimension();
604 CartesianMeshAMRMng amr_mng(m_cartesian_mesh);
605
606 if (dim == 2) {
607 //UniqueArray<Int32> cells_in_patchs;
608 for (auto& x : options()->coarseZone2d()) {
609 // _cellsInPatch(Real3(x->position()), Real3(x->length()), false, x->level(), cells_in_patchs);
610 // defaultMesh()->modifier()->flagCellToCoarsen(cells_in_patchs);
611 // defaultMesh()->modifier()->coarsenItemsV2(true);
612 // cells_in_patchs.clear();
613 amr_mng.coarseZone({ { x->position() }, { x->length() } });
614 m_cartesian_mesh->computeDirections();
615 }
616 }
617 if (dim == 3) {
618 // UniqueArray<Int32> cells_in_patchs;
619 for (auto& x : options()->coarseZone3d()) {
620 // _cellsInPatch(x->position(), x->length(), true, x->level(), cells_in_patchs);
621 // defaultMesh()->modifier()->flagCellToCoarsen(cells_in_patchs);
622 // defaultMesh()->modifier()->coarsenItemsV2(true);
623 // cells_in_patchs.clear();
624 amr_mng.coarseZone({ { x->position() }, { x->length() } });
625 m_cartesian_mesh->computeDirections();
626 }
627 }
628}
629
630/*---------------------------------------------------------------------------*/
631/*---------------------------------------------------------------------------*/
632
633void AMRCartesianMeshTesterModule::
634_mergePatches()
635{
636 CartesianMeshAMRMng amr_mng(m_cartesian_mesh);
637 amr_mng.mergePatches();
638
639 m_cartesian_mesh->computeDirections();
640}
641
642/*---------------------------------------------------------------------------*/
643/*---------------------------------------------------------------------------*/
644
645void AMRCartesianMeshTesterModule::
646_reduceNbGhostLayers()
647{
648 for (auto& x : options()->reduceNbGhostLayers()) {
649 Integer final_nb_ghost_layer{ m_cartesian_mesh->reduceNbGhostLayers(x->level(), x->nbGhostLayers()) };
650
651 if (parallelMng()->commSize() != 1 && final_nb_ghost_layer != x->nbGhostLayers()) {
652 ARCANE_FATAL("Bad nb ghost layers");
653 }
654 //info() << "Final nb ghost layer : " << final_nb_ghost_layer;
655 }
656}
657
658/*---------------------------------------------------------------------------*/
659/*---------------------------------------------------------------------------*/
660
661void AMRCartesianMeshTesterModule::
662compute()
663{
664 _compute1();
665 // info() << "NbPatch : " << m_cartesian_mesh->nbPatch();
666 // info() << "NbPatch : " << m_cartesian_mesh->patches().size();
667 //
668 // for (Integer i = 0; i < m_cartesian_mesh->patches().size(); ++i) {
669 // auto patch = m_cartesian_mesh->amrPatch(i);
670 // info() << "Patch #" << i;
671 // info() << "\tMin Point : " << patch.patchInterface()->position().minPoint();
672 // info() << "\tMax Point : " << patch.patchInterface()->position().maxPoint();
673 // info() << "\tLevel : " << patch.patchInterface()->position().level();
674 // }
675}
676
677/*---------------------------------------------------------------------------*/
678/*---------------------------------------------------------------------------*/
684{
685 Int32 nb_children = cell.nbHChildren();
686 if (nb_children==0)
687 return;
688 // Pour les mailles AMR, la densité est la moyenne des noeuds qui la compose.
689 for( Int32 j=0; j<nb_children; ++j ) {
690 Real sub_density = 0.0;
691 Cell sub_cell = cell.hChild(j);
692 Integer sub_cell_nb_node = sub_cell.nbNode();
693 for( Integer k=0; k<sub_cell_nb_node; ++k )
694 sub_density += m_node_density[sub_cell.node(k)];
695 sub_density /= (Real)sub_cell_nb_node;
696 m_density[sub_cell] =sub_density;
697 _computeSubCellDensity(sub_cell);
698 }
699}
700
701/*---------------------------------------------------------------------------*/
702/*---------------------------------------------------------------------------*/
703
704void AMRCartesianMeshTesterModule::
705_compute1()
706{
707 // Pour test, on parcours les N directions
708 // et pour chaque maille, on modifie sa densité
709 // par la formule new_density = (density+density_next+density_prev) / 3.0.
710
711 // Effectue l'operation en deux fois. Une premiere sur les
712 // mailles internes, et une deuxieme sur les mailles externes.
713 // Du coup, il faut passer par une variable intermediaire (m_old_density)
714 // mais on evite un test dans la boucle principale
715 IMesh* mesh = defaultMesh();
716 Integer nb_dir = mesh->dimension();
717 for( Integer idir=0; idir<nb_dir; ++idir){
718 m_old_density.copy(m_density);
719 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
720 // Travail sur les mailles internes
721 info() << "Direction=" << idir << " cells=" << cdm.innerCells().name()
722 << " n=" << cdm.innerCells().size();
723 ENUMERATE_CELL(icell,cdm.innerCells()){
724 Cell cell = *icell;
725 DirCell cc(cdm.cell(cell));
726 Cell next = cc.next();
727 Cell prev = cc.previous();
728 Real d = m_old_density[icell] + m_old_density[next] + m_old_density[prev];
729 m_density[icell] = d / 3.0;
731 }
732 // Travail sur les mailles externes
733 // Test si la maille avant ou apres est nulle.
734 ENUMERATE_CELL(icell,cdm.outerCells()){
735 Cell cell = *icell;
736 DirCell cc(cdm[icell]);
737 Cell next = cc.next();
738 Cell prev = cc.previous();
739 Real d = m_old_density[icell];
740 Integer n = 1;
741 if (!next.null()){
742 d += m_old_density[next];
743 ++n;
744 }
745 if (!prev.null()){
746 d += m_old_density[prev];
747 ++n;
748 }
749 m_density[icell] = d / n;
751 }
752 }
753 // Modifie la densité aux noeuds.
754 // Elle sera égale à la moyenne des densités des mailles entourant ce noeud
755 ENUMERATE_NODE(inode,mesh->allNodes()){
756 Node node = *inode;
757 Integer nb_cell = node.nbCell();
758 Real density = 0.0;
759 for( Integer i=0; i<nb_cell; ++i )
760 density += m_density[node.cell(i)];
761 density /= (Real)nb_cell;
762 m_node_density[inode] = density;
763 }
764}
765
766/*---------------------------------------------------------------------------*/
767/*---------------------------------------------------------------------------*/
768
769void AMRCartesianMeshTesterModule::
770_compute2()
771{
772 // Pour test, on parcours les N directions
773 // et pour chaque maille, on modifie sa densité
774 // par la formule new_density = (density+density_next+density_prev) / 3.0.
775
776 // A noter que cette methode ne donne pas le meme comportement que
777 // _compute1() car les mailles de bord et internes sont mises à jour
778 // dans un ordre différent.
779 Integer nb_dir = defaultMesh()->dimension();
780 for( Integer idir=0; idir<nb_dir; ++idir){
781 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
782 // Travail sur toutes les mailles
783 ENUMERATE_CELL(icell,cdm.allCells()){
784 DirCell cc(cdm[icell]);
785 Cell next = cc.next();
786 Cell prev = cc.previous();
787 Real d = m_density[icell];
788 Integer n = 1;
789 if (!next.null()){
790 d += m_density[next];
791 ++n;
792 }
793 if (!prev.null()){
794 d += m_density[prev];
795 ++n;
796 }
797 m_density[icell] = d / n;
798 }
799 }
800}
801
802/*---------------------------------------------------------------------------*/
803/*---------------------------------------------------------------------------*/
804
805void AMRCartesianMeshTesterModule::
806_writePostProcessing()
807{
808 info() << "Post-process AMR";
809 IPostProcessorWriter* post_processor = options()->postProcessor();
810 Directory output_directory = Directory(subDomain()->exportDirectory(),"amrtestpost1");
811 output_directory.createDirectory();
812 info() << "Creating output dir '" << output_directory.path() << "' for export";
813 UniqueArray<Real> times;
814 times.add(m_global_time());
815 post_processor->setTimes(times);
816 post_processor->setMesh(defaultMesh());
817 post_processor->setBaseDirectoryName(output_directory.path());
818
819 VariableList variables;
820 //variables.add(m_density.variable());
821 //variables.add(m_node_density.variable());
822 for( VariableCellReal* v : m_cell_patch_variables )
823 variables.add(v->variable());
824 post_processor->setVariables(variables);
825 ItemGroupList groups;
826 groups.add(allCells());
827 for( CartesianPatch p : m_cartesian_mesh->patches() )
828 groups.add(p.cells());
829 post_processor->setGroups(groups);
830 IVariableMng* vm = subDomain()->variableMng();
831 vm->writePostProcessing(post_processor);
832}
833
834/*---------------------------------------------------------------------------*/
835/*---------------------------------------------------------------------------*/
836
837void AMRCartesianMeshTesterModule::
838_testDirections()
839{
840 Integer nb_patch = m_cartesian_mesh->nbPatch();
841 Integer nb_dir = m_cartesian_mesh->mesh()->dimension();
842 NodeDirectionMng node_dm2;
843 for( Integer ipatch=0; ipatch<nb_patch; ++ipatch ){
844 ICartesianMeshPatch* p = m_cartesian_mesh->patch(ipatch);
845 for( Integer idir=0; idir<nb_dir; ++idir ){
846 NodeDirectionMng node_dm(p->nodeDirection(idir));
847 node_dm2 = p->nodeDirection(idir);
848 NodeGroup dm_all_nodes = node_dm.allNodes();
849 ENUMERATE_NODE(inode,dm_all_nodes){
850 DirNode dir_node(node_dm[inode]);
851 DirNode dir_node2(node_dm2[inode]);
852 Node prev_node = dir_node.previous();
853 Node next_node = dir_node.next();
854 Node prev_node2 = dir_node2.previous();
855 Node next_node2 = dir_node2.next();
856 m_utils->checkSameId(prev_node, prev_node2);
857 m_utils->checkSameId(next_node, next_node2);
858 }
859 }
860 }
861}
862
863void AMRCartesianMeshTesterModule::
864_checkDirections()
865{
866 m_cartesian_mesh->computeDirections();
867 IMesh* mesh = m_cartesian_mesh->mesh();
868 bool print_hash = true;
869
870 auto check_hash = [&](const IItemFamily* item_family, const String& expected_hash, ArrayView<Int64> own_items_uid_around, Integer nb_items_around) {
871 String cell_hash = _checkDirectionUniqueIdsHashCollective(own_items_uid_around, nb_items_around);
872
873 if (print_hash) {
874 info() << "HASH_RESULT direction items of family=" << item_family->name()
875 << " v= " << cell_hash << " expected= " << expected_hash;
876 }
877
878 if (cell_hash != expected_hash)
879 ARCANE_FATAL("Bad hash for uniqueId() for direction items of family '{0}' v='{1}' expected='{2}'",
880 item_family->fullName(), cell_hash, expected_hash);
881 };
882
883 if (!options()->cellsDirectionHash().empty()) {
884 debug() << "Check cells direction hash";
885 UniqueArray<Int64> own_cells_uid_around_cells;
886 Integer nb_items_around = _cellsUidAroundCells(own_cells_uid_around_cells);
887 check_hash(mesh->cellFamily(), options()->cellsDirectionHash(), own_cells_uid_around_cells, nb_items_around);
888 }
889 if (!options()->facesDirectionHash().empty()) {
890 debug() << "Check faces direction hash";
891 UniqueArray<Int64> own_cells_uid_around_faces;
892 Integer nb_items_around = _cellsUidAroundFaces(own_cells_uid_around_faces);
893 check_hash(mesh->faceFamily(), options()->facesDirectionHash(), own_cells_uid_around_faces, nb_items_around);
894 }
895
896 if (!options()->nodesDirectionHash().empty()) {
897 debug() << "Check nodes direction hash";
898 UniqueArray<Int64> own_nodes_uid_around_nodes;
899 Integer nb_items_around = _nodesUidAroundNodes(own_nodes_uid_around_nodes);
900 check_hash(mesh->nodeFamily(), options()->nodesDirectionHash(), own_nodes_uid_around_nodes, nb_items_around);
901 }
902}
903
915_checkDirectionUniqueIdsHashCollective(ArrayView<Int64> own_items_uid_around, Integer nb_items_around)
916{
917 // +1 car on a le uid dedans.
918 Integer size_of_once_case_around = nb_items_around + 1;
919
920 UniqueArray<Int64> final_all_items_uid;
921 {
922 UniqueArray<Int64> global_items_uid_around;
923 parallelMng()->allGatherVariable(own_items_uid_around, global_items_uid_around);
924
925 UniqueArray<Int64*> global_items_uid(global_items_uid_around.size() / size_of_once_case_around);
926 {
927 Int64 index = 0;
928 for (Int64 i = 0; i < global_items_uid_around.size(); i += size_of_once_case_around) {
929 Int64 uid = global_items_uid_around[i];
930 ARCANE_ASSERT((uid != -1), ("Un uid dans le tableau est = -1"));
931 global_items_uid[index++] = &(global_items_uid_around[i]);
932 }
933 }
934
935 std::sort(global_items_uid.begin(), global_items_uid.end(),
936 [](const Int64* a, const Int64* b) {
937 return *a < *b;
938 });
939
940 final_all_items_uid.resize(global_items_uid_around.size());
941
942 Int64 index = 0;
943 Int64 previous_uid = -1;
944
945 for (Int64* ptr_uid : global_items_uid) {
946 if (*ptr_uid == previous_uid) {
947 ARCANE_FATAL("Le uid {0} est dupliqué", *ptr_uid);
948 }
949 previous_uid = *ptr_uid;
950 for (Integer iaround = 0; iaround < size_of_once_case_around; ++iaround) {
951 final_all_items_uid[index++] = ptr_uid[iaround];
952 }
953 }
954 }
955
956 // info() << "final_all_items_uid : " << final_all_items_uid;
957
958 UniqueArray<Byte> hash_result;
959 MD5HashAlgorithm hash_algo;
960 hash_algo.computeHash64(asBytes(final_all_items_uid.constSpan()), hash_result);
961 return Convert::toHexaString(hash_result);
962}
963
974_cellsUidAroundCells(UniqueArray<Int64>& own_cells_uid_around_cells)
975{
976 IParallelMng* pm = parallelMng();
977 IMesh* mesh = m_cartesian_mesh->mesh();
978
979 if (pm->commSize() != 1 && mesh->ghostLayerMng()->nbGhostLayer() == 0) {
980 ARCANE_FATAL("Pas compatible sans ghost");
981 }
982
983 Integer nb_patch = m_cartesian_mesh->nbPatch();
984 Integer nb_dir = mesh->dimension();
985 Integer nb_items = mesh->cellFamily()->allItems().own().size();
986
987 // On a que pred et succ.
988 constexpr Integer nb_items_per_dir = 2;
989 constexpr Integer ipred = 0;
990 constexpr Integer isucc = 1;
991
992 // +1 car on a le uid dedans.
993 Integer size_of_once_case_around = nb_dir * nb_items_per_dir + 1;
994
995 own_cells_uid_around_cells.resize(nb_items * size_of_once_case_around, -1);
996
997 Integer index = 0;
998 ENUMERATE_ (Cell, icell, mesh->cellFamily()->allItems().own()) {
999 own_cells_uid_around_cells[index] = icell->uniqueId();
1000 index += size_of_once_case_around;
1001 }
1002
1003 auto set_value = [&](Integer dir, Int64 uid, Int64 uid_pred, Int64 uid_succ) -> void {
1004 // debug() << " -- dir : " << dir
1005 // << " -- uid : " << uid
1006 // << " -- uid_pred : " << uid_pred
1007 // << " -- uid_succ : " << uid_succ;
1008
1009 ARCANE_ASSERT((uid != -1), ("Uid ne peut pas être égal à -1"));
1010
1011 for (Integer i = 0; i < own_cells_uid_around_cells.size(); i += size_of_once_case_around) {
1012 if (own_cells_uid_around_cells[i] == uid) {
1013 Integer pos_final = i + 1 + (dir * nb_items_per_dir);
1014 Integer pos_pred = pos_final + ipred;
1015 Integer pos_succ = pos_final + isucc;
1016 // En AMR classique, il ne peut pas y avoir une maille dans deux
1017 // patchs différents (pas de mailles de recouvrement).
1018 if (m_cartesian_mesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::Cell) {
1019 if (own_cells_uid_around_cells[pos_pred] != -1 && own_cells_uid_around_cells[pos_pred] != uid_pred) {
1020 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);
1021 }
1022 if (own_cells_uid_around_cells[pos_succ] != -1 && own_cells_uid_around_cells[pos_succ] != uid_succ) {
1023 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);
1024 }
1025 own_cells_uid_around_cells[pos_pred] = uid_pred;
1026 own_cells_uid_around_cells[pos_succ] = uid_succ;
1027 }
1028 // En AMR par patch, une maille II_Overlap n'a pas forcément les mêmes
1029 // voisins pour un patch ou pour un autre.
1030 // On retire les vérifications (pour l'instant) (si modif, changement de hash !).
1031 else {
1032 own_cells_uid_around_cells[pos_pred] = std::max(own_cells_uid_around_cells[pos_pred], uid_pred);
1033 own_cells_uid_around_cells[pos_succ] = std::max(own_cells_uid_around_cells[pos_succ], uid_succ);
1034 }
1035 return;
1036 }
1037 }
1038 };
1039
1040 for (Integer idir = 0; idir < nb_dir; ++idir) {
1041 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
1042 ENUMERATE_ (Cell, icell, cdm.allCells().own()) {
1043 DirCell cc(cdm.cell(*icell));
1044 Cell next = cc.next();
1045 Cell prev = cc.previous();
1046 set_value(idir, icell->uniqueId(), prev.uniqueId(), next.uniqueId());
1047 }
1048 }
1049
1050 for (Integer ipatch = 0; ipatch < nb_patch; ++ipatch) {
1051 ICartesianMeshPatch* p = m_cartesian_mesh->patch(ipatch);
1052 for (Integer idir = 0; idir < nb_dir; ++idir) {
1053 CellDirectionMng cdm(p->cellDirection(idir));
1054 ENUMERATE_ (Cell, icell, cdm.allCells().own()) {
1055 DirCell cc(cdm.cell(*icell));
1056 Cell next = cc.next();
1057 Cell prev = cc.previous();
1058 set_value(idir, icell->uniqueId(), prev.uniqueId(), next.uniqueId());
1059 }
1060 }
1061 }
1062
1063 return size_of_once_case_around-1;
1064}
1065
1076_cellsUidAroundFaces(UniqueArray<Int64>& own_cells_uid_around_faces)
1077{
1078 IParallelMng* pm = parallelMng();
1079 IMesh* mesh = m_cartesian_mesh->mesh();
1080
1081 if (pm->commSize() != 1 && mesh->ghostLayerMng()->nbGhostLayer() == 0) {
1082 ARCANE_FATAL("Pas compatible sans ghost");
1083 }
1084
1085 Integer nb_patch = m_cartesian_mesh->nbPatch();
1086 Integer nb_dir = mesh->dimension();
1087 Integer nb_items = mesh->faceFamily()->allItems().own().size();
1088
1089 // On a que pred et succ.
1090 constexpr Integer nb_items_per_dir = 2;
1091 constexpr Integer ipred = 0;
1092 constexpr Integer isucc = 1;
1093
1094 // +1 car on a le uid dedans.
1095 Integer size_of_once_case_around = nb_items_per_dir * nb_patch + 1;
1096
1097 own_cells_uid_around_faces.resize(nb_items * size_of_once_case_around, -1);
1098
1099 Integer index = 0;
1100 ENUMERATE_ (Item, iitem, mesh->faceFamily()->allItems().own()) {
1101 own_cells_uid_around_faces[index] = iitem->uniqueId();
1102 index += size_of_once_case_around;
1103 }
1104
1105 auto set_value = [&](Integer ipatch, Int64 uid, Int64 uid_pred, Int64 uid_succ) -> void {
1106 // debug() << " -- uid : " << uid
1107 // << " -- uid_pred : " << uid_pred
1108 // << " -- uid_succ : " << uid_succ;
1109
1110 ARCANE_ASSERT((uid != -1), ("Uid ne peut pas être égal à -1"));
1111
1112 for (Integer i = 0; i < own_cells_uid_around_faces.size(); i += size_of_once_case_around) {
1113 if (own_cells_uid_around_faces[i] == uid) {
1114 Integer pos_final = i + 1 + ipatch * nb_items_per_dir;
1115 Integer pos_pred = pos_final + ipred;
1116 Integer pos_succ = pos_final + isucc;
1117 if (own_cells_uid_around_faces[pos_pred] != -1 && own_cells_uid_around_faces[pos_pred] != uid_pred) {
1118 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);
1119 }
1120 if (own_cells_uid_around_faces[pos_succ] != -1 && own_cells_uid_around_faces[pos_succ] != uid_succ) {
1121 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);
1122 }
1123 own_cells_uid_around_faces[pos_pred] = uid_pred;
1124 own_cells_uid_around_faces[pos_succ] = uid_succ;
1125 return;
1126 }
1127 }
1128 };
1129
1130 // // TODO : Il faut pouvoir récupérer le patch correspondant.
1131 // for (Integer idir = 0; idir < nb_dir; ++idir) {
1132 // FaceDirectionMng fdm(m_cartesian_mesh->faceDirection(idir));
1133 // ENUMERATE_ (Face, iface, fdm.allFaces().own()) {
1134 // DirFace cc(fdm.face(*iface));
1135 // Cell next = cc.nextCell();
1136 // Cell prev = cc.previousCell();
1137 // set_value(iface->uniqueId(), prev.uniqueId(), next.uniqueId());
1138 // }
1139 // }
1140
1141 for (Integer ipatch = 0; ipatch < nb_patch; ++ipatch) {
1142 ICartesianMeshPatch* p = m_cartesian_mesh->patch(ipatch);
1143 for (Integer idir = 0; idir < nb_dir; ++idir) {
1144 FaceDirectionMng fdm(p->faceDirection(idir));
1145 ENUMERATE_ (Face, iface, fdm.allFaces().own()) {
1146 DirFace cc(fdm.face(*iface));
1147 Cell next = cc.nextCell();
1148 Cell prev = cc.previousCell();
1149 set_value(ipatch, iface->uniqueId(), prev.uniqueId(), next.uniqueId());
1150 }
1151 }
1152 }
1153
1154 return size_of_once_case_around-1;
1155}
1156
1172_nodesUidAroundNodes(UniqueArray<Int64>& own_nodes_uid_around_nodes)
1173{
1174 IParallelMng* pm = parallelMng();
1175 IMesh* mesh = m_cartesian_mesh->mesh();
1176
1177 if (pm->commSize() != 1 && mesh->ghostLayerMng()->nbGhostLayer() == 0) {
1178 ARCANE_FATAL("Pas compatible sans ghost");
1179 }
1180
1181 Integer nb_patch = m_cartesian_mesh->nbPatch();
1182 Integer nb_dir = mesh->dimension();
1183 Integer nb_items = mesh->nodeFamily()->allItems().own().size();
1184
1185 // On a que pred et succ.
1186 constexpr Integer nb_items_per_dir = 2;
1187 constexpr Integer ipred = 0;
1188 constexpr Integer isucc = 1;
1189
1190 // +1 car on a le uid dedans.
1191 Integer size_of_once_case_around = nb_dir * nb_items_per_dir * nb_patch + 1;
1192
1193 own_nodes_uid_around_nodes.resize(nb_items * size_of_once_case_around, -1);
1194
1195 Integer index = 0;
1196 ENUMERATE_ (Item, iitem, mesh->nodeFamily()->allItems().own()) {
1197 own_nodes_uid_around_nodes[index] = iitem->uniqueId();
1198 index += size_of_once_case_around;
1199 }
1200
1201 auto set_value = [&](Integer dir, Integer ipatch, Int64 uid, Int64 uid_pred, Int64 uid_succ) {
1202 // debug() << " -- dir : " << dir
1203 // << " -- ipatch : " << ipatch
1204 // << " -- uid : " << uid
1205 // << " -- uid_pred : " << uid_pred
1206 // << " -- uid_succ : " << uid_succ;
1207
1208 ARCANE_ASSERT((uid != -1), ("Uid ne peut pas être égal à -1"));
1209
1210 for (Integer i = 0; i < own_nodes_uid_around_nodes.size(); i += size_of_once_case_around) {
1211 if (own_nodes_uid_around_nodes[i] == uid) {
1212 Integer pos_final = i + 1 + ipatch * (nb_items_per_dir * nb_dir) + dir * nb_items_per_dir;
1213 Integer pos_pred = pos_final + ipred;
1214 Integer pos_succ = pos_final + isucc;
1215 if (own_nodes_uid_around_nodes[pos_pred] != -1 && own_nodes_uid_around_nodes[pos_pred] != uid_pred) {
1216 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);
1217 }
1218 if (own_nodes_uid_around_nodes[pos_succ] != -1 && own_nodes_uid_around_nodes[pos_succ] != uid_succ) {
1219 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);
1220 }
1221 own_nodes_uid_around_nodes[pos_pred] = uid_pred;
1222 own_nodes_uid_around_nodes[pos_succ] = uid_succ;
1223 return;
1224 }
1225 }
1226 };
1227
1228 // // TODO : Il faut pouvoir récupérer le patch correspondant.
1229 // for (Integer idir = 0; idir < nb_dir; ++idir) {
1230 // NodeDirectionMng ndm(m_cartesian_mesh->nodeDirection(idir));
1231 // ENUMERATE_ (Node, inode, ndm.allNodes().own()) {
1232 // DirNode cc(ndm.node(*inode));
1233 // Node next = cc.next();
1234 // Node prev = cc.previous();
1235 // set_value(idir, 0, inode->uniqueId(), prev.uniqueId(), next.uniqueId());
1236 // }
1237 // }
1238
1239 for (Integer ipatch = 0; ipatch < nb_patch; ++ipatch) {
1240 ICartesianMeshPatch* p = m_cartesian_mesh->patch(ipatch);
1241 for (Integer idir = 0; idir < nb_dir; ++idir) {
1242 NodeDirectionMng ndm(p->nodeDirection(idir));
1243 ENUMERATE_ (Node, inode, ndm.allNodes().own()) {
1244 DirNode cc(ndm.node(*inode));
1245 Node next = cc.next();
1246 Node prev = cc.previous();
1247 set_value(idir, ipatch, inode->uniqueId(), prev.uniqueId(), next.uniqueId());
1248 }
1249 }
1250 }
1251
1252 return size_of_once_case_around-1;
1253}
1254
1255/*---------------------------------------------------------------------------*/
1256/*---------------------------------------------------------------------------*/
1257
1258void AMRCartesianMeshTesterModule::
1259_checkSync()
1260{
1261 IMesh* mesh = m_cartesian_mesh->mesh();
1262 Integer nb_error = 0;
1263
1264 VariableCellInt32 test_var(VariableBuildInfo(mesh, "ArcaneTestAMRCheckSync"));
1265 test_var.fill(0);
1266 ENUMERATE_ (Cell, icell, mesh->ownCells()) {
1267 test_var[icell] = 1;
1268 }
1269 test_var.synchronize();
1270 ENUMERATE_ (Cell, icell, mesh->allCells()) {
1271 if (test_var[icell] != 1) {
1272 nb_error++;
1273 }
1274 }
1275 if (nb_error > 0) {
1276 ARCANE_FATAL("Bad sync -- Nb error : {0}", nb_error);
1277 }
1278}
1279
1280/*---------------------------------------------------------------------------*/
1281/*---------------------------------------------------------------------------*/
1282
1283void AMRCartesianMeshTesterModule::
1284_cellsInPatch(Real3 position, Real3 length, bool is_3d, Int32 level, UniqueArray<Int32>& cells_in_patch)
1285{
1286 // Parcours les mailles actives et ajoute dans la liste des mailles
1287 // à raffiner celles qui sont contenues dans le boîte englobante
1288 // spécifiée dans le jeu de données.
1289 Real3 min_pos = position;
1290 Real3 max_pos = min_pos + length;
1291 ENUMERATE_ (Cell, icell, mesh()->allCells()) {
1292 if ((icell->level() == level) || (level == -1 && icell->nbHChildren() == 0)) {
1293 Real3 center = m_cell_center[icell];
1294 bool is_inside_x = center.x > min_pos.x && center.x < max_pos.x;
1295 bool is_inside_y = center.y > min_pos.y && center.y < max_pos.y;
1296 bool is_inside_z = (center.z > min_pos.z && center.z < max_pos.z) || !is_3d;
1297 if (is_inside_x && is_inside_y && is_inside_z) {
1298 cells_in_patch.add(icell.itemLocalId());
1299 }
1300 }
1301 }
1302}
1303
1304/*---------------------------------------------------------------------------*/
1305/*---------------------------------------------------------------------------*/
1306
1307ARCANE_REGISTER_MODULE_AMRCARTESIANMESHTESTER(AMRCartesianMeshTesterModule);
1308
1309/*---------------------------------------------------------------------------*/
1310/*---------------------------------------------------------------------------*/
1311
1312} // End namespace ArcaneTest
1313
1314/*---------------------------------------------------------------------------*/
1315/*---------------------------------------------------------------------------*/
#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.
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.
List< String > StringList
Tableau de chaînes de caractères unicode.
Definition UtilsTypes.h:509
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:341
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