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