Arcane  v3.16.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ParallelCorefinementService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7#include "arcane/corefinement/ParallelCorefinementService.h"
8
9#include <arcane/utils/List.h>
10#include <arcane/utils/Limits.h>
11#include <arcane/utils/ITraceMng.h>
12#include <arcane/utils/ScopedPtr.h>
13
14#include <arcane/core/IItemFamily.h>
15#include <arcane/core/IMesh.h>
16#include <arcane/core/IMeshModifier.h>
17#include <arcane/core/IMeshSubMeshTransition.h>
18#include <arcane/core/IParallelMng.h>
19#include <arcane/core/ISerializeMessageList.h>
20#include <arcane/core/Timer.h>
21#include <arcane/core/internal/SerializeMessage.h>
22
23#include <arcane/core/IParallelExchanger.h>
24
25#include <set>
26#include <list>
27#include <map>
28#include <vector>
29
30#include <arcane/geometry/IGeometry.h>
31#include <arcane/geometry/IGeometryMng.h>
32#include <arcane/corefinement/surfaceutils/ISurface.h>
33
34using namespace Arcane;
35using namespace Arcane::Numerics;
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
41{
42 public:
43
45 : migrationTimer(p->subDomain(), "CorefinementMigration", Timer::TimerVirtual)
46 , corefinementTimer(p->subDomain(), "CorefinementAll", Timer::TimerVirtual)
47 {
48 ;
49 }
50
51 public:
52
53 class Box
54 {
55 public:
56
57 Box(const Real3& lower_left,
58 const Real3& upper_right,
59 const VariableNodeReal3& nodesCoordinates)
60 : m_lower_left(lower_left)
61 , m_upper_right(upper_right)
62 , m_nodes_coordinates(nodesCoordinates)
63 {}
64 bool isInside(const Real3& coord) const
65 {
66 return coord.x > m_lower_left.x and coord.y > m_lower_left.y and coord.z > m_lower_left.z and coord.x < m_upper_right.x and coord.y < m_upper_right.y and coord.z < m_upper_right.z;
67 }
68
69 bool isInside(const Face& face)
70 {
71 for (Node node : face.nodes()) {
72 // m_trace->info() << inode->localId() << " " << m_nodes_coordinates[inode] << " : " << isInside(m_nodes_coordinates[inode]);
73 if (isInside(m_nodes_coordinates[node]))
74 return true;
75 }
76 return false;
77 }
78
79 ITraceMng* m_trace;
80
81 private:
82
83 const Real3 m_lower_left, m_upper_right;
84 const VariableNodeReal3& m_nodes_coordinates;
85 };
86
88
89 class CheckCloseFaces {
90 public:
91 CheckCloseFaces(const VariableNodeReal3 & nodesCoordinates, const Real distance)
92 : m_nodes_coordinates(nodesCoordinates),
93 m_distance(distance) { }
94
95 bool operator()(const Face & faceA, const Face & faceB)
96 {
97 for (Node nodeA : faceA.nodes()) {
98 for (Node nodeB : faceB.nodes()) {
99 if (math::normeR3(m_nodes_coordinates[nodeA] - m_nodes_coordinates[nodeB]) < m_distance)
100 return true;
101 }
102 }
103 return false;
104 }
105
106 private:
107 const VariableNodeReal3 & m_nodes_coordinates;
108 const Real m_distance;
109 };
110
111 /*---------------------------------------------------------------------------*/
112 /*---------------------------------------------------------------------------*/
113
115 typedef std::pair<Integer,Integer> IntPair;
116 bool operator()(const IntPair & a, const IntPair & b) const {
117 if (a.first == b.first)
118 return a.second < b.second;
119 else
120 return a.first < b.first;
121 }
122 static IntPair order(const IntPair & p) {
123 if (p.first > p.second)
124 return IntPair(p.second,p.first);
125 else
126 return p;
127 }
128 };
129
130 static void surfaceSetup(std::map<NodeComparator::IntPair, Integer > & edges, FaceGroup group, IGeometry * geometry) {
131 typedef NodeComparator::IntPair IntPair;
132 Real3 normal(0.,0.,0.);
133 ENUMERATE_FACE(iface,group) {
134 const Face face = *iface;
135 const NodeVectorView nodes = face.nodes();
136 const Integer nnodes = nodes.size();
137 for(Integer i=0;i<nnodes;++i) {
138 const IntPair p = NodeComparator::order(IntPair(nodes[i].localId(),nodes[(i+1)%nnodes].localId()));
139 edges[p]++;
140 }
141 }
142 }
143
144 class AddEdges {
145 public:
146 void operator()(const NodeComparator::IntPair & p) {
147 const Integer indexA = mapNodes[p.first];
148 const Integer indexB = mapNodes[p.second];
149 if (not indexA and not indexB) {
150 mapNodes[p.first] = mapNodes[p.second] = newRef();
151 } else if (not indexA and indexB) {
152 mapNodes[p.first] = mapNodes[p.second];
153 } else if (indexA and not indexB) {
154 mapNodes[p.second] = mapNodes[p.first];
155 } else if (indexA and indexB) {
156 allRefs[mapNodes[p.second]-1] = allRefs[mapNodes[p.first]-1];
157 }
158 }
159
160 Integer connexCount() {
161 std::set<Integer> refSet;
162 for(Integer i=0;i<(Integer)allRefs.size();++i)
163 refSet.insert(*allRefs[i]);
164 return refSet.size();
165 }
166
167 private:
168 std::vector<std::shared_ptr<Integer> > allRefs;
169 typedef std::map<Integer,Integer> MapNodes;
170 MapNodes mapNodes;
171
172 Integer newRef() {
173 Integer ref = allRefs.size()+1; // reserve 0 pour la non-valeur
174 allRefs.push_back(std::shared_ptr<Integer>(new Integer(ref)));
175 return ref;
176 }
177 };
178
179
180 static void exchange_items(IMesh * mesh,
181 UniqueArray<std::set<Int32> > & nodes_to_send,
182 UniqueArray<std::set<Int32> > & faces_to_send,
183 UniqueArray<std::set<Int32> > & cells_to_send) {
184 ITraceMng * traceMng = mesh->traceMng();
185 if (mesh == NULL) traceMng->fatal() << "Incompatible Mesh type";
186 IParallelMng * parallel_mng = mesh->parallelMng();
187
188 ScopedPtrT<IParallelExchanger> exchanger(parallel_mng->createExchanger());
189
190 const Integer nbSubDomain = parallel_mng->commSize();
191
192 // Initialisation de l'échangeur de données
193 for(Integer isd=0;isd<nbSubDomain;++isd)
194 if (not cells_to_send[isd].empty())
195 exchanger->addSender(isd);
196 exchanger->initializeCommunicationsMessages();
197
198 for(Integer i=0, ns=exchanger->nbSender(); i<ns; ++i)
199 {
200 ISerializeMessage* sm = exchanger->messageToSend(i);
201 Int32 rank = sm->destRank();
202 ISerializer* s = sm->serializer();
203 const std::set<Int32> & cell_set = cells_to_send[rank];
204 Int32UniqueArray items_to_send(cell_set.size());
205 std::copy(cell_set.begin(), cell_set.end(), items_to_send.begin());
206 mesh->/*modifier()->*/serializeCells(s, items_to_send);
207 }
208 exchanger->processExchange();
209
210 for( Integer i=0, ns=exchanger->nbReceiver(); i<ns; ++i )
211 {
212 ISerializeMessage* sm = exchanger->messageToReceive(i);
213 ISerializer* s = sm->serializer();
214 mesh->modifier()->addCells(s);
215 }
216
217 mesh->modifier()->endUpdate(true, false); // recalcul des ghosts sans suppression des anciens
218 }
219
220 Timer migrationTimer;
221 Timer corefinementTimer;
222};
223
224/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
226
229 ArcaneParallelCorefinementObject(sbi),
230 m_internal(new Internal(this))
231{
232 ;
233}
234
235/*---------------------------------------------------------------------------*/
236
242
243/*---------------------------------------------------------------------------*/
244
245void
247init(const FaceGroup & masterGroup,
248 const FaceGroup & slaveGroup,
249 const Real boxTolerance,
250 IGeometry * geometry)
251{
252 m_master_group = masterGroup;
253 m_slave_group = slaveGroup;
254 m_box_tolerance = boxTolerance;
255 m_geometry = geometry;
256}
257
258/*---------------------------------------------------------------------------*/
259
260void
262update()
263{
264// info() << "All groups list : ";
265// ItemGroupCollection coll = mesh()->groups();
266// for(ItemGroupCollection::Iterator i=coll.begin(); i !=coll.end(); ++i) {
267// ItemGroup g = *i;
268// info() << "\tGroup : " << g.name() << " size=" << g.size();
269// }
270 m_internal->corefinementTimer.start();
271 m_internal->migrationTimer.start();
272
273 pinfo() << "Surface infos berfore migration "
274 << m_master_group.name() << "(" << m_master_group.size() << ") and "
275 << m_slave_group.name() << "(" << m_slave_group.size() << ")";
276
277 IParallelMng * parallel_mng = subDomain()->parallelMng();
278
279 // 1- Calcul des boites englobantes coté Master
280 // + Slave pour minimiser (et non eviter) de multiples composantes connexes
281 // (non supporté par le coraffinement simple)
282 const Real maxValue = FloatInfo<Real>::maxValue();
283 const VariableNodeReal3 & nodesCoordinates = PRIMARYMESH_CAST(mesh())->nodesCoordinates();
284 Real3
285 master_lower_left(maxValue,maxValue,maxValue),
286 master_upper_right(-maxValue,-maxValue,-maxValue),
287 slave_lower_left(maxValue,maxValue,maxValue),
288 slave_upper_right(-maxValue,-maxValue,-maxValue);
289
290
291 // Not optimized box computation (many nodes are min/max several times)
292 // Master BOX
293 ENUMERATE_FACE(iface,m_master_group) {
294 for (Node node : iface->nodes()) {
295 master_lower_left = math::min(master_lower_left, nodesCoordinates[node]);
296 master_upper_right = math::max(master_upper_right, nodesCoordinates[node]);
297 }
298 }
299 ENUMERATE_FACE(iface,m_slave_group) {
300 for (Node node : iface->nodes()) {
301 master_lower_left = math::min(master_lower_left, nodesCoordinates[node]);
302 master_upper_right = math::max(master_upper_right, nodesCoordinates[node]);
303 }
304 }
305
306 // Slave BOX
307 ENUMERATE_FACE(iface,m_slave_group) {
308 for (Node node : iface->nodes()) {
309 slave_lower_left = math::min(slave_lower_left, nodesCoordinates[node]);
310 slave_upper_right = math::max(slave_upper_right, nodesCoordinates[node]);
311 }
312 }
313
314 // Extend current box
315 master_lower_left.subSame(m_box_tolerance);
316 master_upper_right.addSame(m_box_tolerance);
317 slave_lower_left.subSame(m_box_tolerance);
318 slave_upper_right.addSame(m_box_tolerance);
319 debug(Trace::Medium) << "Local Box sizes :"
320 << " M= " << master_lower_left << " - " << master_upper_right
321 << " S= " << slave_lower_left << " - " << slave_upper_right;
322
323 // 2- migration des faces esclaves en fonction des boites maitres
324 // + migration des faces maitres 'utiles' vers les processeurs esclaves
325 UniqueArray<Real3> myBox;
326 myBox.add(master_lower_left);
327 myBox.add(master_upper_right);
328 myBox.add(slave_lower_left);
329 myBox.add(slave_upper_right);
330
331 const Integer nbSubDomain = subDomain()->nbSubDomain();
332 UniqueArray<Real3> allBoxes(4*nbSubDomain);
333 parallel_mng->allGather(myBox,allBoxes);
334
335 // NB: ne traite pas les aretes.
336 // exchangers utilisés en mode slave->master puis master->slave
337 UniqueArray<std::set<Int32> > nodes_to_send; nodes_to_send.resize(nbSubDomain);
338 UniqueArray<std::set<Int32> > faces_to_send; faces_to_send.resize(nbSubDomain);
339 UniqueArray<std::set<Int32> > cells_to_send; cells_to_send.resize(nbSubDomain);
340
341 // On peut optimiser les calculs d'inclusion en ayant déjà la boite englobante locale
342 // Si pas d'intersection des boites locale et distante => rien à faire.
343#ifndef NO_USER_WARNING
344#warning "optimisations possibles"
345#endif /* NO_USER_WARNING */
346 for(Integer i_sub_domain=0; i_sub_domain<nbSubDomain;++i_sub_domain) {
347 if (i_sub_domain == subDomain()->subDomainId()) continue;
348 Internal::Box masterBox(allBoxes[4*i_sub_domain],allBoxes[4*i_sub_domain+1],nodesCoordinates);
349 masterBox.m_trace = traceMng();
350 ENUMERATE_FACE(iface,m_slave_group) {
351 if (masterBox.isInside(*iface)) {
352 faces_to_send[i_sub_domain].insert(iface->localId());
353 Cell boundaryCell = iface->boundaryCell();
354 if (boundaryCell.null())
355 fatal() << "Non boundary face used in co-refinement";
356 cells_to_send[i_sub_domain].insert(boundaryCell.localId());
357 for (Node node : boundaryCell.nodes())
358 nodes_to_send[i_sub_domain].insert(node.localId());
359 }
360 }
361
362 Internal::Box slaveBox(allBoxes[4*i_sub_domain+2],allBoxes[4*i_sub_domain+3],nodesCoordinates);
363 slaveBox.m_trace = traceMng();
364 ENUMERATE_FACE(iface,m_master_group) {
365 if (masterBox.isInside(*iface)) {
366 faces_to_send[i_sub_domain].insert(iface->localId());
367 Cell boundaryCell = iface->boundaryCell();
368 if (boundaryCell.null())
369 fatal() << "Non boundary face used in co-refinement";
370 cells_to_send[i_sub_domain].insert(boundaryCell.localId());
371 for (Node node : boundaryCell.nodes())
372 nodes_to_send[i_sub_domain].insert(node.localId());
373 }
374 }
375 }
376
377 Internal::exchange_items(mesh(),nodes_to_send,faces_to_send,cells_to_send);
378
379 debug(Trace::Medium) << "Surface infos after migration "
380 << m_master_group.name() << "(" << m_master_group.size() << ") and "
381 << m_slave_group.name() << "(" << m_slave_group.size() << ")";
382
383 m_internal->migrationTimer.stop();
384
385 // 3- Calcul des composantes connexes
386 // On vérifie pour l'instant que localement nous n'avons qu'une composante connexe.
387 // Pour cela, on vérifie que le bord des surfaces ne forment qu'une courbe
388
389 // Choix des surfaces pour le co-raffinement local
390 FaceGroup slave_coref_group = m_slave_group;
391 FaceGroup master_coref_group = m_master_group;
392
393 typedef Internal::NodeComparator::IntPair IntPair;
394 std::map<IntPair, Integer > slave_edges; // paires des sommets indexés par leurs localIds
395 std::map<IntPair, Integer > master_edges; // paires des sommets indexés par leurs localIds
396 Internal::surfaceSetup(slave_edges,slave_coref_group,m_geometry);
397 Internal::surfaceSetup(master_edges,master_coref_group,m_geometry);
398
399 {
400 Internal::AddEdges addEdges;
401 for(std::map<IntPair, Integer>::iterator i=slave_edges.begin(); i!=slave_edges.end(); ++i)
402 if (i->second == 1)
403 addEdges(i->first);
404 else if (i->second > 2)
405 fatal() << "Not manifold slave surface";
406 if (addEdges.connexCount() > 1)
407 fatal() << "Slave surface is not connex";
408 }
409 {
410 Internal::AddEdges addEdges;
411 for(std::map<IntPair, Integer>::iterator i=master_edges.begin(); i!=master_edges.end(); ++i)
412 if (i->second == 1)
413 addEdges(i->first);
414 else if (i->second > 2)
415 fatal() << "Not manifold master surface";
416 if (addEdges.connexCount() > 1)
417 fatal() << "Master surface is not connex";
418 }
419
420 // 4- Calcul du co-raffinement par composantes connexes
421 // Actuellement une seule composante par surface
422 // A partir de cette étape si modif de maillage le résultat du coraffinement est invalidé
423 // car une renumérotation des items locaux est possible
424
425 ISurfaceUtils * surfaceUtils = options()->surfaceUtils();
426 ISurface * masterSurface = surfaceUtils->createSurface();
427 surfaceUtils->setFaceToSurface(masterSurface,master_coref_group);
428 ISurface * slaveSurface = surfaceUtils->createSurface();
429 surfaceUtils->setFaceToSurface(slaveSurface,slave_coref_group);
430
431 FaceFaceContactList coarse_contacts;
432 surfaceUtils->computeSurfaceContact(masterSurface,slaveSurface,coarse_contacts);
433
434// { // test d'intégrité du co-raffinement local
435// Real3 normalA_coref(0,0,0), normalA_local(0,0,0);
436// Real3 normalB_coref(0,0,0), normalB_local(0,0,0);
437
438// ENUMERATE_FACE(iface,m_master_group.own())
439// normalA_local += m_geometry->computeOrientedMeasure(*iface);
440// ENUMERATE_FACE(iface,m_slave_group.own())
441// normalB_local += m_geometry->computeOrientedMeasure(*iface);
442
443// for(Integer i=0; i<coarse_contacts.size(); ++i) {
444// const ISurfaceUtils::FaceFaceContact & contact = coarse_contacts[i];
445// if (not contact.faceA.null() and contact.faceA.isOwn())
446// normalA_coref += contact.normalA;
447// if (not contact.faceB.null() and contact.faceB.isOwn())
448// normalB_coref += contact.normalB;
449// }
450// pinfo() << "Global co-refinement stats0 : "
451// << math::normeR3(normalA_coref) << " vs " << math::normeR3(normalA_local) << " ; "
452// << math::normeR3(normalB_coref) << " vs " << math::normeR3(normalB_local);
453// }
454
455#ifndef NO_USER_WARNING
456#warning "utiliser un destroySurface ???"
457#endif /* NO_USER_WARNING */
458 delete masterSurface;
459 delete slaveSurface;
460
461 // 5- Filtrage des contacts par la distance de leurs 2 faces
462 // et diffusion des faces maitres utiles coté esclave.
463 m_contacts.clear();
464
465 // Enregistrement des besoins de raffinement pour des void-face
466 ItemInternalList internals = mesh()->faceFamily()->itemsInternal();
467 // La clef des SharedCorefinement est en référence à l'internals précédent
468 typedef std::map<Integer,Real3> SharedCorefinement;
469 SharedCorefinement voidface_shared_corefinement;
470 ARCANE_ASSERT(( coarse_contacts.empty() == master_coref_group.empty() ),("Incompatible emptyness"));
471
472 if (coarse_contacts.empty())
473 {
474 ENUMERATE_FACE(iface,m_slave_group.own()) {
475 voidface_shared_corefinement[iface->localId()];
476 }
477 }
478 else
479 {
480 Internal::CheckCloseFaces checkFaces(nodesCoordinates,m_box_tolerance);
481 SharedCorefinement facevoid_shared_corefinement; // pour aggregation sur le master
482 for(FaceFaceContactList::iterator i = coarse_contacts.begin(); i != coarse_contacts.end(); ++i) {
483 const ISurfaceUtils::FaceFaceContact & contact = *i;
484 const Face master_face = contact.faceA;
485 const Face slave_face = contact.faceB;
486 if (slave_face.null()) {
487 if (master_face.isOwn()) {
488 facevoid_shared_corefinement[master_face.localId()] += contact.normalA;
489 } // else not use since non local
490 } else if (master_face.null()) {
491 if (slave_face.isOwn()) {
492 // Cette face doit etre post-traitée en parallèle
493 voidface_shared_corefinement[slave_face.localId()];
494 } // else not use since non local
495 } else if (master_face.isOwn() or slave_face.isOwn()) {
496 if (checkFaces(master_face,slave_face)) {
497 // Distance compatible avec la sélection de la boite
498 // Contact admissible (stockage + préparation pour diffusion)
499 if (master_face.isOwn()) // si !master_face.isOwn() il recevra l'info par son owner
500 m_contacts.add(contact);
501 } else {
502 // Complétion du co-raffinement du non-contact
503 if (master_face.isOwn()) {
504 facevoid_shared_corefinement[master_face.localId()] += contact.normalA;
505 }
506 if (slave_face.isOwn()) {
507 voidface_shared_corefinement[slave_face.localId()];
508 }
509 }
510 }
511 }
512
513 // Intégration des face-void aggrégés
514 for(SharedCorefinement::const_iterator i=facevoid_shared_corefinement.begin();
515 i != facevoid_shared_corefinement.end(); ++i) {
516 Face faceA(internals[i->first]);
517 Face faceB; // null
518 ARCANE_ASSERT((faceA.isOwn()),("Non local facevoid"));
519 ISurfaceUtils::FaceFaceContact contact(faceA,faceB);
520 contact.normalA = i->second;
521 // info() << "Global co-refinement info : facevoid add " << faceA.uniqueId() << " " << contact.normalA;
522 m_contacts.add(contact);
523 }
524 }
525
526 // 6- Sérialisation des données vers les esclaves; préparation de la synthèse void-face
527
528 // Compatibilité des données à envoyer
529 // Comptabilise des sous-faces bi-parent (faceface)
530 UniqueArray<Integer> info_to_send(nbSubDomain,0);
531 for(FaceFaceContactList::iterator i = m_contacts.begin(); i != m_contacts.end(); ++i)
532 {
533 const ISurfaceUtils::FaceFaceContact & contact = *i;
534 const Face master_face = contact.faceA;
535 const Face slave_face = contact.faceB;
536 if (not slave_face.null()) {
537 ARCANE_ASSERT((not master_face.null()),("Integrity error")); // pas construction du remplissage de m_contacts
538 if (slave_face.isOwn()) {
539 if (master_face.isOwn()) {
540 // Traitement local des void-faces
541 SharedCorefinement::iterator vf_finder = voidface_shared_corefinement.find(slave_face.localId());
542 if (vf_finder != voidface_shared_corefinement.end()) {
543 vf_finder->second += contact.normalB;
544 // info() << "Global co-ref Voidface add1 to slave " << slave_face.uniqueId() << " " << contact.normalB << " from " << master_face.uniqueId() << " " << contact.normalA;
545 }
546 }
547 } else { // has to be sent
548 if (master_face.isOwn())
549 ++info_to_send[slave_face.owner()];
550 }
551 }
552 }
553
554 // Liste de synthèse des messages (emissions / réceptions)
555 ISerializeMessageList * messageList = NULL;
556 if (parallel_mng->isParallel())
557 messageList = parallel_mng->createSerializeMessageList();
558
559 // Préparation de la réception
560 UniqueArray<Integer> info_to_recv(nbSubDomain,0);
561 parallel_mng->allToAll(info_to_send,info_to_recv,1);
562 std::list<std::shared_ptr<SerializeMessage> > recv_messages;
563 for(Integer i=0;i<nbSubDomain;++i)
564 {
565 if (info_to_recv[i] > 0)
566 {
567 SerializeMessage * message = new SerializeMessage(parallel_mng->commRank(),i,ISerializeMessage::MT_Recv);
568 recv_messages.push_back(std::shared_ptr<SerializeMessage>(message));
569 messageList->addMessage(message);
570 }
571 }
572
573 // Préparation des émissions
574 UniqueArray<std::shared_ptr<SerializeMessage> > sent_messages(nbSubDomain);
575 for(Integer i=0;i<nbSubDomain;++i)
576 {
577 const Integer faceface_info_to_send = info_to_send[i];
578 if (faceface_info_to_send > 0)
579 {
580 SerializeMessage * message = new SerializeMessage(parallel_mng->commRank(),i,ISerializeMessage::MT_Send);
581 sent_messages[i].reset(message);
582 messageList->addMessage(message);
583 SerializeBuffer & sbuf = message->buffer();
584 sbuf.setMode(ISerializer::ModeReserve); // phase préparatoire
585 sbuf.reserveInteger(2); // Nb d'item faceface puis voidface
586 sbuf.reserve(DT_Int64,2*faceface_info_to_send); // Les uid
587 sbuf.reserve(DT_Real,6*faceface_info_to_send); // Les normales (rien pour voidface)
588 sbuf.reserve(DT_Real,6*faceface_info_to_send); // Les centres (rien pour voidface)
589 sbuf.allocateBuffer(); // allocation mémoire
591 sbuf.putInteger(faceface_info_to_send);
592 }
593 }
594
595 // Remplissage des messages sortants
596 for(FaceFaceContactList::iterator i = m_contacts.begin(); i != m_contacts.end(); ++i)
597 {
598 const ISurfaceUtils::FaceFaceContact & contact = *i;
599 const Face master_face = contact.faceA;
600 const Face slave_face = contact.faceB;
601 if (not slave_face.null() and not slave_face.isOwn() and master_face.isOwn())
602 {
603 std::shared_ptr<SerializeMessage> message = sent_messages[slave_face.owner()];
604 SerializeBuffer & sbuf = message->buffer();
605 // Pas possible de mettre des Real3 ??? (meme si on peut les réserver)
606 sbuf.put(master_face.uniqueId().asInt64());
607 sbuf.putReal(contact.normalA.x); sbuf.putReal(contact.normalA.y); sbuf.putReal(contact.normalA.z);
608 sbuf.putReal(contact.centerA.x); sbuf.putReal(contact.centerA.y); sbuf.putReal(contact.centerA.z);
609 sbuf.put(slave_face.uniqueId().asInt64());
610 sbuf.putReal(contact.normalB.x); sbuf.putReal(contact.normalB.y); sbuf.putReal(contact.normalB.z);
611 sbuf.putReal(contact.centerB.x); sbuf.putReal(contact.centerB.y); sbuf.putReal(contact.centerB.z);
612
613 // pinfo() << "Global co-ref " << parallel_mng->commRank() << " push to "
614 // << slave_face.owner() << " " << master_face.uniqueId() << " - " << slave_face.uniqueId()
615 // << " : " << contact.normalA << " " << contact.normalB;
616 }
617 }
618
619 // Traitement des communications
620 if (messageList) {
621 messageList->processPendingMessages();
622 messageList->waitMessages(Parallel::WaitAll);
623 delete messageList; messageList = NULL; // Destruction propre
624 }
625
626 // Traitement des messages reçus
627 for(std::list<std::shared_ptr<SerializeMessage> >::iterator i=recv_messages.begin(); i!=recv_messages.end(); ++i)
628 {
629 std::shared_ptr<SerializeMessage> & message = *i;
630 const Integer origDomainId = message->destRank();
631 ARCANE_ASSERT((origDomainId != subDomain()->subDomainId()),("Local to local sent"));
632 SerializeBuffer& sbuf = message->buffer();
634 const Integer faceface_count = sbuf.getInteger();
635 ARCANE_ASSERT((faceface_count == info_to_recv[origDomainId]),("Bad recv faceface count"));
636 Int64UniqueArray uids(2*faceface_count);
637 Int32UniqueArray lids(2*faceface_count);
638 sbuf.get(uids);
639 mesh()->faceFamily()->itemsUniqueIdToLocalId(lids,uids,true);
640
641 // Traitement des pairs face-face
642 for(Integer j=0;j<faceface_count;++j)
643 {
644 Face faceA(internals[lids[2*j ]]);
645 Face faceB(internals[lids[2*j+1]]);
646 ARCANE_ASSERT((faceB.isOwn()),("Not local information recieved"));
647 ISurfaceUtils::FaceFaceContact contact(faceA,faceB);
648 contact.normalA.x = sbuf.getReal(); contact.normalA.y = sbuf.getReal(); contact.normalA.z = sbuf.getReal();
649 contact.centerA.x = sbuf.getReal(); contact.centerA.y = sbuf.getReal(); contact.centerA.z = sbuf.getReal();
650 contact.normalB.x = sbuf.getReal(); contact.normalB.y = sbuf.getReal(); contact.normalB.z = sbuf.getReal();
651 contact.centerB.x = sbuf.getReal(); contact.centerB.y = sbuf.getReal(); contact.centerB.z = sbuf.getReal();
652 m_contacts.add(contact);
653
654 SharedCorefinement::iterator vf_finder = voidface_shared_corefinement.find(faceB.localId());
655 if (vf_finder != voidface_shared_corefinement.end()) {
656 vf_finder->second += contact.normalB;
657 // info() << "Global co-ref Voidface add2 to slave " << faceB.uniqueId() << " " << contact.normalB << " from " << faceA.uniqueId() << " " << contact.normalA;
658 }
659 }
660 }
661
662 // 7- Traitement final des pairs void-face
663 for(SharedCorefinement::const_iterator i=voidface_shared_corefinement.begin();
664 i != voidface_shared_corefinement.end(); ++i) {
665 Face faceA; // null
666 Face faceB(internals[i->first]);
667 ARCANE_ASSERT((faceB.isOwn()),("Non local voidface"));
668 Real3 faceB_normal = m_geometry->computeOrientedMeasure(faceB);
669 Real faceB_area = math::normeR3(faceB_normal);
670 if (math::normeR3(i->second) < faceB_area) {
671 ISurfaceUtils::FaceFaceContact contact(faceA,faceB);
672 contact.normalB = faceB_normal - i->second;
673 // info() << "Global co-refinement info : voidface add " << faceB.uniqueId() << " " << contact.normalB << " " << faceB_normal;
674 m_contacts.add(contact);
675 }
676 }
677
678 // 8- Nettoyage des réplicats inutiles
679 // Non implémentés et ATTN cela peut modifier les numérotations locales
680
681 m_internal->corefinementTimer.stop();
682
683 UniqueArray<Real> times(2);
684 times[0] = m_internal->corefinementTimer.totalTime();
685 times[1] = m_internal->migrationTimer.totalTime();
686 parallel_mng->reduce(Parallel::ReduceMin,times);
687 info() << "Corefinement timers : all=" << times[0] << " migration=" << times[1] << " #domains=" << parallel_mng->commSize();
688}
689
690/*---------------------------------------------------------------------------*/
691
692const IParallelCorefinement::FaceFaceContactList &
694contacts()
695{
696 return m_contacts;
697}
698
699/*---------------------------------------------------------------------------*/
700/*---------------------------------------------------------------------------*/
701
702ARCANE_REGISTER_SERVICE_PARALLELCOREFINEMENT(ParallelCorefinement,ParallelCorefinementService);
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
void put(Span< const Real > values) override
Ajoute le tableau values.
Real getReal() override
Récupère un réel.
void reserve(eBasicDataType dt, Int64 n) override
Réserve de la mémoire pour n objets de type dt.
void allocateBuffer() override
Alloue la mémoire du sérialiseur.
Integer getInteger() override
Récupère une taille.
void get(ArrayView< Real > values) override
Récupère le tableau values.
void setMode(eMode new_mode) override
Positionne le fonctionnement actuel.
void putReal(Real value) override
Ajoute le réel value.
void putInteger(Integer value) override
Ajoute l'entier value.
Maille d'un maillage.
Definition Item.h:1191
Face d'une maille.
Definition Item.h:944
Informations sur le type flottant.
Definition Limits.h:48
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual ISerializeMessageList * createSerializeMessageList()=0
Créé une liste pour gérer les 'ISerializeMessage'.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Effectue un regroupement sur tous les processeurs. Il s'agit d'une opération collective....
virtual IParallelExchanger * createExchanger()=0
Retourne une interface pour transférer des messages entre processeurs.
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.
@ ModePut
Le sérialiseur attend des reserve()
virtual void setFaceToSurface(ISurface *surface, FaceGroup face_group)=0
Définit les faces d'une surface.
virtual ISurface * createSurface()=0
Création d'une nouvelle surface.
virtual void computeSurfaceContact(ISurface *surface1, ISurface *surface2, FaceFaceContactList &contact)=0
compute for each face of surface1 the nearest face of surface2
Purely virtual interface for surface representation.
Definition ISurface.h:25
Interface du gestionnaire de traces.
virtual TraceMessage fatal()=0
Flot pour un message d'erreur fatale.
bool empty() const
Teste si le groupe est vide.
Definition ItemGroup.h:102
Int32 size() const
Nombre d'éléments du vecteur.
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:782
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
bool isOwn() const
true si l'entité est appartient au sous-domaine
Definition Item.h:253
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Definition Item.h:216
virtual void processPendingMessages()=0
Envoie les messages de la liste qui ne l'ont pas encore été.
virtual Integer waitMessages(eWaitType wt)=0
Attend que les messages aient terminé leur exécution.
virtual void addMessage(ISerializeMessage *msg)=0
Ajoute un message à la liste.
Interface d'un message de sérialisation entre IMessagePassingMng.
virtual Int32 destRank() const =0
Rang du destinataire (si isSend() est vrai) ou envoyeur.
virtual ISerializer * serializer()=0
Sérialiseur.
Noeud d'un maillage.
Definition Item.h:573
Interface de calculs géométriques.
Definition IGeometry.h:25
void init(const FaceGroup &masterGroup, const FaceGroup &slaveGroup, const Real boxTolerance, IGeometry *geometry)
Initialisation.
ParallelCorefinementService(const Arcane::ServiceBuildInfo &sbi)
const FaceFaceContactList & contacts()
Access to computed contacts.
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
constexpr __host__ __device__ Real3 & add(Real3 b)
Ajoute b au triplet.
Definition Real3.h:234
constexpr __host__ __device__ Real3 & addSame(Real b)
Ajoute b à chaque composante du triplet.
Definition Real3.h:266
Encapsulation d'un pointeur qui se détruit automatiquement.
Definition ScopedPtr.h:44
Implémentation d'un tampon pour la sérialisation.
Message utilisant un SerializeBuffer.
Structure contenant les informations pour créer un service.
Gestion d'un timer.
Definition Timer.h:62
@ TimerVirtual
Timer utilisant le temps CPU (obsolète).
Definition Timer.h:74
Vecteur 1D de données avec sémantique par valeur (style STL).
__host__ __device__ Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
Definition MathUtils.h:336
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:392
ItemVectorViewT< Node > NodeVectorView
Vue sur un vecteur de noeuds.
Definition ItemTypes.h:289
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
@ ReduceMin
Minimum des valeurs.
Real normeR3(Real3 v1)
Norme d'un vecteur.
Definition MathUtils.h:653
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:426
Int32 Integer
Type représentant un entier.
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:428
double Real
Type représentant un réel.
@ DT_Int64
Donnée de type entier 64 bits.
Definition DataTypes.h:44
@ DT_Real
Donnée de type réel.
Definition DataTypes.h:41
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