15#include "arcane/utils/StringBuilder.h"
17#include "arcane/core/IGhostLayerMng.h"
18#include "arcane/core/IItemFamily.h"
19#include "arcane/core/IMesh.h"
20#include "arcane/core/IMeshFactoryMng.h"
21#include "arcane/core/IMeshMng.h"
22#include "arcane/core/IMeshModifier.h"
23#include "arcane/core/IPrimaryMesh.h"
24#include "arcane/core/MeshBuildInfo.h"
26#include "arcane/core/IMeshSection.h"
27#include "arcane/std/MeshCut_axl.h"
49 NodeOnEdge(
const Node first_node,
const Node second_node)
51 const Int64 a = first_node.uniqueId();
52 const Int64 b = second_node.uniqueId();
55 m_node1 = second_node;
60 m_node0 = second_node;
67 NodeOnEdge(
Int64 first_node,
Int64 second_node)
69 if (first_node < second_node) {
70 m_uid_node0 = first_node;
71 m_uid_node1 = second_node;
74 m_uid_node0 = second_node;
75 m_uid_node1 = first_node;
79 NodeOnEdge() =
default;
81 bool operator<(
const NodeOnEdge& other)
const
83 if (m_uid_node0 != other.m_uid_node0) {
84 return m_uid_node0 < other.m_uid_node0;
86 return m_uid_node1 < other.m_uid_node1;
89 bool operator==(
const NodeOnEdge& other)
const
91 return m_uid_node0 == other.m_uid_node0 && m_uid_node1 == other.m_uid_node1;
97 Int64 m_uid_node0 = -1;
98 Int64 m_uid_node1 = -1;
100 Int64 m_uid_new_node = -1;
101 Int32 m_owner_new_node = -1;
112 FaceLite(
const Ref<NodeOnEdge>& node0,
const Ref<NodeOnEdge>& node1)
113 : m_node0(node0->m_uid_node0 < node1->m_uid_node0 ? node0 : node1)
114 , m_node1(node0->m_uid_node0 < node1->m_uid_node0 ? node1 : node0)
116 const Int64 node00 = node0->m_uid_node0;
117 const Int64 node01 = node0->m_uid_node1;
118 const Int64 node10 = node1->m_uid_node0;
119 const Int64 node11 = node1->m_uid_node1;
121 if (node00 < node10) {
125 else if (node00 > node10) {
130 if (node01 == node11) {
133 if (node01 < node11) {
144 bool operator<(
const FaceLite& other)
const
146 return m_node0->operator<(*(other.m_node0.get())) || (m_node0->operator==(*(other.m_node0.get())) && m_node1->operator<(*(other.m_node1.get())));
149 bool operator==(
const FaceLite& other)
const
151 return m_node0->operator==(*(other.m_node0.get())) && m_node1->operator==(*(other.m_node1.get()));
154 Ref<NodeOnEdge> m_node0;
155 Ref<NodeOnEdge> m_node1;
157 Int64 m_uid_new_face = -1;
158 Int32 m_owner_new_face = -1;
167struct NodeIntersection
169 NodeIntersection(
const Node first_node,
const Node second_node,
const Real3& intersection_pos)
170 : m_new_node(
makeRef(new NodeOnEdge(first_node, second_node)))
171 , m_intersection_pos(intersection_pos)
174 NodeIntersection(
Int64 first_node,
Int64 second_node,
const Real3& intersection_pos)
175 : m_new_node(
makeRef(new NodeOnEdge(first_node, second_node)))
176 , m_intersection_pos(intersection_pos)
179 NodeIntersection() =
default;
181 bool operator<(
const NodeIntersection& other)
const
183 return m_new_node->operator<(*(other.m_new_node.get()));
186 bool operator==(
const NodeIntersection& other)
const
188 return m_new_node->operator==(*(other.m_new_node.get()));
191 Ref<NodeOnEdge> m_new_node;
192 Real3 m_intersection_pos{ -1 };
198struct UnknownNodeOrFace
200 UnknownNodeOrFace(
Int64 node0_uid,
Int64 node1_uid,
Int32 who) : m_node0_uid(node0_uid), m_node1_uid(node1_uid), m_who(who){}
201 bool null()
const {
return m_who == -1;}
202 bool operator==(
const UnknownNodeOrFace& other)
const{
return m_node0_uid == other.m_node0_uid && m_node1_uid == other.m_node1_uid;}
246 return m_cloned_mesh->handle();
274 Int32 m_mesh_uid = -1;
280ARCANE_REGISTER_SERVICE_MESHCUT(MeshCut, MeshCutService);
301 ARCANE_NOT_YET_IMPLEMENTED(
"Not supported yet");
311 m_mesh_uid = unique_id;
320 if (
mesh()->ghostLayerMng()->nbGhostLayer() < 1) {
321 ARCANE_FATAL(
"A ghost layer is required for this service");
333 if (m_cloned_mesh !=
nullptr) {
337 if (mesh()->dimension() != 3) {
341 IMeshMng* mm = subDomain()->meshMng();
343 if (m_mesh_uid == -1) {
345 m_mesh_uid =
options()->getUniqueIdServiceMesh();
352 String service_mesh_name = mesh()->name() +
"_MeshCut" + m_mesh_uid;
354 MeshHandle* mesh_handle = mm->findMeshHandle(service_mesh_name,
false);
356 if (mesh_handle ==
nullptr) {
357 IParallelMng* pm = subDomain()->parallelMng();
358 MeshBuildInfo mbi(service_mesh_name);
362 mbi.addParallelMng(
makeRef(pm));
363 m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi);
364 m_cloned_mesh->modifier()->setDynamic(
true);
365 m_cloned_mesh->setDimension(2);
366 m_cloned_mesh->endAllocate();
369 m_cloned_mesh = mesh_handle->mesh()->toPrimaryMesh();
370 m_cloned_mesh->modifier()->clearItems();
380 auto [p0, normal] = m_plans[plan_pos];
382 const Int32 mesh_dim = mesh()->dimension();
387 UniqueArray<Int32> face_already_computed;
400 UniqueArray<NodeIntersection> point_coords_tmp;
405 bool has_face_on_plane =
false;
407 bool cell_useful =
true;
408 Int32 nb_node_on_plane = 0;
413 bool has_neg =
false;
414 bool has_pos =
false;
415 for (Node node : cell.nodes()) {
416 Real d = node_dist[node];
427 if (!(has_neg && has_pos))
435 if (nb_node_on_plane >= mesh_dim) {
436 for (Face face : cell.faces()) {
440 if (face.nbNode() != nb_node_on_plane)
443 bool has_egal =
true;
444 for (Node node : face.nodes()) {
445 if (node_dist[node] != 0) {
455 if (face_already_computed.contains(face.localId())) {
464 face_already_computed.add(face.localId());
465 for (Node node : face.nodes()) {
466 auto ni = NodeIntersection{ node, node, node_coord[node] };
467 point_coords_tmp.add(ni);
469 has_face_on_plane =
true;
480 if (!has_face_on_plane) {
484 static constexpr Integer edges_tetraedron4[6][2] = {
485 { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 }
487 static constexpr Integer edges_pyramid5[8][2] = {
488 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 0, 4 }, { 1, 4 }, { 2, 4 }, { 3, 4 }
490 static constexpr Integer edges_pentaedron6[9][2] = {
491 { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 3 }, { 1, 4 }, { 2, 5 }, { 3, 4 }, { 4, 5 }, { 5, 3 }
493 static constexpr Integer edges_hexaedron8[12][2] = {
494 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 }
498 const Integer(*edge_def)[2] =
nullptr;
500 auto type = cell.itemTypeId();
502 if (type == ITI_Tetraedron4) {
504 edge_def = edges_tetraedron4;
506 else if (type == ITI_Pyramid5) {
508 edge_def = edges_pyramid5;
510 else if (type == ITI_Pentaedron6) {
512 edge_def = edges_pentaedron6;
514 else if (type == ITI_Hexaedron8) {
516 edge_def = edges_hexaedron8;
520 ARCANE_FATAL(
"Cell type not supported -- type: {0}", type);
524 for (
Integer i = 0; i < nb_edges; ++i) {
525 Node node0 = cell.node(edge_def[i][0]);
526 Node node1 = cell.node(edge_def[i][1]);
528 bool need_compute_intersection =
true;
531 if (node_dist[node0] == 0) {
532 const Real3 p = node_coord[node0];
534 auto ni = NodeIntersection{ node0, node0, p };
536 if (!point_coords_tmp.contains(ni)) {
537 point_coords_tmp.add(ni);
539 need_compute_intersection =
false;
543 if (node_dist[node1] == 0) {
544 const Real3 p = node_coord[node1];
546 auto ni = NodeIntersection{ node1, node1, p };
548 if (!point_coords_tmp.contains(ni)) {
549 point_coords_tmp.add(ni);
551 need_compute_intersection =
false;
555 if (need_compute_intersection && node_dist[node0] * node_dist[node1] < 0) {
559 Real t = std::abs(node_dist[node0]) / (std::abs(node_dist[node0]) + std::abs(node_dist[node1]));
563 p.x = node_coord[node0].x + t * (node_coord[node1].x - node_coord[node0].x);
564 p.y = node_coord[node0].y + t * (node_coord[node1].y - node_coord[node0].y);
565 p.z = node_coord[node0].z + t * (node_coord[node1].z - node_coord[node0].z);
567 auto ni = NodeIntersection{ node0, node1, p };
569 if (!point_coords_tmp.contains(ni)) {
570 point_coords_tmp.add(ni);
577 if (point_coords_tmp.size() >= mesh_dim) {
580 if (point_coords_tmp.size() > 6)
581 ARCANE_FATAL(
"Pas implem : {0}", point_coords_tmp.size());
583 new_cells.add(point_coords_tmp.size());
584 new_cells.add(sd_nb_cell);
589 for (
const auto& node : point_coords_tmp) {
590 bary += node.m_intersection_pos;
592 bary /= point_coords_tmp.size();
596 const Real3 arbitrary = (std::abs(normal.x) > 0.9) ? Real3{ 0.0, 1.0, 0.0 } : Real3{ 1.0, 0.0, 0.0 };
604 UniqueArray<Int64> indices;
605 indices.reserve(point_coords_tmp.size());
606 for (
Int64 i = 0; i < point_coords_tmp.size(); ++i) {
610 std::sort(indices.begin(), indices.end(),
612 const Real3& pa = point_coords_tmp[ia].m_intersection_pos;
613 const Real3& pb = point_coords_tmp[ib].m_intersection_pos;
616 const Real3 va{ pa - bary };
617 const Real3 vb{ pb - bary };
627 const Real angle_a = std::atan2(a_y, a_x);
628 const Real angle_b = std::atan2(b_y, b_x);
630 return angle_a < angle_b;
639 for (
Int64& idx : indices) {
641 std::optional<Int64> pos = new_nodes.span().findFirst(point_coords_tmp[idx]);
647 new_cells.add(
static_cast<Int32>(pos.value()) + ajust_node_pos);
652 NodeIntersection& elem = point_coords_tmp[idx];
655 if (elem.m_new_node->m_node0.owner() == elem.m_new_node->m_node1.owner()) {
656 elem.m_new_node->m_owner_new_node = elem.m_new_node->m_node0.owner();
662 if (elem.m_new_node->m_node0.isOwn()) {
663 elem.m_new_node->m_uid_new_node = sd_nb_node++;
667 elem.m_new_node->m_uid_new_node = -2;
670 new_cells.add(new_nodes.size() + ajust_node_pos);
671 idx = new_nodes.size();
677 Int64 idxm1 = indices[indices.size() - 1];
678 for (
Int64 idx : indices) {
679 FaceLite fl(new_nodes[idx].m_new_node, new_nodes[idxm1].m_new_node);
680 if (!new_faces.contains(fl)) {
688 if (new_nodes[idx].m_new_node->m_owner_new_node == new_nodes[idxm1].m_new_node->m_owner_new_node) {
689 fl.m_owner_new_face = new_nodes[idx].m_new_node->m_owner_new_node;
690 if (fl.m_owner_new_face == subDomain()->subDomainId()) {
691 fl.m_uid_new_face = sd_nb_face++;
694 fl.m_uid_new_face = -2;
704 point_coords_tmp.clear();
712_makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray<Int64>& new_cells, UniqueArray<NodeIntersection>& new_nodes)
714 IParallelMng* pm = subDomain()->parallelMng();
716 Int32 decal = sd_nb_cell;
717 pm->scan(MessagePassing::ReduceSum, ArrayView{ 1, &decal });
730 while (pos0 < new_cells.size()) {
731 Int64 type = new_cells[pos0++];
732 new_cells[pos0++] += decal;
734 for (Int32 i = 0; i < type; ++i) {
735 Int64& pos_to_uid = new_cells[pos0++];
736 pos_to_uid = new_nodes[pos_to_uid].m_new_node->m_uid_new_node;
746_fillNodeUID(Int32& sd_nb_node, UniqueArray<NodeIntersection>& new_nodes)
756 IParallelMng* pm = subDomain()->parallelMng();
757 Int32 my_proc = pm->commRank();
758 UniqueArray<UniqueArray<Ref<NodeOnEdge>>> requested_nodes(subDomain()->nbSubDomain());
819 UniqueArray<UniqueArray<Int64>> request_uid(subDomain()->nbSubDomain());
821 debug() <<
"[Node][" << my_proc <<
"] Step 1";
823 for (
auto& elem : new_nodes) {
825 if (elem.m_new_node->m_uid_new_node >= 0) {
830 if (elem.m_new_node->m_owner_new_node < 0) {
832 Node node0 = elem.m_new_node->m_node0;
833 Node node1 = elem.m_new_node->m_node1;
839 Int64 min_uid = INT64_MAX;
840 Int32 owner_min = -1;
841 for (Cell cell0 : node0.cells()) {
842 for (Cell cell1 : node1.cells()) {
843 if (cell0 == cell1) {
844 if (cell0.uniqueId() < min_uid) {
845 min_uid = cell0.uniqueId();
846 owner_min = cell0.owner();
853 if (owner_min == subDomain()->subDomainId()) {
854 elem.m_new_node->m_owner_new_node = subDomain()->subDomainId();
855 elem.m_new_node->m_uid_new_node = sd_nb_node++;
865 elem.m_new_node->m_owner_new_node = owner_min;
866 elem.m_new_node->m_uid_new_node = -2;
872 request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0);
873 request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1);
875 requested_nodes[elem.m_new_node->m_owner_new_node].add(elem.m_new_node);
885 request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0);
886 request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1);
888 requested_nodes[elem.m_new_node->m_owner_new_node].add(elem.m_new_node);
898 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain() * 2);
900 debug() <<
"[Node][" << my_proc <<
"] Step 1.2";
902 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
903 if (sr == subDomain()->subDomainId()) {
906 Int32 size = request_uid[sr].size();
907 requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr,
false);
908 requests[sr * 2 + 1] = pm->send(request_uid[sr], sr,
false);
912 pm->waitAllRequests(requests);
983 UniqueArray<UniqueArray<Int64>> answers_uid(subDomain()->nbSubDomain());
985 UniqueArray<UnknownNodeOrFace> unknown_node;
986 debug() <<
"[Node][" << my_proc <<
"] Step 2";
988 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
989 if (sr == subDomain()->subDomainId()) {
993 pm->recv(ArrayView{ 1, &size }, sr);
995 UniqueArray<Int64> requested_uid(size);
996 pm->recv(requested_uid, sr);
999 answers_uid[sr].add(0);
1002 for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) {
1004 std::optional<Int64> pos = new_nodes.span().findFirst(NodeIntersection{ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], Real3{ 0 } });
1006 answers_uid[sr].add(new_nodes[pos.value()].m_new_node->m_uid_new_node);
1020 answers_uid[sr].add(-1);
1021 unknown_node.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr });
1027 answers_uid[sr][0] = answers_uid[sr].size() - 1;
1030 UniqueArray<Int64> who;
1031 debug() <<
"[Node][" << my_proc <<
"] Step 2.2";
1037 for (Int32 i = 0; i < unknown_node.size(); ++i) {
1038 if (unknown_node[i].null())
1041 who.add(unknown_node[i].m_who);
1042 unknown_node[i].m_who = -1;
1043 for (Int32 j = i + 1; j < unknown_node.size(); ++j) {
1044 if (unknown_node[j].null())
1046 if (unknown_node[j] == unknown_node[i]) {
1047 who.add(unknown_node[j].m_who);
1048 unknown_node[j].m_who = -1;
1052 for (
auto proc : who) {
1053 answers_uid[proc].add(unknown_node[i].m_node0_uid);
1054 answers_uid[proc].add(unknown_node[i].m_node1_uid);
1055 answers_uid[proc].add(who.size());
1056 answers_uid[proc].addRange(who);
1062 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain() * 2);
1065 debug() <<
"[Node][" << my_proc <<
"] Step 2.3";
1066 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1067 if (sr == subDomain()->subDomainId()) {
1071 Int32 size = answers_uid[sr].size();
1072 requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr,
false);
1073 requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr,
false);
1078 pm->waitAllRequests(requests);
1197 UniqueArray<UniqueArray<Int64>> request_uid(subDomain()->nbSubDomain());
1198 UniqueArray<UniqueArray<Ref<NodeOnEdge>>> requested_nodes2(subDomain()->nbSubDomain());
1201 debug() <<
"[Node][" << my_proc <<
"] Step 3";
1204 bool need_more_comm =
false;
1206 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1207 if (sr == subDomain()->subDomainId()) {
1211 Int32 total_size = 0;
1212 pm->recv(ArrayView{ 1, &total_size }, sr);
1214 UniqueArray<Int64> answered_uid(total_size);
1215 pm->recv(answered_uid, sr);
1217 if (total_size == 1) {
1221 Int32 answer_to_request_size =
static_cast<Int32
>(answered_uid[0]);
1223 Span<Int64> answer_to_request = answered_uid.subView(1, answer_to_request_size);
1224 Span<Int64> additionnal_answer = answered_uid.subView(answer_to_request_size+1, answered_uid.size() - (answer_to_request_size+1));
1231 for (Int32 answer = 0; answer < answer_to_request.size(); ++answer) {
1232 Ref<NodeOnEdge> node_on_edge = requested_nodes[sr][answer];
1234 if (answer_to_request[answer] != -1) {
1235 node_on_edge->m_uid_new_node = answer_to_request[answer];
1243 while (pos < additionnal_answer.size()) {
1244 Int64& uid0 = additionnal_answer[pos++];
1245 Int64 uid1 = additionnal_answer[pos++];
1246 Int64 decal = additionnal_answer[pos++];
1247 if (uid0 == node_on_edge->m_uid_node0 && uid1 == node_on_edge->m_uid_node1) {
1253 if (pos >= additionnal_answer.size()) {
1254 ARCANE_FATAL(
"Unknown node -- UID0 : {0} -- UID1 : {1}", node_on_edge->m_uid_node0, node_on_edge->m_uid_node1);
1260 Span<Int64> sub_additionnal_answer;
1262 while (pos < additionnal_answer.size()) {
1263 Int64 pos_node_in_array = additionnal_answer[pos++];
1265 Int64 decal = additionnal_answer[pos++];
1267 Ref<NodeOnEdge> node_on_edge = requested_nodes[sr][pos_node_in_array];
1268 sub_additionnal_answer = additionnal_answer.subSpan(pos, decal);
1275 Node node0 = node_on_edge->m_node0;
1276 Node node1 = node_on_edge->m_node1;
1282 Int64 min_uid = INT64_MAX;
1283 Int32 owner_min = -1;
1284 for (Cell cell0 : node0.cells()) {
1285 for (Cell cell1 : node1.cells()) {
1286 if (cell0 == cell1) {
1287 if (cell0.uniqueId() < min_uid && sub_additionnal_answer.contains(cell0.owner())) {
1288 min_uid = cell0.uniqueId();
1289 owner_min = cell0.owner();
1296 if (owner_min == subDomain()->subDomainId()) {
1297 node_on_edge->m_owner_new_node = subDomain()->subDomainId();
1298 node_on_edge->m_uid_new_node = sd_nb_node++;
1301 if (sub_additionnal_answer.size() > 1) {
1302 need_more_comm =
true;
1310 for (
auto proc : sub_additionnal_answer) {
1311 if (proc == my_proc)
1313 request_uid[proc].add(node_on_edge->m_uid_new_node);
1320 need_more_comm =
true;
1321 node_on_edge->m_owner_new_node = owner_min;
1322 node_on_edge->m_uid_new_node = -2;
1324 if (request_uid[my_proc].empty()) {
1325 request_uid[my_proc].resize(subDomain()->nbSubDomain(), 0);
1328 request_uid[my_proc][owner_min]++;
1330 requested_nodes2[owner_min].add(node_on_edge);
1342 if (need_more_comm) {
1344 UniqueArray<Parallel::Request> requests(subDomain()->nbSubDomain());
1347 debug() <<
"[Node][" << my_proc <<
"] Step 3.2";
1349 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1350 if (sr == subDomain()->subDomainId()) {
1354 if (request_uid[sr].empty())
continue;
1355 requests[sr] = pm->send(request_uid[sr], sr,
false);
1359 pm->waitAllRequests(requests);
1374 if (!request_uid[my_proc].empty()) {
1376 debug() <<
"[Node][" << my_proc <<
"] Step 4";
1378 for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) {
1379 if (sr == subDomain()->subDomainId()) {
1383 Int64 size = request_uid[my_proc][sr];
1384 if (size == 0)
continue;
1389 UniqueArray<Int64> requested_uid(size);
1390 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 <<
"] Étape 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 <<
"] Étape 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 <<
"] Étape 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 <<
"] Étape 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 <<
"] Étape 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 <<
"] Étape 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 <<
"] Étape 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 <<
"] Étape 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() <<
"Nouveau maillage : " << m_cloned_mesh->name() <<
" -- NbNœuds : " << m_cloned_mesh->nbNode() <<
" -- NbMailles : " << 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 envoyant une exception FatalErrorException.
CaseOptionsMeshCut * options() const
Options du jeu de données du service.
ArcaneMeshCutObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
virtual void clearItems()=0
Supprime toutes les entitées de toutes les familles de ce maillage.
virtual IMeshModifier * modifier()=0
Interface de modification associée.
CellGroup ownCells() const
Retourne le groupe contenant toutes les mailles propres à ce domaine.
NodeGroup allNodes() const
Retourne le groupe contenant tous les noeuds.
void addPlane(const Real3 &p0, const Real3 &normal) override
Méthode permettant d'ajouter un plan au service de coupe. L'utilisation de ces plans dépend du servic...
void setServiceMeshUniqueId(Int32 unique_id) override
Méthode permettant de définir un identifiant unique pour créer plusieurs services de section pour un ...
void setVariables(VariableCollection variables) override
Méthode permettant d'ajouter un ensemble de variables à copier sur le nouveau maillage.
VariableCollection variables() override
Méthode permettant d'obtenir un ensemble de variables copiées sur le nouveau maillage.
void updateSection() override
Méthode permettant de mettre à jour la section du maillage avec tous les plans.
MeshHandle meshSection() override
Méthode permettant d'obtenir la section du maillage.
Classe gérant un vecteur réel de 3 dimensions.
eServiceType creationType() const
Type du service pouvant être créé par cette instance.
Structure contenant les informations pour créer un service.
Vue d'un tableau d'éléments de type T.
Vecteur 1D de données avec sémantique par valeur (style STL).
__host__ __device__ Real dot(Real2 u, Real2 v)
Produit scalaire de u par v dans .
Real3 normalizedCrossProduct3(Real3 v1, Real3 v2)
Produit vectoriel normalisé.
__host__ __device__ Real3 normalizeReal3(Real3 v)
Normalisation d'un Real3.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
MeshVariableScalarRefT< Node, Real > VariableNodeReal
Grandeur au noeud de type réel.
constexpr __host__ __device__ bool isNearlyZeroWithEpsilon(const Type &a, const Type &epsilon)
Teste si une valeur est approximativement égale à zéro dans un epsilon.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
bool operator<(const Item &item1, const Item &item2)
Compare deux entités.
eServiceType
Type du service.
@ ST_CaseOption
Le service s'utilise au niveau du jeu de données.
double Real
Type représentant un réel.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
@ Cell
Le maillage est AMR par maille.
std::int32_t Int32
Type entier signé sur 32 bits.