14#include "arcane/utils/StringBuilder.h"
16#include "arcane/core/IGhostLayerMng.h"
17#include "arcane/core/IItemFamily.h"
18#include "arcane/core/IMesh.h"
19#include "arcane/core/IMeshFactoryMng.h"
20#include "arcane/core/IMeshMng.h"
21#include "arcane/core/IMeshModifier.h"
22#include "arcane/core/IPrimaryMesh.h"
23#include "arcane/core/MeshBuildInfo.h"
25#include "arcane/core/IMeshSection.h"
26#include "arcane/std/MeshCut_axl.h"
48 NodeOnEdge(
const Node first_node,
const Node second_node)
50 const Int64 a = first_node.uniqueId();
51 const Int64 b = second_node.uniqueId();
54 m_node1 = second_node;
59 m_node0 = second_node;
66 NodeOnEdge(
Int64 first_node,
Int64 second_node)
68 if (first_node < second_node) {
69 m_uid_node0 = first_node;
70 m_uid_node1 = second_node;
73 m_uid_node0 = second_node;
74 m_uid_node1 = first_node;
78 NodeOnEdge() =
default;
80 bool operator<(
const NodeOnEdge& other)
const
82 if (m_uid_node0 != other.m_uid_node0) {
83 return m_uid_node0 < other.m_uid_node0;
85 return m_uid_node1 < other.m_uid_node1;
88 bool operator==(
const NodeOnEdge& other)
const
90 return m_uid_node0 == other.m_uid_node0 && m_uid_node1 == other.m_uid_node1;
96 Int64 m_uid_node0 = -1;
97 Int64 m_uid_node1 = -1;
99 Int64 m_uid_new_node = -1;
100 Int32 m_owner_new_node = -1;
111 FaceLite(
const Ref<NodeOnEdge>& node0,
const Ref<NodeOnEdge>& node1)
112 : m_node0(node0->m_uid_node0 < node1->m_uid_node0 ? node0 : node1)
113 , m_node1(node0->m_uid_node0 < node1->m_uid_node0 ? node1 : node0)
115 const Int64 node00 = node0->m_uid_node0;
116 const Int64 node01 = node0->m_uid_node1;
117 const Int64 node10 = node1->m_uid_node0;
118 const Int64 node11 = node1->m_uid_node1;
120 if (node00 < node10) {
124 else if (node00 > node10) {
129 if (node01 == node11) {
132 if (node01 < node11) {
143 bool operator<(
const FaceLite& other)
const
145 return m_node0->operator<(*(other.m_node0.get())) || (m_node0->operator==(*(other.m_node0.get())) && m_node1->operator<(*(other.m_node1.get())));
148 bool operator==(
const FaceLite& other)
const
150 return m_node0->operator==(*(other.m_node0.get())) && m_node1->operator==(*(other.m_node1.get()));
153 Ref<NodeOnEdge> m_node0;
154 Ref<NodeOnEdge> m_node1;
156 Int64 m_uid_new_face = -1;
157 Int32 m_owner_new_face = -1;
166struct NodeIntersection
168 NodeIntersection(
const Node first_node,
const Node second_node,
const Real3& intersection_pos)
169 : m_new_node(
makeRef(new NodeOnEdge(first_node, second_node)))
170 , m_intersection_pos(intersection_pos)
173 NodeIntersection(
Int64 first_node,
Int64 second_node,
const Real3& intersection_pos)
174 : m_new_node(
makeRef(new NodeOnEdge(first_node, second_node)))
175 , m_intersection_pos(intersection_pos)
178 NodeIntersection() =
default;
180 bool operator<(
const NodeIntersection& other)
const
182 return m_new_node->operator<(*(other.m_new_node.get()));
185 bool operator==(
const NodeIntersection& other)
const
187 return m_new_node->operator==(*(other.m_new_node.get()));
190 Ref<NodeOnEdge> m_new_node;
191 Real3 m_intersection_pos{ -1 };
197struct UnknownNodeOrFace
199 UnknownNodeOrFace(
Int64 node0_uid,
Int64 node1_uid,
Int32 who) : m_node0_uid(node0_uid), m_node1_uid(node1_uid), m_who(who){}
200 bool null()
const {
return m_who == -1;}
201 bool operator==(
const UnknownNodeOrFace& other)
const{
return m_node0_uid == other.m_node0_uid && m_node1_uid == other.m_node1_uid;}
245 return m_cloned_mesh->handle();
273 Int32 m_mesh_uid = -1;
279ARCANE_REGISTER_SERVICE_MESHCUT(MeshCut, MeshCutService);
300 ARCANE_NOT_YET_IMPLEMENTED(
"Not supported yet");
310 m_mesh_uid = unique_id;
319 if (
mesh()->ghostLayerMng()->nbGhostLayer() < 1) {
320 ARCANE_FATAL(
"A ghost layer is required for this service");
332 if (m_cloned_mesh !=
nullptr) {
336 if (mesh()->dimension() != 3) {
340 IMeshMng* mm = subDomain()->meshMng();
342 if (m_mesh_uid == -1) {
344 m_mesh_uid =
options()->getUniqueIdServiceMesh();
351 String service_mesh_name = mesh()->name() +
"_MeshCut" + m_mesh_uid;
353 MeshHandle* mesh_handle = mm->findMeshHandle(service_mesh_name,
false);
355 if (mesh_handle ==
nullptr) {
356 IParallelMng* pm = subDomain()->parallelMng();
357 MeshBuildInfo mbi(service_mesh_name);
361 mbi.addParallelMng(
makeRef(pm));
362 m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi);
363 m_cloned_mesh->modifier()->setDynamic(
true);
364 m_cloned_mesh->setDimension(2);
365 m_cloned_mesh->endAllocate();
368 m_cloned_mesh = mesh_handle->mesh()->toPrimaryMesh();
369 m_cloned_mesh->modifier()->clearItems();
379 auto [p0, normal] = m_plans[plan_pos];
381 const Int32 mesh_dim = mesh()->dimension();
386 UniqueArray<Int32> face_already_computed;
399 UniqueArray<NodeIntersection> point_coords_tmp;
404 bool has_face_on_plane =
false;
406 bool cell_useful =
true;
407 Int32 nb_node_on_plane = 0;
412 bool has_neg =
false;
413 bool has_pos =
false;
414 for (Node node : cell.nodes()) {
415 Real d = node_dist[node];
426 if (!(has_neg && has_pos))
434 if (nb_node_on_plane >= mesh_dim) {
435 for (Face face : cell.faces()) {
439 if (face.nbNode() != nb_node_on_plane)
442 bool has_egal =
true;
443 for (Node node : face.nodes()) {
444 if (node_dist[node] != 0) {
454 if (face_already_computed.contains(face.localId())) {
463 face_already_computed.add(face.localId());
464 for (Node node : face.nodes()) {
465 auto ni = NodeIntersection{ node, node, node_coord[node] };
466 point_coords_tmp.add(ni);
468 has_face_on_plane =
true;
479 if (!has_face_on_plane) {
483 static constexpr Integer edges_tetraedron4[6][2] = {
484 { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 }
486 static constexpr Integer edges_pyramid5[8][2] = {
487 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 0, 4 }, { 1, 4 }, { 2, 4 }, { 3, 4 }
489 static constexpr Integer edges_pentaedron6[9][2] = {
490 { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 3 }, { 1, 4 }, { 2, 5 }, { 3, 4 }, { 4, 5 }, { 5, 3 }
492 static constexpr Integer edges_hexaedron8[12][2] = {
493 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 }
497 const Integer(*edge_def)[2] =
nullptr;
499 auto type = cell.itemTypeId();
501 if (type == ITI_Tetraedron4) {
503 edge_def = edges_tetraedron4;
505 else if (type == ITI_Pyramid5) {
507 edge_def = edges_pyramid5;
509 else if (type == ITI_Pentaedron6) {
511 edge_def = edges_pentaedron6;
513 else if (type == ITI_Hexaedron8) {
515 edge_def = edges_hexaedron8;
519 ARCANE_FATAL(
"Cell type not supported -- type: {0}", type);
523 for (
Integer i = 0; i < nb_edges; ++i) {
524 Node node0 = cell.node(edge_def[i][0]);
525 Node node1 = cell.node(edge_def[i][1]);
527 bool need_compute_intersection =
true;
530 if (node_dist[node0] == 0) {
531 const Real3 p = node_coord[node0];
533 auto ni = NodeIntersection{ node0, node0, p };
535 if (!point_coords_tmp.contains(ni)) {
536 point_coords_tmp.add(ni);
538 need_compute_intersection =
false;
542 if (node_dist[node1] == 0) {
543 const Real3 p = node_coord[node1];
545 auto ni = NodeIntersection{ node1, node1, p };
547 if (!point_coords_tmp.contains(ni)) {
548 point_coords_tmp.add(ni);
550 need_compute_intersection =
false;
554 if (need_compute_intersection && node_dist[node0] * node_dist[node1] < 0) {
558 Real t = std::abs(node_dist[node0]) / (std::abs(node_dist[node0]) + std::abs(node_dist[node1]));
562 p.x = node_coord[node0].x + t * (node_coord[node1].x - node_coord[node0].x);
563 p.y = node_coord[node0].y + t * (node_coord[node1].y - node_coord[node0].y);
564 p.z = node_coord[node0].z + t * (node_coord[node1].z - node_coord[node0].z);
566 auto ni = NodeIntersection{ node0, node1, p };
568 if (!point_coords_tmp.contains(ni)) {
569 point_coords_tmp.add(ni);
576 if (point_coords_tmp.size() >= mesh_dim) {
579 if (point_coords_tmp.size() > 6)
580 ARCANE_FATAL(
"Pas implem : {0}", point_coords_tmp.size());
582 new_cells.add(point_coords_tmp.size());
583 new_cells.add(sd_nb_cell);
588 for (
const auto& node : point_coords_tmp) {
589 bary += node.m_intersection_pos;
591 bary /= point_coords_tmp.size();
595 const Real3 arbitrary = (std::abs(normal.x) > 0.9) ? Real3{ 0.0, 1.0, 0.0 } : Real3{ 1.0, 0.0, 0.0 };
603 UniqueArray<Int64> indices;
604 indices.reserve(point_coords_tmp.size());
605 for (
Int64 i = 0; i < point_coords_tmp.size(); ++i) {
609 std::sort(indices.begin(), indices.end(),
611 const Real3& pa = point_coords_tmp[ia].m_intersection_pos;
612 const Real3& pb = point_coords_tmp[ib].m_intersection_pos;
615 const Real3 va{ pa - bary };
616 const Real3 vb{ pb - bary };
626 const Real angle_a = std::atan2(a_y, a_x);
627 const Real angle_b = std::atan2(b_y, b_x);
629 return angle_a < angle_b;
638 for (
Int64& idx : indices) {
640 std::optional<Int64> pos = new_nodes.span().findFirst(point_coords_tmp[idx]);
646 new_cells.add(
static_cast<Int32>(pos.value()) + ajust_node_pos);
651 NodeIntersection& elem = point_coords_tmp[idx];
654 if (elem.m_new_node->m_node0.owner() == elem.m_new_node->m_node1.owner()) {
655 elem.m_new_node->m_owner_new_node = elem.m_new_node->m_node0.owner();
661 if (elem.m_new_node->m_node0.isOwn()) {
662 elem.m_new_node->m_uid_new_node = sd_nb_node++;
666 elem.m_new_node->m_uid_new_node = -2;
669 new_cells.add(new_nodes.size() + ajust_node_pos);
670 idx = new_nodes.size();
676 Int64 idxm1 = indices[indices.size() - 1];
677 for (
Int64 idx : indices) {
678 FaceLite fl(new_nodes[idx].m_new_node, new_nodes[idxm1].m_new_node);
679 if (!new_faces.contains(fl)) {
687 if (new_nodes[idx].m_new_node->m_owner_new_node == new_nodes[idxm1].m_new_node->m_owner_new_node) {
688 fl.m_owner_new_face = new_nodes[idx].m_new_node->m_owner_new_node;
689 if (fl.m_owner_new_face == subDomain()->subDomainId()) {
690 fl.m_uid_new_face = sd_nb_face++;
693 fl.m_uid_new_face = -2;
703 point_coords_tmp.clear();
711_makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray<Int64>& new_cells, UniqueArray<NodeIntersection>& new_nodes)
713 IParallelMng* pm = subDomain()->parallelMng();
715 Int32 decal = sd_nb_cell;
716 pm->scan(MessagePassing::ReduceSum, ArrayView{ 1, &decal });
729 while (pos0 < new_cells.size()) {
730 Int64 type = new_cells[pos0++];
731 new_cells[pos0++] += decal;
733 for (Int32 i = 0; i < type; ++i) {
734 Int64& pos_to_uid = new_cells[pos0++];
735 pos_to_uid = new_nodes[pos_to_uid].m_new_node->m_uid_new_node;
745_fillNodeUID(Int32& sd_nb_node, UniqueArray<NodeIntersection>& new_nodes)
755 IParallelMng* pm = subDomain()->parallelMng();
756 Int32 my_proc = pm->commRank();
757 UniqueArray<UniqueArray<Ref<NodeOnEdge>>> requested_nodes(subDomain()->nbSubDomain());
818 UniqueArray<UniqueArray<Int64>> request_uid(subDomain()->nbSubDomain());
820 debug() <<
"[Node][" << my_proc <<
"] Step 1";
822 for (
auto& elem : new_nodes) {
824 if (elem.m_new_node->m_uid_new_node >= 0) {
829 if (elem.m_new_node->m_owner_new_node < 0) {
831 Node node0 = elem.m_new_node->m_node0;
832 Node node1 = elem.m_new_node->m_node1;
838 Int64 min_uid = INT64_MAX;
839 Int32 owner_min = -1;
840 for (Cell cell0 : node0.cells()) {
841 for (Cell cell1 : node1.cells()) {
842 if (cell0 == cell1) {
843 if (cell0.uniqueId() < min_uid) {
844 min_uid = cell0.uniqueId();
845 owner_min = cell0.owner();
852 if (owner_min == subDomain()->subDomainId()) {
853 elem.m_new_node->m_owner_new_node = subDomain()->subDomainId();
854 elem.m_new_node->m_uid_new_node = sd_nb_node++;
864 elem.m_new_node->m_owner_new_node = owner_min;
865 elem.m_new_node->m_uid_new_node = -2;
871 request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0);
872 request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1);
874 requested_nodes[elem.m_new_node->m_owner_new_node].add(elem.m_new_node);
884 request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0);
885 request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1);
887 requested_nodes[elem.m_new_node->m_owner_new_node].add(elem.m_new_node);
897 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain() * 2);
899 debug() <<
"[Node][" << my_proc <<
"] Step 1.2";
901 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
902 if (sr == subDomain()->subDomainId()) {
905 Int32 size = request_uid[sr].size();
906 requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr,
false);
907 requests[sr * 2 + 1] = pm->send(request_uid[sr], sr,
false);
911 pm->waitAllRequests(requests);
982 UniqueArray<UniqueArray<Int64>> answers_uid(subDomain()->nbSubDomain());
984 UniqueArray<UnknownNodeOrFace> unknown_node;
985 debug() <<
"[Node][" << my_proc <<
"] Step 2";
987 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
988 if (sr == subDomain()->subDomainId()) {
992 pm->recv(ArrayView{ 1, &size }, sr);
994 UniqueArray<Int64> requested_uid(size);
995 pm->recv(requested_uid, sr);
998 answers_uid[sr].add(0);
1001 for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) {
1003 std::optional<Int64> pos = new_nodes.span().findFirst(NodeIntersection{ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], Real3{ 0 } });
1005 answers_uid[sr].add(new_nodes[pos.value()].m_new_node->m_uid_new_node);
1019 answers_uid[sr].add(-1);
1020 unknown_node.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr });
1026 answers_uid[sr][0] = answers_uid[sr].size() - 1;
1029 UniqueArray<Int64> who;
1030 debug() <<
"[Node][" << my_proc <<
"] Step 2.2";
1036 for (Int32 i = 0; i < unknown_node.size(); ++i) {
1037 if (unknown_node[i].null())
1040 who.add(unknown_node[i].m_who);
1041 unknown_node[i].m_who = -1;
1042 for (Int32 j = i + 1; j < unknown_node.size(); ++j) {
1043 if (unknown_node[j].null())
1045 if (unknown_node[j] == unknown_node[i]) {
1046 who.add(unknown_node[j].m_who);
1047 unknown_node[j].m_who = -1;
1051 for (
auto proc : who) {
1052 answers_uid[proc].add(unknown_node[i].m_node0_uid);
1053 answers_uid[proc].add(unknown_node[i].m_node1_uid);
1054 answers_uid[proc].add(who.size());
1055 answers_uid[proc].addRange(who);
1061 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain() * 2);
1064 debug() <<
"[Node][" << my_proc <<
"] Step 2.3";
1065 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1066 if (sr == subDomain()->subDomainId()) {
1070 Int32 size = answers_uid[sr].size();
1071 requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr,
false);
1072 requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr,
false);
1077 pm->waitAllRequests(requests);
1196 UniqueArray<UniqueArray<Int64>> request_uid(subDomain()->nbSubDomain());
1197 UniqueArray<UniqueArray<Ref<NodeOnEdge>>> requested_nodes2(subDomain()->nbSubDomain());
1200 debug() <<
"[Node][" << my_proc <<
"] Step 3";
1203 bool need_more_comm =
false;
1205 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1206 if (sr == subDomain()->subDomainId()) {
1210 Int32 total_size = 0;
1211 pm->recv(ArrayView{ 1, &total_size }, sr);
1213 UniqueArray<Int64> answered_uid(total_size);
1214 pm->recv(answered_uid, sr);
1216 if (total_size == 1) {
1220 Int32 answer_to_request_size =
static_cast<Int32
>(answered_uid[0]);
1222 Span<Int64> answer_to_request = answered_uid.subView(1, answer_to_request_size);
1223 Span<Int64> additionnal_answer = answered_uid.subView(answer_to_request_size+1, answered_uid.size() - (answer_to_request_size+1));
1230 for (Int32 answer = 0; answer < answer_to_request.size(); ++answer) {
1231 Ref<NodeOnEdge> node_on_edge = requested_nodes[sr][answer];
1233 if (answer_to_request[answer] != -1) {
1234 node_on_edge->m_uid_new_node = answer_to_request[answer];
1242 while (pos < additionnal_answer.size()) {
1243 Int64& uid0 = additionnal_answer[pos++];
1244 Int64 uid1 = additionnal_answer[pos++];
1245 Int64 decal = additionnal_answer[pos++];
1246 if (uid0 == node_on_edge->m_uid_node0 && uid1 == node_on_edge->m_uid_node1) {
1252 if (pos >= additionnal_answer.size()) {
1253 ARCANE_FATAL(
"Unknown node -- UID0 : {0} -- UID1 : {1}", node_on_edge->m_uid_node0, node_on_edge->m_uid_node1);
1259 Span<Int64> sub_additionnal_answer;
1261 while (pos < additionnal_answer.size()) {
1262 Int64 pos_node_in_array = additionnal_answer[pos++];
1264 Int64 decal = additionnal_answer[pos++];
1266 Ref<NodeOnEdge> node_on_edge = requested_nodes[sr][pos_node_in_array];
1267 sub_additionnal_answer = additionnal_answer.subSpan(pos, decal);
1274 Node node0 = node_on_edge->m_node0;
1275 Node node1 = node_on_edge->m_node1;
1281 Int64 min_uid = INT64_MAX;
1282 Int32 owner_min = -1;
1283 for (Cell cell0 : node0.cells()) {
1284 for (Cell cell1 : node1.cells()) {
1285 if (cell0 == cell1) {
1286 if (cell0.uniqueId() < min_uid && sub_additionnal_answer.contains(cell0.owner())) {
1287 min_uid = cell0.uniqueId();
1288 owner_min = cell0.owner();
1295 if (owner_min == subDomain()->subDomainId()) {
1296 node_on_edge->m_owner_new_node = subDomain()->subDomainId();
1297 node_on_edge->m_uid_new_node = sd_nb_node++;
1300 if (sub_additionnal_answer.size() > 1) {
1301 need_more_comm =
true;
1309 for (
auto proc : sub_additionnal_answer) {
1310 if (proc == my_proc)
1312 request_uid[proc].add(node_on_edge->m_uid_new_node);
1319 need_more_comm =
true;
1320 node_on_edge->m_owner_new_node = owner_min;
1321 node_on_edge->m_uid_new_node = -2;
1323 if (request_uid[my_proc].empty()) {
1324 request_uid[my_proc].resize(subDomain()->nbSubDomain(), 0);
1327 request_uid[my_proc][owner_min]++;
1329 requested_nodes2[owner_min].add(node_on_edge);
1341 if (need_more_comm) {
1343 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain());
1346 debug() <<
"[Node][" << my_proc <<
"] Step 3.2";
1348 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1349 if (sr == subDomain()->subDomainId()) {
1353 if (request_uid[sr].empty())
continue;
1354 requests[sr] = pm->send(request_uid[sr], sr,
false);
1358 pm->waitAllRequests(requests);
1373 if (!request_uid[my_proc].empty()) {
1375 debug() <<
"[Node][" << my_proc <<
"] Step 4";
1377 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1378 if (sr == subDomain()->subDomainId()) {
1382 Int64 size = request_uid[my_proc][sr];
1383 if (size == 0)
continue;
1388 UniqueArray<Int64> requested_uid(size);
1389 pm->recv(requested_uid, sr);
1391 for (Int32 i = 0; i < size; ++i) {
1392 Ref<NodeOnEdge> node_on_edge = requested_nodes2[sr][i];
1393 node_on_edge->m_uid_new_node = requested_uid[i];
1407Int32 MeshCutService::
1408_makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray<NodeIntersection>& new_nodes)
1410 IParallelMng* pm = subDomain()->parallelMng();
1412 UniqueArray<Int32> all_nb_node(pm->commSize());
1413 pm->allGather(ArrayView{ 1, &sd_nb_node }, all_nb_node);
1416 for (
auto& elem : all_nb_node) {
1417 const Int32 old = elem;
1424 for (
auto& elem : new_nodes) {
1425 elem.m_new_node->m_uid_new_node += all_nb_node[elem.m_new_node->m_owner_new_node];
1433void MeshCutService::
1434_fillFaceUID(Int32& sd_nb_face, UniqueArray<FaceLite>& new_faces)
1437 IParallelMng* pm = subDomain()->parallelMng();
1438 Int32 my_proc = pm->commRank();
1439 UniqueArray<UniqueArray<Int32>> requested_faces(subDomain()->nbSubDomain());
1443 UniqueArray<UniqueArray<Int64>> request_uid(subDomain()->nbSubDomain());
1445 debug() <<
"[Face][" << my_proc <<
"] Step 1";
1447 for (
auto& elem : new_faces) {
1449 if (elem.m_uid_new_face >= 0) {
1452 if (elem.m_owner_new_face < 0) {
1454 Node node00 = elem.m_node0->m_node0;
1455 Node node01 = elem.m_node0->m_node1;
1456 Node node10 = elem.m_node1->m_node0;
1457 Node node11 = elem.m_node1->m_node1;
1459 Int64 min_uid = INT64_MAX;
1460 Int32 owner_min = -1;
1463 for (Cell cell00 : node00.cells()) {
1464 for (Cell cell01 : node01.cells()) {
1465 if (cell00 == cell01) {
1466 for (Cell cell10 : node10.cells()) {
1467 if (cell01 == cell10 ) {
1468 for (Cell cell11 : node11.cells()) {
1469 if (cell10 == cell11) {
1470 if (cell11.uniqueId() < min_uid) {
1471 min_uid = cell11.uniqueId();
1472 owner_min = cell11.owner();
1482 if (owner_min == subDomain()->subDomainId()) {
1483 elem.m_owner_new_face = subDomain()->subDomainId();
1484 elem.m_uid_new_face = sd_nb_face++;
1492 elem.m_owner_new_face = owner_min;
1493 elem.m_uid_new_face = -2;
1494 request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node);
1495 request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node);
1497 requested_faces[elem.m_owner_new_face].add(iter);
1505 request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node);
1506 request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node);
1508 requested_faces[elem.m_owner_new_face].add(iter);
1517 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain() * 2);
1520 debug() <<
"[Face][" << my_proc <<
"] Step 1.2";
1522 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1523 if (sr == subDomain()->subDomainId()) {
1526 Int32 size = request_uid[sr].size();
1527 requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr,
false);
1528 requests[sr * 2 + 1] = pm->send(request_uid[sr], sr,
false);
1532 pm->waitAllRequests(requests);
1537 UniqueArray<UniqueArray<Int64>> answers_uid(subDomain()->nbSubDomain());
1539 UniqueArray<UnknownNodeOrFace> unknown_face;
1540 debug() <<
"[Face][" << my_proc <<
"] Step 2";
1542 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1543 if (sr == subDomain()->subDomainId()) {
1547 pm->recv(ArrayView{ 1, &size }, sr);
1549 UniqueArray<Int64> requested_uid(size);
1550 pm->recv(requested_uid, sr);
1552 answers_uid[sr].add(0);
1554 for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) {
1555 std::optional<Int64> pos = _find(new_faces, requested_uid[ipair_uid], requested_uid[ipair_uid + 1]);
1557 answers_uid[sr].add(new_faces[pos.value()].m_uid_new_face);
1571 answers_uid[sr].add(-1);
1572 unknown_face.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr });
1578 answers_uid[sr][0] = answers_uid[sr].size() - 1;
1581 UniqueArray<Int64> who;
1582 debug() <<
"[Face][" << my_proc <<
"] Step 2.2";
1584 for (Int32 i = 0; i < unknown_face.size(); ++i) {
1585 if (unknown_face[i].null())
1588 who.add(unknown_face[i].m_who);
1589 unknown_face[i].m_who = -1;
1590 for (Int32 j = i + 1; j < unknown_face.size(); ++j) {
1591 if (unknown_face[j].null())
1593 if (unknown_face[j] == unknown_face[i]) {
1594 who.add(unknown_face[j].m_who);
1595 unknown_face[j].m_who = -1;
1599 for (
auto proc : who) {
1600 answers_uid[proc].add(unknown_face[i].m_node0_uid);
1601 answers_uid[proc].add(unknown_face[i].m_node1_uid);
1602 answers_uid[proc].add(who.size());
1603 answers_uid[proc].addRange(who);
1609 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain() * 2);
1612 debug() <<
"[Face][" << my_proc <<
"] Step 2.3";
1613 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1614 if (sr == subDomain()->subDomainId()) {
1618 Int32 size = answers_uid[sr].size();
1619 requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr,
false);
1620 requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr,
false);
1623 pm->waitAllRequests(requests);
1627 UniqueArray<UniqueArray<Int64>> request_uid(subDomain()->nbSubDomain());
1628 UniqueArray<UniqueArray<Int32>> requested_faces2(subDomain()->nbSubDomain());
1631 debug() <<
"[Face][" << my_proc <<
"] Step 3";
1633 bool need_more_comm =
false;
1635 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1636 if (sr == subDomain()->subDomainId()) {
1640 Int32 total_size = 0;
1641 pm->recv(ArrayView{ 1, &total_size }, sr);
1643 UniqueArray<Int64> answered_uid(total_size);
1644 pm->recv(answered_uid, sr);
1646 if (total_size == 1) {
1650 Int32 answer_to_request_size =
static_cast<Int32
>(answered_uid[0]);
1652 Span<Int64> answer_to_request = answered_uid.subView(1, answer_to_request_size);
1653 Span<Int64> additionnal_answer = answered_uid.subView(answer_to_request_size + 1, answered_uid.size() - (answer_to_request_size + 1));
1659 for (Int32 answer = 0; answer < answer_to_request.size(); ++answer) {
1660 FaceLite& face_lite = new_faces[requested_faces[sr][answer]];
1662 if (answer_to_request[answer] != -1) {
1663 face_lite.m_uid_new_face = answer_to_request[answer];
1671 while (pos < additionnal_answer.size()) {
1672 Int64& uid0 = additionnal_answer[pos++];
1673 Int64 uid1 = additionnal_answer[pos++];
1674 Int64 decal = additionnal_answer[pos++];
1675 if (uid0 == face_lite.m_node0->m_uid_new_node && uid1 == face_lite.m_node1->m_uid_new_node) {
1681 if (pos >= additionnal_answer.size()) {
1682 ARCANE_FATAL(
"Unknown face -- UID0 : {0} -- UID1 : {1}", face_lite.m_node0->m_uid_new_node, face_lite.m_node1->m_uid_new_node);
1688 Span<Int64> sub_additionnal_answer;
1690 while (pos < additionnal_answer.size()) {
1691 Int64 pos_node_in_array = additionnal_answer[pos++];
1693 Int64 decal = additionnal_answer[pos++];
1695 FaceLite& face_lite = new_faces[requested_faces[sr][pos_node_in_array]];
1696 sub_additionnal_answer = additionnal_answer.subSpan(pos, decal);
1704 Node node00 = face_lite.m_node0->m_node0;
1705 Node node01 = face_lite.m_node0->m_node1;
1706 Node node10 = face_lite.m_node1->m_node0;
1707 Node node11 = face_lite.m_node1->m_node1;
1709 Int64 min_uid = INT64_MAX;
1710 Int32 owner_min = -1;
1713 for (Cell cell00 : node00.cells()) {
1714 for (Cell cell01 : node01.cells()) {
1715 if (cell00 == cell01) {
1716 for (Cell cell10 : node10.cells()) {
1717 if (cell01 == cell10) {
1718 for (Cell cell11 : node11.cells()) {
1719 if (cell10 == cell11) {
1720 if (cell11.uniqueId() < min_uid && sub_additionnal_answer.contains(cell11.owner())) {
1721 min_uid = cell11.uniqueId();
1722 owner_min = cell11.owner();
1733 if (owner_min == subDomain()->subDomainId()) {
1734 face_lite.m_owner_new_face = subDomain()->subDomainId();
1735 face_lite.m_uid_new_face = sd_nb_face++;
1738 if (sub_additionnal_answer.size() > 1) {
1739 need_more_comm =
true;
1747 for (
auto proc : sub_additionnal_answer) {
1748 if (proc == my_proc)
1750 request_uid[proc].add(face_lite.m_uid_new_face);
1757 need_more_comm =
true;
1758 face_lite.m_owner_new_face = owner_min;
1759 face_lite.m_uid_new_face = -2;
1761 if (request_uid[my_proc].empty()) {
1762 request_uid[my_proc].resize(subDomain()->nbSubDomain(), 0);
1765 request_uid[my_proc][owner_min]++;
1767 requested_faces2[owner_min].add(requested_faces[sr][pos_node_in_array]);
1776 if (need_more_comm) {
1778 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain());
1781 debug() <<
"[Face][" << my_proc <<
"] Step 3.2";
1783 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1784 if (sr == subDomain()->subDomainId()) {
1788 if (request_uid[sr].empty())
continue;
1789 requests[sr] = pm->send(request_uid[sr], sr,
false);
1793 pm->waitAllRequests(requests);
1797 debug() <<
"[Face][" << my_proc <<
"] Step 7";
1799 if (!request_uid[my_proc].empty()) {
1800 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1801 if (sr == subDomain()->subDomainId()) {
1805 Int64 size = request_uid[my_proc][sr];
1806 if (size == 0)
continue;
1811 UniqueArray<Int64> requested_uid(size);
1812 pm->recv(requested_uid, sr);
1814 for (Int32 i = 0; i < size; ++i) {
1815 FaceLite& face_lite = new_faces[requested_faces2[sr][i]];
1816 face_lite.m_uid_new_face = requested_uid[i];
1830Int32 MeshCutService::
1831_makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray<FaceLite>& new_faces)
1833 IParallelMng* pm = subDomain()->parallelMng();
1835 UniqueArray<Int32> all_nb_node(pm->commSize());
1836 pm->allGather(ArrayView{ 1, &sd_nb_face }, all_nb_node);
1839 for (
auto& elem : all_nb_node) {
1840 const Int32 old = elem;
1847 for (
auto& elem : new_faces) {
1848 elem.m_uid_new_face += all_nb_node[elem.m_owner_new_face];
1856void MeshCutService::
1860 Int32 g_nb_node = 0;
1861 Int32 g_nb_face = 0;
1863 UniqueArray<Int64> new_cells;
1865 UniqueArray<NodeIntersection> new_nodes;
1866 UniqueArray<FaceLite> new_faces;
1868 for (Int32 i = 0; i < m_plans.size(); ++i) {
1870 debug() <<
"Plan : " << m_plans[i].first <<
", " << m_plans[i].second;
1872 UniqueArray<NodeIntersection> plan_new_nodes;
1873 UniqueArray<FaceLite> plan_new_faces;
1875 Int32 ajust = new_nodes.size();
1877 Int32 previous_g_nb_node = g_nb_node;
1878 Int32 previous_g_nb_face = g_nb_face;
1880 Int32 nb_node_for_this_plan = g_nb_node;
1881 Int32 nb_face_for_this_plan = g_nb_face;
1883 debug() <<
"[" << subDomain()->parallelMng()->commRank() <<
"] _createNodesAndCells";
1884 _createNodesAndCells(i, g_nb_node, plan_new_nodes, ajust, nb_cell, new_cells, g_nb_face, plan_new_faces);
1895 debug() <<
"[" << subDomain()->parallelMng()->commRank() <<
"] _fillNodeUID";
1896 _fillNodeUID(g_nb_node, plan_new_nodes);
1897 nb_node_for_this_plan = g_nb_node - nb_node_for_this_plan;
1899 nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, plan_new_nodes);
1900 g_nb_node = previous_g_nb_node + nb_node_for_this_plan;
1922 _fillFaceUID(g_nb_face, plan_new_faces);
1923 nb_face_for_this_plan = g_nb_face - nb_face_for_this_plan;
1925 nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, plan_new_faces);
1926 g_nb_face = previous_g_nb_face + nb_face_for_this_plan;
1940 new_nodes.addRange(plan_new_nodes);
1941 new_faces.addRange(plan_new_faces);
1944 _makeUniqueCellUID(nb_cell, new_cells, new_nodes);
1966 _addFaces(new_faces);
1967 _addCells(new_cells);
1968 m_cloned_mesh->modifier()->endUpdate();
1969 _setCoordNodesAndOwner(new_nodes);
1970 _setFacesOwner(new_faces);
1972 m_cloned_mesh->nodeFamily()->notifyItemsOwnerChanged();
1973 m_cloned_mesh->faceFamily()->notifyItemsOwnerChanged();
1975 info() <<
"New mesh : " << m_cloned_mesh->name() <<
" -- NbNode : " << m_cloned_mesh->nbNode() <<
" -- NbCells : " << m_cloned_mesh->nbCell();
1981std::optional<Int64> MeshCutService::
1982_find(Span<FaceLite> new_faces, Int64 node_uid0, Int64 node_uid1)
1984 for (Int32 i = 0; i < new_faces.size(); ++i) {
1985 if (new_faces[i].m_node0->m_uid_new_node == node_uid0 && new_faces[i].m_node1->m_uid_new_node == node_uid1) {
1989 return std::nullopt;
1995void MeshCutService::
1996_addFaces(UniqueArray<FaceLite>& new_faces)
const
1998 UniqueArray<Int64> faces_infos;
1999 faces_infos.reserve(new_faces.size() * 4);
2003 for (
auto& elem : new_faces) {
2004 faces_infos.add(ITI_Line2);
2005 faces_infos.add(elem.m_uid_new_face);
2006 faces_infos.add(elem.m_node0->m_uid_new_node);
2007 faces_infos.add(elem.m_node1->m_uid_new_node);
2011 m_cloned_mesh->modifier()->addFaces(nb_faces, faces_infos);
2017void MeshCutService::
2018_addCells(UniqueArray<Int64>& new_cells)
2023 while (pos0 < new_cells.size()) {
2024 const Int64 type = new_cells[pos0];
2027 new_cells[pos0++] = ITI_Triangle3;
2029 new_cells[pos0++] = ITI_Quad4;
2031 new_cells[pos0++] = ITI_Pentagon5;
2033 new_cells[pos0++] = ITI_Hexagon6;
2037 pos0 += 1 +
static_cast<Int32
>(type);
2042 m_cloned_mesh->modifier()->addCells(nb_cells, new_cells);
2048void MeshCutService::
2049_setCoordNodesAndOwner(UniqueArray<NodeIntersection>& new_nodes)
2052 ENUMERATE_ (Node, inode, m_cloned_mesh->allNodes()) {
2053 const Int64 uid = inode->uniqueId();
2054 for (
const auto& elem : new_nodes) {
2055 if (elem.m_new_node->m_uid_new_node == uid) {
2056 node_coords[inode] = elem.m_intersection_pos;
2057 inode->mutableItemBase().setOwner(elem.m_new_node->m_owner_new_node, subDomain()->subDomainId());
2067void MeshCutService::
2068_setFacesOwner(UniqueArray<FaceLite>& new_faces)
2070 ENUMERATE_ (Face, iface, m_cloned_mesh->allFaces()) {
2071 const Int64 uid = iface->uniqueId();
2072 for (
const auto& elem : new_faces) {
2073 if (elem.m_uid_new_face == uid) {
2074 iface->mutableItemBase().setOwner(elem.m_owner_new_face, subDomain()->subDomainId());
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
CaseOptionsMeshCut * options() const
Options du jeu de données du service.
ArcaneMeshCutObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
virtual void clearItems()=0
Deletes all entities of all families in this mesh.
virtual IMeshModifier * modifier()=0
Associated modifier interface.
CellGroup ownCells() const
Returns the group containing all cells specific to this domain.
NodeGroup allNodes() const
Returns the group containing all nodes.
void addPlane(const Real3 &p0, const Real3 &normal) override
Method allowing to add a plane to the cut service. The use of these planes depends on the service.
void setServiceMeshUniqueId(Int32 unique_id) override
Method allowing to set a unique id allowing to create multiple section services for a mesh.
void setVariables(VariableCollection variables) override
Method allowing to add a set of variables to copy on the new mesh.
VariableCollection variables() override
Method allowing to get a set of variables copied on the new mesh.
void updateSection() override
Method allowing to update the mesh section with all planes.
MeshHandle meshSection() override
Méthod allowing to get the mesh section.
Class managing a 3-dimensional real vector.
eServiceType creationType() const
Type of service that can be created by this instance.
Structure containing the information to create a service.
View of an array of elements of type T.
1D data vector with value semantics (STL style).
__host__ __device__ Real dot(Real2 u, Real2 v)
Dot product of u by v in .
Real3 normalizedCrossProduct3(Real3 v1, Real3 v2)
Normalized cross product.
__host__ __device__ Real3 normalizeReal3(Real3 v)
Normalization of a Real3.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
MeshVariableScalarRefT< Node, Real > VariableNodeReal
Real type quantity at node.
constexpr __host__ __device__ bool isNearlyZeroWithEpsilon(const Type &a, const Type &epsilon)
Tests if a value is approximately equal to zero within an epsilon.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
bool operator<(const Item &item1, const Item &item2)
Compare two entities.
eServiceType
Service type.
@ ST_CaseOption
The service is used at the dataset level.
double Real
Type representing a real number.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
@ Cell
The mesh is AMR by cell.
std::int32_t Int32
Signed integer type of 32 bits.