Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ParallelAMRConsistency.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* ParallelAMRConsistency.cc (C) 2000-2024 */
9/* */
10/* Parallel consistency of node/face UIDs in the AMR case */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/HashTableMap.h"
15#include "arcane/utils/Real3.h"
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/ITraceMng.h"
19#include "arcane/utils/Collection.h"
20
21#include "arcane/mesh/DynamicMesh.h"
22#include "arcane/mesh/FaceFamily.h"
23#include "arcane/mesh/MapCoordToUid.h"
24#include "arcane/mesh/ParallelAMRConsistency.h"
25
26#include "arcane/core/IMesh.h"
27#include "arcane/core/IMeshSubMeshTransition.h"
29#include "arcane/core/ItemGroup.h"
30#include "arcane/core/Item.h"
31#include "arcane/core/ISubDomain.h"
32#include "arcane/core/VariableTypes.h"
33#include "arcane/core/IItemFamily.h"
34#include "arcane/core/ItemCompare.h"
35#include "arcane/core/IParallelMng.h"
36#include "arcane/core/GeometricUtilities.h"
37#include "arcane/core/SerializeBuffer.h"
38#include "arcane/core/ItemPrinter.h"
39#include "arcane/core/IMeshUtilities.h"
40
41#include <set>
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
46namespace Arcane::mesh
47{
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
52
53#ifdef ACTIVATE_PERF_COUNTER
54const std::string ParallelAMRConsistency::PerfCounter::m_names[ParallelAMRConsistency::PerfCounter::NbCounters] = {
55 "INIT",
56 "COMPUTE",
57 "GATHERFACE",
58 "UPDATE",
59 "REHASH",
60 "ENDUPDATE"
61};
62#endif
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
70, m_mesh(mesh)
71, m_nodes_coord(m_mesh->toPrimaryMesh()->nodesCoordinates())
72, m_nodes_info(1000, true)
73, m_active_nodes(1000, true)
74, m_active_faces(5000, true)
75, m_active_faces2(5000, true)
76, m_is_updated(false)
77{
78 ;
79}
80
81/*---------------------------------------------------------------------------*/
82/*---------------------------------------------------------------------------*/
83
84void ParallelAMRConsistency::
85init()
86{
87 CHECKPERF(m_perf_counter.start(PerfCounter::INIT))
88 // Marks nodes on the boundary
89 Integer nb_active_face = static_cast<Integer>(m_mesh->nbFace() * 0.2); // 20% of shared faces (estimated)
90 m_shared_face_uids.reserve(nb_active_face);
91 m_shared_face_uids.clear();
92 m_connected_shared_face_uids.reserve(nb_active_face);
93 m_connected_shared_face_uids.clear();
94 Integer sid = m_mesh->parallelMng()->commRank();
95 ENUMERATE_FACE (iface, m_mesh->allFaces()) {
96 Face face = *iface;
97 ItemUniqueId face_uid = face.uniqueId();
98 int face_flags = face.itemBase().flags();
99 if (face.nbCell() == 2 && (face.cell(0).level() == 0 && face.cell(1).level() == 0)) {
100 if ((face.cell(0).owner() != sid || face.cell(1).owner() != sid) ||
101 (face_flags & ItemFlags::II_Shared) ||
102 (face_flags & ItemFlags::II_SubDomainBoundary)) {
103 m_shared_face_uids.add(face_uid);
104 }
105 else if (_hasSharedNodes(face)) {
106 m_connected_shared_face_uids.add(face_uid);
107 }
108 }
109 else if (face.nbCell() == 1 && face.cell(0).level() == 0) {
110 if (_hasSharedNodes(face)) {
111 m_connected_shared_face_uids.add(face_uid);
112 }
113 }
114 }
115 m_is_updated = true;
116
117 CHECKPERF(m_perf_counter.stop(PerfCounter::INIT))
118}
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121/*---------------------------------------------------------------------------*/
122/*---------------------------------------------------------------------------*/
123
124void ParallelAMRConsistency::
125_addFaceToList(Face face, FaceInfoMap& face_map)
126{
127 Integer nb_node = face.nbNode();
128 Real3 center(0., 0., 0.);
129 Integer data_index = m_face_info_mng.size();
130 for (Node node : face.nodes()) {
131 Real3 node_coord = m_nodes_coord[node];
132 ItemUniqueId uid = node.uniqueId();
133 m_face_info_mng.add(uid);
134 center += node_coord;
135 }
136 center /= nb_node;
137 //info() << "ADD FACE uid=" << face.uniqueId() << " nb_node="
138 //<< nb_node << " center=" << center;
139 FaceInfo fi(face.uniqueId(), face.cell(0).uniqueId(), nb_node, face.owner(), data_index, &m_face_info_mng);
140 fi.setCenter(center);
141 face_map.add(face.uniqueId(), fi);
142}
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
147bool ParallelAMRConsistency::
148_hasSharedNodes(Face face)
149{
150 //CHECK that one edge is connected to a ghost cell
151 for (Node node : face.nodes()) {
152 if (node.itemBase().flags() & ItemFlags::II_Shared)
153 return true;
154 }
155 return false;
156}
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
168{
169 CHECKPERF(m_perf_counter.start(PerfCounter::COMPUTE))
170 //UniqueArray<ItemInternal*> active_faces;
171 // Marks nodes on the boundary
172 Integer nb_active_face = static_cast<Integer>(m_mesh->nbFace() * 0.2); // 20% of shared faces (estimated)
173
174 m_nodes_info.resize((nb_active_face * 2) + 5);
175 m_nodes_info.clear();
176 ENUMERATE_NODE (i_item, m_mesh->allNodes()) {
177 Real3 node_coord = m_nodes_coord[i_item];
178 ItemUniqueId uid = i_item->uniqueId();
179 NodeInfo node_info(uid, i_item->owner());
180 node_info.setCoord(node_coord);
181 m_nodes_info.add(uid, node_info);
182 }
183
184 m_active_faces.resize((nb_active_face * 2) + 5);
185 m_active_nodes.resize((nb_active_face * 2) + 5);
186 m_active_faces.clear();
187 m_face_info_mng.m_nodes_unique_id.clear();
188 m_face_info_mng.m_nodes_unique_id.reserve(nb_active_face);
189
190 FaceFamily* true_face_family = dynamic_cast<FaceFamily*>(m_mesh->faceFamily());
191 if (!true_face_family)
192 ARCANE_FATAL("can not obtain FaceFamily");
193
194 Int32 sid = m_mesh->parallelMng()->commRank();
195 //UniqueArray<ItemInternal*> active_faces;
196 ItemMap active_faces;
197 UniqueArray<ItemUniqueId> active_faces_to_send;
198 typedef std::set<ItemInternal*> Set;
199 Set active_nodes_set;
200 ItemMap active_nodes;
201 // Iterates over faces and marks active boundary nodes
202 DynamicMesh* mesh = dynamic_cast<DynamicMesh*>(m_mesh);
203 if (!mesh)
204 throw FatalErrorException(A_FUNCINFO, "can not obtain DynamicMesh");
205 ItemInternalMap& faces_map = mesh->facesMap();
206
207 for (Integer iface = 0; iface < m_shared_face_uids.size(); ++iface) {
208 Int64 face_uid = m_shared_face_uids[iface];
209 Face face = faces_map.findItem(face_uid);
210 {
212 true_face_family->allSubFaces(face, subfaces);
213 if (subfaces.size() != 1) {
214 for (Integer s = 0; s < subfaces.size(); s++) {
215 Face face2 = subfaces[s];
217 Int64 uid = face2.uniqueId();
218 bool face_to_send = face_finder.isNewUid(uid);
219 if (face_to_send) {
220 _addFaceToList(face2, m_active_faces);
221
222 //active_faces.add(face2);
223 active_faces.insert(ItemMapValue(uid, face2));
224 active_faces_to_send.add(ItemUniqueId(uid));
225 for (Node node : face2.nodes()) {
226 node.mutableItemBase().addFlags(ItemFlags::II_Shared | ItemFlags::II_SubDomainBoundary);
227 active_nodes.insert(ItemMapValue(node.uniqueId(), node));
228 }
229 for (Edge edge : face2.edges()) {
230 edge.mutableItemBase().addFlags(ItemFlags::II_Shared | ItemFlags::II_SubDomainBoundary);
231 }
232 }
233 }
234 }
235 }
236 }
237 for (Integer iface = 0; iface < m_connected_shared_face_uids.size(); ++iface) {
238 Int64 face_uid = m_connected_shared_face_uids[iface];
239 Face face(faces_map.findItem(face_uid));
240
241 {
242 Integer nb_node = face.nbNode();
243 typedef std::pair<Real3, Real3> Edge;
244 UniqueArray<Edge> edges;
245 edges.reserve(nb_node);
246 for (Integer i = 0; i < nb_node; ++i) {
247 Integer next = i == nb_node - 1 ? 0 : i + 1;
248 Node node1 = face.node(i);
249 Node node2 = face.node(next);
252 edges.add(Edge(m_nodes_coord[node1], m_nodes_coord[node2] - m_nodes_coord[node1]));
253 }
254 }
256 true_face_family->allSubFaces(face, subfaces);
257 for (Integer s = 0; s < subfaces.size(); s++) {
258 Face face2(subfaces[s]);
259 Int64 uid = face2.uniqueId();
260 bool face_to_send = face_finder.isNewUid(uid);
261 if (face_to_send) {
262 Integer nb_node2 = face2.nbNode();
263 for (Integer i = 0; i < nb_node2; ++i) {
264 Node node_i = face2.node(i);
265 Real3 Xi = m_nodes_coord[node_i];
266 for (Integer j = 0; j < edges.size(); ++j) {
267 Real3 n = Xi - edges[j].first;
268 Real sinteta = math::cross(edges[j].second, n).squareNormL2();
269 if (math::isZero(sinteta)) {
271 //active_nodes_set.insert(node_i);
272 active_nodes.insert(ItemMapValue(node_i.uniqueId(), node_i));
273 _addNodeToList(node_i, m_active_nodes);
274 }
275 }
276 }
277 }
278 }
279 }
280 }
281
282 UniqueArray<ItemUniqueId> active_nodes_to_send(arcaneCheckArraySize(active_nodes.size()));
283 ItemMap::const_iterator nit(active_nodes.begin()), nend(active_nodes.end());
284 for (int i = 0; nit != nend; ++nit, ++i) {
285 Item node = nit->second;
286 active_nodes_to_send[i] = node.uniqueId();
287 //active_nodes.insert(ItemMapValue(uid,node)) ;
288 }
289 CHECKPERF(m_perf_counter.stop(PerfCounter::COMPUTE))
290
291 //CHECKPERF( m_perf_counter.start(PerfCounter::GATHERFACE) )
292 ItemUidSet update_face_uids;
293 ItemUidSet update_node_uids;
294 _gatherFaces(active_faces_to_send, active_nodes_to_send, m_active_faces, node_finder, face_finder, update_face_uids, update_node_uids);
295 //CHECKPERF( m_perf_counter.stop(PerfCounter::GATHERFACE) )
296
297 CHECKPERF(m_perf_counter.start(PerfCounter::UPDATE))
298 //UPDATE FACES
299 //for (Integer index = 0; index < active_faces.size(); index++)
300 for (ItemUidSet::iterator iter = update_face_uids.begin(); iter != update_face_uids.end(); ++iter) {
301 Int64 face_uid = *iter;
302 Item face = active_faces[face_uid];
303 //const Int64 current_uid = face->uniqueId();
304 FaceInfo& fi = m_active_faces[face.uniqueId()];
305 Int64 new_uid = fi.uniqueId();
306 faces_map.remove(face_uid);
307 //if (current_uid != fi.uniqueId())
308 ARCANE_ASSERT((face_uid != new_uid), ("AMR CONSISTENCY UPDATE FACE ERROR"));
309 face.mutableItemBase().setUniqueId(fi.uniqueId());
310 face.mutableItemBase().setOwner(fi.owner(), sid);
311 //debug() << "[\t ParallelAMRConsistency] NEW FACE BEFORE " << face->uniqueId()<<" new uid "<<fi.uniqueId() << " " << fi.owner();
312 faces_map.add(new_uid, ItemCompatibility::_itemInternal(face));
313 }
314
315 //UPDATE NODES
316 //ENUMERATE_NODE(i_item,m_mesh->allNodes())
317 ItemInternalMap& nodes_map = mesh->nodesMap();
318 for (ItemUidSet::iterator iter = update_node_uids.begin(); iter != update_node_uids.end(); ++iter) {
319 //ItemInternal* node = i_item->internal() ;
320 Int64 node_uid = *iter;
321 Item node = active_nodes[node_uid];
322 if (node.null())
323 ARCANE_FATAL("AMR CONSISTENCY NULL NODE ERROR");
324 //const Int64 node_uid = node->uniqueId();
325 NodeInfo ni = m_nodes_info[node.uniqueId()];
326 Int64 new_uid = ni.uniqueId();
327 //if (node_uid != ni.uniqueId())
328 ARCANE_ASSERT((node_uid != new_uid), ("AMR CONSISTENCY UPDATE NODE ERROR"));
329 //debug() << "[\t ParallelAMRConsistency] OLD NEW NODE " << node_uid << " " << ni.uniqueId()<<" owner "<<ni.owner();
330 nodes_map.remove(node_uid);
331 node.mutableItemBase().setUniqueId(ni.uniqueId());
332 node.mutableItemBase().setOwner(ni.owner(), sid);
334 nodes_map.add(new_uid, ItemCompatibility::_itemInternal(node));
335 }
336 CHECKPERF(m_perf_counter.stop(PerfCounter::UPDATE))
337
338 CHECKPERF(m_perf_counter.start(PerfCounter::ENDUPDATE))
339 m_mesh->nodeFamily()->partialEndUpdate();
340 m_mesh->faceFamily()->partialEndUpdate();
341 CHECKPERF(m_perf_counter.stop(PerfCounter::ENDUPDATE))
342}
343
344/*---------------------------------------------------------------------------*/
345/*---------------------------------------------------------------------------*/
346
347/*---------------------------------------------------------------------------*/
348/*---------------------------------------------------------------------------*/
358 ConstArrayView<ItemUniqueId> nodes_to_send,
359 FaceInfoMap& face_map,
360 MapCoordToUid& node_finder,
361 MapCoordToUid& face_finder,
362 ItemUidSet& updated_face_uids,
363 ItemUidSet& updated_node_uids)
364{
365 CHECKPERF(m_perf_counter.start(PerfCounter::GATHERFACE))
366
367 IParallelMng* pm = m_mesh->parallelMng();
368 Integer sub_domain_id = pm->commRank();
369 Integer nb_sub_domain = pm->commSize();
370
371 const Real tol = 10e-12;
372
373 SerializeBuffer sbuf;
374 sbuf.setMode(ISerializer::ModeReserve);
375 Integer nb_to_send = faces_to_send.size();
376 Integer nb_node_to_send = nodes_to_send.size();
377
378 Int64UniqueArray unique_ids(nb_to_send);
379 Int64UniqueArray cells_unique_ids(nb_to_send);
380 Int64UniqueArray nodes_unique_id;
381 nodes_unique_id.reserve(nb_node_to_send);
382 RealUniqueArray coords;
383 coords.reserve(3 * nb_to_send);
384 RealUniqueArray nodes_coords;
385 nodes_coords.reserve(3 * nb_node_to_send);
386 for (Integer i = 0; i < nb_to_send; ++i) {
387 const FaceInfo& fi = face_map[faces_to_send[i]];
388 unique_ids[i] = fi.uniqueId().asInt64();
389 cells_unique_ids[i] = fi.cellUniqueId().asInt64();
390 coords.add(fi.center().x);
391 coords.add(fi.center().y);
392 coords.add(fi.center().z);
393 }
394 debug() << "SEND NODE : " << nb_node_to_send;
395 for (Integer i = 0; i < nb_node_to_send; ++i) {
396 //debug()<<"SEND NODE : "<<nodes_to_send[i];
397 ItemUniqueId nuid(nodes_to_send[i]);
398 nodes_unique_id.add(nuid.asInt64());
399 NodeInfo ni = m_nodes_info[nuid];
400 Real3 c = ni.getCoord();
401 nodes_coords.add(c.x);
402 nodes_coords.add(c.y);
403 nodes_coords.add(c.z);
404 }
405 sbuf.reserveInteger(1); // for the number of faces
406 sbuf.reserveInteger(1); // for the sub-domain number
407 sbuf.reserveInteger(1); // for the number of nodes in the list
408 sbuf.reserveArray(unique_ids); // for the unique id of the faces
409 sbuf.reserveArray(cells_unique_ids); // for the unique id of the face cells
410 sbuf.reserveArray(nodes_unique_id); // for the list of nodes
411 sbuf.reserveArray(coords); // for the center coordinates
412 sbuf.reserveArray(nodes_coords); // for the node coordinates
413
414 sbuf.allocateBuffer();
416
417 sbuf.putInteger(nb_to_send);
418 sbuf.putInteger(sub_domain_id);
419 sbuf.putInteger(nodes_unique_id.size());
420 sbuf.putArray(unique_ids);
421 sbuf.putArray(cells_unique_ids);
422 sbuf.putArray(nodes_unique_id);
423 sbuf.putArray(coords);
424 sbuf.putArray(nodes_coords);
425
426 SerializeBuffer recv_buf;
427 pm->allGather(&sbuf, &recv_buf);
429
430 for (Integer i = 0; i < nb_sub_domain; ++i) {
431 Integer nb_face = recv_buf.getInteger();
432 Integer sid = recv_buf.getInteger();
433 Integer nb_node_unique_id = recv_buf.getInteger();
434 info() << " [\t ParallelAMRConsistency::_gatherFaces] READ nface=" << nb_face << " FROM sid=" << sid << " " << m_face_info_mng.size();
435 recv_buf.getArray(unique_ids);
436 recv_buf.getArray(cells_unique_ids);
437 recv_buf.getArray(nodes_unique_id);
438 recv_buf.getArray(coords);
439 recv_buf.getArray(nodes_coords);
440
441 // Iterate through all received faces; if some are missing,
442 // they are ignored.
443 for (Integer z = 0; z < nb_face; ++z) {
444 ItemUniqueId new_uid(unique_ids[z]);
445 ItemUniqueId cell_uid(cells_unique_ids[z]);
446
447 Real3 center;
448 center.x = coords[z * 3];
449 center.y = coords[z * 3 + 1];
450 center.z = coords[z * 3 + 2];
451
452 const Int64 current_uid = face_finder.find(center, tol);
453 if ((current_uid != NULL_ITEM_ID) && (new_uid < current_uid)) {
454 if (!face_map.hasKey(ItemUniqueId(current_uid))) {
455 error() << "face uid not found \n";
456 }
457 //UPDATE FACE_FINDER
458 face_finder.insert(center, new_uid, tol);
459 updated_face_uids.insert(current_uid);
460
461 FaceInfo& fi_old = face_map[ItemUniqueId(current_uid)];
462 Integer data_index = fi_old.getDataIndex();
463 Integer nb_node = fi_old.nbNode();
464 FaceInfo fi(new_uid, cell_uid, nb_node, sid, data_index, &m_face_info_mng);
465 fi.setCenter(center);
466 face_map[ItemUniqueId(current_uid)] = fi;
467 }
468 }
469
470 for (Integer z = 0; z < nb_node_unique_id; ++z) {
471 ItemUniqueId nuid(nodes_unique_id[z]);
472 Real3 node_coord;
473 node_coord.x = nodes_coords[z * 3];
474 node_coord.y = nodes_coords[z * 3 + 1];
475 node_coord.z = nodes_coords[z * 3 + 2];
476 Int64 current_node_uid = node_finder.find(node_coord, tol);
477 if ((current_node_uid != NULL_ITEM_ID) && (nuid < current_node_uid)) {
478 ItemUniqueId c_nuid(current_node_uid);
479 if (nuid < m_nodes_info[c_nuid].uniqueId()) {
480 NodeInfo ni(nuid, sid);
481 ni.setCoord(node_coord);
482 m_nodes_info[c_nuid] = ni;
483
484 // UPDATE NODE FINDER
485 updated_node_uids.insert(current_node_uid);
486 }
487 }
488 }
489 }
490 CHECKPERF(m_perf_counter.stop(PerfCounter::GATHERFACE))
491
492 CHECKPERF(m_perf_counter.start(PerfCounter::UPDATE))
493 //update node_finder
494 for (ItemUidSet::iterator iter = updated_node_uids.begin(); iter != updated_node_uids.end(); ++iter) {
495 ItemUniqueId uid(*iter);
496 NodeInfo& ni = m_nodes_info[uid];
497 node_finder.insert(ni.getCoord(), ni.uniqueId(), tol);
498 }
499
500 //update m_face_info_mng
501 _update(m_face_info_mng.m_nodes_unique_id, m_nodes_info);
502
503 CHECKPERF(m_perf_counter.stop(PerfCounter::UPDATE))
504
505 //pm->barrier();
506}
507
508/*---------------------------------------------------------------------------*/
509/*---------------------------------------------------------------------------*/
510
511void ParallelAMRConsistency::
512_update(Array<ItemUniqueId>& nodes_unique_id, NodeInfoList const& nodes_info)
513{
514 for (Integer i = 0, n = nodes_unique_id.size(); i < n; ++i) {
515 ItemUniqueId& uid = nodes_unique_id[i];
516 NodeInfoList::Data const* data = nodes_info.lookup(uid);
517 if (data)
518 nodes_unique_id[i] = data->value().uniqueId();
519 else
520 info() << "ERROR " << i << " " << uid << " not found";
521 }
522}
523
524/*---------------------------------------------------------------------------*/
525/*---------------------------------------------------------------------------*/
526
527void ParallelAMRConsistency::
528_addNodeToList(Node node, NodeInfoList& node_map)
529{
530 Real3 node_coord = m_nodes_coord[node];
531 ItemUniqueId uid = node.uniqueId();
532 NodeInfoList::Data* i = node_map.lookup(uid);
533 if (!i) {
534 NodeInfo node_info(uid, node.owner());
535 node_info.setCoord(node_coord);
536 node_map.add(uid, node_info);
537 }
538}
539
540/*---------------------------------------------------------------------------*/
541/*---------------------------------------------------------------------------*/
542
543void ParallelAMRConsistency::
544_addFaceToList2(Face face, FaceInfoMap2& face_map)
545{
546 Integer nb_node = face.nbNode();
547 ItemUniqueId uid = face.uniqueId();
548 FaceInfoMap2::Data* i = face_map.lookup(uid);
549 if (!i) {
550 Real3 center(0., 0., 0.);
551 for (Node node : face.nodes()) {
552 Real3 node_coord = m_nodes_coord[node];
553 center += node_coord;
554 }
555 center /= nb_node;
556 FaceInfo2 fi(face.uniqueId(), face.owner());
557 fi.setCenter(center);
558 face_map.add(uid, fi);
559 }
560}
561
562/*---------------------------------------------------------------------------*/
563/*---------------------------------------------------------------------------*/
571makeNewItemsConsistent2(MapCoordToUid& node_finder, MapCoordToUid& face_finder)
572{
573 // Marks nodes on the boundary
574 Integer nb_active_face = static_cast<Integer>(m_mesh->nbFace() * 0.2); // 20% of shared faces (estimated)
575 m_active_nodes.resize((nb_active_face * 2) + 5);
576 m_active_faces.resize((nb_active_face * 2) + 5);
577
578 FaceFamily* true_face_family = dynamic_cast<FaceFamily*>(m_mesh->itemFamily(IK_Face));
579 if (!true_face_family)
580 throw FatalErrorException(A_FUNCINFO, "can not obtain FaceFamily");
581
582 Int32 sid = m_mesh->parallelMng()->commRank();
583
584 typedef std::set<Item> Set;
585 Set active_nodes_set, active_faces_set;
586 // Iterate through faces and mark active boundary nodes
587 DynamicMesh* mesh = dynamic_cast<DynamicMesh*>(m_mesh);
588 if (!mesh)
589 throw FatalErrorException(A_FUNCINFO, "can not obtain DynamicMesh");
590 ItemInternalMap& faces_map = mesh->facesMap();
591
592 faces_map.eachItem([&](Face face) {
593 bool is_sub_domain_boundary_face = false;
595 is_sub_domain_boundary_face = true; // true is not needed
596 }
597 else {
598 if (face.cell(0).level() == 0 && face.cell(1).level() == 0) {
599 if ((face.cell(0).owner() != sid || face.cell(1).owner() != sid))
600 is_sub_domain_boundary_face = true;
601 }
602 }
603
604 if (is_sub_domain_boundary_face) {
606 true_face_family->allSubFaces(face, subfaces);
607 for (Integer s = 0; s < subfaces.size(); s++) {
608 Face face2 = subfaces[s];
610 _addFaceToList2(face2, m_active_faces2);
611 active_faces_set.insert(face2);
612 for (Node node : face2.nodes()) {
613 node.mutableItemBase().addFlags(ItemFlags::II_Shared | ItemFlags::II_SubDomainBoundary);
614 active_nodes_set.insert(node);
615 _addNodeToList(node, m_active_nodes);
616 }
617 for (Edge edge : face2.edges())
618 edge.mutableItemBase().addFlags(ItemFlags::II_Shared | ItemFlags::II_SubDomainBoundary);
619 }
620 }
621 });
622
623 UniqueArray<ItemUniqueId> active_faces_to_send(arcaneCheckArraySize(active_faces_set.size()));
624 UniqueArray<ItemUniqueId> active_nodes_to_send(arcaneCheckArraySize(active_nodes_set.size()));
625
626 UniqueArray<Item> active_faces(arcaneCheckArraySize(active_faces_set.size()));
627 UniqueArray<Item> active_nodes(arcaneCheckArraySize(active_nodes_set.size()));
628
629 Set::const_iterator fit(active_faces_set.begin()), fend(active_faces_set.end());
630 Integer i = 0;
631 for (; fit != fend; ++fit) {
632 Item face = *fit;
633 active_faces_to_send[i] = (face.uniqueId());
634 active_faces[i] = face;
635 i++;
636 }
637 Set::const_iterator nit(active_nodes_set.begin()), nend(active_nodes_set.end());
638 i = 0;
639 for (; nit != nend; ++nit) {
640 Item node = *nit;
641 active_nodes_to_send[i] = (node.uniqueId());
642 //debug() << "ACTIVE NODE TO SEND " << node->uniqueId() << " " << active_nodes_to_send[i];
643 active_nodes[i] = node;
644 i++;
645 }
646
647 _gatherItems(active_nodes_to_send, active_faces_to_send, m_active_nodes, m_active_faces2, node_finder, face_finder);
648
649 for (Integer index = 0; index < active_faces.size(); index++) {
650 Item face = active_faces[index];
651 const Int64 current_uid = face.uniqueId();
652 FaceInfo2& fi = m_active_faces2[face.uniqueId()];
653 if (current_uid != fi.uniqueId()) {
654 face.mutableItemBase().setUniqueId(fi.uniqueId());
655 face.mutableItemBase().setOwner(fi.owner(), sid);
656 //debug() << "[\t ParallelAMRConsistency] NEW FACE BEFORE " << fi.uniqueId() << " " << fi.owner();
657 }
658 }
659 for (Integer index = 0; index < active_nodes.size(); index++) {
660 Item node = active_nodes[index];
661 const Int64 current_uid = node.uniqueId();
662 NodeInfo& ni = m_active_nodes[node.uniqueId()];
663 if (current_uid != ni.uniqueId()) {
664 node.mutableItemBase().setUniqueId(ni.uniqueId());
665 node.mutableItemBase().setOwner(ni.owner(), sid);
666 //debug() << "[\t ParallelAMRConsistency] NEW FACE BEFORE " << fi.uniqueId() << " " << fi.owner();
667 }
668 }
669
670 // It is necessary to re-sort #m_faces_map because the uniqueId() of
671 // faces have been modified
672 faces_map.notifyUniqueIdsChanged();
673 // same for nodes
674 mesh->nodesMap().notifyUniqueIdsChanged();
675}
676
677/*---------------------------------------------------------------------------*/
678/*---------------------------------------------------------------------------*/
679
680/*---------------------------------------------------------------------------*/
681/*---------------------------------------------------------------------------*/
691 ConstArrayView<ItemUniqueId> faces_to_send,
692 NodeInfoList& node_map,
693 FaceInfoMap2& face_map,
694 MapCoordToUid& node_finder,
695 MapCoordToUid& face_finder)
696{
697 IParallelMng* pm = m_mesh->parallelMng();
698 Integer sub_domain_id = pm->commRank();
699 Integer nb_sub_domain = pm->commSize();
700
701 SerializeBuffer sbuf;
702 sbuf.setMode(ISerializer::ModeReserve);
703 Integer nb_to_send = faces_to_send.size();
704 Integer nb_node_to_send = nodes_to_send.size();
705 Int64UniqueArray unique_ids(nb_to_send);
706 Int64UniqueArray node_unique_ids(nb_node_to_send);
707 RealUniqueArray coords;
708 coords.reserve(3 * nb_to_send);
709 RealUniqueArray nodes_coords;
710 nodes_coords.reserve(3 * nb_node_to_send);
711
712 for (Integer i = 0; i < nb_node_to_send; ++i) {
713 const NodeInfo& ni = node_map[nodes_to_send[i]];
714 node_unique_ids[i] = ni.uniqueId().asInt64();
715 const Real3 c = ni.getCoord();
716 nodes_coords.add(c.x);
717 nodes_coords.add(c.y);
718 nodes_coords.add(c.z);
719 }
720
721 for (Integer i = 0; i < nb_to_send; ++i) {
722 const FaceInfo2& fi = face_map[faces_to_send[i]];
723 unique_ids[i] = fi.uniqueId().asInt64();
724 coords.add(fi.center().x);
725 coords.add(fi.center().y);
726 coords.add(fi.center().z);
727 }
728
729 sbuf.reserveInteger(1); // for the number of faces
730 sbuf.reserveInteger(1); // for the sub-domain number
731 sbuf.reserveInteger(1); // for the number of nodes in the list
732 sbuf.reserveArray(unique_ids); // for the unique id of the faces
733 sbuf.reserveArray(node_unique_ids); // for the list of nodes
734 sbuf.reserveArray(coords); // for the center coordinates
735 sbuf.reserveArray(nodes_coords); // for the node coordinates
736
737 sbuf.allocateBuffer();
739
740 sbuf.putInteger(nb_to_send);
741 sbuf.putInteger(sub_domain_id);
742 sbuf.putInteger(node_unique_ids.size());
743 sbuf.putArray(unique_ids);
744 sbuf.putArray(node_unique_ids);
745 sbuf.putArray(coords);
746 sbuf.putArray(nodes_coords);
747
748 SerializeBuffer recv_buf;
749 pm->allGather(&sbuf, &recv_buf);
751
752 for (Integer i = 0; i < nb_sub_domain; ++i) {
753 Integer nb_face = recv_buf.getInteger();
754 Integer sid = recv_buf.getInteger();
755 Integer nb_node_unique_id = recv_buf.getInteger();
756 //info() << " [\t ParallelAMRConsistency::_gatherFaces] READ nface=" << nb_face << " FROM sid=" << sid;
757
758 recv_buf.getArray(unique_ids);
759 recv_buf.getArray(node_unique_ids);
760 recv_buf.getArray(coords);
761 recv_buf.getArray(nodes_coords);
762
763 // Iterate through all received faces; if some are missing,
764 // they are ignored.
765 const Real tol = 10e-6;
766 for (Integer z = 0; z < nb_face; ++z) {
767 ItemUniqueId new_uid(unique_ids[z]);
768
769 Real3 center;
770 center.x = coords[z * 3];
771 center.y = coords[z * 3 + 1];
772 center.z = coords[z * 3 + 2];
773
774 const Int64 current_uid = face_finder.find(center, tol);
775 if ((current_uid != NULL_ITEM_ID) && (new_uid < current_uid)) {
776 if (!face_map.hasKey(ItemUniqueId(current_uid))) {
777 error() << "face uid not found \n";
778 }
779 FaceInfo2 fi(new_uid, sid);
780 fi.setCenter(center);
781 face_map[ItemUniqueId(current_uid)] = fi;
782 }
783 }
784
785 for (Integer z = 0; z < nb_node_unique_id; ++z) {
786 ItemUniqueId nuid(node_unique_ids[z]);
787 Real3 node_coord;
788 node_coord.x = nodes_coords[z * 3];
789 node_coord.y = nodes_coords[z * 3 + 1];
790 node_coord.z = nodes_coords[z * 3 + 2];
791 Int64 current_node_uid = node_finder.find(node_coord, tol);
792 if ((current_node_uid != NULL_ITEM_ID) && (nuid < current_node_uid)) {
793 NodeInfo ni(nuid, sid);
794 ni.setCoord(node_coord);
795 ItemUniqueId c_nuid(current_node_uid);
796 node_map[c_nuid] = ni;
797 }
798 }
799 }
800 pm->barrier();
801}
802
803/*---------------------------------------------------------------------------*/
804/*---------------------------------------------------------------------------*/
805
806} // End namespace Arcane::mesh
807
808/*---------------------------------------------------------------------------*/
809/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
Integer size() const
Number of elements in the vector.
Base class for 1D data vectors.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
void getArray(Array< Real > &values) override
Resize and fill values.
void allocateBuffer() override
Allocates the serializer memory.
void reserveArray(Span< const Real > values) override
Reserve to save the number of elements and the values elements.
void putArray(Span< const Real > values) override
Save the number of elements and the values elements.
Integer getInteger() override
Retrieve a size.
void setMode(eMode new_mode) override
Sets the current mode.
void putInteger(Integer value) override
Add the integer value.
Int32 level() const
Definition Item.h:1473
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
Edge of a cell.
Definition Item.h:875
Face of a cell.
Definition Item.h:1032
Cell cell(Int32 i) const
i-th cell of the face
Definition Item.h:1793
Int32 nbCell() const
Number of cells of the face (1 or 2).
Definition Item.h:1129
EdgeConnectedListViewType edges() const
List of edges of the face.
Definition Item.h:1246
bool hasKey(KeyTypeConstRef id)
true if a value with key id is present
virtual FaceGroup allFaces()=0
Group of all faces.
virtual Integer nbFace()=0
Number of mesh faces.
virtual IParallelMng * parallelMng()=0
Parallelism manager.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Performs an all-gather operation across all processors. This is a collective operation....
virtual void barrier()=0
Performs a barrier.
Int32 flags() const
Flags of the entity.
@ II_Shared
The entity is shared by another subdomain.
Definition ItemFlags.h:59
@ II_SubDomainBoundary
The entity is at the boundary of two subdomains.
Definition ItemFlags.h:60
Unique identifier of an entity.
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
NodeConnectedListViewType nodes() const
List of nodes of the entity.
Definition Item.h:843
Int32 nbNode() const
Number of nodes of the entity.
Definition Item.h:837
Base class for a mesh element.
Definition Item.h:84
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
Definition Item.h:394
Int32 owner() const
Owner subdomain number of the entity.
Definition Item.h:252
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
constexpr bool null() const
true if the entity is null (i.e. not connected to the mesh)
Definition Item.h:230
impl::ItemBase itemBase() const
Internal part of the entity.
Definition Item.h:383
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
void addFlags(Int32 added_flags)
Adds the flags added_flags to those of the entity.
Node of a mesh.
Definition Item.h:598
Class managing a 3-dimensional real vector.
Definition Real3.h:132
constexpr __host__ __device__ Real squareNormL2() const
Returns the square of the L2 norm of the triplet $ .
Definition Real3.h:455
Implementation of a buffer for serialization.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Implementation of a mesh.
Definition DynamicMesh.h:98
Info on an active Face.
Info on an active Face.
Associative array of ItemInternal.
void remove(Int64 key)
Removes the value associated with the key key.
impl::ItemBase findItem(Int64 uid) const
Returns the unique ID entity uid.
void notifyUniqueIdsChanged()
Notifies that the unique IDs of the entities have changed.
void eachItem(const Lambda &lambda)
Template function to iterate over the instance's entities.
bool add(Int64 key, ItemInternal *v)
Adds the value v corresponding to the key key.
structure for searching for a node based on its coordinates The hashing key is the geometric position...
void makeNewItemsConsistent2(MapCoordToUid &node_finder, MapCoordToUid &face_finder)
Determines the faces to send to neighbors.
void makeNewItemsConsistent(NodeMapCoordToUid &node_finder, FaceMapCoordToUid &face_finder)
Determines the faces to send to neighbors.
void _gatherFaces(ConstArrayView< ItemUniqueId > faces_to_send, ConstArrayView< ItemUniqueId > nodes_to_send, FaceInfoMap &face_map, MapCoordToUid &node_finder, MapCoordToUid &face_finder, ItemUidSet &updated_face_uids, ItemUidSet &updated_node_uids)
void _gatherItems(ConstArrayView< ItemUniqueId > nodes_to_send, ConstArrayView< ItemUniqueId > faces_to_send, NodeInfoList &node_map, FaceInfoMap2 &face_map, MapCoordToUid &node_finder, MapCoordToUid &face_finder)
__host__ __device__ Real3 cross(Real3 v1, Real3 v2)
Cross product of two 3-component vectors.
Definition MathUtils.h:759
bool isZero(const BuiltInProxy< _Type > &a)
Tests if a value is exactly equal to zero.
Integer arcaneCheckArraySize(unsigned long long size)
Checks that size can be converted into an 'Integer' to serve as the size of an array....
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:339
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
UniqueArray< Real > RealUniqueArray
Dynamic 1D array of reals.
Definition UtilsTypes.h:349
@ IK_Face
Face mesh entity.
double Real
Type representing a real number.
std::int32_t Int32
Signed integer type of 32 bits.
Real y
second component of the triplet
Definition Real3.h:36
Real z
third component of the triplet
Definition Real3.h:37
Real x
first component of the triplet
Definition Real3.h:35