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