Arcane  v3.14.10.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
21#include "arcane/core/ISubDomain.h"
22#include "arcane/core/ServiceFinder2.h"
23#include "arcane/core/FactoryService.h"
24#include "arcane/core/SerializeBuffer.h"
25#include "arcane/core/IMeshPartitioner.h"
26#include "arcane/core/IMainFactory.h"
27#include "arcane/core/IMeshModifier.h"
28#include "arcane/core/Properties.h"
29#include "arcane/core/IInitialPartitioner.h"
30#include "arcane/core/Timer.h"
31#include "arcane/core/IMesh.h"
32#include "arcane/core/IMeshSubMeshTransition.h"
33#include "arcane/core/IItemFamily.h"
34#include "arcane/core/IDirectExecution.h"
35#include "arcane/core/IParallelMng.h"
36#include "arcane/core/IMeshUtilities.h"
37#include "arcane/core/IMeshWriter.h"
38#include "arcane/core/ITimeStats.h"
39#include "arcane/core/ServiceBuilder.h"
40
41#include "arcane/std/ArcaneCasePartitioner_axl.h"
42
43#include "arcane/core/IMeshPartitionConstraintMng.h"
44#include "arcane/mesh/ExternalPartitionConstraint.h"
45
46#include <map>
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
51namespace Arcane
52{
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
57class ArcaneCasePartitioner;
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
64{
65 public:
66
68 {
69 VariableCellInt32* m_true_cells_owner = nullptr;
70 VariableNodeInt32* m_true_nodes_owner = nullptr;
71 };
72
73 public:
74
76 : m_sub_domain(sd)
77 , m_main(mt)
78 {
79 }
80 void build() override {}
81 void partitionAndDistributeMeshes(ConstArrayView<IMesh*> meshes) override;
82
83 private:
84
86 void _mergeConstraints(ConstArrayView<IMesh*> meshes);
87
89 void _printStats(Integer nb_part,IMesh* mesh,VariableCellInt32& new_owners);
90
91 public:
92
93 ISubDomain* m_sub_domain = nullptr;
94 ArcaneCasePartitioner* m_main = nullptr;
97};
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
106{
107 public:
108
109 public:
110
112 ~ArcaneCasePartitioner() override;
113
114 public:
115
116 void build() override {}
117 void execute() override;
118 void setParallelMng(IParallelMng*) override {}
119 bool isActive() const override { return true; }
120
121 private:
122
124 void _initCorrespondance(Int32 my_rank);
125
128
131
132
133 private:
134
135 std::ofstream m_sortiesCorrespondance;
136
137 ArcaneInitialPartitioner* m_init_part = nullptr;
138
139 void _partitionMesh(Int32 nb_part);
142 Integer nb_layer,Integer maxLocalIdCell, Integer maxLocalIdNode);
146};
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
153{
154 Integer nb_mesh = meshes.size();
155 if (nb_mesh!=1)
156 ARCANE_FATAL("Can not partition multiple meshes");
157
158 IMesh* mesh = meshes[0];
159 ISubDomain* sd = m_sub_domain;
160 ITraceMng* tm = sd->traceMng();
161
162 tm->info()<<" _regroupeContraintes: nbMailles = "<<meshes[0]->nbCell() <<", nbMaillesLocales = "<< meshes[0]->ownCells().size();
163
164 Integer nb_contraintes = m_main->options()->constraints.size();
165 tm->info() << "Number of constraints = " << nb_contraintes;
166 if (nb_contraintes==0)
167 return;
168
172 cells_new_owner[icell] = (*icell).owner();
173 }
174
175 sd->timeStats()->dumpTimeAndMemoryUsage(sd->parallelMng());
176 IMeshPartitionConstraint* c = new mesh::ExternalPartitionConstraint(mesh, m_main->options()->constraints);
177 mesh->partitionConstraintMng()->addConstraint(c);
178 mesh->partitionConstraintMng()->computeAndApplyConstraints();
179
180 cells_new_owner.synchronize();
181 mesh->utilities()->changeOwnersFromCells();
182 mesh->modifier()->setDynamic(true);
183 bool compact = mesh->properties()->getBool("compact");
184 mesh->properties()->setBool("compact", true);
185 mesh->toPrimaryMesh()->exchangeItems();
186 mesh->properties()->setBool("compact", compact);
187#if 0
188#ifdef ARCANE_DEBUG
191 mesh_writer = mesh_writer_factory.createInstance("Lima",true);
192 IParallelMng* pm = sd->parallelMng();
193 Int32 my_rank = pm->commRank();
194
195 StringBuilder filename = "cut_mesh_after_";
196 filename += my_rank;
197 filename += ".mli";
198 mesh_writer->writeMeshToFile(mesh,filename);
199#endif
200#endif
201}
202
203/*---------------------------------------------------------------------------*/
204/*---------------------------------------------------------------------------*/
205
208{
209 String lib_name = m_main->options()->library();
210 ISubDomain* sd = m_sub_domain;
211 IParallelMng* pm = sd->parallelMng();
212 Int32 nb_rank = pm->commSize();
213 //Int32 my_rank = pm->commRank();
215 auto mesh_partitioner(service_builder.createReference(lib_name,SB_AllowNull));
216 ITraceMng* tm = sd->traceMng();
217 tm->info() << "DoInitialPartition. Service=" << lib_name;
218
219 if (!mesh_partitioner.get())
220 ARCANE_FATAL("can not found service named '{0}' for initial mesh partitioning", lib_name);
221
222 _mergeConstraints(meshes);
223
224 Integer nb_mesh = meshes.size();
225 if (nb_mesh!=1)
226 ARCANE_FATAL("Can not partition multiple meshes");
227
228 m_part_indexes.resize(nb_mesh);
229 Int32 nb_part = m_main->options()->nbCutPart();
230 if (nb_part==0)
231 nb_part = nb_rank;
232 tm->info() << "NbPart = " << nb_part << " nb_mesh=" << nb_mesh;
233
234 for( Integer i=0; i<nb_mesh; ++i ){
235 IMesh* mesh = meshes[i];
239 m_part_indexes[i].m_true_cells_owner = p_true_cells_owner;
240 m_part_indexes[i].m_true_nodes_owner = p_true_nodes_owner;
247 bool is_dynamic = mesh->isDynamic();
248 mesh->modifier()->setDynamic(true);
249 // Premier partitionnement (optionnel) pour donner un premier resultat correct
250 //mesh_partitioner->partitionMesh(mesh);
251 //mesh->exchangeItems(false);
252
253 // Partitionnement final
254 {
255 sd->timeStats()->dumpTimeAndMemoryUsage(pm);
256 Timer t(sd,"InitPartTimer",Timer::TimerReal);
257 {
259 mesh_partitioner->partitionMesh(mesh,nb_part);
260 }
261 tm->info() << "Partitioning time t=" << t.lastActivationTime();
262 sd->timeStats()->dumpTimeAndMemoryUsage(pm);
263 }
267 cells_new_owner[icell] = new_owner % nb_rank;
268 }
271 }
273 mesh->utilities()->changeOwnersFromCells();
274 //mesh->modifier()->setDynamic(true);
275 //PRIMARYMESH_CAST(mesh)->exchangeItems();
276 bool compact = mesh->properties()->getBool("compact");
277 mesh->properties()->setBool("compact", true);
278 mesh->toPrimaryMesh()->exchangeItems();
279 mesh->modifier()->setDynamic(is_dynamic);
280 mesh->properties()->setBool("compact", compact);
281 }
282
283 // ajout d'une 2ème couche de mailles
284 // il ne faut plus faire exchangeItems avec les 2 couches de mailles
285 IMesh* mesh = meshes[0];
286 if (m_main->options()->nbGhostLayer()==2)
287 mesh->updateGhostLayers(false);
288}
289
290/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
292
295{
298 Int32 new_owner = new_owners[icell];
300 }
301 IParallelMng* pm = mesh->parallelMng();
302 pm->reduce(Parallel::ReduceSum,nb_cells);
303 ITraceMng* tm = m_sub_domain->traceMng();
304 tm->info() << " -- Partitioning statistics --";
305 tm->info() << " Part NbCell";
306 for( Integer i=0; i<nb_part; ++i ){
307 tm->info() << Trace::Width(6) << i << Trace::Width(18) << nb_cells[i];
308 }
309}
310
311/*---------------------------------------------------------------------------*/
312/*---------------------------------------------------------------------------*/
313
314ArcaneCasePartitioner::
315ArcaneCasePartitioner(const ServiceBuildInfo& sb)
317{
318 m_init_part = new ArcaneInitialPartitioner(this,sb.subDomain());
319 info() << "** ** SET INITIAL PARTITIONER 2";
320 sb.subDomain()->setInitialPartitioner(m_init_part);
321}
322
323/*---------------------------------------------------------------------------*/
324/*---------------------------------------------------------------------------*/
325
326ArcaneCasePartitioner::
327~ArcaneCasePartitioner()
328{
329}
330
331/*---------------------------------------------------------------------------*/
332/*---------------------------------------------------------------------------*/
333
335execute()
336{
337 Int32 nb_part = options()->nbCutPart();
338 info() << "ArcaneCasePartitioner::execute() nb_part=" << nb_part;
339 if (nb_part!=0){
340 subDomain()->timeStats()->dumpTimeAndMemoryUsage(subDomain()->parallelMng());
341 _partitionMesh(nb_part);
342 }
343}
344
345/*---------------------------------------------------------------------------*/
346/*---------------------------------------------------------------------------*/
347
348/*---------------------------------------------------------------------------*/
349/*---------------------------------------------------------------------------*/
350
351void ArcaneCasePartitioner::
352_partitionMesh(Int32 nb_part)
353{
354 //String lib_name = m_main->options()->library(); //"Metis";
355 ISubDomain* sd = subDomain();
356 IMesh* current_mesh = mesh();
357 IParallelMng* pm = sd->parallelMng();
358 Int32 nb_rank = pm->commSize();
359 Int32 my_rank = pm->commRank();
360
361 //FactoryT<IMeshWriter> mesh_writer_factory(sd->serviceMng());
362 String mesh_writer_name = options()->writerServiceName();
363 if (mesh_writer_name.empty())
364 pfatal() << "No service selected to write the mesh";
366 auto mesh_writer = sb.createReference(mesh_writer_name,SB_Collective);
367
368 String pattern = options()->meshFileNamePattern();
369 info() << "Mesh file pattern=" << pattern;
370
371 // Partitionne le maillage.
372 // En retour, \a cells_new_owner contient le numéro de la partie à laquelle
373 // chaque maille appartiendra. Pour sauver le fichier, il faut que toutes
374 // les mailles d'une partie soient sur le même sous-domaine. Pour cela,
375 // on stocke le numéro de la partie dans \a true_cells_owner, puis
376 // on échange le maillage.
377 //mesh_partitioner->partitionMesh(current_mesh,nb_part);
378 VariableCellInt32 true_cells_owner(*m_init_part->m_part_indexes[0].m_true_cells_owner);
379 VariableNodeInt32 true_nodes_owner(*m_init_part->m_part_indexes[0].m_true_nodes_owner);
381 //VariableItemInt32& cells_new_owner(current_cell_family->itemsNewOwner());
383 Integer total_current_nb_cell = pm->reduce(Parallel::ReduceSum,current_all_cells.own().size());
384 info() << "TOTAL_NB_CELL=" << total_current_nb_cell;
385
386 IMainFactory* main_factory = sd->application()->mainFactory();
387 IPrimaryMesh* new_mesh = main_factory->createMesh(sd,pm->sequentialParallelMng(),"SubMesh");
388 new_mesh->setDimension(mesh()->dimension());
389 // Pour optimiser, il n'y a pas besoin de trier ni de compacter les entités.
390 new_mesh->properties()->setBool("compact",false);
391 new_mesh->properties()->setBool("sort",false);
392 new_mesh->modifier()->setDynamic(true);
393 new_mesh->allocateCells(0,Int64ConstArrayView(),true);
394
395 Integer saved_nb_cell = 0;
397 Integer max_nb_cell = 0;
398
399 if (options()->createCorrespondances())
401
402 // recherche une fois pour toute les id max
403 Integer maxLocalIdCell = mesh()->cellFamily()->maxLocalId();
404 Integer maxLocalIdNode = mesh()->nodeFamily()->maxLocalId();
405
406 // Force le propriétaire des entités pour au sous-domaine 0 car
407 // new_mesh utilise un parallelMng() séquentiel.
408 for( IItemFamily* family : mesh()->itemFamilies() ){
409 ENUMERATE_ITEM(iitem,family->allItems()){
410 iitem->mutableItemBase().setOwner(0,0);
411 }
412 }
413
414 // Pour chaque partie à traiter, créé un maillage
415 // contenant les entités de cette partie
416 // et le sauvegarde
417 info() << "NbPart=" << nb_part << " my_rank=" << my_rank;
418 for( Integer i=0; i<nb_part; ++i ){
419 if ((i % nb_rank)!=my_rank){
420 if (my_rank==0 && options()->createCorrespondances()){
421
422 info()<<"Receive on master to build correspondence file on sub-domain "<<i
423 <<" sent from processor "<<i % nb_rank;
424 Int32UniqueArray taillesTab(2);
425 Int64UniqueArray nodesUniqueId;
426 Int64UniqueArray cellsUniqueId;
427
428 pm->recv(taillesTab, i % nb_rank);
429 nodesUniqueId.resize(taillesTab[0]);
430 cellsUniqueId.resize(taillesTab[1]);
431 pm->recv(nodesUniqueId, i % nb_rank);
432 pm->recv(cellsUniqueId, i % nb_rank);
433 _writeCorrespondance(i, nodesUniqueId, cellsUniqueId);
434 }
435 continue;
436 }
437
438 new_mesh->destroyGroups();
439 new_mesh->modifier()->clearItems();
440 new_mesh->modifier()->endUpdate();
441 UniqueArray<Cell> cells_selected_for_new_mesh;
442 ENUMERATE_CELL(icell,current_all_cells.own()){
443 if (true_cells_owner[icell]==i){
444 Cell cell = *icell;
445 cells_selected_for_new_mesh.add(cell);
446 //info() << "ADD CELL " << ItemPrinter(cell);
447 }
448 }
449
450 // sélectionne les mailles fantômes en plus si nécessaire
451 _addGhostLayers(current_all_cells, cells_selected_for_new_mesh, options()->nbGhostLayer(), maxLocalIdCell, maxLocalIdNode);
452
453 Int32UniqueArray cells_local_id;
454 Int64UniqueArray cells_unique_id;
455 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
456 Cell cell = cells_selected_for_new_mesh[j];
457 cells_local_id.add(cell.localId());
458 cells_unique_id.add(static_cast<Int64>(cell.uniqueId()));
459 }
460
461 Integer nb_cell_to_copy = cells_local_id.size();
462 SerializeBuffer buffer;
463 current_mesh->serializeCells(&buffer,cells_local_id);
464 info() << "NB_CELL_TO_SERIALIZE=" << nb_cell_to_copy;
465 new_mesh->modifier()->addCells(&buffer);
466 new_mesh->modifier()->endUpdate();
467 // Pour mettre a jour les coordonnees
468 //new_mesh->nodeFamily()->endUpdate();
469 ItemInternalList new_cells = new_mesh->itemsInternal(IK_Cell);
470 ItemInternalList current_cells = current_mesh->itemsInternal(IK_Cell);
471 VariableNodeReal3& new_coordinates(new_mesh->nodesCoordinates());
472 VariableNodeReal3& current_coordinates(current_mesh->toPrimaryMesh()->nodesCoordinates());
473 Int32UniqueArray new_cells_local_id(nb_cell_to_copy);
474 new_mesh->cellFamily()->itemsUniqueIdToLocalId(new_cells_local_id,cells_unique_id);
475 for( Integer zid=0; zid<nb_cell_to_copy; ++zid ){
476 Cell current_cell = current_cells[cells_local_id[zid]];
477 Cell new_cell = new_cells[new_cells_local_id[zid]];
478 if (current_cell.uniqueId()!=new_cell.uniqueId())
479 fatal() << "Inconsistent unique ids";
480 Integer nb_node = current_cell.nbNode();
481 //info() << "Current=" << ItemPrinter(current_cell)
482 // << " new=" << ItemPrinter(new_cell)
483 // << " nb_node=" << nb_node;
484 for( Integer z2=0; z2<nb_node; ++z2 ){
485 Real3 coord = current_coordinates[current_cell.node(z2)];
486 // info() << "Node=" << ItemPrinter(new_cell.node(z2)) << " coord=" << coord
487 // << " orig_node=" << ItemPrinter(current_cell.node(z2));
488 new_coordinates[new_cell.node(z2)] = coord;
489 // Positionne le propriétaire final du noeud
490 new_cell.node(z2).mutableItemBase().setOwner(true_nodes_owner[current_cell.node(z2)],0);
491 }
492 }
493 // Maintenant, il faut recopier les groupes
494 {
495 _computeGroups(current_mesh->nodeFamily(),new_mesh->nodeFamily());
496 _computeGroups(current_mesh->edgeFamily(),new_mesh->edgeFamily());
497 _computeGroups(current_mesh->faceFamily(),new_mesh->faceFamily());
498 _computeGroups(current_mesh->cellFamily(),new_mesh->cellFamily());
499
500 if (options()->nbGhostLayer()>0)
501 _addGhostGroups(new_mesh, cells_selected_for_new_mesh, true_cells_owner, true_nodes_owner, new_cells_local_id, i);
502 }
503 Integer new_nb_cell = new_mesh->nbCell();
504 info() << "NB_NEW_CELL=" << new_nb_cell;
505 min_nb_cell = math::min(min_nb_cell,new_nb_cell);
506 max_nb_cell = math::max(max_nb_cell,new_nb_cell);
507 saved_nb_cell += new_nb_cell;
508 String filename;
509 if (pattern.empty()){
510 StringBuilder sfilename = "cut_mesh_";
511 sfilename += i;
512 sfilename += ".mli";
513 filename = sfilename;
514 }
515 else{
516 //ATTENTION potentiel debordement si pattern est trop long.
517 //Verifier aussi qu'il y a un %d. A terme, utiliser String::format()
518 char buf[4096];
519 if (pattern.length()>128){
520 pfatal() << "Pattern too long (max=128)";
521 }
522 sprintf(buf,pattern.localstr(),i);
523 filename = String(StringView(buf));
524 }
525 {
526 info() << "Writing mesh file filename='" << filename << "'";
527 bool is_bad = mesh_writer->writeMeshToFile(new_mesh, filename);
528 if (is_bad)
529 ARCANE_FATAL("Can not write mesh file '{0}'", filename);
530 }
531
532 // Fichier Correspondance
533 if (options()->createCorrespondances()){
534 info()<<"Participation to build correspondence file on sub-domain "<<i;
535
536 Int32UniqueArray taillesTab;
537 taillesTab.add(new_mesh->nodeFamily()->nbItem());
538 taillesTab.add(new_mesh->cellFamily()->nbItem());
539 Int64UniqueArray nodesUniqueId(taillesTab[0]);
540 Int64UniqueArray cellsUniqueId(taillesTab[1]);
541
542 NodeInfoListView nodes(new_mesh->nodeFamily());
543 for( int j=0; j<taillesTab[0]; ++j ){
544 Node node = nodes[j];
545 nodesUniqueId[j] = node.uniqueId();
546 }
547
548 CellInfoListView cells(new_mesh->cellFamily());
549 for( int j=0; j<taillesTab[1]; ++j ){
550 Cell cell = cells[j];
551 cellsUniqueId[j] = cell.uniqueId();
552 }
553
554 if (my_rank!=0){
555 pm->send(taillesTab, 0);
556 pm->send(nodesUniqueId, 0);
557 pm->send(cellsUniqueId, 0);
558 }
559 else {
560 _writeCorrespondance(i, nodesUniqueId, cellsUniqueId);
561 }
562 }
563 } // end i<nb_part
564
565 Integer total_new_nb_cell = pm->reduce(Parallel::ReduceSum,saved_nb_cell);
566 Integer total_min_nb_cell = pm->reduce(Parallel::ReduceMin,min_nb_cell);
567 Integer total_max_nb_cell = pm->reduce(Parallel::ReduceMax,max_nb_cell);
568 info() << "TOTAL_NEW_NB_CELL=" << total_new_nb_cell
569 << " min=" << total_min_nb_cell
570 << " max=" << total_max_nb_cell
571 << " computed_average=" << (total_current_nb_cell/nb_part);
572
573 subDomain()->timeStats()->dumpTimeAndMemoryUsage(pm);
574
575 if (options()->createCorrespondances())
577
578 if (options()->nbGhostLayer()==0)
579 if (total_new_nb_cell!=total_current_nb_cell)
580 pfatal() << "Bad number of saved cells current=" << total_current_nb_cell
581 << " saved=" << total_new_nb_cell;
582
583 pinfo()<<"Total Memory Used : "<<platform::getMemoryUsed();
584}
585
586/*---------------------------------------------------------------------------*/
587/*---------------------------------------------------------------------------*/
588
591{
592 info()<<" _initCorrespondance("<<my_rank<<")";
593
594 if (my_rank)
595 return;
596
597 m_sortiesCorrespondance.open("Correspondances");
598
599 if (m_sortiesCorrespondance.fail ()){
600 pfatal() << "Unable to write to file 'Correspondances' ";
601 }
602
603 m_sortiesCorrespondance << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
604 m_sortiesCorrespondance << "<!-- Correspondance file generated by Arcane/Decoupe3D V2 -->\n";
605 m_sortiesCorrespondance << "\n<cpus>\n";
606}
607
608/*---------------------------------------------------------------------------*/
609/*---------------------------------------------------------------------------*/
610
613{
614 info()<<" _writeCorrespondance("<<rank<<", nodesUniqueId.size() = "
615 <<nodesUniqueId.size()<<", cellsUniqueId.size() = "<<cellsUniqueId.size()<<")";
616
617 m_sortiesCorrespondance << " <cpu id=\"" << rank << "\">" << "\n"
618 << " <noeuds>" << "\n" << " ";
619 for( Integer i=0; i<nodesUniqueId.size(); ++i )
620 m_sortiesCorrespondance <<nodesUniqueId[i]<< " ";
621
622 m_sortiesCorrespondance << "\n" << " </noeuds>"
623 << "\n"
624 << " <mailles>" << "\n"
625 << " ";
626 for( Integer i=0; i<cellsUniqueId.size(); ++i )
627 m_sortiesCorrespondance <<cellsUniqueId[i]<< " ";
628 m_sortiesCorrespondance << "\n" << " </mailles>" << "\n"
629 << " </cpu>" << "\n";
630}
631
632/*---------------------------------------------------------------------------*/
633/*---------------------------------------------------------------------------*/
634
637{
638 if (my_rank)
639 return;
640
641 m_sortiesCorrespondance << "</cpus>\n";
642 m_sortiesCorrespondance.close ();
643}
644
645/*---------------------------------------------------------------------------*/
646/*---------------------------------------------------------------------------*/
661{
662 info() << "Compute groups family=" << current_family->name();
663
664 ItemGroup new_all_items = new_family->allItems();
665 Integer nb_new_item = new_all_items.size();
666
669 {
670 Integer index = 0;
672 new_items_uid[index] = (*iitem).uniqueId();
673 new_items_lid[index] = iitem.itemLocalId();
674 ++index;
675 }
676 }
678 // Détermine le localId() dans le maillage d'origine des entités
679 current_family->itemsUniqueIdToLocalId(items_lid,new_items_uid);
680
682 items_current_to_new_local_id.fill(NULL_ITEM_LOCAL_ID);
683 for( Integer i=0; i<nb_new_item; ++i )
685
688 ItemGroup group = *igroup;
689 if (group.isOwn())
690 continue;
691 if (group.isAllItems())
692 continue;
693 create_local_ids.clear();
694 ENUMERATE_ITEM(iitem,group){
695 Int32 current_uid = iitem.itemLocalId();
697 if (new_lid!=NULL_ITEM_LOCAL_ID)
699 }
700 new_family->createGroup(group.name(),create_local_ids,true);
701 }
702}
703
704/*---------------------------------------------------------------------------*/
705/*---------------------------------------------------------------------------*/
706/* \brief Ajoute au tableau de mailles le nombre de couches de mailles désiré
707 */
708void ArcaneCasePartitioner::
710 Integer nbCouches,Integer maxLocalIdCell, Integer maxLocalIdNode)
711{
712 if (nbCouches==0)
713 return;
714
716 filtre_lid_cell.fill(0);
718 filtre_lid_node.fill(0);
719
720 // on marque les mailles déjà sélectionnées
721 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
723 filtre_lid_cell[cell.localId()] = 1;
724 }
725
726 // recherhe pour tous les noeuds associés aux mailles sélectionnées une mailles reliée
727 // à ce même noeud qui ne soit pas sélectionnée
728 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
729 Cell cell = cells_selected_for_new_mesh[j];
730
731 NodeVectorView nodes = cell.nodes();
732 for( Integer k=0, ks=nodes.size(); k<ks; ++k){
733 Node node = nodes[k];
734 if (filtre_lid_node[node.localId()]==0){
735 // les mailles reliées par un noeud
736 CellVectorView cells_vois = node.cells();
737
738 for( Integer i=0, is=cells_vois.size(); i<is; ++i ){
739 Cell cell_vois = cells_vois[i];
740 if (filtre_lid_cell[cell_vois.localId()]==0){
741
742 // ajoute la maille qui n'a pas encore été vue
743 cells_selected_for_new_mesh.add(cell_vois);
744
745 filtre_lid_cell[cell_vois.localId()] = 1;
746 }
747 }
748 filtre_lid_node[node.localId()] = 1;
749 }
750 }
751 }
752
753 // pour la deuxième couche (si besoin) il est plus simple de le faire récurcivement
754 _addGhostLayers(current_all_cells, cells_selected_for_new_mesh, nbCouches-1, maxLocalIdCell, maxLocalIdNode);
755
756}
757/*---------------------------------------------------------------------------*/
758/*---------------------------------------------------------------------------*/
759/* \brief Ajoute les groupes de mailles TOUT, LOCAL et MF_* en fonctions des groupes voisins
760 * Ajoute aussi le groupe de noeuds LOCALN (mais pas les NF_*)
761 */
762void ArcaneCasePartitioner::
763_addGhostGroups(IMesh* new_mesh, Array<Cell>& cells_selected_for_new_mesh, VariableCellInt32& true_cells_owner,
764 VariableNodeInt32& true_nodes_owner,
765 Int32Array& new_cells_local_id, Integer id_loc)
766{
767 info()<<"ArcaneCasePartitioner::_addGhostGroups (id_loc = "<<id_loc<<")";
768 // il faut déterminer les groupes voisins existant
769 // on utilise un "map" pour stocker les différents sous-domaines qui apparaissent et le nombre de mailles dedans
770 std::map<Integer, Integer> dom_vois;
771 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
772 Cell cell = cells_selected_for_new_mesh[j];
773 dom_vois[true_cells_owner[cell]] += 1;
774 }
775
776 // on utilise une seconde map pour lister les mailles suivant le domaine de destination
777 std::map<Integer,SharedArray<Int32> > map_groupes;
778 for (std::map<Integer, Integer>::const_iterator iter=dom_vois.begin(); iter!=dom_vois.end(); ++iter){
779 Integer no_sous_dom = iter->first;
780 Integer nb_mailles_sous_dom = iter->second;
781
782 // réservation de la mémoire pour les différentes listes
783 Int32Array& tab = map_groupes[no_sous_dom];
784 tab.reserve(nb_mailles_sous_dom);
785 }
786
787 for( Integer j=0, js=cells_selected_for_new_mesh.size(); j<js; ++j ){
788 Cell cell = cells_selected_for_new_mesh[j];
789 Integer no_sous_dom = true_cells_owner[cell];
790
791 // remplissage des listes par sous-domaine
792 Int32Array & liste_lid = map_groupes[no_sous_dom];
793 liste_lid.add(new_cells_local_id[j]);
794 }
795
796 // création (si nécessaire) des différents groupes et on y met les mailles
797 for (std::map<Integer,SharedArray<Int32> >::iterator iter=map_groupes.begin(); iter!=map_groupes.end(); ++iter){
798 Integer no_sous_dom = iter->first;
799 Int32Array & liste_lid = iter->second;
800
801 ItemGroup groupe_loc;
802 if (no_sous_dom==id_loc)
803 groupe_loc = new_mesh->cellFamily()->findGroup("LOCAL", true);
804 else {
805 String nom_mf("MF_");
806 nom_mf = nom_mf+no_sous_dom;
807 groupe_loc = new_mesh->cellFamily()->findGroup(nom_mf, true);
808 }
809
810 groupe_loc.addItems(liste_lid, false);
811 }
812
813 // Faire le groupe LOCALN : noeuds locaux
814 {
815 // TODO: Optimiser la maniere de construire ce groupe
816 Int32UniqueArray liste_lid;
817 Integer nbnodes = new_mesh->nodeFamily()->nbItem();
818 liste_lid.reserve(nbnodes);
819 NodeInfoListView nodes(new_mesh->nodeFamily());
820 for (int j= 0 ; j < nbnodes ; ++j) {
821 Node node= nodes[j];
822 if (true_nodes_owner[node] == id_loc)
823 liste_lid.add(node.localId());
824 }
825
826 ItemGroup groupe_loc = new_mesh->nodeFamily()->findGroup("LOCALN", true);
827 groupe_loc.addItems(liste_lid, false);
828 }
829
830
831 // le groupe avec toute les mailles
832 ItemGroup groupe_glob = new_mesh->cellFamily()->findGroup("TOUT", true);
833
834 groupe_glob.addItems(new_cells_local_id, false);
835}
836/*---------------------------------------------------------------------------*/
837/*---------------------------------------------------------------------------*/
838
839ARCANE_REGISTER_SERVICE_ARCANECASEPARTITIONER(ArcaneCasePartitioner,ArcaneCasePartitioner);
840
841/*---------------------------------------------------------------------------*/
842/*---------------------------------------------------------------------------*/
843
844}
845
846/*---------------------------------------------------------------------------*/
847/*---------------------------------------------------------------------------*/
#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:120
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:513
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:515
@ IK_Cell
Entité de maillage de genre maille.
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:327
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:638
Int32 Integer
Type représentant un entier.