Arcane  v3.15.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ArcaneCasePartitioner.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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/* ArcaneCasePartitioner.cc (C) 2000-2024 */
9/* */
10/* Service de partitionnement externe du maillage. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ScopedPtr.h"
15#include "arcane/utils/StringBuilder.h"
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/ITraceMng.h"
18
19#include "arcane/core/BasicService.h"
20#include "arcane/core/ISubDomain.h"
21#include "arcane/core/ServiceFinder2.h"
22#include "arcane/core/FactoryService.h"
23#include "arcane/core/SerializeBuffer.h"
24#include "arcane/core/IMeshPartitioner.h"
25#include "arcane/core/IMainFactory.h"
26#include "arcane/core/IMeshModifier.h"
27#include "arcane/core/Properties.h"
28#include "arcane/core/IInitialPartitioner.h"
29#include "arcane/core/Timer.h"
30#include "arcane/core/IMesh.h"
31#include "arcane/core/IMeshSubMeshTransition.h"
32#include "arcane/core/IItemFamily.h"
33#include "arcane/core/IDirectExecution.h"
34#include "arcane/core/IParallelMng.h"
35#include "arcane/core/IMeshUtilities.h"
36#include "arcane/core/IMeshWriter.h"
37#include "arcane/core/ITimeStats.h"
38#include "arcane/core/ServiceBuilder.h"
39#include "arcane/core/IMeshPartitionConstraintMng.h"
40#include "arcane/core/ExternalPartitionConstraint.h"
41
42#include "arcane/std/ArcaneCasePartitioner_axl.h"
43
44#include <map>
45
46/*---------------------------------------------------------------------------*/
47/*---------------------------------------------------------------------------*/
48
49namespace Arcane
50{
51
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54
55class ArcaneCasePartitioner;
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
62{
63 public:
64
66 {
67 VariableCellInt32* m_true_cells_owner = nullptr;
68 VariableNodeInt32* m_true_nodes_owner = nullptr;
69 };
70
71 public:
72
74 : m_sub_domain(sd)
75 , m_main(mt)
76 {
77 }
78 void build() override {}
79 void partitionAndDistributeMeshes(ConstArrayView<IMesh*> meshes) override;
80
81 private:
82
84 void _mergeConstraints(ConstArrayView<IMesh*> meshes);
85
87 void _printStats(Integer nb_part,IMesh* mesh,VariableCellInt32& new_owners);
88
89 public:
90
91 ISubDomain* m_sub_domain = nullptr;
92 ArcaneCasePartitioner* m_main = nullptr;
95};
96
97/*---------------------------------------------------------------------------*/
98/*---------------------------------------------------------------------------*/
104{
105 public:
106
107 public:
108
110 ~ArcaneCasePartitioner() override;
111
112 public:
113
114 void build() override {}
115 void execute() override;
116 void setParallelMng(IParallelMng*) override {}
117 bool isActive() const override { return true; }
118
119 private:
120
122 void _initCorrespondance(Int32 my_rank);
123
126
129
130
131 private:
132
133 std::ofstream m_sortiesCorrespondance;
134
135 ArcaneInitialPartitioner* m_init_part = nullptr;
136
137 void _partitionMesh(Int32 nb_part);
140 Integer nb_layer,Integer maxLocalIdCell, Integer maxLocalIdNode);
144};
145
146/*---------------------------------------------------------------------------*/
147/*---------------------------------------------------------------------------*/
148
151{
152 Integer nb_mesh = meshes.size();
153 if (nb_mesh!=1)
154 ARCANE_FATAL("Can not partition multiple meshes");
155
156 IMesh* mesh = meshes[0];
157 ISubDomain* sd = m_sub_domain;
158 ITraceMng* tm = sd->traceMng();
159
160 tm->info()<<" _regroupeContraintes: nbMailles = "<<meshes[0]->nbCell() <<", nbMaillesLocales = "<< meshes[0]->ownCells().size();
161
162 Integer nb_contraintes = m_main->options()->constraints.size();
163 tm->info() << "Number of constraints = " << nb_contraintes;
164 if (nb_contraintes==0)
165 return;
166
170 cells_new_owner[icell] = (*icell).owner();
171 }
172
173 sd->timeStats()->dumpTimeAndMemoryUsage(sd->parallelMng());
174 IMeshPartitionConstraint* c = new ExternalPartitionConstraint(mesh, m_main->options()->constraints);
175 mesh->partitionConstraintMng()->addConstraint(c);
176 mesh->partitionConstraintMng()->computeAndApplyConstraints();
177
178 cells_new_owner.synchronize();
179 mesh->utilities()->changeOwnersFromCells();
180 mesh->modifier()->setDynamic(true);
181 bool compact = mesh->properties()->getBool("compact");
182 mesh->properties()->setBool("compact", true);
183 mesh->toPrimaryMesh()->exchangeItems();
184 mesh->properties()->setBool("compact", compact);
185#if 0
186#ifdef ARCANE_DEBUG
189 mesh_writer = mesh_writer_factory.createInstance("Lima",true);
190 IParallelMng* pm = sd->parallelMng();
191 Int32 my_rank = pm->commRank();
192
193 StringBuilder filename = "cut_mesh_after_";
194 filename += my_rank;
195 filename += ".mli2";
196 mesh_writer->writeMeshToFile(mesh,filename);
197#endif
198#endif
199}
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203
206{
207 String lib_name = m_main->options()->library();
208 ISubDomain* sd = m_sub_domain;
209 IParallelMng* pm = sd->parallelMng();
210 Int32 nb_rank = pm->commSize();
211 //Int32 my_rank = pm->commRank();
213 auto mesh_partitioner(service_builder.createReference(lib_name,SB_AllowNull));
214 ITraceMng* tm = sd->traceMng();
215 tm->info() << "DoInitialPartition. Service=" << lib_name;
216
217 if (!mesh_partitioner.get())
218 ARCANE_FATAL("can not found service named '{0}' for initial mesh partitioning", lib_name);
219
220 _mergeConstraints(meshes);
221
222 Integer nb_mesh = meshes.size();
223 if (nb_mesh!=1)
224 ARCANE_FATAL("Can not partition multiple meshes");
225
226 m_part_indexes.resize(nb_mesh);
227 Int32 nb_part = m_main->options()->nbCutPart();
228 if (nb_part==0)
229 nb_part = nb_rank;
230 tm->info() << "NbPart = " << nb_part << " nb_mesh=" << nb_mesh;
231
232 for( Integer i=0; i<nb_mesh; ++i ){
233 IMesh* mesh = meshes[i];
237 m_part_indexes[i].m_true_cells_owner = p_true_cells_owner;
238 m_part_indexes[i].m_true_nodes_owner = p_true_nodes_owner;
245 bool is_dynamic = mesh->isDynamic();
246 mesh->modifier()->setDynamic(true);
247 // Premier partitionnement (optionnel) pour donner un premier resultat correct
248 //mesh_partitioner->partitionMesh(mesh);
249 //mesh->exchangeItems(false);
250
251 // Partitionnement final
252 {
253 sd->timeStats()->dumpTimeAndMemoryUsage(pm);
254 Timer t(sd,"InitPartTimer",Timer::TimerReal);
255 {
257 mesh_partitioner->partitionMesh(mesh,nb_part);
258 }
259 tm->info() << "Partitioning time t=" << t.lastActivationTime();
260 sd->timeStats()->dumpTimeAndMemoryUsage(pm);
261 }
265 cells_new_owner[icell] = new_owner % nb_rank;
266 }
269 }
271 mesh->utilities()->changeOwnersFromCells();
272 //mesh->modifier()->setDynamic(true);
273 //PRIMARYMESH_CAST(mesh)->exchangeItems();
274 bool compact = mesh->properties()->getBool("compact");
275 mesh->properties()->setBool("compact", true);
276 mesh->toPrimaryMesh()->exchangeItems();
277 mesh->modifier()->setDynamic(is_dynamic);
278 mesh->properties()->setBool("compact", compact);
279 }
280
281 // ajout d'une 2ème couche de mailles
282 // il ne faut plus faire exchangeItems avec les 2 couches de mailles
283 IMesh* mesh = meshes[0];
284 if (m_main->options()->nbGhostLayer()==2)
285 mesh->updateGhostLayers(false);
286}
287
288/*---------------------------------------------------------------------------*/
289/*---------------------------------------------------------------------------*/
290
293{
296 Int32 new_owner = new_owners[icell];
298 }
299 IParallelMng* pm = mesh->parallelMng();
300 pm->reduce(Parallel::ReduceSum,nb_cells);
301 ITraceMng* tm = m_sub_domain->traceMng();
302 tm->info() << " -- Partitioning statistics --";
303 tm->info() << " Part NbCell";
304 for( Integer i=0; i<nb_part; ++i ){
305 tm->info() << Trace::Width(6) << i << Trace::Width(18) << nb_cells[i];
306 }
307}
308
309/*---------------------------------------------------------------------------*/
310/*---------------------------------------------------------------------------*/
311
312ArcaneCasePartitioner::
313ArcaneCasePartitioner(const ServiceBuildInfo& sb)
315{
316 m_init_part = new ArcaneInitialPartitioner(this,sb.subDomain());
317 info() << "** ** SET INITIAL PARTITIONER 2";
318 sb.subDomain()->setInitialPartitioner(m_init_part);
319}
320
321/*---------------------------------------------------------------------------*/
322/*---------------------------------------------------------------------------*/
323
324ArcaneCasePartitioner::
325~ArcaneCasePartitioner()
326{
327}
328
329/*---------------------------------------------------------------------------*/
330/*---------------------------------------------------------------------------*/
331
333execute()
334{
335 Int32 nb_part = options()->nbCutPart();
336 info() << "ArcaneCasePartitioner::execute() nb_part=" << nb_part;
337 if (nb_part!=0){
338 subDomain()->timeStats()->dumpTimeAndMemoryUsage(subDomain()->parallelMng());
339 _partitionMesh(nb_part);
340 }
341}
342
343/*---------------------------------------------------------------------------*/
344/*---------------------------------------------------------------------------*/
345
346/*---------------------------------------------------------------------------*/
347/*---------------------------------------------------------------------------*/
348
349void ArcaneCasePartitioner::
350_partitionMesh(Int32 nb_part)
351{
352 //String lib_name = m_main->options()->library(); //"Metis";
353 ISubDomain* sd = subDomain();
354 IMesh* current_mesh = mesh();
355 IParallelMng* pm = sd->parallelMng();
356 Int32 nb_rank = pm->commSize();
357 Int32 my_rank = pm->commRank();
358
359 //FactoryT<IMeshWriter> mesh_writer_factory(sd->serviceMng());
360 String mesh_writer_name = options()->writerServiceName();
361 if (mesh_writer_name.empty())
362 pfatal() << "No service selected to write the mesh";
364 auto mesh_writer = sb.createReference(mesh_writer_name,SB_Collective);
365
366 String pattern = options()->meshFileNamePattern();
367 info() << "Mesh file pattern=" << pattern;
368
369 // Partitionne le maillage.
370 // En retour, \a cells_new_owner contient le numéro de la partie à laquelle
371 // chaque maille appartiendra. Pour sauver le fichier, il faut que toutes
372 // les mailles d'une partie soient sur le même sous-domaine. Pour cela,
373 // on stocke le numéro de la partie dans \a true_cells_owner, puis
374 // on échange le maillage.
375 //mesh_partitioner->partitionMesh(current_mesh,nb_part);
376 VariableCellInt32 true_cells_owner(*m_init_part->m_part_indexes[0].m_true_cells_owner);
377 VariableNodeInt32 true_nodes_owner(*m_init_part->m_part_indexes[0].m_true_nodes_owner);
379 //VariableItemInt32& cells_new_owner(current_cell_family->itemsNewOwner());
381 Integer total_current_nb_cell = pm->reduce(Parallel::ReduceSum,current_all_cells.own().size());
382 info() << "TOTAL_NB_CELL=" << total_current_nb_cell;
383
384 IMainFactory* main_factory = sd->application()->mainFactory();
385 IPrimaryMesh* new_mesh = main_factory->createMesh(sd,pm->sequentialParallelMng(),"SubMesh");
386 new_mesh->setDimension(mesh()->dimension());
387 // Pour optimiser, il n'y a pas besoin de trier ni de compacter les entités.
388 new_mesh->properties()->setBool("compact",false);
389 new_mesh->properties()->setBool("sort",false);
390 new_mesh->modifier()->setDynamic(true);
391 new_mesh->allocateCells(0,Int64ConstArrayView(),true);
392
393 Integer saved_nb_cell = 0;
395 Integer max_nb_cell = 0;
396
397 if (options()->createCorrespondances())
399
400 // recherche une fois pour toute les id max
401 Integer maxLocalIdCell = mesh()->cellFamily()->maxLocalId();
402 Integer maxLocalIdNode = mesh()->nodeFamily()->maxLocalId();
403
404 // Force le propriétaire des entités pour au sous-domaine 0 car
405 // new_mesh utilise un parallelMng() séquentiel.
406 for( IItemFamily* family : mesh()->itemFamilies() ){
407 ENUMERATE_ITEM(iitem,family->allItems()){
408 iitem->mutableItemBase().setOwner(0,0);
409 }
410 }
411
412 // Pour chaque partie à traiter, créé un maillage
413 // contenant les entités de cette partie
414 // et le sauvegarde
415 info() << "NbPart=" << nb_part << " my_rank=" << my_rank;
416 for( Integer i=0; i<nb_part; ++i ){
417 if ((i % nb_rank)!=my_rank){
418 if (my_rank==0 && options()->createCorrespondances()){
419
420 info()<<"Receive on master to build correspondence file on sub-domain "<<i
421 <<" sent from processor "<<i % nb_rank;
422 Int32UniqueArray taillesTab(2);
423 Int64UniqueArray nodesUniqueId;
424 Int64UniqueArray cellsUniqueId;
425
426 pm->recv(taillesTab, i % nb_rank);
427 nodesUniqueId.resize(taillesTab[0]);
428 cellsUniqueId.resize(taillesTab[1]);
429 pm->recv(nodesUniqueId, i % nb_rank);
430 pm->recv(cellsUniqueId, i % nb_rank);
431 _writeCorrespondance(i, nodesUniqueId, cellsUniqueId);
432 }
433 continue;
434 }
435
436 new_mesh->destroyGroups();
437 new_mesh->modifier()->clearItems();
438 new_mesh->modifier()->endUpdate();
439 UniqueArray<Cell> cells_selected_for_new_mesh;
440 ENUMERATE_CELL(icell,current_all_cells.own()){
441 if (true_cells_owner[icell]==i){
442 Cell cell = *icell;
443 cells_selected_for_new_mesh.add(cell);
444 //info() << "ADD CELL " << ItemPrinter(cell);
445 }
446 }
447
448 // sélectionne les mailles fantômes en plus si nécessaire
449 _addGhostLayers(current_all_cells, cells_selected_for_new_mesh, options()->nbGhostLayer(), maxLocalIdCell, maxLocalIdNode);
450
451 Int32UniqueArray cells_local_id;
452 Int64UniqueArray cells_unique_id;
453 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
454 Cell cell = cells_selected_for_new_mesh[j];
455 cells_local_id.add(cell.localId());
456 cells_unique_id.add(static_cast<Int64>(cell.uniqueId()));
457 }
458
459 Integer nb_cell_to_copy = cells_local_id.size();
460 SerializeBuffer buffer;
461 current_mesh->serializeCells(&buffer,cells_local_id);
462 info() << "NB_CELL_TO_SERIALIZE=" << nb_cell_to_copy;
463 new_mesh->modifier()->addCells(&buffer);
464 new_mesh->modifier()->endUpdate();
465 // Pour mettre a jour les coordonnees
466 //new_mesh->nodeFamily()->endUpdate();
467 ItemInternalList new_cells = new_mesh->itemsInternal(IK_Cell);
468 ItemInternalList current_cells = current_mesh->itemsInternal(IK_Cell);
469 VariableNodeReal3& new_coordinates(new_mesh->nodesCoordinates());
470 VariableNodeReal3& current_coordinates(current_mesh->toPrimaryMesh()->nodesCoordinates());
471 Int32UniqueArray new_cells_local_id(nb_cell_to_copy);
472 new_mesh->cellFamily()->itemsUniqueIdToLocalId(new_cells_local_id,cells_unique_id);
473 for( Integer zid=0; zid<nb_cell_to_copy; ++zid ){
474 Cell current_cell = current_cells[cells_local_id[zid]];
475 Cell new_cell = new_cells[new_cells_local_id[zid]];
476 if (current_cell.uniqueId()!=new_cell.uniqueId())
477 fatal() << "Inconsistent unique ids";
478 Integer nb_node = current_cell.nbNode();
479 //info() << "Current=" << ItemPrinter(current_cell)
480 // << " new=" << ItemPrinter(new_cell)
481 // << " nb_node=" << nb_node;
482 for( Integer z2=0; z2<nb_node; ++z2 ){
483 Real3 coord = current_coordinates[current_cell.node(z2)];
484 // info() << "Node=" << ItemPrinter(new_cell.node(z2)) << " coord=" << coord
485 // << " orig_node=" << ItemPrinter(current_cell.node(z2));
486 new_coordinates[new_cell.node(z2)] = coord;
487 // Positionne le propriétaire final du noeud
488 new_cell.node(z2).mutableItemBase().setOwner(true_nodes_owner[current_cell.node(z2)],0);
489 }
490 }
491 // Maintenant, il faut recopier les groupes
492 {
493 _computeGroups(current_mesh->nodeFamily(),new_mesh->nodeFamily());
494 _computeGroups(current_mesh->edgeFamily(),new_mesh->edgeFamily());
495 _computeGroups(current_mesh->faceFamily(),new_mesh->faceFamily());
496 _computeGroups(current_mesh->cellFamily(),new_mesh->cellFamily());
497
498 if (options()->nbGhostLayer()>0)
499 _addGhostGroups(new_mesh, cells_selected_for_new_mesh, true_cells_owner, true_nodes_owner, new_cells_local_id, i);
500 }
501 Integer new_nb_cell = new_mesh->nbCell();
502 info() << "NB_NEW_CELL=" << new_nb_cell;
503 min_nb_cell = math::min(min_nb_cell,new_nb_cell);
504 max_nb_cell = math::max(max_nb_cell,new_nb_cell);
505 saved_nb_cell += new_nb_cell;
506 String filename;
507 if (pattern.empty()){
508 StringBuilder sfilename = "cut_mesh_";
509 sfilename += i;
510 sfilename += ".mli2";
511 filename = sfilename;
512 }
513 else{
514 //ATTENTION potentiel debordement si pattern est trop long.
515 //Verifier aussi qu'il y a un %d. A terme, utiliser String::format()
516 char buf[4096];
517 if (pattern.length()>128){
518 pfatal() << "Pattern too long (max=128)";
519 }
520 sprintf(buf,pattern.localstr(),i);
521 filename = String(StringView(buf));
522 }
523 {
524 info() << "Writing mesh file filename='" << filename << "'";
525 bool is_bad = mesh_writer->writeMeshToFile(new_mesh, filename);
526 if (is_bad)
527 ARCANE_FATAL("Can not write mesh file '{0}'", filename);
528 }
529
530 // Fichier Correspondance
531 if (options()->createCorrespondances()){
532 info()<<"Participation to build correspondence file on sub-domain "<<i;
533
534 Int32UniqueArray taillesTab;
535 taillesTab.add(new_mesh->nodeFamily()->nbItem());
536 taillesTab.add(new_mesh->cellFamily()->nbItem());
537 Int64UniqueArray nodesUniqueId(taillesTab[0]);
538 Int64UniqueArray cellsUniqueId(taillesTab[1]);
539
540 NodeInfoListView nodes(new_mesh->nodeFamily());
541 for( int j=0; j<taillesTab[0]; ++j ){
542 Node node = nodes[j];
543 nodesUniqueId[j] = node.uniqueId();
544 }
545
546 CellInfoListView cells(new_mesh->cellFamily());
547 for( int j=0; j<taillesTab[1]; ++j ){
548 Cell cell = cells[j];
549 cellsUniqueId[j] = cell.uniqueId();
550 }
551
552 if (my_rank!=0){
553 pm->send(taillesTab, 0);
554 pm->send(nodesUniqueId, 0);
555 pm->send(cellsUniqueId, 0);
556 }
557 else {
558 _writeCorrespondance(i, nodesUniqueId, cellsUniqueId);
559 }
560 }
561 } // end i<nb_part
562
563 Integer total_new_nb_cell = pm->reduce(Parallel::ReduceSum,saved_nb_cell);
564 Integer total_min_nb_cell = pm->reduce(Parallel::ReduceMin,min_nb_cell);
565 Integer total_max_nb_cell = pm->reduce(Parallel::ReduceMax,max_nb_cell);
566 info() << "TOTAL_NEW_NB_CELL=" << total_new_nb_cell
567 << " min=" << total_min_nb_cell
568 << " max=" << total_max_nb_cell
569 << " computed_average=" << (total_current_nb_cell/nb_part);
570
571 subDomain()->timeStats()->dumpTimeAndMemoryUsage(pm);
572
573 if (options()->createCorrespondances())
575
576 if (options()->nbGhostLayer()==0)
577 if (total_new_nb_cell!=total_current_nb_cell)
578 pfatal() << "Bad number of saved cells current=" << total_current_nb_cell
579 << " saved=" << total_new_nb_cell;
580
581 pinfo()<<"Total Memory Used : "<<platform::getMemoryUsed();
582}
583
584/*---------------------------------------------------------------------------*/
585/*---------------------------------------------------------------------------*/
586
589{
590 info()<<" _initCorrespondance("<<my_rank<<")";
591
592 if (my_rank)
593 return;
594
595 m_sortiesCorrespondance.open("Correspondances");
596
597 if (m_sortiesCorrespondance.fail ()){
598 pfatal() << "Unable to write to file 'Correspondances' ";
599 }
600
601 m_sortiesCorrespondance << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
602 m_sortiesCorrespondance << "<!-- Correspondance file generated by Arcane/Decoupe3D V2 -->\n";
603 m_sortiesCorrespondance << "\n<cpus>\n";
604}
605
606/*---------------------------------------------------------------------------*/
607/*---------------------------------------------------------------------------*/
608
611{
612 info()<<" _writeCorrespondance("<<rank<<", nodesUniqueId.size() = "
613 <<nodesUniqueId.size()<<", cellsUniqueId.size() = "<<cellsUniqueId.size()<<")";
614
615 m_sortiesCorrespondance << " <cpu id=\"" << rank << "\">" << "\n"
616 << " <noeuds>" << "\n" << " ";
617 for( Integer i=0; i<nodesUniqueId.size(); ++i )
618 m_sortiesCorrespondance <<nodesUniqueId[i]<< " ";
619
620 m_sortiesCorrespondance << "\n" << " </noeuds>"
621 << "\n"
622 << " <mailles>" << "\n"
623 << " ";
624 for( Integer i=0; i<cellsUniqueId.size(); ++i )
625 m_sortiesCorrespondance <<cellsUniqueId[i]<< " ";
626 m_sortiesCorrespondance << "\n" << " </mailles>" << "\n"
627 << " </cpu>" << "\n";
628}
629
630/*---------------------------------------------------------------------------*/
631/*---------------------------------------------------------------------------*/
632
635{
636 if (my_rank)
637 return;
638
639 m_sortiesCorrespondance << "</cpus>\n";
640 m_sortiesCorrespondance.close ();
641}
642
643/*---------------------------------------------------------------------------*/
644/*---------------------------------------------------------------------------*/
659{
660 info() << "Compute groups family=" << current_family->name();
661
662 ItemGroup new_all_items = new_family->allItems();
663 Integer nb_new_item = new_all_items.size();
664
667 {
668 Integer index = 0;
670 new_items_uid[index] = (*iitem).uniqueId();
671 new_items_lid[index] = iitem.itemLocalId();
672 ++index;
673 }
674 }
676 // Détermine le localId() dans le maillage d'origine des entités
677 current_family->itemsUniqueIdToLocalId(items_lid,new_items_uid);
678
680 items_current_to_new_local_id.fill(NULL_ITEM_LOCAL_ID);
681 for( Integer i=0; i<nb_new_item; ++i )
683
686 ItemGroup group = *igroup;
687 if (group.isOwn())
688 continue;
689 if (group.isAllItems())
690 continue;
691 create_local_ids.clear();
692 ENUMERATE_ITEM(iitem,group){
693 Int32 current_uid = iitem.itemLocalId();
695 if (new_lid!=NULL_ITEM_LOCAL_ID)
697 }
698 new_family->createGroup(group.name(),create_local_ids,true);
699 }
700}
701
702/*---------------------------------------------------------------------------*/
703/*---------------------------------------------------------------------------*/
704/* \brief Ajoute au tableau de mailles le nombre de couches de mailles désiré
705 */
706void ArcaneCasePartitioner::
708 Integer nbCouches,Integer maxLocalIdCell, Integer maxLocalIdNode)
709{
710 if (nbCouches==0)
711 return;
712
714 filtre_lid_cell.fill(0);
716 filtre_lid_node.fill(0);
717
718 // on marque les mailles déjà sélectionnées
719 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
721 filtre_lid_cell[cell.localId()] = 1;
722 }
723
724 // recherhe pour tous les noeuds associés aux mailles sélectionnées une mailles reliée
725 // à ce même noeud qui ne soit pas sélectionnée
726 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
727 Cell cell = cells_selected_for_new_mesh[j];
728
729 NodeVectorView nodes = cell.nodes();
730 for( Integer k=0, ks=nodes.size(); k<ks; ++k){
731 Node node = nodes[k];
732 if (filtre_lid_node[node.localId()]==0){
733 // les mailles reliées par un noeud
734 CellVectorView cells_vois = node.cells();
735
736 for( Integer i=0, is=cells_vois.size(); i<is; ++i ){
737 Cell cell_vois = cells_vois[i];
738 if (filtre_lid_cell[cell_vois.localId()]==0){
739
740 // ajoute la maille qui n'a pas encore été vue
741 cells_selected_for_new_mesh.add(cell_vois);
742
743 filtre_lid_cell[cell_vois.localId()] = 1;
744 }
745 }
746 filtre_lid_node[node.localId()] = 1;
747 }
748 }
749 }
750
751 // pour la deuxième couche (si besoin) il est plus simple de le faire récurcivement
752 _addGhostLayers(current_all_cells, cells_selected_for_new_mesh, nbCouches-1, maxLocalIdCell, maxLocalIdNode);
753
754}
755/*---------------------------------------------------------------------------*/
756/*---------------------------------------------------------------------------*/
757/* \brief Ajoute les groupes de mailles TOUT, LOCAL et MF_* en fonctions des groupes voisins
758 * Ajoute aussi le groupe de noeuds LOCALN (mais pas les NF_*)
759 */
760void ArcaneCasePartitioner::
761_addGhostGroups(IMesh* new_mesh, Array<Cell>& cells_selected_for_new_mesh, VariableCellInt32& true_cells_owner,
762 VariableNodeInt32& true_nodes_owner,
763 Int32Array& new_cells_local_id, Integer id_loc)
764{
765 info()<<"ArcaneCasePartitioner::_addGhostGroups (id_loc = "<<id_loc<<")";
766 // il faut déterminer les groupes voisins existant
767 // on utilise un "map" pour stocker les différents sous-domaines qui apparaissent et le nombre de mailles dedans
768 std::map<Integer, Integer> dom_vois;
769 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
770 Cell cell = cells_selected_for_new_mesh[j];
771 dom_vois[true_cells_owner[cell]] += 1;
772 }
773
774 // on utilise une seconde map pour lister les mailles suivant le domaine de destination
775 std::map<Integer,SharedArray<Int32> > map_groupes;
776 for (std::map<Integer, Integer>::const_iterator iter=dom_vois.begin(); iter!=dom_vois.end(); ++iter){
777 Integer no_sous_dom = iter->first;
778 Integer nb_mailles_sous_dom = iter->second;
779
780 // réservation de la mémoire pour les différentes listes
781 Int32Array& tab = map_groupes[no_sous_dom];
782 tab.reserve(nb_mailles_sous_dom);
783 }
784
785 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
786 Cell cell = cells_selected_for_new_mesh[j];
787 Integer no_sous_dom = true_cells_owner[cell];
788
789 // remplissage des listes par sous-domaine
790 Int32Array & liste_lid = map_groupes[no_sous_dom];
791 liste_lid.add(new_cells_local_id[j]);
792 }
793
794 // création (si nécessaire) des différents groupes et on y met les mailles
795 for (std::map<Integer,SharedArray<Int32> >::iterator iter=map_groupes.begin(); iter!=map_groupes.end(); ++iter){
796 Integer no_sous_dom = iter->first;
797 Int32Array & liste_lid = iter->second;
798
799 ItemGroup groupe_loc;
800 if (no_sous_dom==id_loc)
801 groupe_loc = new_mesh->cellFamily()->findGroup("LOCAL", true);
802 else {
803 String nom_mf("MF_");
804 nom_mf = nom_mf+no_sous_dom;
805 groupe_loc = new_mesh->cellFamily()->findGroup(nom_mf, true);
806 }
807
808 groupe_loc.addItems(liste_lid, false);
809 }
810
811 // Faire le groupe LOCALN : noeuds locaux
812 {
813 // TODO: Optimiser la maniere de construire ce groupe
814 Int32UniqueArray liste_lid;
815 Integer nbnodes = new_mesh->nodeFamily()->nbItem();
816 liste_lid.reserve(nbnodes);
817 NodeInfoListView nodes(new_mesh->nodeFamily());
818 for (int j= 0 ; j < nbnodes ; ++j) {
819 Node node= nodes[j];
820 if (true_nodes_owner[node] == id_loc)
821 liste_lid.add(node.localId());
822 }
823
824 ItemGroup groupe_loc = new_mesh->nodeFamily()->findGroup("LOCALN", true);
825 groupe_loc.addItems(liste_lid, false);
826 }
827
828
829 // le groupe avec toute les mailles
830 ItemGroup groupe_glob = new_mesh->cellFamily()->findGroup("TOUT", true);
831
832 groupe_glob.addItems(new_cells_local_id, false);
833}
834/*---------------------------------------------------------------------------*/
835/*---------------------------------------------------------------------------*/
836
837ARCANE_REGISTER_SERVICE_ARCANECASEPARTITIONER(ArcaneCasePartitioner,ArcaneCasePartitioner);
838
839/*---------------------------------------------------------------------------*/
840/*---------------------------------------------------------------------------*/
841
842}
843
844/*---------------------------------------------------------------------------*/
845/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
Generation de la classe de base du Service.
CaseOptionsArcaneCasePartitioner * options() const
Options du jeu de données du service.
Service de partitionnement externe du maillage.
bool isActive() const override
Vrai si le service est actif.
void execute() override
Exécute l'opération du service.
void _initCorrespondance(Int32 my_rank)
Ouverture du fichier Correspondance (seulement sur le proc 0)
void _computeGroups(IItemFamily *current_family, IItemFamily *new_family)
Recopie les groupes de la famille courante dans la nouvelle.
void build() override
Construction de niveau build du service.
void _finalizeCorrespondance(Int32 my_rank)
Fermeture du fichier Correspondance (seulement sur le proc 0)
void setParallelMng(IParallelMng *) override
Positionne le gestionnaire de parallèlisme associé. Cette méthode doit être appelée avant execute()
void _writeCorrespondance(Int32 rank, Int64Array &nodesUniqueId, Int64Array &cellsUniqueId)
Ecriture du fichier Correspondance.
void partitionAndDistributeMeshes(ConstArrayView< IMesh * > meshes) override
Partitionne les maillages.
void _printStats(Integer nb_part, IMesh *mesh, VariableCellInt32 &new_owners)
Affiche des statistiques sur le partitionnement.
void _mergeConstraints(ConstArrayView< IMesh * > meshes)
Regroupe les mailles associées aux contraintes sur un même proc.
UniqueArray< TrueOwnerInfo > m_part_indexes
Stocke pour chaque maillage une variable indiquant pour chaque maille quelle partie la possède.
Tableau d'items de types quelconques.
Maille d'un maillage.
Definition Item.h:1178
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
Interface d'un partitionneur initial.
Interface d'une famille d'entités.
Manufacture des classes d'Arcane.
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual Integer nbCell()=0
Nombre de mailles du maillage.
virtual CellGroup ownCells()=0
Groupe de toutes les mailles propres au domaine.
virtual IItemFamily * edgeFamily()=0
Retourne la famille des arêtes.
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
Interface d'une contrainte de partitionnement d'un maillage.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual ItemInternalList itemsInternal(eItemKind)=0
Tableau interne des éléments du maillage de type type.
virtual IMeshModifier * modifier()=0
Interface de modification associée.
virtual ARCANE_DEPRECATED_240 void serializeCells(ISerializer *buffer, Int32ConstArrayView cells_local_id)=0
virtual void destroyGroups()=0
Détruit tous les groupes de toutes les familles.
virtual IMeshUtilities * utilities()=0
Interface des fonctions utilitaires associée.
virtual IMeshPartitionConstraintMng * partitionConstraintMng()=0
Gestionnaire des contraintes de partitionnement associées à ce maillage.
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
virtual bool isDynamic() const =0
Indique si le maillage est dynamique (peut évoluer)
virtual Properties * properties()=0
Propriétés associées à ce maillage.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual IParallelMng * sequentialParallelMng()=0
Retourne un gestionnaire de parallélisme séquentiel.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
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 VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual void setInitialPartitioner(IInitialPartitioner *partitioner)=0
Positionne le partitionneur initial.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
bool isOwn() const
Retourne si le groupe contient uniquement des éléments propres au sous-domaine.
Definition ItemGroup.cc:157
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
Definition ItemGroup.cc:609
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:210
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
Structure contenant les informations pour créer un service.
Sentinelle pour le timer. La sentinelle associée à un timer permet de déclancher celui-ci au moment d...
Definition Timer.h:89
Gestion d'un timer.
Definition Timer.h:62
@ TimerReal
Timer utilisant le temps réel.
Definition Timer.h:76
Paramètres nécessaires à la construction d'une variable.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Interface du gestionnaire de traces.
Constructeur de chaîne de caractère unicode.
Chaîne de caractères unicode.
bool empty() const
Vrai si la chaîne est vide (nulle ou "")
Definition String.cc:315
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
Int64 length() const
Retourne la longueur de la chaîne.
Definition String.cc:338
TraceMessage pinfo() const
Flot pour un message d'information en parallèle.
TraceMessage pfatal() const
Flot pour un message d'erreur fatale en parallèle.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage fatal() const
Flot pour un message d'erreur fatale.
Formattage du flot en longueur.
Vecteur 1D de données avec sémantique par valeur (style STL).
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:392
ARCCORE_HOST_DEVICE Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
Definition MathUtils.h:336
ItemVectorViewT< Node > NodeVectorView
Vue sur un vecteur de noeuds.
Definition ItemTypes.h:289
ItemVectorViewT< Cell > CellVectorView
Vue sur un vecteur de mailles.
Definition ItemTypes.h:304
MeshVariableScalarRefT< Node, Int32 > VariableNodeInt32
Grandeur au noeud de type entier 32 bits.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
MeshVariableScalarRefT< Cell, Int32 > VariableCellInt32
Grandeur au centre des mailles de type entier 32 bits.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ SB_Collective
Indique que tous les processus font la même opération.
@ SB_AllowNull
Autorise l'absence du service.
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:550
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
Definition ItemTypes.h:466
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:552
@ IK_Cell
Entité de maillage de genre maille.
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:338
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:691
Int32 Integer
Type représentant un entier.