From fe7adea3d96b42226e47aeebe6dd013d3fdbe470 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Wed, 8 Jul 2026 16:13:19 +0200 Subject: [PATCH 01/17] [arcane:core,std] Add first version of CutMesh service --- arcane/src/arcane/core/IMeshSection.h | 62 +++ arcane/src/arcane/core/srcs.cmake | 1 + arcane/src/arcane/std/MeshCut.axl | 16 + arcane/src/arcane/std/MeshCutService.cc | 480 ++++++++++++++++++++++++ arcane/src/arcane/std/srcs.cmake | 2 + 5 files changed, 561 insertions(+) create mode 100644 arcane/src/arcane/core/IMeshSection.h create mode 100644 arcane/src/arcane/std/MeshCut.axl create mode 100644 arcane/src/arcane/std/MeshCutService.cc diff --git a/arcane/src/arcane/core/IMeshSection.h b/arcane/src/arcane/core/IMeshSection.h new file mode 100644 index 0000000000..baf514d773 --- /dev/null +++ b/arcane/src/arcane/core/IMeshSection.h @@ -0,0 +1,62 @@ +// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*- +//----------------------------------------------------------------------------- +// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com) +// See the top-level COPYRIGHT file for details. +// SPDX-License-Identifier: Apache-2.0 +//----------------------------------------------------------------------------- +/*---------------------------------------------------------------------------*/ +/* IMeshSection.h (C) 2000-2026 */ +/* */ +/* TODO. */ +/*---------------------------------------------------------------------------*/ +#ifndef ARCANE_CORE_IMESHSECTION_H +#define ARCANE_CORE_IMESHSECTION_H +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#include "arcane/core/ArcaneTypes.h" +#include "arcane/core/IService.h" + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +namespace Arcane +{ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +class VariableCollection; +class MeshHandle; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +class ARCANE_CORE_EXPORT IMeshSection +{ + public: + + //! Releases resources + virtual ~IMeshSection() = default; + + public: + + virtual void addPlan(const Real3& p0, const Real3& normal) = 0; + + virtual void setVariables(VariableCollection variables) = 0; + virtual VariableCollection variables() = 0; + + virtual void updateSection() = 0; + virtual MeshHandle meshSection() = 0; + +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +} // namespace Arcane + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#endif diff --git a/arcane/src/arcane/core/srcs.cmake b/arcane/src/arcane/core/srcs.cmake index efef2268d7..b9fa187e01 100644 --- a/arcane/src/arcane/core/srcs.cmake +++ b/arcane/src/arcane/core/srcs.cmake @@ -248,6 +248,7 @@ set(ARCANE_ORIGINAL_SOURCES IMeshPartitionConstraintMng.h IMeshPartitioner.h IMeshPartitionerBase.h + IMeshSection.h IMeshStats.h IMeshSubMeshTransition.h IMeshUniqueIdMng.h diff --git a/arcane/src/arcane/std/MeshCut.axl b/arcane/src/arcane/std/MeshCut.axl new file mode 100644 index 0000000000..ca2b67e897 --- /dev/null +++ b/arcane/src/arcane/std/MeshCut.axl @@ -0,0 +1,16 @@ + + + + + TODO + + + + + + + + + + + diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc new file mode 100644 index 0000000000..6b6f444042 --- /dev/null +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -0,0 +1,480 @@ +// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*- +//----------------------------------------------------------------------------- +// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com) +// See the top-level COPYRIGHT file for details. +// SPDX-License-Identifier: Apache-2.0 +//----------------------------------------------------------------------------- +/*---------------------------------------------------------------------------*/ +/* MeshCutService.cc (C) 2000-2026 */ +/* */ +/* TODO. */ +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#include "arcane/core/IMesh.h" +#include "arcane/core/IMeshFactoryMng.h" +#include "arcane/core/IMeshMng.h" +#include "arcane/core/IMeshModifier.h" +#include "arcane/core/IMeshSection.h" +#include "arcane/core/IPrimaryMesh.h" +#include "arcane/core/MeshBuildInfo.h" + +#include "arcane/std/MeshCut_axl.h" + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +namespace Arcane +{ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +class MeshCutService +: public ArcaneMeshCutObject +{ + public: + + explicit MeshCutService(const ServiceBuildInfo& sbi) + : ArcaneMeshCutObject(sbi) + {} + + public: + + void addPlan(const Real3& p0, const Real3& normal) override; + + public: + + void setVariables(VariableCollection variables) override; + void updateSection() override; + + MeshHandle meshSection() override + { + return m_cloned_mesh->handle(); + } + VariableCollection variables() override { return {}; } + + private: + + void _createMesh(); + void _createCells(Int32 plan_pos, Int32& nb_cell, Int32& nb_node, UniqueArray& cells_infos, UniqueArray& pos_node); + void _compute(); + + private: + + VariableCollection m_variables_ori; + IPrimaryMesh* m_cloned_mesh = nullptr; + UniqueArray> m_plans; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +ARCANE_REGISTER_SERVICE_MESHCUT(MeshCutService, MeshCutService); + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +struct NodeIntersection +{ + NodeIntersection(const Node aa, const Node bb, const Real3& inter) + : m_intersection_pos(inter) + { + const Int32 a = aa.localId(); + const Int32 b = bb.localId(); + if (a < b) { + m_lid_node0 = a; + m_lid_node1 = b; + } + else { + m_lid_node0 = b; + m_lid_node1 = a; + } + } + + NodeIntersection() = default; + + bool operator<(const NodeIntersection& other) const + { + if (m_lid_node0 != other.m_lid_node0) { + return m_lid_node0 < other.m_lid_node0; + } + return m_lid_node1 < other.m_lid_node1; + } + + bool operator==(const NodeIntersection& other) const + { + return m_lid_node0 == other.m_lid_node0 && m_lid_node1 == other.m_lid_node1; + } + + Int32 m_lid_node0 = -1; + Int32 m_lid_node1 = -1; + Real3 m_intersection_pos{ -1 }; + Int64 m_uid_new_node = -1; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +addPlan(const Real3& p0, const Real3& normal) +{ + m_plans.add({ p0, math::normalizeReal3(normal) }); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +setVariables(VariableCollection variables) +{ + m_variables_ori = variables; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +updateSection() +{ + if (m_cloned_mesh == nullptr) { + _createMesh(); + } + else { + m_cloned_mesh->modifier()->clearItems(); + } + _compute(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_createMesh() +{ + if (mesh()->dimension() != 3) { + ARCANE_FATAL("Only 3D meshes are supported"); + } + + IMeshMng* mm = subDomain()->meshMng(); + IParallelMng* pm = subDomain()->parallelMng(); + // TODO gérer cas où il y a plusieurs services pour même maillage. + MeshBuildInfo mbi(mesh()->name() + "_MeshCut"); + mbi.addParallelMng(makeRef(pm)); + m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi); + m_cloned_mesh->modifier()->setDynamic(true); + m_cloned_mesh->setDimension(2); + m_cloned_mesh->endAllocate(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_createCells(Int32 plan_pos, Int32& sd_nb_cell, Int32& sd_nb_node, UniqueArray& cells_infos, UniqueArray& pos_node) +{ + auto [p0, normal] = m_plans[plan_pos]; + + VariableNodeReal3& node_coord = mesh()->nodesCoordinates(); + VariableNodeReal node_dist(VariableBuildInfo(mesh(), "NodeDist")); + + UniqueArray face_already_computed; + + // Calcul de la distance signée de chaque noeud par rapport au plan de coupe. + ENUMERATE_ (Node, inode, allNodes()) { + node_dist[inode] = math::dot({ node_coord[inode] - p0 }, normal); + } + + UniqueArray point_coords; + UniqueArray point_coords_tmp; + + ENUMERATE_ (Cell, icell, ownCells()) { + ItemWithNodes cell = *icell; + + // On regarde si la maille traverse le plan ou si une de ces faces est collé dessus. + bool colineaire = false; + { + bool cont = true; + + // Si au moins un noeud est sur le plan, peut-être que la face est colinéaire. + bool has_egal = false; + { + // On vérifie que la maille est dans le plan. + bool has_neg = false, has_pos = false; + for (Node node : cell.nodes()) { + Real d = node_dist[node]; + if (d < 0) + has_neg = true; + else if (d > 0) + has_pos = true; + else + has_egal = true; + } + if (!(has_neg && has_pos)) + cont = false; + } + // On vérifie si une des faces est sur le plan. + if (!cont && has_egal) { + for (Face face : icell->faces()) { + has_egal = true; + for (Node node : face.nodes()) { + if (!math::isNearlyZero(node_dist[node])) { + has_egal = false; + break; + } + } + if (has_egal) { + if (face_already_computed.contains(face.localId())) { + cont = false; + break; + } + face_already_computed.add(face.localId()); + for (Node node : face.nodes()) { + auto ni = NodeIntersection{ node, node, node_coord[node] }; + point_coords_tmp.add(ni); + } + cont = true; + cell = face; + colineaire = true; + break; + } + } + } + if (!cont) { + continue; + } + } + + if (!colineaire) { + // Tableaux définissant les arêtes pour chaque type d'élément. + // hexa_edge: 12 arêtes pour un hexaédre (8 noeuds), chaque arête = [n0, n1] indices locaux. + static constexpr Integer hexa_edge[12][2] = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 } + }; + // tetra_edge: 6 arêtes pour un tétraèdre (4 noeuds). + static constexpr Integer tetra_edge[6][2] = { + { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } + }; + // quad_edge: 4 arêtes pour un quadrangle (4 noeuds). + static constexpr Integer quad_edge[4][2] = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 } + }; + // tri_edge: 3 arêtes pour un triangle (3 noeuds). + static constexpr Integer tri_edge[3][2] = { + { 0, 1 }, { 1, 2 }, { 2, 0 } + }; + + Integer nb_edges = 0; + const Integer(*edge_def)[2] = nullptr; + + Integer nb_node = cell.nbNode(); + + if (nb_node == 8) { + nb_edges = 12; + edge_def = hexa_edge; + } + else if (nb_node == 4) { + nb_edges = 6; + edge_def = tetra_edge; + } + else if (nb_node == 4) { + nb_edges = 4; + edge_def = quad_edge; + } + else if (nb_node == 3) { + nb_edges = 3; + edge_def = tri_edge; + } + else { + ARCANE_FATAL("Type de maille non supporté: nbNode={0}", nb_node); + } + + // Itère sur toutes les arêtes de la maille. + for (Integer i = 0; i < nb_edges; ++i) { + Node node0 = cell.node(edge_def[i][0]); + Node node1 = cell.node(edge_def[i][1]); + + bool aaaa = true; + + // Si le noeud 0 est sur le plan. + if (math::isNearlyZero(node_dist[node0])) { + const Real3 p = node_coord[node0]; + + auto ni = NodeIntersection{ node0, node0, p }; + + if (!point_coords_tmp.contains(ni)) { + point_coords_tmp.add(ni); + } + aaaa = false; + } + + // Si le noeud 1 est sur le plan. + if (math::isNearlyZero(node_dist[node1])) { + const Real3 p = node_coord[node1]; + + auto ni = NodeIntersection{ node1, node1, p }; + + if (!point_coords_tmp.contains(ni)) { + point_coords_tmp.add(ni); + } + aaaa = false; + } + + // Si l'arrête passe à travers le plan. + if (aaaa && node_dist[node0] * node_dist[node1] < 0) { + + // Paramètre d'interpolation t dans [0,1] pour le point d'intersection + // le long de l'arête de node0 à node1. + Real t = std::abs(node_dist[node0]) / (std::abs(node_dist[node0]) + std::abs(node_dist[node1])); + + // Calcul du point d'intersection par interpolation linéaire. + Real3 p; + p.x = node_coord[node0].x + t * (node_coord[node1].x - node_coord[node0].x); + p.y = node_coord[node0].y + t * (node_coord[node1].y - node_coord[node0].y); + p.z = node_coord[node0].z + t * (node_coord[node1].z - node_coord[node0].z); + + auto ni = NodeIntersection{ node0, node1, p }; + + if (!point_coords_tmp.contains(ni)) { + point_coords_tmp.add(ni); + } + } + } + } + + if (point_coords_tmp.size() >= 3) { + // On ajoute le uniqueId du nouveau noeud. Si ce noeud a déjà été créé, on récupère son uniqueId. + { + for (auto& new_node : point_coords_tmp) { + auto pos = point_coords.span().findFirst(new_node); + if (pos) { + new_node.m_uid_new_node = point_coords[pos.value()].m_uid_new_node; + } + else { + new_node.m_uid_new_node = sd_nb_node++; + pos_node.add(new_node.m_intersection_pos); + point_coords.add(new_node); + } + } + } + + if (point_coords_tmp.size() == 3) + cells_infos.add(ITI_Triangle3); + else if (point_coords_tmp.size() == 4) + cells_infos.add(ITI_Quad4); + else if (point_coords_tmp.size() == 5) + cells_infos.add(ITI_Pentagon5); + else if (point_coords_tmp.size() == 6) + cells_infos.add(ITI_Hexagon6); + else + ARCANE_FATAL("Pas implem : {0}", point_coords_tmp.size()); + + cells_infos.add(sd_nb_cell); + + { + // Calcul du barycentre de tous les points d'intersection. + Real3 bary{ 0 }; + for (const auto& node : point_coords_tmp) { + bary += node.m_intersection_pos; + } + bary /= point_coords_tmp.size(); + + // On choisit un vecteur de référence arbitraire non parallèle au normal. + // Si normal.x est grand (proche de l'axe X), utiliser l'axe Y ; sinon utiliser l'axe X. + const Real3 arbitrary = (std::abs(normal.x) > 0.9) ? Real3{ 0.0, 1.0, 0.0 } : Real3{ 1.0, 0.0, 0.0 }; + // u et v forment une base orthonormale du plan de coupe. + // Ils sont perpendiculaires au normal et l'un à l'autre. + const Real3 u = math::normalizedCrossProduct3(arbitrary, normal); + const Real3 v = math::normalizedCrossProduct3(normal, u); + + // On trie les points d'intersection par angle polaire autour du barycentre. + // Cela garantit que le polygone résultant est correctement ordonné (sens inverse des aiguilles d'une montre). + UniqueArray indices; + indices.reserve(point_coords_tmp.size()); + for (Int64 i = 0; i < point_coords_tmp.size(); ++i) { + indices.add(i); + } + + std::sort(indices.begin(), indices.end(), + [&](Int64 ia, Int64 ib) { + const Real3& pa = point_coords_tmp[ia].m_intersection_pos; + const Real3& pb = point_coords_tmp[ib].m_intersection_pos; + + // Vecteurs allant du barycentre vers chaque point. + const Real3 va{ pa - bary }; + const Real3 vb{ pb - bary }; + + // Projeter sur la base 2D du plan (u, v). + const Real a_x = math::dot(va, u); + const Real a_y = math::dot(va, v); + + const Real b_x = math::dot(vb, u); + const Real b_y = math::dot(vb, v); + + // Comparer les angles en utilisant atan2. + const Real angle_a = std::atan2(a_y, a_x); + const Real angle_b = std::atan2(b_y, b_x); + + return angle_a < angle_b; + }); + + for (Int64 idx : indices) { + ARCANE_FATAL_IF(point_coords_tmp[idx].m_uid_new_node == -1, "aaa {0}", point_coords_tmp[idx].m_uid_new_node); + cells_infos.add(point_coords_tmp[idx].m_uid_new_node); + } + } + sd_nb_cell++; + } + point_coords_tmp.clear(); + } + + // for (auto elem : point_coords) { + // info() << "UID : " << elem.m_uid_new_node << "\t -- Node0 : " << elem.m_lid_node0 << "\t -- Node1 : " << elem.m_lid_node1 << "\t -- Pos : " << elem.m_intersection_pos; + // } +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_compute() +{ + UniqueArray cells_infos; + cells_infos.reserve(10000); + + UniqueArray pos_node; + pos_node.reserve(10000); + + Int32 nb_cell = 0; + Int32 nb_node = 0; + + for (Int32 i = 0; i < m_plans.size(); ++i) { + _createCells(i, nb_cell, nb_node, cells_infos, pos_node); + } + + m_cloned_mesh->modifier()->addCells(nb_cell, cells_infos); + m_cloned_mesh->modifier()->endUpdate(); + + { + VariableNodeReal3& node_coords(m_cloned_mesh->nodesCoordinates()); + ENUMERATE_ (Node, inode, m_cloned_mesh->allNodes()) { + node_coords[inode] = pos_node[inode->uniqueId()]; + } + } + + info() << "New mesh -- NbNode : " << m_cloned_mesh->nbNode() << " -- NbCells : " << m_cloned_mesh->nbCell(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +} // namespace Arcane + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/std/srcs.cmake b/arcane/src/arcane/std/srcs.cmake index db40e67d17..1a6cbfb1f4 100644 --- a/arcane/src/arcane/std/srcs.cmake +++ b/arcane/src/arcane/std/srcs.cmake @@ -56,6 +56,7 @@ ProfilingInfo.cc ProfilingInfo.h MasterModule.cc + MeshCutService.cc UnitTestModule.cc ArcaneStdRegisterer.h TextReader.h @@ -155,4 +156,5 @@ set(AXL_FILES SplitSDMeshPartitioner KdiPostProcessor VtkPolyhedralMeshIO + MeshCut ) From 267cfd4e8e5aa72515518cfcf4660dc53541e664 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Wed, 15 Jul 2026 09:19:48 +0200 Subject: [PATCH 02/17] [arcane:std] Add first version of MeshSection service --- arcane/src/arcane/std/MeshSection.axl | 16 ++ arcane/src/arcane/std/MeshSectionService.cc | 204 ++++++++++++++++++++ arcane/src/arcane/std/srcs.cmake | 2 + 3 files changed, 222 insertions(+) create mode 100644 arcane/src/arcane/std/MeshSection.axl create mode 100644 arcane/src/arcane/std/MeshSectionService.cc diff --git a/arcane/src/arcane/std/MeshSection.axl b/arcane/src/arcane/std/MeshSection.axl new file mode 100644 index 0000000000..fa01fb2cb8 --- /dev/null +++ b/arcane/src/arcane/std/MeshSection.axl @@ -0,0 +1,16 @@ + + + + + TODO + + + + + + + + + + + diff --git a/arcane/src/arcane/std/MeshSectionService.cc b/arcane/src/arcane/std/MeshSectionService.cc new file mode 100644 index 0000000000..af94e6345a --- /dev/null +++ b/arcane/src/arcane/std/MeshSectionService.cc @@ -0,0 +1,204 @@ +// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*- +//----------------------------------------------------------------------------- +// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com) +// See the top-level COPYRIGHT file for details. +// SPDX-License-Identifier: Apache-2.0 +//----------------------------------------------------------------------------- +/*---------------------------------------------------------------------------*/ +/* MeshSectionService.cc (C) 2000-2026 */ +/* */ +/* TODO. */ +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#include "arcane/core/IMesh.h" +#include "arcane/core/IMeshFactoryMng.h" +#include "arcane/core/IMeshMng.h" +#include "arcane/core/IMeshModifier.h" +#include "arcane/core/IMeshSection.h" +#include "arcane/core/IPrimaryMesh.h" +#include "arcane/core/MeshBuildInfo.h" + +#include "arcane/std/MeshSection_axl.h" + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +namespace Arcane +{ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +class MeshSectionService +: public ArcaneMeshSectionObject +{ + public: + + explicit MeshSectionService(const ServiceBuildInfo& sbi) + : ArcaneMeshSectionObject(sbi) + {} + + public: + + void addPlan(const Real3& p0, const Real3& normal) override; + + public: + + void setVariables(VariableCollection variables) override; + void updateSection() override; + + MeshHandle meshSection() override + { + return m_cloned_mesh->handle(); + } + VariableCollection variables() override { return {}; } + + private: + + void _createMesh(); + void _createCells(Int32& nb_cell, UniqueArray& cells_infos, std::unordered_map& pos_node); + void _compute(); + + private: + + VariableCollection m_variables_ori; + IPrimaryMesh* m_cloned_mesh = nullptr; + UniqueArray> m_plans; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +ARCANE_REGISTER_SERVICE_MESHSECTION(MeshSectionService, MeshSectionService); + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshSectionService:: +addPlan(const Real3& p0, const Real3& normal) +{ + m_plans.add({ p0, math::normalizeReal3(normal) }); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshSectionService:: +setVariables(VariableCollection variables) +{ + m_variables_ori = variables; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshSectionService:: +updateSection() +{ + if (m_cloned_mesh == nullptr) { + _createMesh(); + } + else { + m_cloned_mesh->modifier()->clearItems(); + } + _compute(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshSectionService:: +_createMesh() +{ + IMeshMng* mm = subDomain()->meshMng(); + IParallelMng* pm = subDomain()->parallelMng(); + // TODO gérer cas où il y a plusieurs services pour même maillage. + MeshBuildInfo mbi(mesh()->name() + "_MeshSection"); + mbi.addParallelMng(makeRef(pm)); + m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi); + m_cloned_mesh->modifier()->setDynamic(true); + m_cloned_mesh->setDimension(mesh()->dimension()); + m_cloned_mesh->endAllocate(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshSectionService:: +_createCells(Int32& sd_nb_cell, UniqueArray& cells_infos, std::unordered_map& pos_node) +{ + VariableNodeReal3& node_coord = mesh()->nodesCoordinates(); + + ENUMERATE_ (Cell, icell, allCells()) { + Real3 b{ 0 }; + for (Node node : icell->nodes()) { + b += node_coord[node]; + } + b /= icell->nbNode(); + + bool in_cut = true; + for (auto& [p0, normal] : m_plans) { + const Real dist = math::dot({ b - p0 }, normal); + if (dist < 0) { + in_cut = false; + break; + } + } + + if (!in_cut) + continue; + + Int16 cell_type = icell->itemTypeId(); + cells_infos.add(cell_type); + + Int64 cell_uid = icell->uniqueId().asInt64(); + cells_infos.add(cell_uid); + + for (Node node : icell->nodes()) { + Int64 node_uid = node.uniqueId().asInt64(); + cells_infos.add(node_uid); + pos_node[node.uniqueId()] = node_coord[node]; + } + ++sd_nb_cell; + } +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshSectionService:: +_compute() +{ + UniqueArray cells_infos; + cells_infos.reserve(10000); + + std::unordered_map coord_map; + + Int32 nb_cell = 0; + + _createCells(nb_cell, cells_infos, coord_map); + + m_cloned_mesh->modifier()->addCells(nb_cell, cells_infos); + m_cloned_mesh->modifier()->endUpdate(); + + { + VariableNodeReal3& node_coords(m_cloned_mesh->nodesCoordinates()); + ENUMERATE_ (Node, inode, m_cloned_mesh->allNodes()) { + node_coords[inode] = coord_map[inode->uniqueId()]; + } + } + + info() << "New mesh -- NbNode : " << m_cloned_mesh->nbNode() << " -- NbCells : " << m_cloned_mesh->nbCell(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +} // namespace Arcane + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/std/srcs.cmake b/arcane/src/arcane/std/srcs.cmake index 1a6cbfb1f4..ae250b4ebc 100644 --- a/arcane/src/arcane/std/srcs.cmake +++ b/arcane/src/arcane/std/srcs.cmake @@ -57,6 +57,7 @@ ProfilingInfo.h MasterModule.cc MeshCutService.cc + MeshSectionService.cc UnitTestModule.cc ArcaneStdRegisterer.h TextReader.h @@ -157,4 +158,5 @@ set(AXL_FILES KdiPostProcessor VtkPolyhedralMeshIO MeshCut + MeshSection ) From 5cfa19da9f7cfe0a528344caf1769e23db899736 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Thu, 16 Jul 2026 14:09:14 +0200 Subject: [PATCH 03/17] [arcane:core,std] Add doc and some improvements --- arcane/src/arcane/core/IMeshSection.h | 47 ++++- arcane/src/arcane/std/MeshCutService.cc | 190 +++++++++++++------- arcane/src/arcane/std/MeshSectionService.cc | 43 +++-- 3 files changed, 195 insertions(+), 85 deletions(-) diff --git a/arcane/src/arcane/core/IMeshSection.h b/arcane/src/arcane/core/IMeshSection.h index baf514d773..2a4bf5d239 100644 --- a/arcane/src/arcane/core/IMeshSection.h +++ b/arcane/src/arcane/core/IMeshSection.h @@ -5,9 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 //----------------------------------------------------------------------------- /*---------------------------------------------------------------------------*/ -/* IMeshSection.h (C) 2000-2026 */ +/* IMeshSection.h (C) 2000-2026 */ /* */ -/* TODO. */ +/* Service interface allowing the creation of a mesh with a section of */ +/* another mesh. */ /*---------------------------------------------------------------------------*/ #ifndef ARCANE_CORE_IMESHSECTION_H #define ARCANE_CORE_IMESHSECTION_H @@ -15,7 +16,6 @@ /*---------------------------------------------------------------------------*/ #include "arcane/core/ArcaneTypes.h" -#include "arcane/core/IService.h" /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -32,6 +32,10 @@ class MeshHandle; /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +/*! + * \brief Service interface allowing the creation of a mesh with a section of + * another mesh. + */ class ARCANE_CORE_EXPORT IMeshSection { public: @@ -41,14 +45,45 @@ class ARCANE_CORE_EXPORT IMeshSection public: - virtual void addPlan(const Real3& p0, const Real3& normal) = 0; - + /*! + * \brief Method allowing to add a plane to the cut service. The use of + * these planes depends on the service. + * + * \param p0 Point of the plane. + * \param normal Normal of the plane. + */ + virtual void addPlane(const Real3& p0, const Real3& normal) = 0; + + /*! + * \brief Method allowing to add a set of variables to copy on the + * new mesh. + * + * \param variables A set of variable on the original mesh. + */ virtual void setVariables(VariableCollection variables) = 0; + + /*! + * \brief Method allowing to get a set of variables copied on the new + * mesh. + * + * \return A set of variables on the cloned mesh. + */ virtual VariableCollection variables() = 0; + /*! + * \brief Method allowing to update the mesh section with all planes. + * + * If a previous call has edited the mesh, all the cells will be destroyed + * before update. + */ virtual void updateSection() = 0; - virtual MeshHandle meshSection() = 0; + /*! + * \brief Méthod allowing to get the mesh section. + * + * \return The mesh section. + */ + virtual MeshHandle meshSection() = 0; }; /*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index 6b6f444042..fad74e2ed1 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -7,7 +7,7 @@ /*---------------------------------------------------------------------------*/ /* MeshCutService.cc (C) 2000-2026 */ /* */ -/* TODO. */ +/* Service allowing the creation of a mesh with a cut of another mesh. */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -30,6 +30,13 @@ namespace Arcane /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +/*! + * \brief Service allowing the creation of a mesh with a cut of another mesh. + * + * For each plan, a cut will be realized. All cuts will be stored in the mesh + * created by this service. To get this mesh, you can call \a meshSection() + * method. + */ class MeshCutService : public ArcaneMeshCutObject { @@ -41,17 +48,17 @@ class MeshCutService public: - void addPlan(const Real3& p0, const Real3& normal) override; - - public: + void addPlane(const Real3& p0, const Real3& normal) override; void setVariables(VariableCollection variables) override; + void updateSection() override; MeshHandle meshSection() override { return m_cloned_mesh->handle(); } + VariableCollection variables() override { return {}; } private: @@ -62,7 +69,7 @@ class MeshCutService private: - VariableCollection m_variables_ori; + // VariableCollection m_variables_ori; IPrimaryMesh* m_cloned_mesh = nullptr; UniqueArray> m_plans; }; @@ -78,13 +85,12 @@ ARCANE_REGISTER_SERVICE_MESHCUT(MeshCutService, MeshCutService); /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -struct NodeIntersection +struct EdgeLite { - NodeIntersection(const Node aa, const Node bb, const Real3& inter) - : m_intersection_pos(inter) + EdgeLite(const Node first_node, const Node second_node) { - const Int32 a = aa.localId(); - const Int32 b = bb.localId(); + const Int32 a = first_node.localId(); + const Int32 b = second_node.localId(); if (a < b) { m_lid_node0 = a; m_lid_node1 = b; @@ -95,9 +101,9 @@ struct NodeIntersection } } - NodeIntersection() = default; + EdgeLite() = default; - bool operator<(const NodeIntersection& other) const + bool operator<(const EdgeLite& other) const { if (m_lid_node0 != other.m_lid_node0) { return m_lid_node0 < other.m_lid_node0; @@ -105,25 +111,50 @@ struct NodeIntersection return m_lid_node1 < other.m_lid_node1; } - bool operator==(const NodeIntersection& other) const + bool operator==(const EdgeLite& other) const { return m_lid_node0 == other.m_lid_node0 && m_lid_node1 == other.m_lid_node1; } Int32 m_lid_node0 = -1; Int32 m_lid_node1 = -1; - Real3 m_intersection_pos{ -1 }; Int64 m_uid_new_node = -1; }; /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +struct NodeIntersection +{ + NodeIntersection(const Node first_node, const Node second_node, const Real3& intersection_pos) + : m_edge(first_node, second_node) + ,m_intersection_pos(intersection_pos) + {} + + NodeIntersection() = default; + + bool operator<(const NodeIntersection& other) const + { + return m_edge.operator<(other.m_edge); + } + + bool operator==(const NodeIntersection& other) const + { + return m_edge.operator==(other.m_edge); + } + + EdgeLite m_edge{}; + Real3 m_intersection_pos{ -1 }; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void MeshCutService:: -addPlan(const Real3& p0, const Real3& normal) +addPlane(const Real3& p0, const Real3& normal) { m_plans.add({ p0, math::normalizeReal3(normal) }); } @@ -134,7 +165,9 @@ addPlan(const Real3& p0, const Real3& normal) void MeshCutService:: setVariables(VariableCollection variables) { - m_variables_ori = variables; + ARCANE_UNUSED(variables); + ARCANE_NOT_YET_IMPLEMENTED("Not supported yet"); + // m_variables_ori = variables; } /*---------------------------------------------------------------------------*/ @@ -181,6 +214,8 @@ _createCells(Int32 plan_pos, Int32& sd_nb_cell, Int32& sd_nb_node, UniqueArraydimension(); + VariableNodeReal3& node_coord = mesh()->nodesCoordinates(); VariableNodeReal node_dist(VariableBuildInfo(mesh(), "NodeDist")); @@ -188,70 +223,97 @@ _createCells(Int32 plan_pos, Int32& sd_nb_cell, Int32& sd_nb_node, UniqueArray point_coords; + + // Tableau qui contiendra tous les noeuds d'une future maille. + // Une maille 3D, si elle est coupée par le plan, donnera forcément une + // maille 2D. Les noeuds de cette maille seront stockés dans ce tableau, + // ainsi que, pour chaque noeud, sa position et l'arête dont il est issu + // (pour éviter les doublons). UniqueArray point_coords_tmp; + // Tableau qui contiendra tous les noeuds du maillage futur. + UniqueArray point_coords; + ENUMERATE_ (Cell, icell, ownCells()) { - ItemWithNodes cell = *icell; + Cell cell = *icell; - // On regarde si la maille traverse le plan ou si une de ces faces est collé dessus. - bool colineaire = false; + bool has_face_on_plane = false; { - bool cont = true; + bool cell_useful = true; + Int32 nb_node_on_plane = 0; - // Si au moins un noeud est sur le plan, peut-être que la face est colinéaire. - bool has_egal = false; + // On regarde si la maille traverse le plan ou si des noeuds sont sur le + // plan. { - // On vérifie que la maille est dans le plan. - bool has_neg = false, has_pos = false; + bool has_neg = false; + bool has_pos = false; for (Node node : cell.nodes()) { Real d = node_dist[node]; if (d < 0) has_neg = true; else if (d > 0) has_pos = true; - else - has_egal = true; + else { + nb_node_on_plane++; + } } + + // Tous les noeuds sont du même coté du plan. if (!(has_neg && has_pos)) - cont = false; + cell_useful = false; } - // On vérifie si une des faces est sur le plan. - if (!cont && has_egal) { - for (Face face : icell->faces()) { - has_egal = true; + + // Si le nombre de noeuds sur le plan correspond au nombre de noeuds + // minimum d'une face, il s'agit peut-être d'une face confondue au plan. + // Dans ce cas, il est nécessaire de faire un traitement spécial pour + // éviter un doublon de mailles dans le maillage final. + if (nb_node_on_plane >= mesh_dim) { + for (Face face : cell.faces()) { + if (face.nbNode() != nb_node_on_plane) + continue; + + bool has_egal = true; for (Node node : face.nodes()) { - if (!math::isNearlyZero(node_dist[node])) { + if (node_dist[node] != 0) { has_egal = false; break; } } + + // On a trouvé la face confondue. if (has_egal) { + + // Si elle a déjà été traitée, on passe pour éviter un doublon. if (face_already_computed.contains(face.localId())) { - cont = false; + cell_useful = false; break; } + + // On sait que la face est confondue au plan et que la future + // maille créée grâce à cette face n'existe pas encore. + // On peut donc directement ajouter les noeuds de la face dans la + // liste des noeuds de la future maille. face_already_computed.add(face.localId()); for (Node node : face.nodes()) { auto ni = NodeIntersection{ node, node, node_coord[node] }; point_coords_tmp.add(ni); } - cont = true; - cell = face; - colineaire = true; + has_face_on_plane = true; + cell_useful = true; break; } } } - if (!cont) { + + if (!cell_useful) continue; - } } - if (!colineaire) { + if (!has_face_on_plane) { // Tableaux définissant les arêtes pour chaque type d'élément. // hexa_edge: 12 arêtes pour un hexaédre (8 noeuds), chaque arête = [n0, n1] indices locaux. static constexpr Integer hexa_edge[12][2] = { @@ -292,7 +354,7 @@ _createCells(Int32 plan_pos, Int32& sd_nb_cell, Int32& sd_nb_node, UniqueArray= 3) { + // Si le nombre de futurs noeuds est suffisant pour en faire une maille. + if (point_coords_tmp.size() >= mesh_dim) { + // On ajoute le uniqueId du nouveau noeud. Si ce noeud a déjà été créé, on récupère son uniqueId. - { - for (auto& new_node : point_coords_tmp) { - auto pos = point_coords.span().findFirst(new_node); - if (pos) { - new_node.m_uid_new_node = point_coords[pos.value()].m_uid_new_node; - } - else { - new_node.m_uid_new_node = sd_nb_node++; - pos_node.add(new_node.m_intersection_pos); - point_coords.add(new_node); - } + for (auto& new_node : point_coords_tmp) { + std::optional pos = point_coords.span().findFirst(new_node.m_edge); + if (pos) { + new_node.m_edge.m_uid_new_node = point_coords[pos.value()].m_uid_new_node; + } + else { + new_node.m_edge.m_uid_new_node = sd_nb_node++; + pos_node.add(new_node.m_intersection_pos); + point_coords.add(new_node.m_edge); } } + // Type cell. if (point_coords_tmp.size() == 3) cells_infos.add(ITI_Triangle3); else if (point_coords_tmp.size() == 4) @@ -375,6 +438,7 @@ _createCells(Int32 plan_pos, Int32& sd_nb_cell, Int32& sd_nb_node, UniqueArray> m_plans; }; @@ -79,7 +86,7 @@ ARCANE_REGISTER_SERVICE_MESHSECTION(MeshSectionService, MeshSectionService); /*---------------------------------------------------------------------------*/ void MeshSectionService:: -addPlan(const Real3& p0, const Real3& normal) +addPlane(const Real3& p0, const Real3& normal) { m_plans.add({ p0, math::normalizeReal3(normal) }); } @@ -90,7 +97,9 @@ addPlan(const Real3& p0, const Real3& normal) void MeshSectionService:: setVariables(VariableCollection variables) { - m_variables_ori = variables; + ARCANE_UNUSED(variables); + ARCANE_NOT_YET_IMPLEMENTED("Not supported yet"); + // m_variables_ori = variables; } /*---------------------------------------------------------------------------*/ @@ -140,17 +149,19 @@ _createCells(Int32& sd_nb_cell, UniqueArray& cells_infos, std::unordered_ } b /= icell->nbNode(); - bool in_cut = true; - for (auto& [p0, normal] : m_plans) { - const Real dist = math::dot({ b - p0 }, normal); - if (dist < 0) { - in_cut = false; - break; + { + bool in_plan = true; + for (auto& [p0, normal] : m_plans) { + const Real dist = math::dot({ b - p0 }, normal); + if (dist < 0) { + in_plan = false; + break; + } } - } - if (!in_cut) - continue; + if (!in_plan) + continue; + } Int16 cell_type = icell->itemTypeId(); cells_infos.add(cell_type); From 7ef390ad6dfa0fcb3cd8469cca9b39ccf2481167 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Thu, 16 Jul 2026 15:51:55 +0200 Subject: [PATCH 04/17] [arcane:tests,std] Add a test for MeshCut and MeshSection --- arcane/src/arcane/std/MeshCut.axl | 2 +- arcane/src/arcane/std/MeshSection.axl | 2 +- arcane/src/arcane/tests/CMakeLists.txt | 5 ++ arcane/src/arcane/tests/MeshCutTest.axl | 14 +++ arcane/src/arcane/tests/MeshCutTest.cc | 93 ++++++++++++++++++++ arcane/src/arcane/tests/MeshSectionTest.axl | 14 +++ arcane/src/arcane/tests/MeshSectionTest.cc | 95 +++++++++++++++++++++ arcane/src/arcane/tests/srcs.cmake | 4 + arcane/tests/testMeshCut-1.arc | 35 ++++++++ arcane/tests/testMeshSection-1.arc | 28 ++++++ 10 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 arcane/src/arcane/tests/MeshCutTest.axl create mode 100644 arcane/src/arcane/tests/MeshCutTest.cc create mode 100644 arcane/src/arcane/tests/MeshSectionTest.axl create mode 100644 arcane/src/arcane/tests/MeshSectionTest.cc create mode 100644 arcane/tests/testMeshCut-1.arc create mode 100644 arcane/tests/testMeshSection-1.arc diff --git a/arcane/src/arcane/std/MeshCut.axl b/arcane/src/arcane/std/MeshCut.axl index ca2b67e897..d9165da2f6 100644 --- a/arcane/src/arcane/std/MeshCut.axl +++ b/arcane/src/arcane/std/MeshCut.axl @@ -2,7 +2,7 @@ - TODO + Service allowing the creation of a mesh with a cut of another mesh. diff --git a/arcane/src/arcane/std/MeshSection.axl b/arcane/src/arcane/std/MeshSection.axl index fa01fb2cb8..8557a1b376 100644 --- a/arcane/src/arcane/std/MeshSection.axl +++ b/arcane/src/arcane/std/MeshSection.axl @@ -2,7 +2,7 @@ - TODO + Service allowing the creation of a mesh with a section of another mesh. diff --git a/arcane/src/arcane/tests/CMakeLists.txt b/arcane/src/arcane/tests/CMakeLists.txt index 746135d3d9..c796242052 100644 --- a/arcane/src/arcane/tests/CMakeLists.txt +++ b/arcane/src/arcane/tests/CMakeLists.txt @@ -1422,6 +1422,11 @@ endif () # ---------------------------------------------------------------------------- +arcane_add_test_sequential(meshcut1 testMeshCut-1.arc) +arcane_add_test_sequential(meshsection1 testMeshSection-1.arc) + +# ---------------------------------------------------------------------------- + include(accelerator/tests.cmake) include(cartesianmesh/tests.cmake) include(geometry/tests.cmake) diff --git a/arcane/src/arcane/tests/MeshCutTest.axl b/arcane/src/arcane/tests/MeshCutTest.axl new file mode 100644 index 0000000000..f2100fc036 --- /dev/null +++ b/arcane/src/arcane/tests/MeshCutTest.axl @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/arcane/src/arcane/tests/MeshCutTest.cc b/arcane/src/arcane/tests/MeshCutTest.cc new file mode 100644 index 0000000000..8ad5d5ec52 --- /dev/null +++ b/arcane/src/arcane/tests/MeshCutTest.cc @@ -0,0 +1,93 @@ +// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*- +//----------------------------------------------------------------------------- +// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com) +// See the top-level COPYRIGHT file for details. +// SPDX-License-Identifier: Apache-2.0 +//----------------------------------------------------------------------------- +/*---------------------------------------------------------------------------*/ +/* MeshCutTest.cc (C) 2000-2026 */ +/* */ +/* MeshCut test service. */ +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#include "arcane/core/BasicUnitTest.h" +#include "arcane/core/IMeshSection.h" +#include "arcane/core/ServiceBuilder.h" + +#include "arcane/tests/MeshCutTest_axl.h" + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +namespace ArcaneTest +{ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +using namespace Arcane; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +class MeshCutTest +: public ArcaneMeshCutTestObject +{ + public: + + explicit MeshCutTest(const ServiceBuildInfo& sbi); + ~MeshCutTest() override = default; + + public: + + void initializeTest() override; + void executeTest() override; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +ARCANE_REGISTER_SERVICE_MESHCUTTEST(MeshCutTest, MeshCutTest); + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +MeshCutTest:: +MeshCutTest(const ServiceBuildInfo& sbi) +: ArcaneMeshCutTestObject(sbi) +{} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutTest:: +initializeTest() +{ +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutTest:: +executeTest() +{ + ServiceBuilder spp0(mesh()->handle()); + Ref pp0 = spp0.createReference("MeshCutService"); + + for (auto plane : options()->plane()) { + pp0->addPlane(plane->p0(), plane->normal()); + } + + pp0->updateSection(); + MeshHandle meshsh = pp0->meshSection(); + IMesh* meshs = meshsh.mesh(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +} // namespace ArcaneTest + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/tests/MeshSectionTest.axl b/arcane/src/arcane/tests/MeshSectionTest.axl new file mode 100644 index 0000000000..26e3d6b642 --- /dev/null +++ b/arcane/src/arcane/tests/MeshSectionTest.axl @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/arcane/src/arcane/tests/MeshSectionTest.cc b/arcane/src/arcane/tests/MeshSectionTest.cc new file mode 100644 index 0000000000..bb62ea9a78 --- /dev/null +++ b/arcane/src/arcane/tests/MeshSectionTest.cc @@ -0,0 +1,95 @@ +// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*- +//----------------------------------------------------------------------------- +// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com) +// See the top-level COPYRIGHT file for details. +// SPDX-License-Identifier: Apache-2.0 +//----------------------------------------------------------------------------- +/*---------------------------------------------------------------------------*/ +/* MeshSectionTest.cc (C) 2000-2026 */ +/* */ +/* MeshSection test service. */ +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#include "arcane/core/BasicUnitTest.h" +#include "arcane/core/ServiceBuilder.h" +#include "arcane/core/IMeshSection.h" + +#include "arcane/tests/MeshSectionTest_axl.h" + + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +namespace ArcaneTest +{ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +using namespace Arcane; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +class MeshSectionTest +: public ArcaneMeshSectionTestObject +{ + public: + + explicit MeshSectionTest(const ServiceBuildInfo& sbi); + ~MeshSectionTest() override = default; + + public: + + void initializeTest() override; + void executeTest() override; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +ARCANE_REGISTER_SERVICE_MESHSECTIONTEST(MeshSectionTest, MeshSectionTest); + + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +MeshSectionTest:: +MeshSectionTest(const ServiceBuildInfo& sbi) +: ArcaneMeshSectionTestObject(sbi) +{} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshSectionTest:: +initializeTest() +{ +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshSectionTest:: +executeTest() +{ + ServiceBuilder spp0(mesh()->handle()); + Ref pp0 = spp0.createReference("MeshSectionService"); + + for (auto plane : options()->plane()) { + pp0->addPlane(plane->p0(), plane->normal()); + } + + pp0->updateSection(); + MeshHandle meshsh = pp0->meshSection(); + IMesh* meshs = meshsh.mesh(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +} // namespace ArcaneTest + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/tests/srcs.cmake b/arcane/src/arcane/tests/srcs.cmake index 457b707dd8..1dae6cf5a6 100644 --- a/arcane/src/arcane/tests/srcs.cmake +++ b/arcane/src/arcane/tests/srcs.cmake @@ -89,6 +89,8 @@ set(ARCANE_SOURCES HyodaMixedCellsUnitTest.cc HllcSchemeTypes.h HllcSchemeModule.cc + MeshCutTest.cc + MeshSectionTest.cc ) set(ARCANE_ACCELERATOR_SOURCES ArcaneTestStandaloneSubDomain.cc @@ -146,4 +148,6 @@ set(AXL_FILES RayMeshIntersectionUnitTest HyodaMixedCellsUnitTest HllcScheme + MeshCutTest + MeshSectionTest ) diff --git a/arcane/tests/testMeshCut-1.arc b/arcane/tests/testMeshCut-1.arc new file mode 100644 index 0000000000..1889985937 --- /dev/null +++ b/arcane/tests/testMeshCut-1.arc @@ -0,0 +1,35 @@ + + + + Test MeshCut 1 + Test MeshCut 1 + UnitTest + + + + + + 1 + 1 + 1 + 0.0 0.0 0.0 + 22.0 + 22.0 + 22.0 + + + + + + + + 1 0 0 + 1 0 0 + + + 1.6 0 0 + 1 0.5 0.1 + + + + diff --git a/arcane/tests/testMeshSection-1.arc b/arcane/tests/testMeshSection-1.arc new file mode 100644 index 0000000000..89f7af02c3 --- /dev/null +++ b/arcane/tests/testMeshSection-1.arc @@ -0,0 +1,28 @@ + + + + Test MeshCut 1 + Test MeshCut 1 + UnitTest + + + + + sod3d-misc.msh + + + + + + + 0.4 0 0 + 1 0 0 + + + 0.6 0 0 + -1 0 0 + + + + + From 2e6792afc7d274a987cbe4d1e485e87e3e533043 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Thu, 16 Jul 2026 16:22:14 +0200 Subject: [PATCH 05/17] [arcane:std] Add a addFaces() to support parallel execution --- arcane/src/arcane/std/MeshCutService.cc | 4 ++ arcane/src/arcane/std/MeshSectionService.cc | 44 ++++++++++++++++----- arcane/src/arcane/tests/CMakeLists.txt | 4 +- arcane/tests/testMeshCut-1.arc | 4 +- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index fad74e2ed1..79e0e7db23 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -11,6 +11,7 @@ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +#include "arcane/core/IGhostLayerMng.h" #include "arcane/core/IMesh.h" #include "arcane/core/IMeshFactoryMng.h" #include "arcane/core/IMeshMng.h" @@ -176,6 +177,9 @@ setVariables(VariableCollection variables) void MeshCutService:: updateSection() { + if (mesh()->ghostLayerMng()->nbGhostLayer() < 1) { + ARCANE_FATAL("A ghost layer is required for this service"); + } if (m_cloned_mesh == nullptr) { _createMesh(); } diff --git a/arcane/src/arcane/std/MeshSectionService.cc b/arcane/src/arcane/std/MeshSectionService.cc index e847ee4e79..b6e9be3590 100644 --- a/arcane/src/arcane/std/MeshSectionService.cc +++ b/arcane/src/arcane/std/MeshSectionService.cc @@ -64,7 +64,7 @@ class MeshSectionService private: void _createMesh(); - void _createCells(Int32& nb_cell, UniqueArray& cells_infos, std::unordered_map& pos_node); + void _createCells(Int32& nb_cell, UniqueArray& cells_infos, Int32& nb_face, UniqueArray& faces_infos, std::unordered_map& pos_node); void _compute(); private: @@ -138,18 +138,21 @@ _createMesh() /*---------------------------------------------------------------------------*/ void MeshSectionService:: -_createCells(Int32& sd_nb_cell, UniqueArray& cells_infos, std::unordered_map& pos_node) +_createCells(Int32& sd_nb_cell, UniqueArray& cells_infos, Int32& sd_nb_face, UniqueArray& faces_infos, std::unordered_map& pos_node) { VariableNodeReal3& node_coord = mesh()->nodesCoordinates(); - ENUMERATE_ (Cell, icell, allCells()) { - Real3 b{ 0 }; - for (Node node : icell->nodes()) { - b += node_coord[node]; - } - b /= icell->nbNode(); + VariableFaceBool is_added(VariableBuildInfo(mesh(), "IsAdded")); + is_added.fill(false); + ENUMERATE_ (Cell, icell, ownCells()) { { + Real3 b{ 0 }; + for (Node node : icell->nodes()) { + b += node_coord[node]; + } + b /= icell->nbNode(); + bool in_plan = true; for (auto& [p0, normal] : m_plans) { const Real dist = math::dot({ b - p0 }, normal); @@ -175,6 +178,24 @@ _createCells(Int32& sd_nb_cell, UniqueArray& cells_infos, std::unordered_ pos_node[node.uniqueId()] = node_coord[node]; } ++sd_nb_cell; + + for (Face face : icell->faces()) { + if (is_added[face]) continue; + is_added[face] = true; + + Int16 face_type = face.itemTypeId(); + faces_infos.add(face_type); + + Int64 face_uid = face.uniqueId().asInt64(); + faces_infos.add(face_uid); + + for (Node node : face.nodes()) { + Int64 node_uid = node.uniqueId().asInt64(); + faces_infos.add(node_uid); + pos_node[node.uniqueId()] = node_coord[node]; + } + ++sd_nb_face; + } } } @@ -187,12 +208,17 @@ _compute() UniqueArray cells_infos; cells_infos.reserve(10000); + UniqueArray faces_infos; + faces_infos.reserve(10000); + std::unordered_map coord_map; Int32 nb_cell = 0; + Int32 nb_face = 0; - _createCells(nb_cell, cells_infos, coord_map); + _createCells(nb_cell, cells_infos, nb_face, faces_infos, coord_map); + m_cloned_mesh->modifier()->addFaces(nb_face, faces_infos); m_cloned_mesh->modifier()->addCells(nb_cell, cells_infos); m_cloned_mesh->modifier()->endUpdate(); diff --git a/arcane/src/arcane/tests/CMakeLists.txt b/arcane/src/arcane/tests/CMakeLists.txt index c796242052..ed934aad00 100644 --- a/arcane/src/arcane/tests/CMakeLists.txt +++ b/arcane/src/arcane/tests/CMakeLists.txt @@ -1422,8 +1422,8 @@ endif () # ---------------------------------------------------------------------------- -arcane_add_test_sequential(meshcut1 testMeshCut-1.arc) -arcane_add_test_sequential(meshsection1 testMeshSection-1.arc) +arcane_add_test(meshcut1 testMeshCut-1.arc) +arcane_add_test(meshsection1 testMeshSection-1.arc) # ---------------------------------------------------------------------------- diff --git a/arcane/tests/testMeshCut-1.arc b/arcane/tests/testMeshCut-1.arc index 1889985937..d4bd7472e8 100644 --- a/arcane/tests/testMeshCut-1.arc +++ b/arcane/tests/testMeshCut-1.arc @@ -9,8 +9,8 @@ - 1 - 1 + 2 + 2 1 0.0 0.0 0.0 22.0 From 64a9aabd6cb452e5e6176df7b2ceaabc8e6d6b7a Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Tue, 21 Jul 2026 11:09:16 +0200 Subject: [PATCH 06/17] [arcane:std] Add a first version of parallel MeshCut --- arcane/src/arcane/std/MeshCutService.cc | 200 +++++++++++++++--------- 1 file changed, 128 insertions(+), 72 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index 79e0e7db23..f950a6e676 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -21,6 +21,7 @@ #include "arcane/core/MeshBuildInfo.h" #include "arcane/std/MeshCut_axl.h" +#include "arccore/base/StringBuilder.h" /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -31,74 +32,19 @@ namespace Arcane /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -/*! - * \brief Service allowing the creation of a mesh with a cut of another mesh. - * - * For each plan, a cut will be realized. All cuts will be stored in the mesh - * created by this service. To get this mesh, you can call \a meshSection() - * method. - */ -class MeshCutService -: public ArcaneMeshCutObject -{ - public: - - explicit MeshCutService(const ServiceBuildInfo& sbi) - : ArcaneMeshCutObject(sbi) - {} - - public: - - void addPlane(const Real3& p0, const Real3& normal) override; - - void setVariables(VariableCollection variables) override; - - void updateSection() override; - - MeshHandle meshSection() override - { - return m_cloned_mesh->handle(); - } - - VariableCollection variables() override { return {}; } - - private: - - void _createMesh(); - void _createCells(Int32 plan_pos, Int32& nb_cell, Int32& nb_node, UniqueArray& cells_infos, UniqueArray& pos_node); - void _compute(); - - private: - - // VariableCollection m_variables_ori; - IPrimaryMesh* m_cloned_mesh = nullptr; - UniqueArray> m_plans; -}; - -/*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - -ARCANE_REGISTER_SERVICE_MESHCUT(MeshCutService, MeshCutService); - -/*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - struct EdgeLite { EdgeLite(const Node first_node, const Node second_node) { - const Int32 a = first_node.localId(); - const Int32 b = second_node.localId(); + const Int64 a = first_node.uniqueId(); + const Int64 b = second_node.uniqueId(); if (a < b) { - m_lid_node0 = a; - m_lid_node1 = b; + m_uid_node0 = a; + m_uid_node1 = b; } else { - m_lid_node0 = b; - m_lid_node1 = a; + m_uid_node0 = b; + m_uid_node1 = a; } } @@ -106,20 +52,21 @@ struct EdgeLite bool operator<(const EdgeLite& other) const { - if (m_lid_node0 != other.m_lid_node0) { - return m_lid_node0 < other.m_lid_node0; + if (m_uid_node0 != other.m_uid_node0) { + return m_uid_node0 < other.m_uid_node0; } - return m_lid_node1 < other.m_lid_node1; + return m_uid_node1 < other.m_uid_node1; } bool operator==(const EdgeLite& other) const { - return m_lid_node0 == other.m_lid_node0 && m_lid_node1 == other.m_lid_node1; + return m_uid_node0 == other.m_uid_node0 && m_uid_node1 == other.m_uid_node1; } - Int32 m_lid_node0 = -1; - Int32 m_lid_node1 = -1; + Int64 m_uid_node0 = -1; + Int64 m_uid_node1 = -1; Int64 m_uid_new_node = -1; + Int32 m_owner_new_node = -1; }; /*---------------------------------------------------------------------------*/ @@ -154,6 +101,63 @@ struct NodeIntersection /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +/*! + * \brief Service allowing the creation of a mesh with a cut of another mesh. + * + * For each plan, a cut will be realized. All cuts will be stored in the mesh + * created by this service. To get this mesh, you can call \a meshSection() + * method. + */ +class MeshCutService +: public ArcaneMeshCutObject +{ + public: + + explicit MeshCutService(const ServiceBuildInfo& sbi) + : ArcaneMeshCutObject(sbi) + {} + + public: + + void addPlane(const Real3& p0, const Real3& normal) override; + + void setVariables(VariableCollection variables) override; + + void updateSection() override; + + MeshHandle meshSection() override + { + return m_cloned_mesh->handle(); + } + + VariableCollection variables() override { return {}; } + + private: + + void _createMesh(); + void _createCells(Int32 plan_pos, Int32& nb_node, Int32& nb_cell, UniqueArray& cells_infos, Int32& sd_nb_face, UniqueArray& faces_infos, std::unordered_map& pos_node); + void _compute(); + + Int64 _edgeUid(Int64 node0_uid, Int64 node1_uid); + + private: + + // VariableCollection m_variables_ori; + IPrimaryMesh* m_cloned_mesh = nullptr; + UniqueArray> m_plans; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +ARCANE_REGISTER_SERVICE_MESHCUT(MeshCutService, MeshCutService); + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + void MeshCutService:: addPlane(const Real3& p0, const Real3& normal) { @@ -214,7 +218,7 @@ _createMesh() /*---------------------------------------------------------------------------*/ void MeshCutService:: -_createCells(Int32 plan_pos, Int32& sd_nb_cell, Int32& sd_nb_node, UniqueArray& cells_infos, UniqueArray& pos_node) +_createCells(Int32 plan_pos, Int32& sd_nb_node, Int32& sd_nb_cell, UniqueArray& cells_infos, Int32& sd_nb_face, UniqueArray& faces_infos, std::unordered_map& pos_node) { auto [p0, normal] = m_plans[plan_pos]; @@ -424,8 +428,11 @@ _createCells(Int32 plan_pos, Int32& sd_nb_cell, Int32& sd_nb_node, UniqueArray cells_infos; cells_infos.reserve(10000); - UniqueArray pos_node; + UniqueArray faces_infos; + faces_infos.reserve(10000); + + std::unordered_map pos_node; pos_node.reserve(10000); Int32 nb_cell = 0; Int32 nb_node = 0; + Int32 nb_face = 0; for (Int32 i = 0; i < m_plans.size(); ++i) { - _createCells(i, nb_cell, nb_node, cells_infos, pos_node); + _createCells(i, nb_node, nb_cell, cells_infos, nb_face, faces_infos, pos_node); } + m_cloned_mesh->modifier()->addFaces(nb_face, faces_infos); m_cloned_mesh->modifier()->addCells(nb_cell, cells_infos); m_cloned_mesh->modifier()->endUpdate(); @@ -542,6 +563,41 @@ _compute() /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +Int64 MeshCutService:: +_edgeUid(Int64 node0_uid, Int64 node1_uid) +{ + if (node0_uid > node1_uid) { + const Int64 tmp = node1_uid; + node1_uid = node0_uid; + node0_uid = tmp; + } + + Int32 num[100]; + + Int32 i = 0; + while (node1_uid != 0) { + num[i] = static_cast(node1_uid % 9); + node1_uid = node1_uid / 9; + i++; + } + num[i++] = 9; + while (node0_uid != 0) { + num[i] = static_cast(node0_uid % 9); + node0_uid = node0_uid / 9; + i++; + } + + StringBuilder sb; + for (int j = i - 1; j >= 0; j--) { + sb.append(String::fromNumber(num[j])); + } + + return std::stol(sb.toString().localstr()); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + } // namespace Arcane /*---------------------------------------------------------------------------*/ From 16f1bec27087aee6bd6664e345fd6c7ec0b4da97 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Tue, 21 Jul 2026 16:19:23 +0200 Subject: [PATCH 07/17] [arcane:std,tests] Add parallel support for MeshCut service --- arcane/src/arcane/std/MeshCutService.cc | 792 +++++++++++++++++++++--- 1 file changed, 696 insertions(+), 96 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index f950a6e676..31e4600e91 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -11,7 +11,10 @@ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +#include "arcane/utils/StringBuilder.h" + #include "arcane/core/IGhostLayerMng.h" +#include "arcane/core/IItemFamily.h" #include "arcane/core/IMesh.h" #include "arcane/core/IMeshFactoryMng.h" #include "arcane/core/IMeshMng.h" @@ -21,7 +24,6 @@ #include "arcane/core/MeshBuildInfo.h" #include "arcane/std/MeshCut_axl.h" -#include "arccore/base/StringBuilder.h" /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -32,25 +34,41 @@ namespace Arcane /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -struct EdgeLite +struct NodeOnEdge { - EdgeLite(const Node first_node, const Node second_node) + NodeOnEdge(const Node first_node, const Node second_node) { const Int64 a = first_node.uniqueId(); const Int64 b = second_node.uniqueId(); if (a < b) { + m_node0 = first_node; + m_node1 = second_node; m_uid_node0 = a; m_uid_node1 = b; } else { + m_node0 = second_node; + m_node1 = first_node; m_uid_node0 = b; m_uid_node1 = a; } } - EdgeLite() = default; + NodeOnEdge(Int64 first_node, Int64 second_node) + { + if (first_node < second_node) { + m_uid_node0 = first_node; + m_uid_node1 = second_node; + } + else { + m_uid_node0 = second_node; + m_uid_node1 = first_node; + } + } + + NodeOnEdge() = default; - bool operator<(const EdgeLite& other) const + bool operator<(const NodeOnEdge& other) const { if (m_uid_node0 != other.m_uid_node0) { return m_uid_node0 < other.m_uid_node0; @@ -58,11 +76,13 @@ struct EdgeLite return m_uid_node1 < other.m_uid_node1; } - bool operator==(const EdgeLite& other) const + bool operator==(const NodeOnEdge& other) const { return m_uid_node0 == other.m_uid_node0 && m_uid_node1 == other.m_uid_node1; } + Node m_node0{}; + Node m_node1{}; Int64 m_uid_node0 = -1; Int64 m_uid_node1 = -1; Int64 m_uid_new_node = -1; @@ -72,26 +92,57 @@ struct EdgeLite /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +struct FaceLite +{ + FaceLite(const Ref& node0, const Ref& node1) + : m_node0(node0->m_uid_node0 < node1->m_uid_node0 ? node0 : node1) + , m_node1(node0->m_uid_node0 < node1->m_uid_node0 ? node1 : node0) + {} + + bool operator<(const FaceLite& other) const + { + return m_node0->operator<(*(other.m_node0.get())) && m_node1->operator<(*(other.m_node1.get())); + } + + bool operator==(const FaceLite& other) const + { + return m_node0->operator==(*(other.m_node0.get())) && m_node1->operator==(*(other.m_node1.get())); + } + + Ref m_node0; + Ref m_node1; + Int64 m_uid_new_face = -1; + Int32 m_owner_new_face = -1; +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + struct NodeIntersection { NodeIntersection(const Node first_node, const Node second_node, const Real3& intersection_pos) - : m_edge(first_node, second_node) - ,m_intersection_pos(intersection_pos) + : m_new_node(makeRef(new NodeOnEdge(first_node, second_node))) + , m_intersection_pos(intersection_pos) + {} + + NodeIntersection(Int64 first_node, Int64 second_node, const Real3& intersection_pos) + : m_new_node(makeRef(new NodeOnEdge(first_node, second_node))) + , m_intersection_pos(intersection_pos) {} NodeIntersection() = default; bool operator<(const NodeIntersection& other) const { - return m_edge.operator<(other.m_edge); + return m_new_node->operator<(*(other.m_new_node.get())); } bool operator==(const NodeIntersection& other) const { - return m_edge.operator==(other.m_edge); + return m_new_node->operator==(*(other.m_new_node.get())); } - EdgeLite m_edge{}; + Ref m_new_node; Real3 m_intersection_pos{ -1 }; }; @@ -135,10 +186,21 @@ class MeshCutService private: void _createMesh(); - void _createCells(Int32 plan_pos, Int32& nb_node, Int32& nb_cell, UniqueArray& cells_infos, Int32& sd_nb_face, UniqueArray& faces_infos, std::unordered_map& pos_node); + void _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_nodes, Int32& sd_nb_cell, UniqueArray& new_cells, Int32& sd_nb_face, UniqueArray& new_faces); + Int32 _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray& new_nodes); + + void _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan); + Int32 _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, Int32 current_plan); + void _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_plan); + Int32 _makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces, Int32 current_plan); void _compute(); - Int64 _edgeUid(Int64 node0_uid, Int64 node1_uid); + std::optional _find(Span new_faces, Int64 node_uid0, Int64 node_uid1); + + void _addFaces(UniqueArray& new_faces) const; + void _addCells(UniqueArray& new_cells); + void _setCoordNodesAndOwner(UniqueArray& new_nodes); + void _setFacesOwner(UniqueArray& new_faces); private: @@ -218,7 +280,7 @@ _createMesh() /*---------------------------------------------------------------------------*/ void MeshCutService:: -_createCells(Int32 plan_pos, Int32& sd_nb_node, Int32& sd_nb_cell, UniqueArray& cells_infos, Int32& sd_nb_face, UniqueArray& faces_infos, std::unordered_map& pos_node) +_createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_nodes, Int32& sd_nb_cell, UniqueArray& new_cells, Int32& sd_nb_face, UniqueArray& new_faces) { auto [p0, normal] = m_plans[plan_pos]; @@ -235,7 +297,6 @@ _createCells(Int32 plan_pos, Int32& sd_nb_node, Int32& sd_nb_cell, UniqueArray point_coords_tmp; - // Tableau qui contiendra tous les noeuds du maillage futur. - UniqueArray point_coords; - ENUMERATE_ (Cell, icell, ownCells()) { Cell cell = *icell; @@ -281,6 +339,9 @@ _createCells(Int32 plan_pos, Int32& sd_nb_node, Int32& sd_nb_cell, UniqueArray= mesh_dim) { for (Face face : cell.faces()) { + // Pour éviter que deux processus créés la même maille. + if (!face.isOwn()) + continue; if (face.nbNode() != nb_node_on_plane) continue; @@ -421,36 +482,12 @@ _createCells(Int32 plan_pos, Int32& sd_nb_node, Int32& sd_nb_cell, UniqueArray= mesh_dim) { - // On ajoute le uniqueId du nouveau noeud. Si ce noeud a déjà été créé, on récupère son uniqueId. - for (auto& new_node : point_coords_tmp) { - std::optional pos = point_coords.span().findFirst(new_node.m_edge); - if (pos) { - new_node.m_edge.m_uid_new_node = point_coords[pos.value()].m_uid_new_node; - } - else { - //info() << "Old UID : " << sd_nb_node++ << " -- New UID : " << _edgeUid(new_node.m_edge.m_uid_node0, new_node.m_edge.m_uid_node1); - //new_node.m_edge.m_uid_new_node = sd_nb_node++; - new_node.m_edge.m_uid_new_node = _edgeUid(new_node.m_edge.m_uid_node0, new_node.m_edge.m_uid_node1); - // pos_node.add(new_node.m_intersection_pos); - pos_node[new_node.m_edge.m_uid_new_node] = new_node.m_intersection_pos; - point_coords.add(new_node.m_edge); - } - } - // Type cell. - if (point_coords_tmp.size() == 3) - cells_infos.add(ITI_Triangle3); - else if (point_coords_tmp.size() == 4) - cells_infos.add(ITI_Quad4); - else if (point_coords_tmp.size() == 5) - cells_infos.add(ITI_Pentagon5); - else if (point_coords_tmp.size() == 6) - cells_infos.add(ITI_Hexagon6); - else + if (point_coords_tmp.size() > 6) ARCANE_FATAL("Pas implem : {0}", point_coords_tmp.size()); - // UID cell. - cells_infos.add(sd_nb_cell); + new_cells.add(point_coords_tmp.size()); + new_cells.add(sd_nb_cell); { // Calcul du barycentre de tous les points d'intersection. @@ -499,100 +536,663 @@ _createCells(Int32 plan_pos, Int32& sd_nb_node, Int32& sd_nb_cell, UniqueArray pos = new_nodes.span().findFirst(point_coords_tmp[idx]); + if (pos) { + new_cells.add(static_cast(pos.value())); + idx = pos.value(); + } + else { + auto& elem = point_coords_tmp[idx]; + + // Si les deux noeuds sont à nous, on est sûr d'être le propriétaire du nouveau noeud. + if (elem.m_new_node->m_node0.owner() == elem.m_new_node->m_node1.owner()) { + elem.m_new_node->m_owner_new_node = elem.m_new_node->m_node0.owner(); //bof + if (elem.m_new_node->m_node0.isOwn()) { + elem.m_new_node->m_uid_new_node = sd_nb_node++; + } + else { + elem.m_new_node->m_uid_new_node = -2; + } + } + new_cells.add(new_nodes.size()); + idx = new_nodes.size(); + new_nodes.add(elem); + } + } - inode = idx; + Int64 idxm1 = indices[indices.size() - 1]; + for (Int64 idx : indices) { + FaceLite fl(new_nodes[idx].m_new_node, new_nodes[idxm1].m_new_node); + if (!new_faces.contains(fl)) { + info() << "Add face" + << " -- N00 " << fl.m_node0->m_uid_node0 + << " -- N01 " << fl.m_node0->m_uid_node1 + << " -- N10 " << fl.m_node1->m_uid_node0 + << " -- N11 " << fl.m_node1->m_uid_node1; + if (new_nodes[idx].m_new_node->m_owner_new_node == new_nodes[idxm1].m_new_node->m_owner_new_node) { + fl.m_owner_new_face = new_nodes[idx].m_new_node->m_owner_new_node; + if (fl.m_owner_new_face == subDomain()->subDomainId()) { + fl.m_uid_new_face = sd_nb_face++; + } + } + new_faces.add(fl); + } + idxm1 = idx; } } sd_nb_cell++; } point_coords_tmp.clear(); } +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +Int32 MeshCutService:: +_makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray& new_nodes) +{ + IParallelMng* pm = subDomain()->parallelMng(); - // for (auto elem : point_coords) { - // info() << "UID : " << elem.m_uid_new_node << "\t -- Node0 : " << elem.m_lid_node0 << "\t -- Node1 : " << elem.m_lid_node1 << "\t -- Pos : " << elem.m_intersection_pos; - // } + Int32 decal = sd_nb_cell; + pm->scan(MessagePassing::ReduceSum, ArrayView{ 1, &decal }); + + Int32 nb_cells_global = decal; + pm->broadcast(ArrayView{ 1, &nb_cells_global }, pm->commSize() - 1); + + decal -= sd_nb_cell; + + info() << "[" << pm->commRank() << "] Scan result (rectified) : " << decal; + + Int32 pos0 = 0; + while (pos0 < new_cells.size()) { + Int64 type = new_cells[pos0++]; + new_cells[pos0++] += decal; + + for (Int32 i = 0; i < type; ++i) { + Int64& pos_to_uid = new_cells[pos0++]; + pos_to_uid = new_nodes[pos_to_uid].m_new_node->m_uid_new_node; + } + } + return nb_cells_global; } /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void MeshCutService:: -_compute() +_fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan) { - UniqueArray cells_infos; - cells_infos.reserve(10000); + IParallelMng* pm = subDomain()->parallelMng(); + Int32 my_proc = pm->commRank(); + UniqueArray> request_uid(subDomain()->nbSubDomain()); - UniqueArray faces_infos; - faces_infos.reserve(10000); + Span current_plan_new_nodes = new_nodes.subView(current_plan, new_nodes.size() - current_plan); - std::unordered_map pos_node; - pos_node.reserve(10000); + // On détermine le futur proprio de chaque noeud. + for (auto& elem : current_plan_new_nodes) { + if (elem.m_new_node->m_uid_new_node >= 0) { + continue; + } + if (elem.m_new_node->m_owner_new_node < 0) { + + Node node0 = elem.m_new_node->m_node0; + Node node1 = elem.m_new_node->m_node1; + + // Le propriétaire du noeud est le propriétaire de la maille ayant le plus + // petit UID, parmi les mailles en commun entre les deux noeuds d'origine. + Int64 min_uid = INT64_MAX; + Int32 owner_min = -1; + for (Cell cell0 : node0.cells()) { + for (Cell cell1 : node1.cells()) { + if (cell0 == cell1) { + if (cell0.uniqueId() < min_uid) { + min_uid = cell0.uniqueId(); + owner_min = cell0.owner(); + } + } + } + } + + if (owner_min == subDomain()->subDomainId()) { + elem.m_new_node->m_owner_new_node = subDomain()->subDomainId(); + elem.m_new_node->m_uid_new_node = sd_nb_node++; + } + else { + elem.m_new_node->m_owner_new_node = owner_min; + elem.m_new_node->m_uid_new_node = -2; + request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0); + request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1); + + info() << "[" << my_proc << "] Ask1" + << " -- UID0 : " << elem.m_new_node->m_uid_node0 + << " -- UID1 : " << elem.m_new_node->m_uid_node1; + } + } + else { + request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0); + request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1); + + info() << "[" << my_proc << "] Ask2" + << " -- UID0 : " << elem.m_new_node->m_uid_node0 + << " -- UID1 : " << elem.m_new_node->m_uid_node1; + } + } + + UniqueArray requests(subDomain()->nbSubDomain() * 2); + + // Si le noeud n'est pas à nous, il faut demander son UID au processus proprio. + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + Int32 size = request_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); + info() << "[" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; + } + + pm->waitAllRequests(requests); + // pm->freeRequests(requests); + + UniqueArray> answers_uid(subDomain()->nbSubDomain()); + + // On reçoit et traite les demandes. + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + Int32 size = 0; + pm->recv(ArrayView{ 1, &size }, sr); + UniqueArray requested_uid(size); + pm->recv(requested_uid, sr); + + for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { + std::optional pos = new_nodes.span().findFirst(NodeIntersection{ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], Real3{ 0 } }); + if (pos) { + answers_uid[sr].add(new_nodes[pos.value()].m_new_node->m_uid_new_node); + info() << "[" << my_proc << "] Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1] + << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; + } + else { + warning() << "Not found"; + answers_uid[sr].add(-1); + } + } + } + + // On envoie les réponses. + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + + Int32 size = answers_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); + } + + pm->waitAllRequests(requests); + // pm->freeRequests(requests); + + // On reçoit et traite les réponses. + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + + Int32 size = 0; + pm->recv(ArrayView{ 1, &size }, sr); + UniqueArray answered_uid(size); + pm->recv(answered_uid, sr); + + for (Int32 ipair_uid = 0; ipair_uid < request_uid[sr].size(); ipair_uid += 2) { + std::optional pos = current_plan_new_nodes.findFirst(NodeIntersection{ request_uid[sr][ipair_uid], request_uid[sr][ipair_uid + 1], Real3{ 0 } }); + if (pos) { + current_plan_new_nodes[pos.value()].m_new_node->m_uid_new_node = answered_uid[ipair_uid / 2]; + info() << "[" << my_proc << "] Apply" + << " -- UID0 : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_node0 + << " -- UID1 : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_node1 + << " -- New UID : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_new_node; + } + else { + ARCANE_FATAL("GL"); + } + } + } +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +Int32 MeshCutService:: +_makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, Int32 current_plan) +{ + IParallelMng* pm = subDomain()->parallelMng(); + + UniqueArray all_nb_node(pm->commSize()); + pm->allGather(ArrayView{ 1, &sd_nb_node }, all_nb_node); + + Int32 sum = 0; + for (auto& elem : all_nb_node) { + const Int32 old = elem; + elem = sum; + sum += old; + } + + info() << "[" << pm->commRank() << "] Gather result (rectified) : " << all_nb_node; + info() << "current_plan : " << current_plan << " -- new_nodes.size() : " << new_nodes.size(); + + ArrayView current_plan_new_nodes = new_nodes.subView(current_plan, new_nodes.size() - current_plan); + + for (auto& elem : current_plan_new_nodes) { + // info() << "[" << pm->commRank() << "] Old UID : " << elem.m_new_node->m_uid_new_node; + elem.m_new_node->m_uid_new_node += all_nb_node[elem.m_new_node->m_owner_new_node]; + // info() << "[" << pm->commRank() << "] New UID : " << elem.m_new_node->m_uid_new_node; + } + return sum; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_plan) +{ + IParallelMng* pm = subDomain()->parallelMng(); + Int32 my_proc = pm->commRank(); + UniqueArray> request_uid(subDomain()->nbSubDomain()); + + Span current_plan_new_faces = new_faces.subView(current_plan, new_faces.size() - current_plan); + + for (auto& elem : current_plan_new_faces) { + + if (elem.m_uid_new_face >= 0) { + continue; + } + if (elem.m_owner_new_face < 0) { + + Node node00 = elem.m_node0->m_node0; + Node node01 = elem.m_node0->m_node1; + Node node10 = elem.m_node1->m_node0; + Node node11 = elem.m_node1->m_node1; + + Int64 min_uid = INT64_MAX; + Int32 owner_min = -1; + + // TODO AH : C'est quand même TURBO moche + for (Cell cell00 : node00.cells()) { + for (Cell cell01 : node01.cells()) { + for (Cell cell10 : node10.cells()) { + for (Cell cell11 : node11.cells()) { + if (cell00 == cell01 && cell00 == cell10 && cell00 == cell11) { + if (cell00.uniqueId() < min_uid) { + min_uid = cell00.uniqueId(); + owner_min = cell00.owner(); + } + } + } + } + } + } + + if (owner_min == subDomain()->subDomainId()) { + elem.m_owner_new_face = subDomain()->subDomainId(); + elem.m_uid_new_face = sd_nb_face++; + } + else { + elem.m_owner_new_face = owner_min; + elem.m_uid_new_face = -2; + request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node); + request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node); + + info() << "[" << my_proc << "] Ask3" + << " -- UID0 : " << elem.m_node0->m_uid_new_node + << " -- UID1 : " << elem.m_node1->m_uid_new_node; + } + } + else { + request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node); + request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node); + + info() << "[" << my_proc << "] Ask4" + << " -- UID0 : " << elem.m_node0->m_uid_new_node + << " -- UID1 : " << elem.m_node1->m_uid_new_node; + } + } + + UniqueArray requests(subDomain()->nbSubDomain() * 2); + + // Si le noeud n'est pas à nous, il faut demander son UID au processus proprio. + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + Int32 size = request_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); + info() << "[" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; + } + + pm->waitAllRequests(requests); + // pm->freeRequests(requests); + + UniqueArray> answers_uid(subDomain()->nbSubDomain()); + + // On reçoit et traite les demandes. + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + Int32 size = 0; + pm->recv(ArrayView{ 1, &size }, sr); + UniqueArray requested_uid(size); + pm->recv(requested_uid, sr); + + for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { + std::optional pos = _find(new_faces, requested_uid[ipair_uid], requested_uid[ipair_uid + 1]); + if (pos) { + answers_uid[sr].add(new_faces[pos.value()].m_uid_new_face); + info() << "[" << my_proc << "] Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1] + << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; + } + else { + warning() << "Not found"; + answers_uid[sr].add(-1); + } + } + } + + // On envoie les réponses. + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + + Int32 size = answers_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); + } + + pm->waitAllRequests(requests); + // pm->freeRequests(requests); + + // On reçoit et traite les réponses. + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + + Int32 size = 0; + pm->recv(ArrayView{ 1, &size }, sr); + UniqueArray answered_uid(size); + pm->recv(answered_uid, sr); + + for (Int32 ipair_uid = 0; ipair_uid < request_uid[sr].size(); ipair_uid += 2) { + std::optional pos = _find(current_plan_new_faces, request_uid[sr][ipair_uid], request_uid[sr][ipair_uid + 1]); + if (pos) { + current_plan_new_faces[pos.value()].m_uid_new_face = answered_uid[ipair_uid / 2]; + info() << "[" << my_proc << "] Apply" + << " -- UID0 : " << current_plan_new_faces[pos.value()].m_node0->m_uid_new_node + << " -- UID1 : " << current_plan_new_faces[pos.value()].m_node1->m_uid_new_node + << " -- New UID : " << current_plan_new_faces[pos.value()].m_uid_new_face; + } + else { + ARCANE_FATAL("GL"); + } + } + } +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +Int32 MeshCutService:: +_makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces, Int32 current_plan) +{ + IParallelMng* pm = subDomain()->parallelMng(); + + UniqueArray all_nb_node(pm->commSize()); + pm->allGather(ArrayView{ 1, &sd_nb_face }, all_nb_node); + + Int32 sum = 0; + for (auto& elem : all_nb_node) { + const Int32 old = elem; + elem = sum; + sum += old; + } + + info() << "[" << pm->commRank() << "] Gather result (rectified) : " << all_nb_node; + + Span current_plan_new_faces = new_faces.subView(current_plan, new_faces.size() - current_plan); + + for (auto& elem : current_plan_new_faces) { + // info() << "[" << pm->commRank() << "] Old UID : " << elem.m_new_node->m_uid_new_node; + elem.m_uid_new_face += all_nb_node[elem.m_owner_new_face]; + // info() << "[" << pm->commRank() << "] New UID : " << elem.m_new_node->m_uid_new_node; + } + return sum; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_compute() +{ Int32 nb_cell = 0; - Int32 nb_node = 0; - Int32 nb_face = 0; + Int32 g_nb_node = 0; + Int32 g_nb_face = 0; + + UniqueArray new_cells; + + UniqueArray new_nodes; + UniqueArray new_faces; for (Int32 i = 0; i < m_plans.size(); ++i) { - _createCells(i, nb_node, nb_cell, cells_infos, nb_face, faces_infos, pos_node); + + Int32 size_of_new_nodes = new_nodes.size(); + Int32 size_of_new_faces = new_faces.size(); + + Int32 previous_g_nb_node = g_nb_node; + Int32 previous_g_nb_face = g_nb_face; + + Int32 nb_node_for_this_plan = g_nb_node; + Int32 nb_face_for_this_plan = g_nb_face; + + _createNodesAndCells(i, g_nb_node, new_nodes, nb_cell, new_cells, g_nb_face, new_faces); + + info() << "qaaaaa"; + + _fillNodeUID(g_nb_node, new_nodes, size_of_new_nodes); + nb_node_for_this_plan = g_nb_node - nb_node_for_this_plan; + + info() << "nb_node_for_this_plan : " << nb_node_for_this_plan; + + nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, new_nodes, size_of_new_nodes); + g_nb_node = previous_g_nb_node + nb_node_for_this_plan; + + for (auto& elem : new_nodes) { + info() << "New node" + << " -- UID : " << elem.m_new_node->m_uid_new_node + << " -- Owner : " << elem.m_new_node->m_owner_new_node + << " -- Pos : " << elem.m_intersection_pos + << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 + << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; + } + + Int32 nb_face = 0; + + _fillFaceUID(g_nb_face, new_faces, size_of_new_faces); + nb_face_for_this_plan = g_nb_face - nb_face_for_this_plan; + + info() << "nb_face_for_this_plan : " << nb_face_for_this_plan; + + nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, new_faces, size_of_new_faces); + g_nb_face = previous_g_nb_face + nb_face_for_this_plan; + + for (auto& elem : new_faces) { + info() << "New face" + << " -- UID : " << elem.m_uid_new_face + << " -- Owner : " << elem.m_owner_new_face + << " -- Node0 : " << elem.m_node0->m_uid_new_node + << " -- Node00 : " << elem.m_node0->m_uid_node0 + << " -- Node01 : " << elem.m_node0->m_uid_node1 + << " -- Node1 : " << elem.m_node1->m_uid_new_node + << " -- Node10 : " << elem.m_node1->m_uid_node0 + << " -- Node11 : " << elem.m_node1->m_uid_node1; + } } - m_cloned_mesh->modifier()->addFaces(nb_face, faces_infos); - m_cloned_mesh->modifier()->addCells(nb_cell, cells_infos); - m_cloned_mesh->modifier()->endUpdate(); + info() << "new_cells : " << new_cells; + + _makeUniqueCellUID(nb_cell, new_cells, new_nodes); { - VariableNodeReal3& node_coords(m_cloned_mesh->nodesCoordinates()); - ENUMERATE_ (Node, inode, m_cloned_mesh->allNodes()) { - node_coords[inode] = pos_node[inode->uniqueId()]; + Int32 pos0 = 0; + while (pos0 < new_cells.size()) { + StringBuilder logs; + logs += "New cell -- Type : "; + Int64 type = new_cells[pos0++]; + logs += type; + logs += " -- UID : "; + logs += new_cells[pos0++]; + + for (Int32 i = 0; i < type; ++i) { + logs += " -- Node"; + logs += i; + logs += " : "; + logs += new_cells[pos0++]; + } + info() << logs; } } + _addFaces(new_faces); + _addCells(new_cells); + m_cloned_mesh->modifier()->endUpdate(); + _setCoordNodesAndOwner(new_nodes); + _setFacesOwner(new_faces); + + m_cloned_mesh->nodeFamily()->notifyItemsOwnerChanged(); + m_cloned_mesh->faceFamily()->notifyItemsOwnerChanged(); + info() << "New mesh -- NbNode : " << m_cloned_mesh->nbNode() << " -- NbCells : " << m_cloned_mesh->nbCell(); } /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -Int64 MeshCutService:: -_edgeUid(Int64 node0_uid, Int64 node1_uid) +std::optional MeshCutService:: +_find(Span new_faces, Int64 node_uid0, Int64 node_uid1) { - if (node0_uid > node1_uid) { - const Int64 tmp = node1_uid; - node1_uid = node0_uid; - node0_uid = tmp; + for (Int32 i = 0; i < new_faces.size(); ++i) { + if (new_faces[i].m_node0->m_uid_new_node == node_uid0 && new_faces[i].m_node1->m_uid_new_node == node_uid1) { + return i; + } } + return std::nullopt; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_addFaces(UniqueArray& new_faces) const +{ + UniqueArray faces_infos; + faces_infos.reserve(10000); - Int32 num[100]; + Int32 nb_faces = 0; - Int32 i = 0; - while (node1_uid != 0) { - num[i] = static_cast(node1_uid % 9); - node1_uid = node1_uid / 9; - i++; + for (auto& elem : new_faces) { + faces_infos.add(ITI_Line2); + faces_infos.add(elem.m_uid_new_face); + faces_infos.add(elem.m_node0->m_uid_new_node); + faces_infos.add(elem.m_node1->m_uid_new_node); + nb_faces++; } - num[i++] = 9; - while (node0_uid != 0) { - num[i] = static_cast(node0_uid % 9); - node0_uid = node0_uid / 9; - i++; + + m_cloned_mesh->modifier()->addFaces(nb_faces, faces_infos); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_addCells(UniqueArray& new_cells) +{ + UniqueArray cells_infos; + cells_infos.reserve(10000); + + Int32 nb_cells = 0; + + Int32 pos0 = 0; + while (pos0 < new_cells.size()) { + Int64 type = new_cells[pos0++]; + Int64 uid = new_cells[pos0++]; + + if (type == 3) + cells_infos.add(ITI_Triangle3); + else if (type == 4) + cells_infos.add(ITI_Quad4); + else if (type == 5) + cells_infos.add(ITI_Pentagon5); + else if (type == 6) + cells_infos.add(ITI_Hexagon6); + else + ARCANE_FATAL("Pas implem : {0}", type); + + cells_infos.add(uid); + + for (Int32 i = 0; i < type; ++i) { + cells_infos.add(new_cells[pos0++]); + } + nb_cells++; } - StringBuilder sb; - for (int j = i - 1; j >= 0; j--) { - sb.append(String::fromNumber(num[j])); + m_cloned_mesh->modifier()->addCells(nb_cells, cells_infos); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_setCoordNodesAndOwner(UniqueArray& new_nodes) +{ + VariableNodeReal3& node_coords(m_cloned_mesh->nodesCoordinates()); + ENUMERATE_ (Node, inode, m_cloned_mesh->allNodes()) { + const Int64 uid = inode->uniqueId(); + for (const auto& elem : new_nodes) { + if (elem.m_new_node->m_uid_new_node == uid) { + node_coords[inode] = elem.m_intersection_pos; + inode->mutableItemBase().setOwner(elem.m_new_node->m_owner_new_node, subDomain()->subDomainId()); + info() << "NodeUID : " << uid << " -- Coord : " << node_coords[inode]; + } + } } +} - return std::stol(sb.toString().localstr()); +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void MeshCutService:: +_setFacesOwner(UniqueArray& new_faces) +{ + ENUMERATE_ (Face, iface, m_cloned_mesh->allFaces()) { + const Int64 uid = iface->uniqueId(); + for (const auto& elem : new_faces) { + if (elem.m_uid_new_face == uid) { + iface->mutableItemBase().setOwner(elem.m_owner_new_face, subDomain()->subDomainId()); + } + } + } } /*---------------------------------------------------------------------------*/ From 73f253227deba85d21ae98b87e5bdc61ff0b63ba Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Fri, 24 Jul 2026 16:17:55 +0200 Subject: [PATCH 08/17] [arcane:std] Cleanup --- arcane/src/arcane/std/MeshCutService.cc | 390 ++++++++++++++---------- 1 file changed, 225 insertions(+), 165 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index 31e4600e91..e273aca465 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -34,6 +34,15 @@ namespace Arcane /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +namespace +{ +/*! + * \brief Noeud sur arête. + * Représente le noeud à l'intersection entre une arête du maillage 3D et + * un plan. + * Si les deux noeuds de la struct sont identiques, c'est qu'il y a un + * noeud du maillage 3D qui est sur le plan. + */ struct NodeOnEdge { NodeOnEdge(const Node first_node, const Node second_node) @@ -81,10 +90,12 @@ struct NodeOnEdge return m_uid_node0 == other.m_uid_node0 && m_uid_node1 == other.m_uid_node1; } - Node m_node0{}; - Node m_node1{}; + Node m_node0; + Node m_node1; + Int64 m_uid_node0 = -1; Int64 m_uid_node1 = -1; + Int64 m_uid_new_node = -1; Int32 m_owner_new_node = -1; }; @@ -92,6 +103,9 @@ struct NodeOnEdge /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +/*! + * \brief Face du maillage 2D issue de deux noeuds d'arêtes. + */ struct FaceLite { FaceLite(const Ref& node0, const Ref& node1) @@ -111,6 +125,7 @@ struct FaceLite Ref m_node0; Ref m_node1; + Int64 m_uid_new_face = -1; Int32 m_owner_new_face = -1; }; @@ -118,6 +133,9 @@ struct FaceLite /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +/*! + * \brief Position d'un noeud d'arête. + */ struct NodeIntersection { NodeIntersection(const Node first_node, const Node second_node, const Real3& intersection_pos) @@ -145,6 +163,7 @@ struct NodeIntersection Ref m_new_node; Real3 m_intersection_pos{ -1 }; }; +} // namespace /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -187,11 +206,11 @@ class MeshCutService void _createMesh(); void _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_nodes, Int32& sd_nb_cell, UniqueArray& new_cells, Int32& sd_nb_face, UniqueArray& new_faces); - Int32 _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray& new_nodes); + void _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray& new_nodes); - void _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan); + void _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan_pos); Int32 _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, Int32 current_plan); - void _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_plan); + void _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_plan_pos); Int32 _makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces, Int32 current_plan); void _compute(); @@ -339,7 +358,7 @@ _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray= mesh_dim) { for (Face face : cell.faces()) { - // Pour éviter que deux processus créés la même maille. + // Pour éviter que deux processus créent la même maille. if (!face.isOwn()) continue; if (face.nbNode() != nb_node_on_plane) @@ -384,46 +403,45 @@ _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray pos = new_nodes.span().findFirst(point_coords_tmp[idx]); if (pos) { + // Attention : on ajoute la position du noeud dans le tableau + // "global", pas le UID de celui-ci ! En effet, on ne le connait + // pas encore, ce sera ajusté dans la méthode + // "_makeUniqueCellUID()". new_cells.add(static_cast(pos.value())); idx = pos.value(); } + // S'il n'est pas présent, on le crée. else { - auto& elem = point_coords_tmp[idx]; + NodeIntersection& elem = point_coords_tmp[idx]; - // Si les deux noeuds sont à nous, on est sûr d'être le propriétaire du nouveau noeud. + // Si les deux noeuds ont le même proprio, on sait que le nouveau noeud aura le même proprio. if (elem.m_new_node->m_node0.owner() == elem.m_new_node->m_node1.owner()) { - elem.m_new_node->m_owner_new_node = elem.m_new_node->m_node0.owner(); //bof + elem.m_new_node->m_owner_new_node = elem.m_new_node->m_node0.owner(); + // Si les deux noeuds sont à nous, on est sûr d'être le + // propriétaire du nouveau noeud. C'est donc à nous de donner le + // UniqueID (unique pour ce processus, la correction sera faite + // plus tard, quand on saura le nombre de noeuds de chaque + // processus). if (elem.m_new_node->m_node0.isOwn()) { elem.m_new_node->m_uid_new_node = sd_nb_node++; } else { + // -2 = nécessite d'être ajouté plus tard. elem.m_new_node->m_uid_new_node = -2; } } @@ -561,20 +597,26 @@ _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArraym_uid_node0 - << " -- N01 " << fl.m_node0->m_uid_node1 - << " -- N10 " << fl.m_node1->m_uid_node0 - << " -- N11 " << fl.m_node1->m_uid_node1; + // info() << "Add face" + // << " -- N00 " << fl.m_node0->m_uid_node0 + // << " -- N01 " << fl.m_node0->m_uid_node1 + // << " -- N10 " << fl.m_node1->m_uid_node0 + // << " -- N11 " << fl.m_node1->m_uid_node1; + + // Même principe qu'avec les noeuds juste au-dessus. if (new_nodes[idx].m_new_node->m_owner_new_node == new_nodes[idxm1].m_new_node->m_owner_new_node) { fl.m_owner_new_face = new_nodes[idx].m_new_node->m_owner_new_node; if (fl.m_owner_new_face == subDomain()->subDomainId()) { fl.m_uid_new_face = sd_nb_face++; } + else { + fl.m_uid_new_face = -2; + } } new_faces.add(fl); } @@ -590,7 +632,7 @@ _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_cells, UniqueArray& new_nodes) { IParallelMng* pm = subDomain()->parallelMng(); @@ -598,13 +640,16 @@ _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray< Int32 decal = sd_nb_cell; pm->scan(MessagePassing::ReduceSum, ArrayView{ 1, &decal }); - Int32 nb_cells_global = decal; - pm->broadcast(ArrayView{ 1, &nb_cells_global }, pm->commSize() - 1); + // Int32 nb_cells_global = decal; + // pm->broadcast(ArrayView{ 1, &nb_cells_global }, pm->commSize() - 1); decal -= sd_nb_cell; - info() << "[" << pm->commRank() << "] Scan result (rectified) : " << decal; + // info() << "[" << pm->commRank() << "] Scan result (rectified) : " << decal; + // En plus de décaler les uids des mailles pour les rendre unique sur tout le + // domaine, on ajoute les vrais UID des noeuds à la place des positions des + // noeuds dans le tableau "new_nodes". Int32 pos0 = 0; while (pos0 < new_cells.size()) { Int64 type = new_cells[pos0++]; @@ -615,26 +660,35 @@ _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray< pos_to_uid = new_nodes[pos_to_uid].m_new_node->m_uid_new_node; } } - return nb_cells_global; + // return nb_cells_global; } /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void MeshCutService:: -_fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan) +_fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan_pos) { IParallelMng* pm = subDomain()->parallelMng(); - Int32 my_proc = pm->commRank(); + // Int32 my_proc = pm->commRank(); UniqueArray> request_uid(subDomain()->nbSubDomain()); - Span current_plan_new_nodes = new_nodes.subView(current_plan, new_nodes.size() - current_plan); + // On souhaite mettre à jour uniquement les nouveaux noeuds, on crée donc + // une vue qui regroupe uniquement les nouveau noeuds. + // Ça permet uniquement de réduire le nombre d'itération de la boucle juste + // après et le temps de recherche (à la fin de la méthode). En effet, les + // "anciens" noeuds ont tous un UID >= 0, ils ne passent donc pas la + // première condition. + Span current_plan_new_nodes = new_nodes.subView(current_plan_pos, new_nodes.size() - current_plan_pos); // On détermine le futur proprio de chaque noeud. for (auto& elem : current_plan_new_nodes) { + // Si le uid est déjà mis, pas besoin de le rechercher... if (elem.m_new_node->m_uid_new_node >= 0) { continue; } + + // Si le proprio n'est pas définit, on doit faire une recherche. if (elem.m_new_node->m_owner_new_node < 0) { Node node0 = elem.m_new_node->m_node0; @@ -642,6 +696,8 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 // Le propriétaire du noeud est le propriétaire de la maille ayant le plus // petit UID, parmi les mailles en commun entre les deux noeuds d'origine. + + // TODO Ajouter traitement particulier pour le cas où node0 == node1 Int64 min_uid = INT64_MAX; Int32 owner_min = -1; for (Cell cell0 : node0.cells()) { @@ -655,34 +711,44 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 } } + // S'il l'on est le proprio, on peut définir le uid du noeud. if (owner_min == subDomain()->subDomainId()) { elem.m_new_node->m_owner_new_node = subDomain()->subDomainId(); elem.m_new_node->m_uid_new_node = sd_nb_node++; } + + // Sinon, on doit aller demander le uid au proprio. else { elem.m_new_node->m_owner_new_node = owner_min; elem.m_new_node->m_uid_new_node = -2; + + // Une requête est composée uniquement des deux UID des noeuds de + // l'arête dont est issue le nouveau noeud. C'est le seul moyen + // d'identifier ce noeud pour l'instant (si on exclut l'identification + // par sa position). request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0); request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1); - info() << "[" << my_proc << "] Ask1" - << " -- UID0 : " << elem.m_new_node->m_uid_node0 - << " -- UID1 : " << elem.m_new_node->m_uid_node1; + // info() << "[" << my_proc << "] Ask1" + // << " -- UID0 : " << elem.m_new_node->m_uid_node0 + // << " -- UID1 : " << elem.m_new_node->m_uid_node1; } } + + // Si le proprio est déjà défini, on doit lui demander le uid du noeud. else { request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0); request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1); - info() << "[" << my_proc << "] Ask2" - << " -- UID0 : " << elem.m_new_node->m_uid_node0 - << " -- UID1 : " << elem.m_new_node->m_uid_node1; + // info() << "[" << my_proc << "] Ask2" + // << " -- UID0 : " << elem.m_new_node->m_uid_node0 + // << " -- UID1 : " << elem.m_new_node->m_uid_node1; } } UniqueArray requests(subDomain()->nbSubDomain() * 2); - // Si le noeud n'est pas à nous, il faut demander son UID au processus proprio. + // On envoie les requêtes. for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; @@ -690,7 +756,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 Int32 size = request_uid[sr].size(); requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); - info() << "[" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; + // info() << "[" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; } pm->waitAllRequests(requests); @@ -703,23 +769,34 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 if (sr == subDomain()->subDomainId()) { continue; } + Int32 size = 0; pm->recv(ArrayView{ 1, &size }, sr); UniqueArray requested_uid(size); pm->recv(requested_uid, sr); + // On traite chaque paire de noeud. for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { + + // On est forcé de rechercher dans tout le tableau parce que les plans + // peuvent avoir des noeuds en communs. std::optional pos = new_nodes.span().findFirst(NodeIntersection{ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], Real3{ 0 } }); if (pos) { answers_uid[sr].add(new_nodes[pos.value()].m_new_node->m_uid_new_node); - info() << "[" << my_proc << "] Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1] - << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; + // info() << "[" << my_proc << "] Found" + // << " -- UID0 : " << requested_uid[ipair_uid] + // << " -- UID1 : " << requested_uid[ipair_uid + 1] + // << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; } + + // En théorie, ça ne devrait pas arriver : au-dessus, on itère sur les + // mailles en commun pour les deux noeuds de l'arête, ce qui doit + // normalement nous donner toutes les mailles qui possèdent cette arête + // (= "edge.cells()"). else { - warning() << "Not found"; - answers_uid[sr].add(-1); + ARCANE_FATAL("Node not found -- internal error in the algorithm"); + // warning() << "Not found"; + // answers_uid[sr].add(-1); } } } @@ -749,15 +826,20 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 UniqueArray answered_uid(size); pm->recv(answered_uid, sr); + // On reprend les pairs de nos requêtes du début. for (Int32 ipair_uid = 0; ipair_uid < request_uid[sr].size(); ipair_uid += 2) { + // On retrouve le noeud correspondant à la requête. + // TODO : Sauvegarder les noeuds dans un tableau pour éviter la recherche ? std::optional pos = current_plan_new_nodes.findFirst(NodeIntersection{ request_uid[sr][ipair_uid], request_uid[sr][ipair_uid + 1], Real3{ 0 } }); if (pos) { current_plan_new_nodes[pos.value()].m_new_node->m_uid_new_node = answered_uid[ipair_uid / 2]; - info() << "[" << my_proc << "] Apply" - << " -- UID0 : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_node0 - << " -- UID1 : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_node1 - << " -- New UID : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_new_node; + // info() << "[" << my_proc << "] Apply" + // << " -- UID0 : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_node0 + // << " -- UID1 : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_node1 + // << " -- New UID : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_new_node; } + + // Pas normal. else { ARCANE_FATAL("GL"); } @@ -783,16 +865,13 @@ _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, I sum += old; } - info() << "[" << pm->commRank() << "] Gather result (rectified) : " << all_nb_node; - - info() << "current_plan : " << current_plan << " -- new_nodes.size() : " << new_nodes.size(); + // info() << "[" << pm->commRank() << "] Gather result (rectified) : " << all_nb_node; - ArrayView current_plan_new_nodes = new_nodes.subView(current_plan, new_nodes.size() - current_plan); + // On ne doit traiter que les nouveaux noeuds. + Span current_plan_new_nodes = new_nodes.subView(current_plan, new_nodes.size() - current_plan); for (auto& elem : current_plan_new_nodes) { - // info() << "[" << pm->commRank() << "] Old UID : " << elem.m_new_node->m_uid_new_node; elem.m_new_node->m_uid_new_node += all_nb_node[elem.m_new_node->m_owner_new_node]; - // info() << "[" << pm->commRank() << "] New UID : " << elem.m_new_node->m_uid_new_node; } return sum; } @@ -801,13 +880,14 @@ _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, I /*---------------------------------------------------------------------------*/ void MeshCutService:: -_fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_plan) +_fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_plan_pos) { + // Cet algo est repris de celui traitant les noeuds. IParallelMng* pm = subDomain()->parallelMng(); - Int32 my_proc = pm->commRank(); + // Int32 my_proc = pm->commRank(); UniqueArray> request_uid(subDomain()->nbSubDomain()); - Span current_plan_new_faces = new_faces.subView(current_plan, new_faces.size() - current_plan); + Span current_plan_new_faces = new_faces.subView(current_plan_pos, new_faces.size() - current_plan_pos); for (auto& elem : current_plan_new_faces) { @@ -850,24 +930,23 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node); request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node); - info() << "[" << my_proc << "] Ask3" - << " -- UID0 : " << elem.m_node0->m_uid_new_node - << " -- UID1 : " << elem.m_node1->m_uid_new_node; + // info() << "[" << my_proc << "] Ask3" + // << " -- UID0 : " << elem.m_node0->m_uid_new_node + // << " -- UID1 : " << elem.m_node1->m_uid_new_node; } } else { request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node); request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node); - info() << "[" << my_proc << "] Ask4" - << " -- UID0 : " << elem.m_node0->m_uid_new_node - << " -- UID1 : " << elem.m_node1->m_uid_new_node; + // info() << "[" << my_proc << "] Ask4" + // << " -- UID0 : " << elem.m_node0->m_uid_new_node + // << " -- UID1 : " << elem.m_node1->m_uid_new_node; } } UniqueArray requests(subDomain()->nbSubDomain() * 2); - // Si le noeud n'est pas à nous, il faut demander son UID au processus proprio. for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; @@ -875,11 +954,10 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ Int32 size = request_uid[sr].size(); requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); - info() << "[" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; + // info() << "[" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; } pm->waitAllRequests(requests); - // pm->freeRequests(requests); UniqueArray> answers_uid(subDomain()->nbSubDomain()); @@ -897,14 +975,15 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ std::optional pos = _find(new_faces, requested_uid[ipair_uid], requested_uid[ipair_uid + 1]); if (pos) { answers_uid[sr].add(new_faces[pos.value()].m_uid_new_face); - info() << "[" << my_proc << "] Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1] - << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; + // info() << "[" << my_proc << "] Found" + // << " -- UID0 : " << requested_uid[ipair_uid] + // << " -- UID1 : " << requested_uid[ipair_uid + 1] + // << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; } else { - warning() << "Not found"; - answers_uid[sr].add(-1); + ARCANE_FATAL("Face not found -- internal error in the algorithm"); + // warning() << "Not found"; + // answers_uid[sr].add(-1); } } } @@ -921,7 +1000,6 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ } pm->waitAllRequests(requests); - // pm->freeRequests(requests); // On reçoit et traite les réponses. for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { @@ -938,10 +1016,10 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ std::optional pos = _find(current_plan_new_faces, request_uid[sr][ipair_uid], request_uid[sr][ipair_uid + 1]); if (pos) { current_plan_new_faces[pos.value()].m_uid_new_face = answered_uid[ipair_uid / 2]; - info() << "[" << my_proc << "] Apply" - << " -- UID0 : " << current_plan_new_faces[pos.value()].m_node0->m_uid_new_node - << " -- UID1 : " << current_plan_new_faces[pos.value()].m_node1->m_uid_new_node - << " -- New UID : " << current_plan_new_faces[pos.value()].m_uid_new_face; + // info() << "[" << my_proc << "] Apply" + // << " -- UID0 : " << current_plan_new_faces[pos.value()].m_node0->m_uid_new_node + // << " -- UID1 : " << current_plan_new_faces[pos.value()].m_node1->m_uid_new_node + // << " -- New UID : " << current_plan_new_faces[pos.value()].m_uid_new_face; } else { ARCANE_FATAL("GL"); @@ -968,14 +1046,12 @@ _makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces, Int32 cur sum += old; } - info() << "[" << pm->commRank() << "] Gather result (rectified) : " << all_nb_node; + // info() << "[" << pm->commRank() << "] Gather result (rectified) : " << all_nb_node; Span current_plan_new_faces = new_faces.subView(current_plan, new_faces.size() - current_plan); for (auto& elem : current_plan_new_faces) { - // info() << "[" << pm->commRank() << "] Old UID : " << elem.m_new_node->m_uid_new_node; elem.m_uid_new_face += all_nb_node[elem.m_owner_new_face]; - // info() << "[" << pm->commRank() << "] New UID : " << elem.m_new_node->m_uid_new_node; } return sum; } @@ -997,8 +1073,8 @@ _compute() for (Int32 i = 0; i < m_plans.size(); ++i) { - Int32 size_of_new_nodes = new_nodes.size(); - Int32 size_of_new_faces = new_faces.size(); + Int32 previous_size_new_nodes = new_nodes.size(); + Int32 previous_size_new_faces = new_faces.size(); Int32 previous_g_nb_node = g_nb_node; Int32 previous_g_nb_face = g_nb_face; @@ -1008,70 +1084,61 @@ _compute() _createNodesAndCells(i, g_nb_node, new_nodes, nb_cell, new_cells, g_nb_face, new_faces); - info() << "qaaaaa"; - - _fillNodeUID(g_nb_node, new_nodes, size_of_new_nodes); + _fillNodeUID(g_nb_node, new_nodes, previous_size_new_nodes); nb_node_for_this_plan = g_nb_node - nb_node_for_this_plan; - info() << "nb_node_for_this_plan : " << nb_node_for_this_plan; - - nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, new_nodes, size_of_new_nodes); + nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, new_nodes, previous_size_new_nodes); g_nb_node = previous_g_nb_node + nb_node_for_this_plan; - for (auto& elem : new_nodes) { - info() << "New node" - << " -- UID : " << elem.m_new_node->m_uid_new_node - << " -- Owner : " << elem.m_new_node->m_owner_new_node - << " -- Pos : " << elem.m_intersection_pos - << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 - << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; - } + // for (auto& elem : new_nodes) { + // info() << "New node" + // << " -- UID : " << elem.m_new_node->m_uid_new_node + // << " -- Owner : " << elem.m_new_node->m_owner_new_node + // << " -- Pos : " << elem.m_intersection_pos + // << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 + // << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; + // } - Int32 nb_face = 0; - _fillFaceUID(g_nb_face, new_faces, size_of_new_faces); + _fillFaceUID(g_nb_face, new_faces, previous_size_new_faces); nb_face_for_this_plan = g_nb_face - nb_face_for_this_plan; - info() << "nb_face_for_this_plan : " << nb_face_for_this_plan; - - nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, new_faces, size_of_new_faces); + nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, new_faces, previous_size_new_faces); g_nb_face = previous_g_nb_face + nb_face_for_this_plan; - for (auto& elem : new_faces) { - info() << "New face" - << " -- UID : " << elem.m_uid_new_face - << " -- Owner : " << elem.m_owner_new_face - << " -- Node0 : " << elem.m_node0->m_uid_new_node - << " -- Node00 : " << elem.m_node0->m_uid_node0 - << " -- Node01 : " << elem.m_node0->m_uid_node1 - << " -- Node1 : " << elem.m_node1->m_uid_new_node - << " -- Node10 : " << elem.m_node1->m_uid_node0 - << " -- Node11 : " << elem.m_node1->m_uid_node1; - } + // for (auto& elem : new_faces) { + // info() << "New face" + // << " -- UID : " << elem.m_uid_new_face + // << " -- Owner : " << elem.m_owner_new_face + // << " -- Node0 : " << elem.m_node0->m_uid_new_node + // << " -- Node00 : " << elem.m_node0->m_uid_node0 + // << " -- Node01 : " << elem.m_node0->m_uid_node1 + // << " -- Node1 : " << elem.m_node1->m_uid_new_node + // << " -- Node10 : " << elem.m_node1->m_uid_node0 + // << " -- Node11 : " << elem.m_node1->m_uid_node1; + // } } - info() << "new_cells : " << new_cells; - _makeUniqueCellUID(nb_cell, new_cells, new_nodes); { - Int32 pos0 = 0; - while (pos0 < new_cells.size()) { - StringBuilder logs; - logs += "New cell -- Type : "; - Int64 type = new_cells[pos0++]; - logs += type; - logs += " -- UID : "; - logs += new_cells[pos0++]; - - for (Int32 i = 0; i < type; ++i) { - logs += " -- Node"; - logs += i; - logs += " : "; - logs += new_cells[pos0++]; - } - info() << logs; - } + // Int32 pos0 = 0; + // while (pos0 < new_cells.size()) { + // StringBuilder logs; + // logs += "New cell -- Type : "; + // Int64 type = new_cells[pos0++]; + // logs += type; + // logs += " -- UID : "; + // logs += new_cells[pos0++]; + // + // for (Int32 i = 0; i < type; ++i) { + // logs += " -- Node"; + // logs += i; + // logs += " : "; + // logs += new_cells[pos0++]; + // } + // info() << logs; + // } } _addFaces(new_faces); @@ -1107,7 +1174,7 @@ void MeshCutService:: _addFaces(UniqueArray& new_faces) const { UniqueArray faces_infos; - faces_infos.reserve(10000); + faces_infos.reserve(new_faces.size() * 4); Int32 nb_faces = 0; @@ -1128,36 +1195,29 @@ _addFaces(UniqueArray& new_faces) const void MeshCutService:: _addCells(UniqueArray& new_cells) { - UniqueArray cells_infos; - cells_infos.reserve(10000); - Int32 nb_cells = 0; Int32 pos0 = 0; while (pos0 < new_cells.size()) { - Int64 type = new_cells[pos0++]; - Int64 uid = new_cells[pos0++]; + const Int64 type = new_cells[pos0]; if (type == 3) - cells_infos.add(ITI_Triangle3); + new_cells[pos0++] = ITI_Triangle3; else if (type == 4) - cells_infos.add(ITI_Quad4); + new_cells[pos0++] = ITI_Quad4; else if (type == 5) - cells_infos.add(ITI_Pentagon5); + new_cells[pos0++] = ITI_Pentagon5; else if (type == 6) - cells_infos.add(ITI_Hexagon6); + new_cells[pos0++] = ITI_Hexagon6; else ARCANE_FATAL("Pas implem : {0}", type); - cells_infos.add(uid); + pos0 += 1 + static_cast(type); // (1)=UID + (type)=UIDNodes - for (Int32 i = 0; i < type; ++i) { - cells_infos.add(new_cells[pos0++]); - } nb_cells++; } - m_cloned_mesh->modifier()->addCells(nb_cells, cells_infos); + m_cloned_mesh->modifier()->addCells(nb_cells, new_cells); } /*---------------------------------------------------------------------------*/ @@ -1173,7 +1233,7 @@ _setCoordNodesAndOwner(UniqueArray& new_nodes) if (elem.m_new_node->m_uid_new_node == uid) { node_coords[inode] = elem.m_intersection_pos; inode->mutableItemBase().setOwner(elem.m_new_node->m_owner_new_node, subDomain()->subDomainId()); - info() << "NodeUID : " << uid << " -- Coord : " << node_coords[inode]; + // info() << "NodeUID : " << uid << " -- Coord : " << node_coords[inode]; } } } From 44f7a4fe7dae07f5cd4da2f8e8076ce78a53d204 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Mon, 27 Jul 2026 12:56:27 +0200 Subject: [PATCH 09/17] [arcane:std] Fix FaceLite constructor --- arcane/src/arcane/std/MeshCutService.cc | 33 ++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index e273aca465..f7594ddf4f 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -111,11 +111,38 @@ struct FaceLite FaceLite(const Ref& node0, const Ref& node1) : m_node0(node0->m_uid_node0 < node1->m_uid_node0 ? node0 : node1) , m_node1(node0->m_uid_node0 < node1->m_uid_node0 ? node1 : node0) - {} + { + const Int64 node00 = node0->m_uid_node0; + const Int64 node01 = node0->m_uid_node1; + const Int64 node10 = node1->m_uid_node0; + const Int64 node11 = node1->m_uid_node1; + + if (node00 < node10) { + m_node0 = node0; + m_node1 = node1; + } + else if (node00 > node10) { + m_node0 = node1; + m_node1 = node0; + } + else { + if (node01 == node11) { + ARCANE_FATAL("Impossible (normalement...)"); + } + if (node01 < node11) { + m_node0 = node0; + m_node1 = node1; + } + else { + m_node0 = node1; + m_node1 = node0; + } + } + } bool operator<(const FaceLite& other) const { - return m_node0->operator<(*(other.m_node0.get())) && m_node1->operator<(*(other.m_node1.get())); + return m_node0->operator<(*(other.m_node0.get())) || (m_node0->operator==(*(other.m_node0.get())) && m_node1->operator<(*(other.m_node1.get()))); } bool operator==(const FaceLite& other) const @@ -313,7 +340,7 @@ _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray Date: Mon, 27 Jul 2026 14:45:02 +0200 Subject: [PATCH 10/17] [arcane:std,core] Allow to use multiple service instance for a mesh --- arcane/src/arcane/core/IMeshSection.h | 8 +++ arcane/src/arcane/std/MeshCut.axl | 5 ++ arcane/src/arcane/std/MeshCutService.cc | 64 +++++++++++++++------ arcane/src/arcane/std/MeshSection.axl | 5 ++ arcane/src/arcane/std/MeshSectionService.cc | 61 +++++++++++++++----- 5 files changed, 112 insertions(+), 31 deletions(-) diff --git a/arcane/src/arcane/core/IMeshSection.h b/arcane/src/arcane/core/IMeshSection.h index 2a4bf5d239..b06f9431b0 100644 --- a/arcane/src/arcane/core/IMeshSection.h +++ b/arcane/src/arcane/core/IMeshSection.h @@ -70,6 +70,14 @@ class ARCANE_CORE_EXPORT IMeshSection */ virtual VariableCollection variables() = 0; + /*! + * \brief Method allowing to set a unique id allowing to create multiple + * section services for a mesh. + * + * \param unique_id Mesh unique id to apply. + */ + virtual void setServiceMeshUniqueId(Int32 unique_id) = 0; + /*! * \brief Method allowing to update the mesh section with all planes. * diff --git a/arcane/src/arcane/std/MeshCut.axl b/arcane/src/arcane/std/MeshCut.axl index d9165da2f6..2d127bf028 100644 --- a/arcane/src/arcane/std/MeshCut.axl +++ b/arcane/src/arcane/std/MeshCut.axl @@ -11,6 +11,11 @@ + + + UniqueID of service mesh. Useful if you need to create multiple instances of this service for a mesh. + + diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index f7594ddf4f..1969734b85 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -212,6 +212,7 @@ class MeshCutService explicit MeshCutService(const ServiceBuildInfo& sbi) : ArcaneMeshCutObject(sbi) + , m_creation_type(sbi.creationType()) {} public: @@ -220,6 +221,10 @@ class MeshCutService void setVariables(VariableCollection variables) override; + void setServiceMeshUniqueId(Int32 unique_id) override; + + VariableCollection variables() override { return {}; } + void updateSection() override; MeshHandle meshSection() override @@ -227,8 +232,6 @@ class MeshCutService return m_cloned_mesh->handle(); } - VariableCollection variables() override { return {}; } - private: void _createMesh(); @@ -250,9 +253,11 @@ class MeshCutService private: + eServiceType m_creation_type; // VariableCollection m_variables_ori; IPrimaryMesh* m_cloned_mesh = nullptr; UniqueArray> m_plans; + Int32 m_mesh_uid = -1; }; /*---------------------------------------------------------------------------*/ @@ -286,18 +291,22 @@ setVariables(VariableCollection variables) /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +void MeshCutService:: +setServiceMeshUniqueId(Int32 unique_id) +{ + m_mesh_uid = unique_id; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + void MeshCutService:: updateSection() { if (mesh()->ghostLayerMng()->nbGhostLayer() < 1) { ARCANE_FATAL("A ghost layer is required for this service"); } - if (m_cloned_mesh == nullptr) { - _createMesh(); - } - else { - m_cloned_mesh->modifier()->clearItems(); - } + _createMesh(); _compute(); } @@ -307,19 +316,42 @@ updateSection() void MeshCutService:: _createMesh() { + if (m_cloned_mesh != nullptr) { + m_cloned_mesh->modifier()->clearItems(); + } + if (mesh()->dimension() != 3) { ARCANE_FATAL("Only 3D meshes are supported"); } IMeshMng* mm = subDomain()->meshMng(); - IParallelMng* pm = subDomain()->parallelMng(); - // TODO gérer cas où il y a plusieurs services pour même maillage. - MeshBuildInfo mbi(mesh()->name() + "_MeshCut"); - mbi.addParallelMng(makeRef(pm)); - m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi); - m_cloned_mesh->modifier()->setDynamic(true); - m_cloned_mesh->setDimension(2); - m_cloned_mesh->endAllocate(); + + if (m_mesh_uid == -1) { + if (m_creation_type == ST_CaseOption) { + m_mesh_uid = options()->getUniqueIdServiceMesh(); + } + else { + m_mesh_uid = 0; + } + } + + String service_mesh_name = mesh()->name() + "_MeshCut" + m_mesh_uid; + + MeshHandle* mesh_handle = mm->findMeshHandle(service_mesh_name, false); + + if (mesh_handle == nullptr) { + IParallelMng* pm = subDomain()->parallelMng(); + MeshBuildInfo mbi(service_mesh_name); + mbi.addParallelMng(makeRef(pm)); + m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi); + m_cloned_mesh->modifier()->setDynamic(true); + m_cloned_mesh->setDimension(2); + m_cloned_mesh->endAllocate(); + } + else { + m_cloned_mesh = mesh_handle->mesh()->toPrimaryMesh(); + m_cloned_mesh->modifier()->clearItems(); + } } /*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/std/MeshSection.axl b/arcane/src/arcane/std/MeshSection.axl index 8557a1b376..7e2f6628e3 100644 --- a/arcane/src/arcane/std/MeshSection.axl +++ b/arcane/src/arcane/std/MeshSection.axl @@ -11,6 +11,11 @@ + + + UniqueID of service mesh. Useful if you need to create multiple instances of this service for a mesh. + + diff --git a/arcane/src/arcane/std/MeshSectionService.cc b/arcane/src/arcane/std/MeshSectionService.cc index b6e9be3590..7e6e949f0f 100644 --- a/arcane/src/arcane/std/MeshSectionService.cc +++ b/arcane/src/arcane/std/MeshSectionService.cc @@ -46,6 +46,7 @@ class MeshSectionService explicit MeshSectionService(const ServiceBuildInfo& sbi) : ArcaneMeshSectionObject(sbi) + , m_creation_type(sbi.creationType()) {} public: @@ -53,13 +54,14 @@ class MeshSectionService void addPlane(const Real3& p0, const Real3& normal) override; void setVariables(VariableCollection variables) override; + VariableCollection variables() override { return {}; } + void setServiceMeshUniqueId(Int32 unique_id) override; void updateSection() override; MeshHandle meshSection() override { return m_cloned_mesh->handle(); } - VariableCollection variables() override { return {}; } private: @@ -72,6 +74,8 @@ class MeshSectionService // VariableCollection m_variables_ori; IPrimaryMesh* m_cloned_mesh = nullptr; UniqueArray> m_plans; + Int32 m_mesh_uid = -1; + eServiceType m_creation_type; }; /*---------------------------------------------------------------------------*/ @@ -105,15 +109,19 @@ setVariables(VariableCollection variables) /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +void MeshSectionService:: +setServiceMeshUniqueId(Int32 unique_id) +{ + m_mesh_uid = unique_id; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + void MeshSectionService:: updateSection() { - if (m_cloned_mesh == nullptr) { - _createMesh(); - } - else { - m_cloned_mesh->modifier()->clearItems(); - } + _createMesh(); _compute(); } @@ -123,15 +131,38 @@ updateSection() void MeshSectionService:: _createMesh() { + if (m_cloned_mesh != nullptr) { + m_cloned_mesh->modifier()->clearItems(); + } + IMeshMng* mm = subDomain()->meshMng(); - IParallelMng* pm = subDomain()->parallelMng(); - // TODO gérer cas où il y a plusieurs services pour même maillage. - MeshBuildInfo mbi(mesh()->name() + "_MeshSection"); - mbi.addParallelMng(makeRef(pm)); - m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi); - m_cloned_mesh->modifier()->setDynamic(true); - m_cloned_mesh->setDimension(mesh()->dimension()); - m_cloned_mesh->endAllocate(); + + if (m_mesh_uid == -1) { + if (m_creation_type == ST_CaseOption) { + m_mesh_uid = options()->getUniqueIdServiceMesh(); + } + else { + m_mesh_uid = 0; + } + } + + String service_mesh_name = mesh()->name() + "_MeshSection" + m_mesh_uid; + + MeshHandle* mesh_handle = mm->findMeshHandle(service_mesh_name, false); + + if (mesh_handle == nullptr) { + IParallelMng* pm = subDomain()->parallelMng(); + MeshBuildInfo mbi(service_mesh_name); + mbi.addParallelMng(makeRef(pm)); + m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi); + m_cloned_mesh->modifier()->setDynamic(true); + m_cloned_mesh->setDimension(mesh()->dimension()); + m_cloned_mesh->endAllocate(); + } + else { + m_cloned_mesh = mesh_handle->mesh()->toPrimaryMesh(); + m_cloned_mesh->modifier()->clearItems(); + } } /*---------------------------------------------------------------------------*/ From 2b6a5f342bf0cdd022eb2c9c4645206d56ec7e38 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Wed, 29 Jul 2026 15:51:42 +0200 Subject: [PATCH 11/17] [arcane:std] Fix UID searching with a 2-step search algo --- arcane/src/arcane/std/MeshCutService.cc | 888 ++++++++++++++++++------ 1 file changed, 681 insertions(+), 207 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index 1969734b85..01d5da9e69 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -190,6 +190,16 @@ struct NodeIntersection Ref m_new_node; Real3 m_intersection_pos{ -1 }; }; + +struct UnknownNode +{ + UnknownNode(Int64 node0_uid, Int64 node1_uid, Int32 who) : m_node0_uid(node0_uid), m_node1_uid(node1_uid), m_who(who){} + bool null() const {return m_who == -1;} + bool operator==(const UnknownNode& other) const{return m_node0_uid == other.m_node0_uid && m_node1_uid == other.m_node1_uid;} + Int64 m_node0_uid; + Int64 m_node1_uid; + Int32 m_who; +}; } // namespace /*---------------------------------------------------------------------------*/ @@ -235,7 +245,7 @@ class MeshCutService private: void _createMesh(); - void _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_nodes, Int32& sd_nb_cell, UniqueArray& new_cells, Int32& sd_nb_face, UniqueArray& new_faces); + void _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_nodes, Int32 ajust_node_pos, Int32& sd_nb_cell, UniqueArray& new_cells, Int32& sd_nb_face, UniqueArray& new_faces); void _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray& new_nodes); void _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan_pos); @@ -342,6 +352,9 @@ _createMesh() if (mesh_handle == nullptr) { IParallelMng* pm = subDomain()->parallelMng(); MeshBuildInfo mbi(service_mesh_name); + // auto mesh_kind = mbi.meshKind(); + // mesh_kind.setMeshDimensionKind(eMeshCellDimensionKind::NonManifold); + // mbi.addMeshKind(mesh_kind); mbi.addParallelMng(makeRef(pm)); m_cloned_mesh = mm->meshFactoryMng()->createMesh(mbi); m_cloned_mesh->modifier()->setDynamic(true); @@ -358,7 +371,7 @@ _createMesh() /*---------------------------------------------------------------------------*/ void MeshCutService:: -_createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_nodes, Int32& sd_nb_cell, UniqueArray& new_cells, Int32& sd_nb_face, UniqueArray& new_faces) +_createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_nodes, Int32 ajust_node_pos, Int32& sd_nb_cell, UniqueArray& new_cells, Int32& sd_nb_face, UniqueArray& new_faces) { auto [p0, normal] = m_plans[plan_pos]; @@ -627,7 +640,7 @@ _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray(pos.value())); + new_cells.add(static_cast(pos.value()) + ajust_node_pos); idx = pos.value(); } // S'il n'est pas présent, on le crée. @@ -650,7 +663,7 @@ _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArraym_uid_new_node = -2; } } - new_cells.add(new_nodes.size()); + new_cells.add(new_nodes.size() + ajust_node_pos); idx = new_nodes.size(); new_nodes.add(elem); } @@ -729,8 +742,8 @@ void MeshCutService:: _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan_pos) { IParallelMng* pm = subDomain()->parallelMng(); - // Int32 my_proc = pm->commRank(); - UniqueArray> request_uid(subDomain()->nbSubDomain()); + Int32 my_proc = pm->commRank(); + UniqueArray>> requested_nodes(subDomain()->nbSubDomain()); // On souhaite mettre à jour uniquement les nouveaux noeuds, on crée donc // une vue qui regroupe uniquement les nouveau noeuds. @@ -740,100 +753,125 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 // première condition. Span current_plan_new_nodes = new_nodes.subView(current_plan_pos, new_nodes.size() - current_plan_pos); - // On détermine le futur proprio de chaque noeud. - for (auto& elem : current_plan_new_nodes) { - // Si le uid est déjà mis, pas besoin de le rechercher... - if (elem.m_new_node->m_uid_new_node >= 0) { - continue; - } - // Si le proprio n'est pas définit, on doit faire une recherche. - if (elem.m_new_node->m_owner_new_node < 0) { + { + UniqueArray> request_uid(subDomain()->nbSubDomain()); + + // On détermine le futur proprio de chaque noeud. + info() << "[Node][" << my_proc << "] Step 1"; - Node node0 = elem.m_new_node->m_node0; - Node node1 = elem.m_new_node->m_node1; + for (auto& elem : current_plan_new_nodes) { + // Si le uid est déjà mis, pas besoin de le rechercher... + if (elem.m_new_node->m_uid_new_node >= 0) { + continue; + } - // Le propriétaire du noeud est le propriétaire de la maille ayant le plus - // petit UID, parmi les mailles en commun entre les deux noeuds d'origine. + // Si le proprio n'est pas définit, on doit faire une recherche. + if (elem.m_new_node->m_owner_new_node < 0) { - // TODO Ajouter traitement particulier pour le cas où node0 == node1 - Int64 min_uid = INT64_MAX; - Int32 owner_min = -1; - for (Cell cell0 : node0.cells()) { - for (Cell cell1 : node1.cells()) { - if (cell0 == cell1) { - if (cell0.uniqueId() < min_uid) { - min_uid = cell0.uniqueId(); - owner_min = cell0.owner(); + Node node0 = elem.m_new_node->m_node0; + Node node1 = elem.m_new_node->m_node1; + + // Le propriétaire du noeud est le propriétaire de la maille ayant le plus + // petit UID, parmi les mailles en commun entre les deux noeuds d'origine. + + // TODO Ajouter traitement particulier pour le cas où node0 == node1 + Int64 min_uid = INT64_MAX; + Int32 owner_min = -1; + for (Cell cell0 : node0.cells()) { + for (Cell cell1 : node1.cells()) { + if (cell0 == cell1) { + if (cell0.uniqueId() < min_uid) { + min_uid = cell0.uniqueId(); + owner_min = cell0.owner(); + } } } } - } - // S'il l'on est le proprio, on peut définir le uid du noeud. - if (owner_min == subDomain()->subDomainId()) { - elem.m_new_node->m_owner_new_node = subDomain()->subDomainId(); - elem.m_new_node->m_uid_new_node = sd_nb_node++; + // S'il l'on est le proprio, on peut définir le uid du noeud. + if (owner_min == subDomain()->subDomainId()) { + elem.m_new_node->m_owner_new_node = subDomain()->subDomainId(); + elem.m_new_node->m_uid_new_node = sd_nb_node++; + + info() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Set UID" + << " -- UID0 : " << elem.m_new_node->m_uid_node0 + << " -- UID1 : " << elem.m_new_node->m_uid_node1 + << " -- New UID : " << elem.m_new_node->m_uid_new_node; + } + + // Sinon, on doit aller demander le uid au proprio. + else { + elem.m_new_node->m_owner_new_node = owner_min; + elem.m_new_node->m_uid_new_node = -2; + + // Une requête est composée uniquement des deux UID des noeuds de + // l'arête dont est issue le nouveau noeud. C'est le seul moyen + // d'identifier ce noeud pour l'instant (si on exclut l'identification + // par sa position). + request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0); + request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1); + + requested_nodes[elem.m_new_node->m_owner_new_node].add(elem.m_new_node); + + info() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Ask1" + << " -- UID0 : " << elem.m_new_node->m_uid_node0 + << " -- UID1 : " << elem.m_new_node->m_uid_node1; + } } - // Sinon, on doit aller demander le uid au proprio. + // Si le proprio est déjà défini, on doit lui demander le uid du noeud. else { - elem.m_new_node->m_owner_new_node = owner_min; - elem.m_new_node->m_uid_new_node = -2; - - // Une requête est composée uniquement des deux UID des noeuds de - // l'arête dont est issue le nouveau noeud. C'est le seul moyen - // d'identifier ce noeud pour l'instant (si on exclut l'identification - // par sa position). request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0); request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1); - // info() << "[" << my_proc << "] Ask1" - // << " -- UID0 : " << elem.m_new_node->m_uid_node0 - // << " -- UID1 : " << elem.m_new_node->m_uid_node1; + requested_nodes[elem.m_new_node->m_owner_new_node].add(elem.m_new_node); + + info() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Ask2" + << " -- UID0 : " << elem.m_new_node->m_uid_node0 + << " -- UID1 : " << elem.m_new_node->m_uid_node1; } } - // Si le proprio est déjà défini, on doit lui demander le uid du noeud. - else { - request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node0); - request_uid[elem.m_new_node->m_owner_new_node].add(elem.m_new_node->m_uid_node1); + { + UniqueArray requests(subDomain()->nbSubDomain() * 2); - // info() << "[" << my_proc << "] Ask2" - // << " -- UID0 : " << elem.m_new_node->m_uid_node0 - // << " -- UID1 : " << elem.m_new_node->m_uid_node1; - } - } + // On envoie les requêtes. + info() << "[Node][" << my_proc << "] Step 2"; - UniqueArray requests(subDomain()->nbSubDomain() * 2); + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + Int32 size = request_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); + info() << "[Node][" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; + } - // On envoie les requêtes. - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; + pm->waitAllRequests(requests); + // pm->freeRequests(requests); } - Int32 size = request_uid[sr].size(); - requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); - requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); - // info() << "[" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; } - pm->waitAllRequests(requests); - // pm->freeRequests(requests); - UniqueArray> answers_uid(subDomain()->nbSubDomain()); + UniqueArray unknown_node; + // On reçoit et traite les demandes. + info() << "[Node][" << my_proc << "] Step 3"; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; } - Int32 size = 0; pm->recv(ArrayView{ 1, &size }, sr); UniqueArray requested_uid(size); pm->recv(requested_uid, sr); + answers_uid[sr].add(0); + // On traite chaque paire de noeud. for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { @@ -842,68 +880,254 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 std::optional pos = new_nodes.span().findFirst(NodeIntersection{ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], Real3{ 0 } }); if (pos) { answers_uid[sr].add(new_nodes[pos.value()].m_new_node->m_uid_new_node); - // info() << "[" << my_proc << "] Found" - // << " -- UID0 : " << requested_uid[ipair_uid] - // << " -- UID1 : " << requested_uid[ipair_uid + 1] - // << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; + info() << "[Node][" << my_proc << " <- " << sr << "] Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1] + << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; } - // En théorie, ça ne devrait pas arriver : au-dessus, on itère sur les - // mailles en commun pour les deux noeuds de l'arête, ce qui doit - // normalement nous donner toutes les mailles qui possèdent cette arête - // (= "edge.cells()"). + // Il peut arriver que l'on nous demande un noeud que nous n'avons pas. + // Par exemple, si un plan arrive pile sur une des arêtes de nos mailles. + // Par contre, on sait qui en a besoin, donc qui possède une maille avec + // le noeud en question. + // Pour donner cette information, on va ajouter "-1" puis, à la fin de + // la réponse, on va placer les processus en question. else { - ARCANE_FATAL("Node not found -- internal error in the algorithm"); - // warning() << "Not found"; - // answers_uid[sr].add(-1); + answers_uid[sr].add(-1); + unknown_node.add({requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr}); + info() << "[Node][" << my_proc << " <- " << sr << "] NOT Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1]; } } + answers_uid[sr][0] = answers_uid[sr].size()-1; } - // On envoie les réponses. - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; + UniqueArray who; + for (Int32 i = 0; i < unknown_node.size(); ++i) { + if (unknown_node[i].null())continue; + who.clear(); + who.add(unknown_node[i].m_who); + unknown_node[i].m_who = -1; + for (Int32 j = i+1; j < unknown_node.size(); ++j) { + if (unknown_node[j].null()) continue; + if (unknown_node[j] == unknown_node[i]) { + who.add(unknown_node[j].m_who); + unknown_node[j].m_who = -1; + } } + info() << "[Node] Additionnal infos -- Node0UID : " << unknown_node[i].m_node0_uid << " -- Node1UID : " << unknown_node[i].m_node1_uid << " -- Who : " << who; + for (auto proc : who) { + answers_uid[proc].add(unknown_node[i].m_node0_uid); + answers_uid[proc].add(unknown_node[i].m_node1_uid); + answers_uid[proc].add(who.size()); + answers_uid[proc].addRange(who); + } + } + + { + UniqueArray requests(subDomain()->nbSubDomain() * 2); + + // On envoie les réponses. + info() << "[Node][" << my_proc << "] Step 4"; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } - Int32 size = answers_uid[sr].size(); - requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); - requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); + Int32 size = answers_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); + + info() << "[Node][" << my_proc << " -> " << sr << "] Send " << answers_uid[sr]; + } + + pm->waitAllRequests(requests); + // pm->freeRequests(requests); } - pm->waitAllRequests(requests); - // pm->freeRequests(requests); + + UniqueArray> request_uid(subDomain()->nbSubDomain()); + UniqueArray>> requested_nodes2(subDomain()->nbSubDomain()); // On reçoit et traite les réponses. + info() << "[Node][" << my_proc << "] Step 5"; + + Int32 iter_requested_nodes = 0; + bool need_more_comm = false; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; } - Int32 size = 0; - pm->recv(ArrayView{ 1, &size }, sr); - UniqueArray answered_uid(size); + Int32 total_size = 0; + pm->recv(ArrayView{ 1, &total_size }, sr); + + UniqueArray answered_uid(total_size); pm->recv(answered_uid, sr); - // On reprend les pairs de nos requêtes du début. - for (Int32 ipair_uid = 0; ipair_uid < request_uid[sr].size(); ipair_uid += 2) { - // On retrouve le noeud correspondant à la requête. - // TODO : Sauvegarder les noeuds dans un tableau pour éviter la recherche ? - std::optional pos = current_plan_new_nodes.findFirst(NodeIntersection{ request_uid[sr][ipair_uid], request_uid[sr][ipair_uid + 1], Real3{ 0 } }); - if (pos) { - current_plan_new_nodes[pos.value()].m_new_node->m_uid_new_node = answered_uid[ipair_uid / 2]; - // info() << "[" << my_proc << "] Apply" - // << " -- UID0 : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_node0 - // << " -- UID1 : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_node1 - // << " -- New UID : " << current_plan_new_nodes[pos.value()].m_new_node->m_uid_new_node; - } + Int32 answer_to_request_size = answered_uid[0]; + + Span answer_to_request = answered_uid.subView(1, answer_to_request_size); + Span additionnal_answer = answered_uid.subView(answer_to_request_size+1, answered_uid.size() - (answer_to_request_size+1)); + + info() << "[Node][" << my_proc << " <- " << sr << "] Decoupe" + << " -- answer_to_request : " << answer_to_request + << " -- additionnal_answer : " << additionnal_answer; + - // Pas normal. + for (Int32 answer = 0; answer < answer_to_request.size(); ++answer) { + Ref node_on_edge = requested_nodes[sr][answer]; + + if (answer_to_request[answer] != -1) { + node_on_edge->m_uid_new_node = answer_to_request[answer]; + info() << "[Node][" << my_proc << "] Apply" + << " -- UID0 : " << node_on_edge->m_uid_node0 + << " -- UID1 : " << node_on_edge->m_uid_node1 + << " -- New UID : " << node_on_edge->m_uid_new_node; + } else { - ARCANE_FATAL("GL"); + need_more_comm = true; + Span sub_additionnal_answer; + + Int32 pos_sort = 0; + Int64 pos = 0; + while (pos < additionnal_answer.size()) { + Int64 uid0 = additionnal_answer[pos++]; + Int64 uid1 = additionnal_answer[pos++]; + Int64 decal = additionnal_answer[pos++]; + if (uid0 == node_on_edge->m_uid_node0 && uid1 == node_on_edge->m_uid_node1) { + sub_additionnal_answer = additionnal_answer.subSpan(pos, decal); + break; + } + pos += decal; + pos_sort++; + } + if (sub_additionnal_answer.data() == nullptr) { + ARCANE_FATAL("Unknown node -- UID0 : {0} -- UID1 : {1}", node_on_edge->m_uid_node0, node_on_edge->m_uid_node1); + } + + info() << "[Node][" << my_proc << " <- " << sr << "] Sub" + << " -- sub_additionnal_answer : " << sub_additionnal_answer; + + Node node0 = node_on_edge->m_node0; + Node node1 = node_on_edge->m_node1; + + // Le propriétaire du noeud est le propriétaire de la maille ayant le plus + // petit UID, parmi les mailles en commun entre les deux noeuds d'origine. + + // TODO Ajouter traitement particulier pour le cas où node0 == node1 + Int64 min_uid = INT64_MAX; + Int32 owner_min = -1; + for (Cell cell0 : node0.cells()) { + for (Cell cell1 : node1.cells()) { + if (cell0 == cell1) { + if (cell0.uniqueId() < min_uid && sub_additionnal_answer.contains(cell0.owner())) { + min_uid = cell0.uniqueId(); + owner_min = cell0.owner(); + } + } + } + } + + // S'il l'on est le proprio, on peut définir le uid du noeud. + if (owner_min == subDomain()->subDomainId()) { + node_on_edge->m_owner_new_node = subDomain()->subDomainId(); + node_on_edge->m_uid_new_node = sd_nb_node++; + + info() << "[Node][" << my_proc << "] Send" + << " -- UID : " << node_on_edge->m_uid_new_node + << " -- for Node UID0 : " << node_on_edge->m_uid_node0 + << " -- UID1 : " << node_on_edge->m_uid_node1 + << " -- to : " << sub_additionnal_answer; + + for (auto proc : sub_additionnal_answer) { + if (proc == my_proc)continue; + request_uid[proc].add(node_on_edge->m_uid_new_node); + } + } + + // Sinon, on doit aller demander le uid au proprio. + else { + node_on_edge->m_owner_new_node = owner_min; + node_on_edge->m_uid_new_node = -2; + + request_uid[my_proc].add(owner_min); + // request_uid[my_proc].add(iter_requested_nodes); + request_uid[my_proc].add(pos_sort); + + requested_nodes2[owner_min].add(node_on_edge); + + + info() << "[Node][" << my_proc << " -> " << node_on_edge->m_owner_new_node << "] Recv UID for Node" + << " -- UID0 : " << node_on_edge->m_uid_node0 + << " -- UID1 : " << node_on_edge->m_uid_node1; + } } + iter_requested_nodes++; } } + + if (need_more_comm) { + { + UniqueArray requests(subDomain()->nbSubDomain()); + + // On envoie les UID complémentaires. + info() << "[Node][" << my_proc << "] Step 6"; + + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + info() << "[Node][" << my_proc << " -> " << sr << "] My RequestsC : " << request_uid[sr]; + continue; + } + if (request_uid[sr].empty()) continue; + requests[sr] = pm->send(request_uid[sr], sr, false); + info() << "[Node][" << my_proc << " -> " << sr << "] RequestsC : " << request_uid[sr]; + } + + pm->waitAllRequests(requests); + } + + // On reçoit et traite les UID complémentaires. + info() << "[Node][" << my_proc << "] Step 7"; + + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + + Int32 size = 0; + + for (Int32 i = 0; i < request_uid[my_proc].size(); i += 2) { + if (request_uid[my_proc][i] == sr) { + size++; + } + } + + if (size == 0) continue; + + info() << "[Node][" << my_proc << " -> " << sr << "] Size recv : " << size; + + + UniqueArray requested_uid(size); + pm->recv(requested_uid, sr); + + for (Int32 i = 0, ii = 0; i < request_uid[my_proc].size(); i += 2, ++ii) { + if (request_uid[my_proc][i] == sr) { + Ref node_on_edge = requested_nodes2[sr][ii]; + node_on_edge->m_uid_new_node = requested_uid[request_uid[my_proc][i+1]]; + info() << "[Node][" << my_proc << "] Apply2" + << " -- UID0 : " << node_on_edge->m_uid_node0 + << " -- UID1 : " << node_on_edge->m_uid_node1 + << " -- New UID : " << node_on_edge->m_uid_new_node; + } + } + } + } + + + info() << "[Node][" << subDomain()->parallelMng()->commRank() << "]"; + subDomain()->parallelMng()->barrier(); } /*---------------------------------------------------------------------------*/ @@ -943,84 +1167,109 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ { // Cet algo est repris de celui traitant les noeuds. IParallelMng* pm = subDomain()->parallelMng(); - // Int32 my_proc = pm->commRank(); - UniqueArray> request_uid(subDomain()->nbSubDomain()); + Int32 my_proc = pm->commRank(); + UniqueArray> requested_faces(subDomain()->nbSubDomain()); Span current_plan_new_faces = new_faces.subView(current_plan_pos, new_faces.size() - current_plan_pos); - for (auto& elem : current_plan_new_faces) { + { + Int32 iter = -1; + UniqueArray> request_uid(subDomain()->nbSubDomain()); - if (elem.m_uid_new_face >= 0) { - continue; - } - if (elem.m_owner_new_face < 0) { - - Node node00 = elem.m_node0->m_node0; - Node node01 = elem.m_node0->m_node1; - Node node10 = elem.m_node1->m_node0; - Node node11 = elem.m_node1->m_node1; - - Int64 min_uid = INT64_MAX; - Int32 owner_min = -1; - - // TODO AH : C'est quand même TURBO moche - for (Cell cell00 : node00.cells()) { - for (Cell cell01 : node01.cells()) { - for (Cell cell10 : node10.cells()) { - for (Cell cell11 : node11.cells()) { - if (cell00 == cell01 && cell00 == cell10 && cell00 == cell11) { - if (cell00.uniqueId() < min_uid) { - min_uid = cell00.uniqueId(); - owner_min = cell00.owner(); + info() << "[Face][" << my_proc << "] Step 1"; + + for (auto& elem : current_plan_new_faces) { + iter++; + if (elem.m_uid_new_face >= 0) { + continue; + } + if (elem.m_owner_new_face < 0) { + + Node node00 = elem.m_node0->m_node0; + Node node01 = elem.m_node0->m_node1; + Node node10 = elem.m_node1->m_node0; + Node node11 = elem.m_node1->m_node1; + + Int64 min_uid = INT64_MAX; + Int32 owner_min = -1; + + // TODO AH : C'est quand même TURBO moche + for (Cell cell00 : node00.cells()) { + for (Cell cell01 : node01.cells()) { + for (Cell cell10 : node10.cells()) { + for (Cell cell11 : node11.cells()) { + if (cell00 == cell01 && cell00 == cell10 && cell00 == cell11) { + if (cell00.uniqueId() < min_uid) { + min_uid = cell00.uniqueId(); + owner_min = cell00.owner(); + } } } } } } - } - if (owner_min == subDomain()->subDomainId()) { - elem.m_owner_new_face = subDomain()->subDomainId(); - elem.m_uid_new_face = sd_nb_face++; + if (owner_min == subDomain()->subDomainId()) { + elem.m_owner_new_face = subDomain()->subDomainId(); + elem.m_uid_new_face = sd_nb_face++; + + info() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Set UID" + << " -- UID0 : " << elem.m_node0->m_uid_new_node + << " -- UID1 : " << elem.m_node1->m_uid_new_node + << " -- New UID : " << elem.m_uid_new_face; + } + else { + elem.m_owner_new_face = owner_min; + elem.m_uid_new_face = -2; + request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node); + request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node); + + requested_faces[elem.m_owner_new_face].add(iter); + + info() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Ask1" + << " -- UID0 : " << elem.m_node0->m_uid_new_node + << " -- UID1 : " << elem.m_node1->m_uid_new_node; + } } else { - elem.m_owner_new_face = owner_min; - elem.m_uid_new_face = -2; request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node); request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node); - // info() << "[" << my_proc << "] Ask3" - // << " -- UID0 : " << elem.m_node0->m_uid_new_node - // << " -- UID1 : " << elem.m_node1->m_uid_new_node; + requested_faces[elem.m_owner_new_face].add(iter); + + info() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Ask2" + << " -- UID0 : " << elem.m_node0->m_uid_new_node + << " -- UID1 : " << elem.m_node1->m_uid_new_node; } } - else { - request_uid[elem.m_owner_new_face].add(elem.m_node0->m_uid_new_node); - request_uid[elem.m_owner_new_face].add(elem.m_node1->m_uid_new_node); - // info() << "[" << my_proc << "] Ask4" - // << " -- UID0 : " << elem.m_node0->m_uid_new_node - // << " -- UID1 : " << elem.m_node1->m_uid_new_node; - } - } + { + UniqueArray requests(subDomain()->nbSubDomain() * 2); - UniqueArray requests(subDomain()->nbSubDomain() * 2); + // On envoie les requêtes. + info() << "[Face][" << my_proc << "] Step 2"; - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + Int32 size = request_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); + info() << "[Face][" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; + } + + pm->waitAllRequests(requests); } - Int32 size = request_uid[sr].size(); - requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); - requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); - // info() << "[" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; } - pm->waitAllRequests(requests); - UniqueArray> answers_uid(subDomain()->nbSubDomain()); + UniqueArray unknown_face; + // On reçoit et traite les demandes. + info() << "[Face][" << my_proc << "] Step 3"; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; @@ -1030,61 +1279,258 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ UniqueArray requested_uid(size); pm->recv(requested_uid, sr); + answers_uid[sr].add(0); + for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { std::optional pos = _find(new_faces, requested_uid[ipair_uid], requested_uid[ipair_uid + 1]); if (pos) { answers_uid[sr].add(new_faces[pos.value()].m_uid_new_face); - // info() << "[" << my_proc << "] Found" - // << " -- UID0 : " << requested_uid[ipair_uid] - // << " -- UID1 : " << requested_uid[ipair_uid + 1] - // << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; + info() << "[Face][" << my_proc << " <- " << sr << "] Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1] + << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; } + + // Il peut arriver que l'on nous demande une face que nous n'avons pas. + // Par exemple, si un plan arrive pile sur une des arêtes de nos mailles. + // Par contre, on sait qui en a besoin, donc qui possède une maille avec + // la face en question. + // Pour donner cette information, on va ajouter "-1" puis, à la fin de + // la réponse, on va placer les processus en question. else { - ARCANE_FATAL("Face not found -- internal error in the algorithm"); - // warning() << "Not found"; - // answers_uid[sr].add(-1); + answers_uid[sr].add(-1); + unknown_face.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr }); + info() << "[Face][" << my_proc << " <- " << sr << "] NOT Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1]; } } + answers_uid[sr][0] = answers_uid[sr].size() - 1; } - // On envoie les réponses. - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { + UniqueArray who; + for (Int32 i = 0; i < unknown_face.size(); ++i) { + if (unknown_face[i].null()) continue; + who.clear(); + who.add(unknown_face[i].m_who); + unknown_face[i].m_who = -1; + for (Int32 j = i + 1; j < unknown_face.size(); ++j) { + if (unknown_face[j].null()) + continue; + if (unknown_face[j] == unknown_face[i]) { + who.add(unknown_face[j].m_who); + unknown_face[j].m_who = -1; + } } + info() << "[Face] Additionnal infos -- Node0UID : " << unknown_face[i].m_node0_uid << " -- Node1UID : " << unknown_face[i].m_node1_uid << " -- Who : " << who; + for (auto proc : who) { + answers_uid[proc].add(unknown_face[i].m_node0_uid); + answers_uid[proc].add(unknown_face[i].m_node1_uid); + answers_uid[proc].add(who.size()); + answers_uid[proc].addRange(who); + } + } - Int32 size = answers_uid[sr].size(); - requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); - requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); + { + UniqueArray requests(subDomain()->nbSubDomain() * 2); + + // On envoie les réponses. + info() << "[Face][" << my_proc << "] Step 4"; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + + Int32 size = answers_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); + } + + pm->waitAllRequests(requests); } - pm->waitAllRequests(requests); + UniqueArray> request_uid(subDomain()->nbSubDomain()); + UniqueArray> requested_faces2(subDomain()->nbSubDomain()); // On reçoit et traite les réponses. + info() << "[Face][" << my_proc << "] Step 5"; + + Int32 iter_requested_faces = 0; + bool need_more_comm = false; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; } - Int32 size = 0; - pm->recv(ArrayView{ 1, &size }, sr); - UniqueArray answered_uid(size); + Int32 total_size = 0; + pm->recv(ArrayView{ 1, &total_size }, sr); + + UniqueArray answered_uid(total_size); pm->recv(answered_uid, sr); - for (Int32 ipair_uid = 0; ipair_uid < request_uid[sr].size(); ipair_uid += 2) { - std::optional pos = _find(current_plan_new_faces, request_uid[sr][ipair_uid], request_uid[sr][ipair_uid + 1]); - if (pos) { - current_plan_new_faces[pos.value()].m_uid_new_face = answered_uid[ipair_uid / 2]; - // info() << "[" << my_proc << "] Apply" - // << " -- UID0 : " << current_plan_new_faces[pos.value()].m_node0->m_uid_new_node - // << " -- UID1 : " << current_plan_new_faces[pos.value()].m_node1->m_uid_new_node - // << " -- New UID : " << current_plan_new_faces[pos.value()].m_uid_new_face; + Int32 answer_to_request_size = answered_uid[0]; + + Span answer_to_request = answered_uid.subView(1, answer_to_request_size); + Span additionnal_answer = answered_uid.subView(answer_to_request_size + 1, answered_uid.size() - (answer_to_request_size + 1)); + + info() << "[Face][" << my_proc << " <- " << sr << "] Decoupe" + << " -- answer_to_request : " << answer_to_request + << " -- additionnal_answer : " << additionnal_answer; + + for (Int32 answer = 0; answer < answer_to_request.size(); ++answer) { + FaceLite& face_lite = new_faces[requested_faces[sr][answer]]; + + if (answer_to_request[answer] != -1) { + face_lite.m_uid_new_face = answer_to_request[answer]; + info() << "[Face][" << my_proc << "] Apply" + << " -- UID0 : " << face_lite.m_node0->m_uid_new_node + << " -- UID1 : " << face_lite.m_node1->m_uid_new_node + << " -- New UID : " << face_lite.m_uid_new_face; } else { - ARCANE_FATAL("GL"); + need_more_comm = true; + Span sub_additionnal_answer; + + Int32 pos_sort = 0; + Int64 pos = 0; + while (pos < additionnal_answer.size()) { + Int64 uid0 = additionnal_answer[pos++]; + Int64 uid1 = additionnal_answer[pos++]; + Int64 decal = additionnal_answer[pos++]; + if (uid0 == face_lite.m_node0->m_uid_new_node && uid1 == face_lite.m_node1->m_uid_new_node) { + sub_additionnal_answer = additionnal_answer.subSpan(pos, decal); + break; + } + pos += decal; + pos_sort++; + } + if (sub_additionnal_answer.data() == nullptr) { + ARCANE_FATAL("Unknown face -- UID0 : {0} -- UID1 : {1}", face_lite.m_node0->m_uid_new_node, face_lite.m_node1->m_uid_new_node); + } + + info() << "[Face][" << my_proc << " <- " << sr << "] Sub" + << " -- sub_additionnal_answer : " << sub_additionnal_answer; + + Node node00 = face_lite.m_node0->m_node0; + Node node01 = face_lite.m_node0->m_node1; + Node node10 = face_lite.m_node1->m_node0; + Node node11 = face_lite.m_node1->m_node1; + + Int64 min_uid = INT64_MAX; + Int32 owner_min = -1; + + // TODO AH : C'est quand même TURBO moche + for (Cell cell00 : node00.cells()) { + for (Cell cell01 : node01.cells()) { + for (Cell cell10 : node10.cells()) { + for (Cell cell11 : node11.cells()) { + if (cell00 == cell01 && cell00 == cell10 && cell00 == cell11) { + if (cell00.uniqueId() < min_uid && sub_additionnal_answer.contains(cell00.owner())) { + min_uid = cell00.uniqueId(); + owner_min = cell00.owner(); + } + } + } + } + } + } + + if (owner_min == subDomain()->subDomainId()) { + face_lite.m_owner_new_face = subDomain()->subDomainId(); + face_lite.m_uid_new_face = sd_nb_face++; + + info() << "[Face][" << my_proc << "] Send" + << " -- UID : " << face_lite.m_uid_new_face + << " -- for Node UID0 : " << face_lite.m_node0->m_uid_new_node + << " -- UID1 : " << face_lite.m_node1->m_uid_new_node + << " -- to : " << sub_additionnal_answer; + + for (auto proc : sub_additionnal_answer) { + if (proc == my_proc) + continue; + request_uid[proc].add(face_lite.m_uid_new_face); + } + } + + // Sinon, on doit aller demander le uid au proprio. + else { + face_lite.m_owner_new_face = owner_min; + face_lite.m_uid_new_face = -2; + + request_uid[my_proc].add(owner_min); + // request_uid[my_proc].add(iter_requested_faces); + request_uid[my_proc].add(pos_sort); + + requested_faces2[owner_min].add(requested_faces[sr][answer]); + + info() << "[Face][" << my_proc << " -> " << face_lite.m_owner_new_face << "] Recv UID for Node" + << " -- UID0 : " << face_lite.m_node0->m_uid_new_node + << " -- UID1 : " << face_lite.m_node1->m_uid_new_node; + } } + iter_requested_faces++; } } + + if (need_more_comm) { + { + UniqueArray requests(subDomain()->nbSubDomain()); + // On envoie les UID complémentaires. + info() << "[Face][" << my_proc << "] Step 6"; + + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + info() << "[Face][" << my_proc << " -> " << sr << "] My RequestsC : " << request_uid[sr]; + continue; + } + if (request_uid[sr].empty()) continue; + requests[sr] = pm->send(request_uid[sr], sr, false); + info() << "[Face][" << my_proc << " -> " << sr << "] RequestsC : " << request_uid[sr]; + } + + pm->waitAllRequests(requests); + } + + // On reçoit et traite les UID complémentaires. + info() << "[Face][" << my_proc << "] Step 7"; + + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + + Int32 size = 0; + + for (Int32 i = 0; i < request_uid[my_proc].size(); i += 2) { + if (request_uid[my_proc][i] == sr) { + size++; + } + } + + if (size == 0) continue; + + info() << "[Face][" << my_proc << " -> " << sr << "] Size recv : " << size; + + UniqueArray requested_uid(size); + pm->recv(requested_uid, sr); + + for (Int32 i = 0, ii = 0; i < request_uid[my_proc].size(); i += 2, ++ii) { + if (request_uid[my_proc][i] == sr) { + FaceLite& face_lite = new_faces[requested_faces2[sr][ii]]; + + face_lite.m_uid_new_face = requested_uid[request_uid[my_proc][i+1]]; + info() << "[Face][" << my_proc << "] Apply2" + << " -- UID0 : " << face_lite.m_node0->m_uid_new_node + << " -- UID1 : " << face_lite.m_node1->m_uid_new_node + << " -- New UID : " << face_lite.m_uid_new_face; + } + } + } + } + + info() << "[Face][" << subDomain()->parallelMng()->commRank() << "]"; + subDomain()->parallelMng()->barrier(); } /*---------------------------------------------------------------------------*/ @@ -1132,8 +1578,12 @@ _compute() for (Int32 i = 0; i < m_plans.size(); ++i) { - Int32 previous_size_new_nodes = new_nodes.size(); - Int32 previous_size_new_faces = new_faces.size(); + info() << "Plan : " << m_plans[i].first << ", " << m_plans[i].second; + + UniqueArray plan_new_nodes; + UniqueArray plan_new_faces; + + Int32 ajust = new_nodes.size(); Int32 previous_g_nb_node = g_nb_node; Int32 previous_g_nb_face = g_nb_face; @@ -1141,41 +1591,65 @@ _compute() Int32 nb_node_for_this_plan = g_nb_node; Int32 nb_face_for_this_plan = g_nb_face; - _createNodesAndCells(i, g_nb_node, new_nodes, nb_cell, new_cells, g_nb_face, new_faces); + info() << "[" << subDomain()->parallelMng()->commRank() << "] _createNodesAndCells"; + _createNodesAndCells(i, g_nb_node, plan_new_nodes, ajust, nb_cell, new_cells, g_nb_face, plan_new_faces); - _fillNodeUID(g_nb_node, new_nodes, previous_size_new_nodes); + for (auto& elem : plan_new_nodes) { + info() << "New node" + << " -- UID : " << elem.m_new_node->m_uid_new_node + << " -- Owner : " << elem.m_new_node->m_owner_new_node + << " -- Pos : " << elem.m_intersection_pos + << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 + << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; + } + + info() << "[" << subDomain()->parallelMng()->commRank() << "] _fillNodeUID"; + _fillNodeUID(g_nb_node, plan_new_nodes, 0); nb_node_for_this_plan = g_nb_node - nb_node_for_this_plan; - nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, new_nodes, previous_size_new_nodes); + nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, plan_new_nodes, 0); g_nb_node = previous_g_nb_node + nb_node_for_this_plan; - // for (auto& elem : new_nodes) { - // info() << "New node" - // << " -- UID : " << elem.m_new_node->m_uid_new_node - // << " -- Owner : " << elem.m_new_node->m_owner_new_node - // << " -- Pos : " << elem.m_intersection_pos - // << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 - // << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; - // } - + for (auto& elem : plan_new_nodes) { + info() << "Fix node" + << " -- UID : " << elem.m_new_node->m_uid_new_node + << " -- Owner : " << elem.m_new_node->m_owner_new_node + << " -- Pos : " << elem.m_intersection_pos + << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 + << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; + } - _fillFaceUID(g_nb_face, new_faces, previous_size_new_faces); + for (auto& elem : plan_new_faces) { + info() << "New face" + << " -- UID : " << elem.m_uid_new_face + << " -- Owner : " << elem.m_owner_new_face + << " -- Node0 : " << elem.m_node0->m_uid_new_node + << " -- Node00 : " << elem.m_node0->m_uid_node0 + << " -- Node01 : " << elem.m_node0->m_uid_node1 + << " -- Node1 : " << elem.m_node1->m_uid_new_node + << " -- Node10 : " << elem.m_node1->m_uid_node0 + << " -- Node11 : " << elem.m_node1->m_uid_node1; + } + _fillFaceUID(g_nb_face, plan_new_faces, 0); nb_face_for_this_plan = g_nb_face - nb_face_for_this_plan; - nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, new_faces, previous_size_new_faces); + nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, plan_new_faces, 0); g_nb_face = previous_g_nb_face + nb_face_for_this_plan; - // for (auto& elem : new_faces) { - // info() << "New face" - // << " -- UID : " << elem.m_uid_new_face - // << " -- Owner : " << elem.m_owner_new_face - // << " -- Node0 : " << elem.m_node0->m_uid_new_node - // << " -- Node00 : " << elem.m_node0->m_uid_node0 - // << " -- Node01 : " << elem.m_node0->m_uid_node1 - // << " -- Node1 : " << elem.m_node1->m_uid_new_node - // << " -- Node10 : " << elem.m_node1->m_uid_node0 - // << " -- Node11 : " << elem.m_node1->m_uid_node1; - // } + for (auto& elem : plan_new_faces) { + info() << "Fix face" + << " -- UID : " << elem.m_uid_new_face + << " -- Owner : " << elem.m_owner_new_face + << " -- Node0 : " << elem.m_node0->m_uid_new_node + << " -- Node00 : " << elem.m_node0->m_uid_node0 + << " -- Node01 : " << elem.m_node0->m_uid_node1 + << " -- Node1 : " << elem.m_node1->m_uid_new_node + << " -- Node10 : " << elem.m_node1->m_uid_node0 + << " -- Node11 : " << elem.m_node1->m_uid_node1; + } + + new_nodes.addRange(plan_new_nodes); + new_faces.addRange(plan_new_faces); } _makeUniqueCellUID(nb_cell, new_cells, new_nodes); From dba4337612ac7333b62431fb84098d540d20090b Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Wed, 29 Jul 2026 17:29:50 +0200 Subject: [PATCH 12/17] [arcane:std] A lot of doc --- arcane/src/arcane/std/MeshCutService.cc | 573 +++++++++++++++++------- 1 file changed, 419 insertions(+), 154 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index 01d5da9e69..4209fce733 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -741,26 +741,82 @@ _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray< void MeshCutService:: _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan_pos) { + + // À partir d'ici, nous avons un tableau de noeuds. Les noeuds dont on est + // sûr qu'ils nous appartiennent ont déjà un UID/Owner. + // + // Il y a deux autres types de noeuds : + // - le noeud dont on pense connaitre le proprio à qui demander le UID, + // - le noeud dont on ne connait pas encore le proprio ni le UID. + IParallelMng* pm = subDomain()->parallelMng(); Int32 my_proc = pm->commRank(); UniqueArray>> requested_nodes(subDomain()->nbSubDomain()); - // On souhaite mettre à jour uniquement les nouveaux noeuds, on crée donc - // une vue qui regroupe uniquement les nouveau noeuds. - // Ça permet uniquement de réduire le nombre d'itération de la boucle juste - // après et le temps de recherche (à la fin de la méthode). En effet, les - // "anciens" noeuds ont tous un UID >= 0, ils ne passent donc pas la - // première condition. - Span current_plan_new_nodes = new_nodes.subView(current_plan_pos, new_nodes.size() - current_plan_pos); - - + // + // + // Première étape : détermination des proprios potentiels et création des + // requêtes. + // + // Détermination des proprios : + // Si un noeud n'a pas encore de proprio, on choisit le proprio parmi les + // mailles des noeuds (N0 et N1) de l'arête dont est issu notre noeud (NN). + // + // N0 NN N1 + // *-------*-------* + // + // NN = elem.m_new_node + // N0 = elem.m_new_node->m_node0 + // N1 = elem.m_new_node->m_node1 + // + // Il peut y avoir des cas où le proprio choisi ne possède pas le noeud. + // Ce cas sera traité plus tard dans la méthode. + // + // À partir de là, on a un proprio pour tous les noeuds. + // + // Création des requêtes : + // On a un message pour chaque processus. + // Ce message est composé de pairs de UID : les UID des noeuds de l'arête + // dont est issu notre noeud (seul moyen d'identifier notre noeud sur tous + // les processus (si l'on ne souhaite pas utiliser sa position)). + // + // Exemple : + // request_uid[][] : + // P0 : --Nous-- + // P1 : [NN09_N0_UID, NN09_N1_UID, NN01_N0_UID, NN01_N1_UID, NN00_N0_UID, NN00_N1_UID] + // P2 : [NN14_N0_UID, NN14_N1_UID, NN15_N0_UID, NN15_N1_UID] + // P3 : [] + // + // request_uid[][] : + // P0 : [] + // P1 : [NN09_N0_UID, NN09_N1_UID] + // P2 : --Nous-- + // P3 : [] + // + // request_uid[][] : + // P0 : [] + // P1 : [NN00_N0_UID, NN00_N1_UID] + // P2 : [] + // P3 : --Nous-- + // + // On stocke aussi, dans un autre tableau, les NodeOnEdge correspondant + // aux paires de UID, afin de les retrouver facilement lorsque l'on aura + // reçu les réponses des processus. + // + // Exemple : + // requested_nodes[][] : + // P0 : --Nous-- + // P1 : [NN09, NN01, NN00] + // P2 : [NN14, NN15] + // P3 : [] + // + // { UniqueArray> request_uid(subDomain()->nbSubDomain()); - // On détermine le futur proprio de chaque noeud. info() << "[Node][" << my_proc << "] Step 1"; - for (auto& elem : current_plan_new_nodes) { + for (auto& elem : new_nodes) { // Si le uid est déjà mis, pas besoin de le rechercher... if (elem.m_new_node->m_uid_new_node >= 0) { continue; @@ -833,11 +889,11 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 } } + // On envoie les requêtes. { UniqueArray requests(subDomain()->nbSubDomain() * 2); - // On envoie les requêtes. - info() << "[Node][" << my_proc << "] Step 2"; + info() << "[Node][" << my_proc << "] Step 1.2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -850,111 +906,298 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 } pm->waitAllRequests(requests); - // pm->freeRequests(requests); } } - UniqueArray> answers_uid(subDomain()->nbSubDomain()); - - UniqueArray unknown_node; + // + // + // Deuxième étape : traitement des requêtes des autres processus et gestion + // des inconnus. + // + // Traitement des requêtes : + // + // On effectue le traitement à la réception (donc processus par processus). + // Pour chaque paire de UID (N0-N1), on la recherche dans notre tableau des + // noeuds. + // On l'a trouve, parfait, on place l'UID du noeud (NN) dans le tableau de + // réponse. + // + // Gestion des inconnus : + // + // Si on ne trouve pas la paire dans notre tableau, on est dans le cas où le + // noeud NN est placé sur un noeud du maillage 3D (donc N0 == N1 et + // position(N0) == position(NN)). + // Lorsque l'on itère sur les mailles de N0, on peut tomber sur des mailles + // qui ne sont pas coupées par le plan, donc qui ne possède pas le noeud. + // + // On n'a pas le noeud dans notre tableau. Par contre, on sait qui demande + // ce noeud ! Grâce aux mailles fantômes, on est sûr que tous les processus + // qui souhaite le UID du noeud NN vont le demander au même processus. Nous + // pouvons donc construire la liste de ces processus demandeurs. Processus + // demandeurs dont on est sûr qu'ils possèdent le noeud NN ! + // Nous allons donc leur envoyer cette liste et il se débrouilleront pour + // trouver le bon proprio parmi les processus de cette liste ! + // + // Réponses : + // + // Le tableau des réponses doit donc contenir deux parties : + // - les UIDs, s'ils sont trouvés, + // - les processus possédant les noeuds inconnus. + // + // Pour avoir la limite entre ces deux parties, on place la taille de la + // première partie en première position du tableau de réponse. + // + // Si un UID est trouvé, on l'ajoute. S'il n'est pas trouvé, on place "-1". + // + // La seconde partie est structurée ainsi : + // - Pour chaque inconnu (pour chaque "-1") : + // - UID du noeud N0 + // - UID du noeud N1 + // - Nombre de processus demandeurs (donc possédant forcément le noeud NN), + // - Rangs des processus demandeurs. + // + // TODO : A changer : + // L'ordre de la seconde partie n'a pas d'importance. + // En effet, l'ordre de cette partie est le même pour tous les processus (il + // n'y a pas de tri par processus selon l'ordre des requêtes (qui + // correspondrait à l'ordre des "-1")). + // C'est pour ça qu'il y a la présence des "UID du noeud N0" et "UID du + // noeud N1". + // (trier avant envoi économiserait de la mémoire et réduirait la taille de + // la réponse, donc TODO). + // + // + // (Pour l'exemple, on suit le précédent exemple) + // answers_uid[][] : + // P0 : [3, -1, NN01_UID, -1, NN09_N0_UID, NN09_N1_UID, 2, 0, 2, NN00_N0_UID, NN00_N1_UID, 2, 0, 3] + // P1 : --Nous-- + // P2 : [1, -1, NN09_N0_UID, NN09_N1_UID, 2, 0, 2 ] + // P3 : [1, -1, NN00_N0_UID, NN00_N1_UID, 2, 0, 3 ] + // + // + { + UniqueArray> answers_uid(subDomain()->nbSubDomain()); + { + UniqueArray unknown_node; + info() << "[Node][" << my_proc << "] Step 2"; - // On reçoit et traite les demandes. - info() << "[Node][" << my_proc << "] Step 3"; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + Int32 size = 0; + pm->recv(ArrayView{ 1, &size }, sr); + UniqueArray requested_uid(size); + pm->recv(requested_uid, sr); - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; - } - Int32 size = 0; - pm->recv(ArrayView{ 1, &size }, sr); - UniqueArray requested_uid(size); - pm->recv(requested_uid, sr); + // Taille de la première partie. + answers_uid[sr].add(0); - answers_uid[sr].add(0); + // On traite chaque paire de noeud de la requête. + for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { - // On traite chaque paire de noeud. - for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { + std::optional pos = new_nodes.span().findFirst(NodeIntersection{ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], Real3{ 0 } }); + if (pos) { + answers_uid[sr].add(new_nodes[pos.value()].m_new_node->m_uid_new_node); + info() << "[Node][" << my_proc << " <- " << sr << "] Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1] + << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; + } - // On est forcé de rechercher dans tout le tableau parce que les plans - // peuvent avoir des noeuds en communs. - std::optional pos = new_nodes.span().findFirst(NodeIntersection{ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], Real3{ 0 } }); - if (pos) { - answers_uid[sr].add(new_nodes[pos.value()].m_new_node->m_uid_new_node); - info() << "[Node][" << my_proc << " <- " << sr << "] Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1] - << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; + // Il peut arriver que l'on nous demande un noeud que nous n'avons pas. + // Par exemple, si un plan arrive pile sur une des arêtes de nos mailles. + // Par contre, on sait qui en a besoin, donc qui possède une maille avec + // le noeud en question. + // Pour donner cette information, on va ajouter "-1" puis, à la fin de + // la réponse, on va placer les processus en question. + else { + answers_uid[sr].add(-1); + unknown_node.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr }); + info() << "[Node][" << my_proc << " <- " << sr << "] NOT Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1]; + } + } + answers_uid[sr][0] = answers_uid[sr].size() - 1; } - // Il peut arriver que l'on nous demande un noeud que nous n'avons pas. - // Par exemple, si un plan arrive pile sur une des arêtes de nos mailles. - // Par contre, on sait qui en a besoin, donc qui possède une maille avec - // le noeud en question. - // Pour donner cette information, on va ajouter "-1" puis, à la fin de - // la réponse, on va placer les processus en question. - else { - answers_uid[sr].add(-1); - unknown_node.add({requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr}); - info() << "[Node][" << my_proc << " <- " << sr << "] NOT Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1]; - } - } - answers_uid[sr][0] = answers_uid[sr].size()-1; - } + UniqueArray who; + info() << "[Node][" << my_proc << "] Step 2.2"; - UniqueArray who; - for (Int32 i = 0; i < unknown_node.size(); ++i) { - if (unknown_node[i].null())continue; - who.clear(); - who.add(unknown_node[i].m_who); - unknown_node[i].m_who = -1; - for (Int32 j = i+1; j < unknown_node.size(); ++j) { - if (unknown_node[j].null()) continue; - if (unknown_node[j] == unknown_node[i]) { - who.add(unknown_node[j].m_who); - unknown_node[j].m_who = -1; + // Dès qu'il y a eu une paire de noeuds inconnus dans une requête, il y + // a eu un enregistrement de fait dans le tableau unknown_node. + // Il faut maintenant lister, pour chaque paire, qui l'a aussi demandé + // (rechercher les doublons) et envoyer cette liste à chacun d'entre eux. + for (Int32 i = 0; i < unknown_node.size(); ++i) { + if (unknown_node[i].null()) + continue; + who.clear(); + who.add(unknown_node[i].m_who); + unknown_node[i].m_who = -1; + for (Int32 j = i + 1; j < unknown_node.size(); ++j) { + if (unknown_node[j].null()) + continue; + if (unknown_node[j] == unknown_node[i]) { + who.add(unknown_node[j].m_who); + unknown_node[j].m_who = -1; + } + } + info() << "[Node] Additionnal infos -- Node0UID : " << unknown_node[i].m_node0_uid << " -- Node1UID : " << unknown_node[i].m_node1_uid << " -- Who : " << who; + for (auto proc : who) { + answers_uid[proc].add(unknown_node[i].m_node0_uid); + answers_uid[proc].add(unknown_node[i].m_node1_uid); + answers_uid[proc].add(who.size()); + answers_uid[proc].addRange(who); + } } } - info() << "[Node] Additionnal infos -- Node0UID : " << unknown_node[i].m_node0_uid << " -- Node1UID : " << unknown_node[i].m_node1_uid << " -- Who : " << who; - for (auto proc : who) { - answers_uid[proc].add(unknown_node[i].m_node0_uid); - answers_uid[proc].add(unknown_node[i].m_node1_uid); - answers_uid[proc].add(who.size()); - answers_uid[proc].addRange(who); - } - } - { - UniqueArray requests(subDomain()->nbSubDomain() * 2); + { + UniqueArray requests(subDomain()->nbSubDomain() * 2); - // On envoie les réponses. - info() << "[Node][" << my_proc << "] Step 4"; - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; - } + // On envoie les réponses. + info() << "[Node][" << my_proc << "] Step 2.3"; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } - Int32 size = answers_uid[sr].size(); - requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); - requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); + Int32 size = answers_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); - info() << "[Node][" << my_proc << " -> " << sr << "] Send " << answers_uid[sr]; - } + info() << "[Node][" << my_proc << " -> " << sr << "] Send " << answers_uid[sr]; + } - pm->waitAllRequests(requests); - // pm->freeRequests(requests); + pm->waitAllRequests(requests); + } } + // + // + // Troisième étape : Mise à jour des UIDs des noeuds et recherche + // complémentaire de proprios. + // + // On commence par découper la réponse en deux, pour retrouver les deux + // parties tèl que défini plus haut. + // On itère sur la première partie. L'ordre des UIDs reçus est le même que + // l'ordre des noeuds du tableau "requested_nodes" complété dans la première + // partie. On peut ainsi aisément récupérer l'objet correspondant + // (`node_on_edge` dans le code juste en dessous). + // + // Si nous avons reçu un UID valide, on met à jour le noeud correspondant + // et on passe au suivant. + // + // Si nous avons "-1", c'est que le propriétaire que nous avons défini dans + // la première partie n'est pas le bon. Nous devons donc organiser un nouvel + // envoi. + // + // Recherche complémentaire de proprios : + // + // Comme l'ordre des infos complémentaires de la seconde partie du message + // n'est pas forcément le même que l'ordre de la première partie (voir TODO + // au dessus), on doit d'abord rechercher, dans la seconde partie, la paire + // de UID correspondant au noeud que nous traitons actuellement. + // + // On trouve forcément une correspondance. + // + // On est sûr que l'ordre dans lequel est organisée la seconde partie est le + // même pour tous. On va donc se caler sur cette ordre pour transmettre le + // prochain message. + // + // Lorsqu'une correspondance est trouvée, on modifie le message. On remplace + // UID0 par la position de l'objet `Ref` dans le tableau + // `requested_nodes` (pour éviter une seconde recherche). + // + // Exemple : + // Rappel tableau requested_nodes[][] (Première étape de la méthode) : + // requested_nodes[][] : + // P0 : --Nous-- + // P1 : [NN09, NN01, NN00] + // + // Avant modif : + // answered_uid[] : + // P0 : --Nous-- + // P1 : [3, -1, NN01_UID, -1, NN09_N0_UID, NN09_N1_UID, 2, 0, 2, NN00_N0_UID, NN00_N1_UID, 2, 0, 3] + // + // Après modif : + // answered_uid[] : + // P0 : --Nous-- + // P1 : [3, -1, NN01_UID, -1, 0, NN09_N1_UID, 2, 0, 2, 2, NN00_N1_UID, 2, 0, 3] + // + // Explication de l'exemple : + // On remplace "NN09_N0_UID" par "0" car le noeud "NN09" se trouve à la + // position 0 du tableau `requested_nodes[1][]` (le premier indice est le + // rang du processus cible (donc 1 ici)). + // On remplace "NN00_N0_UID" par "2" car le noeud "NN00" se trouve à la + // position 2 du tableau `requested_nodes[1][]`. + // + // Cette algorithme est en deux étapes pour préserver simplement l'ordre de + // la seconde partie de la réponse. + // + // Une fois `answered_uid[1]` modifié (donc une fois que l'on a fini + // d'itérer sur la première partie de la réponse), on passe à la recherche + // du propriétaire des noeuds restants. + // + // On itère sur la seconde partie de la réponse. Tous les processus + // itèreront dans le même ordre ! + // + // On récupère l'objet `Ref` à l'aide de sa position dans le + // tableau `requested_nodes`. On reproduit l'algo de recherche de proprio de + // la première étape de la méthode en s'assurant de tomber sur un proprio de + // la liste des proprios potentiels. + // + // Par rapport à la première étape de la méthode, on sait de qui recevoir + // des informations et on sait dans quel ordre les interpréter. Donc inutile + // d'envoyer des messages vides si aucune infos n'est nécessaire. + // + // On va utiliser le tableau "request_uid" pour stocker les messages à + // envoyer mais aussi la taille des messages que l'on devra recevoir. + // + // Pour les messages à envoyer, on stocke uniquement les UIDs qui devront + // être appliqués. + // Pour chaque UID stocké du coté du processus envoyeur, l'objet + // `Ref` correspondant est stocké dans le tableau + // `requested_nodes2` du coté du processus receveur. + // + // Exemple : + // L'algo a déterminé que + // - "NN09" appartient à "2" (et non à "0") et + // - "NN00" appartient à "0" (et non à "3"). + // + // request_uid[][] : + // P0 : --Nous-- [0, 0, 1, 0] + // P1 : [] + // P2 : [] + // P3 : [NN00_UID] + // + // (à lire : P0 attend un message de taille 1 de la part de P2) + // ( P0 envoie NN00_UID à P3) + // + // request_uid[][] : + // P0 : [NN09_UID] + // P1 : [] + // P2 : --Nous-- [0, 0, 0, 0] + // P3 : [] + // + // request_uid[][] : + // P0 : [] + // P1 : [] + // P2 : [] + // P3 : --Nous-- [1, 0, 0, 0] + // + // UniqueArray> request_uid(subDomain()->nbSubDomain()); UniqueArray>> requested_nodes2(subDomain()->nbSubDomain()); // On reçoit et traite les réponses. - info() << "[Node][" << my_proc << "] Step 5"; + info() << "[Node][" << my_proc << "] Step 3"; - Int32 iter_requested_nodes = 0; + // Permet de savoir si les prochaines étapes sont utiles. bool need_more_comm = false; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; @@ -966,7 +1209,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 UniqueArray answered_uid(total_size); pm->recv(answered_uid, sr); - Int32 answer_to_request_size = answered_uid[0]; + Int32 answer_to_request_size = static_cast(answered_uid[0]); Span answer_to_request = answered_uid.subView(1, answer_to_request_size); Span additionnal_answer = answered_uid.subView(answer_to_request_size+1, answered_uid.size() - (answer_to_request_size+1)); @@ -987,53 +1230,68 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 << " -- New UID : " << node_on_edge->m_uid_new_node; } else { - need_more_comm = true; - Span sub_additionnal_answer; - Int32 pos_sort = 0; Int64 pos = 0; while (pos < additionnal_answer.size()) { - Int64 uid0 = additionnal_answer[pos++]; + Int64& uid0 = additionnal_answer[pos++]; Int64 uid1 = additionnal_answer[pos++]; Int64 decal = additionnal_answer[pos++]; if (uid0 == node_on_edge->m_uid_node0 && uid1 == node_on_edge->m_uid_node1) { - sub_additionnal_answer = additionnal_answer.subSpan(pos, decal); + uid0 = answer; break; } pos += decal; - pos_sort++; } - if (sub_additionnal_answer.data() == nullptr) { + if (pos >= additionnal_answer.size()) { ARCANE_FATAL("Unknown node -- UID0 : {0} -- UID1 : {1}", node_on_edge->m_uid_node0, node_on_edge->m_uid_node1); } + } + } - info() << "[Node][" << my_proc << " <- " << sr << "] Sub" - << " -- sub_additionnal_answer : " << sub_additionnal_answer; + Int32 pos = 0; + Span sub_additionnal_answer; - Node node0 = node_on_edge->m_node0; - Node node1 = node_on_edge->m_node1; + while (pos < additionnal_answer.size()) { + Int64 pos_node_in_array = additionnal_answer[pos++]; + pos++; + Int64 decal = additionnal_answer[pos++]; - // Le propriétaire du noeud est le propriétaire de la maille ayant le plus - // petit UID, parmi les mailles en commun entre les deux noeuds d'origine. + Ref node_on_edge = requested_nodes[sr][pos_node_in_array]; + sub_additionnal_answer = additionnal_answer.subSpan(pos, decal); - // TODO Ajouter traitement particulier pour le cas où node0 == node1 - Int64 min_uid = INT64_MAX; - Int32 owner_min = -1; - for (Cell cell0 : node0.cells()) { - for (Cell cell1 : node1.cells()) { - if (cell0 == cell1) { - if (cell0.uniqueId() < min_uid && sub_additionnal_answer.contains(cell0.owner())) { - min_uid = cell0.uniqueId(); - owner_min = cell0.owner(); - } + pos += decal; + + info() << "[Node][" << my_proc << " <- " << sr << "] Sub" + << " -- sub_additionnal_answer : " << sub_additionnal_answer; + + Node node0 = node_on_edge->m_node0; + Node node1 = node_on_edge->m_node1; + + // Le propriétaire du noeud est le propriétaire de la maille ayant le plus + // petit UID, parmi les mailles en commun entre les deux noeuds d'origine. + + // TODO Ajouter traitement particulier pour le cas où node0 == node1 + Int64 min_uid = INT64_MAX; + Int32 owner_min = -1; + for (Cell cell0 : node0.cells()) { + for (Cell cell1 : node1.cells()) { + if (cell0 == cell1) { + if (cell0.uniqueId() < min_uid && sub_additionnal_answer.contains(cell0.owner())) { + min_uid = cell0.uniqueId(); + owner_min = cell0.owner(); } } } + } - // S'il l'on est le proprio, on peut définir le uid du noeud. - if (owner_min == subDomain()->subDomainId()) { - node_on_edge->m_owner_new_node = subDomain()->subDomainId(); - node_on_edge->m_uid_new_node = sd_nb_node++; + // S'il l'on est le proprio, on peut définir le uid du noeud. + if (owner_min == subDomain()->subDomainId()) { + node_on_edge->m_owner_new_node = subDomain()->subDomainId(); + node_on_edge->m_uid_new_node = sd_nb_node++; + + // On enregistre le UID à envoyer. + if (sub_additionnal_answer.size() > 1) { + need_more_comm = true; info() << "[Node][" << my_proc << "] Send" << " -- UID : " << node_on_edge->m_uid_new_node @@ -1042,38 +1300,43 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 << " -- to : " << sub_additionnal_answer; for (auto proc : sub_additionnal_answer) { - if (proc == my_proc)continue; + if (proc == my_proc) + continue; request_uid[proc].add(node_on_edge->m_uid_new_node); } } + } - // Sinon, on doit aller demander le uid au proprio. - else { - node_on_edge->m_owner_new_node = owner_min; - node_on_edge->m_uid_new_node = -2; + // Sinon, on doit aller demander le uid au proprio. + else { + need_more_comm = true; + node_on_edge->m_owner_new_node = owner_min; + node_on_edge->m_uid_new_node = -2; - request_uid[my_proc].add(owner_min); - // request_uid[my_proc].add(iter_requested_nodes); - request_uid[my_proc].add(pos_sort); + if (request_uid[my_proc].empty()) { + request_uid[my_proc].resize(subDomain()->nbSubDomain(), 0); + } - requested_nodes2[owner_min].add(node_on_edge); + request_uid[my_proc][owner_min]++; + requested_nodes2[owner_min].add(node_on_edge); - info() << "[Node][" << my_proc << " -> " << node_on_edge->m_owner_new_node << "] Recv UID for Node" - << " -- UID0 : " << node_on_edge->m_uid_node0 - << " -- UID1 : " << node_on_edge->m_uid_node1; - } + info() << "[Node][" << my_proc << " -> " << node_on_edge->m_owner_new_node << "] Recv UID for Node" + << " -- UID0 : " << node_on_edge->m_uid_node0 + << " -- UID1 : " << node_on_edge->m_uid_node1; } - iter_requested_nodes++; } } + // Si nous n'avons pas de UID manquants et que personne n'a besoin de l'un + // de nos UIDs, on passe cette étape. + // Sinon : if (need_more_comm) { { UniqueArray requests(subDomain()->nbSubDomain()); // On envoie les UID complémentaires. - info() << "[Node][" << my_proc << "] Step 6"; + info() << "[Node][" << my_proc << "] Step 3.2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -1088,22 +1351,27 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 pm->waitAllRequests(requests); } + // + // + // Quatrième étape : Mise à jour des UIDs manquants. + // + // On est sûr d'avoir une réponse complète, donc c'est plus simple. + // On récupère le nombre de messages à recevoir de la part de l'autre + // processus et on traite son message dans l'ordre. Le tableau + // `requested_nodes2[][]` est dans le même ordre ce qui facilite les + // choses. + // + // + // On reçoit et traite les UID complémentaires. - info() << "[Node][" << my_proc << "] Step 7"; - + info() << "[Node][" << my_proc << "] Step 4"; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; } - Int32 size = 0; - - for (Int32 i = 0; i < request_uid[my_proc].size(); i += 2) { - if (request_uid[my_proc][i] == sr) { - size++; - } - } - + Int64 size = request_uid[my_proc][sr]; if (size == 0) continue; info() << "[Node][" << my_proc << " -> " << sr << "] Size recv : " << size; @@ -1112,20 +1380,17 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 UniqueArray requested_uid(size); pm->recv(requested_uid, sr); - for (Int32 i = 0, ii = 0; i < request_uid[my_proc].size(); i += 2, ++ii) { - if (request_uid[my_proc][i] == sr) { - Ref node_on_edge = requested_nodes2[sr][ii]; - node_on_edge->m_uid_new_node = requested_uid[request_uid[my_proc][i+1]]; - info() << "[Node][" << my_proc << "] Apply2" - << " -- UID0 : " << node_on_edge->m_uid_node0 - << " -- UID1 : " << node_on_edge->m_uid_node1 - << " -- New UID : " << node_on_edge->m_uid_new_node; - } + for (Int32 i = 0; i < size; i += 1) { + Ref node_on_edge = requested_nodes2[sr][i]; + node_on_edge->m_uid_new_node = requested_uid[i]; + info() << "[Node][" << my_proc << "] Apply2" + << " -- UID0 : " << node_on_edge->m_uid_node0 + << " -- UID1 : " << node_on_edge->m_uid_node1 + << " -- New UID : " << node_on_edge->m_uid_new_node; } } } - info() << "[Node][" << subDomain()->parallelMng()->commRank() << "]"; subDomain()->parallelMng()->barrier(); } From 2e7b9d71503d02d878ce73f85ec695df553ed1b1 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Thu, 30 Jul 2026 17:05:21 +0200 Subject: [PATCH 13/17] [arcane:std] Report fixes of _fillNodeUID() to _fillFaceUID() method --- arcane/src/arcane/std/MeshCutService.cc | 366 +++++++++++++----------- 1 file changed, 192 insertions(+), 174 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index 4209fce733..7266066120 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -248,9 +248,9 @@ class MeshCutService void _createNodesAndCells(Int32 plan_pos, Int32& sd_nb_node, UniqueArray& new_nodes, Int32 ajust_node_pos, Int32& sd_nb_cell, UniqueArray& new_cells, Int32& sd_nb_face, UniqueArray& new_faces); void _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray& new_nodes); - void _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan_pos); + void _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes); Int32 _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, Int32 current_plan); - void _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_plan_pos); + void _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces); Int32 _makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces, Int32 current_plan); void _compute(); @@ -739,7 +739,7 @@ _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray< /*---------------------------------------------------------------------------*/ void MeshCutService:: -_fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 current_plan_pos) +_fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) { // À partir d'ici, nous avons un tableau de noeuds. Les noeuds dont on est @@ -987,6 +987,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 } Int32 size = 0; pm->recv(ArrayView{ 1, &size }, sr); + UniqueArray requested_uid(size); pm->recv(requested_uid, sr); @@ -1209,6 +1210,10 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 UniqueArray answered_uid(total_size); pm->recv(answered_uid, sr); + if (total_size == 1) { + continue; + } + Int32 answer_to_request_size = static_cast(answered_uid[0]); Span answer_to_request = answered_uid.subView(1, answer_to_request_size); @@ -1230,7 +1235,6 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 << " -- New UID : " << node_on_edge->m_uid_new_node; } else { - Int64 pos = 0; while (pos < additionnal_answer.size()) { Int64& uid0 = additionnal_answer[pos++]; @@ -1248,7 +1252,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 } } - Int32 pos = 0; + Int64 pos = 0; Span sub_additionnal_answer; while (pos < additionnal_answer.size()) { @@ -1363,36 +1367,35 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes, Int32 // // - // On reçoit et traite les UID complémentaires. - info() << "[Node][" << my_proc << "] Step 4"; + if (!request_uid[my_proc].empty()) { + // On reçoit et traite les UID complémentaires. + info() << "[Node][" << my_proc << "] Step 4"; - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; - } + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } - Int64 size = request_uid[my_proc][sr]; - if (size == 0) continue; + Int64 size = request_uid[my_proc][sr]; + if (size == 0) continue; - info() << "[Node][" << my_proc << " -> " << sr << "] Size recv : " << size; + info() << "[Node][" << my_proc << " -> " << sr << "] Size recv : " << size; - UniqueArray requested_uid(size); - pm->recv(requested_uid, sr); + UniqueArray requested_uid(size); + pm->recv(requested_uid, sr); - for (Int32 i = 0; i < size; i += 1) { - Ref node_on_edge = requested_nodes2[sr][i]; - node_on_edge->m_uid_new_node = requested_uid[i]; - info() << "[Node][" << my_proc << "] Apply2" - << " -- UID0 : " << node_on_edge->m_uid_node0 - << " -- UID1 : " << node_on_edge->m_uid_node1 - << " -- New UID : " << node_on_edge->m_uid_new_node; + for (Int32 i = 0; i < size; ++i) { + Ref node_on_edge = requested_nodes2[sr][i]; + node_on_edge->m_uid_new_node = requested_uid[i]; + info() << "[Node][" << my_proc << "] Apply2" + << " -- UID0 : " << node_on_edge->m_uid_node0 + << " -- UID1 : " << node_on_edge->m_uid_node1 + << " -- New UID : " << node_on_edge->m_uid_new_node; + } } } } - - info() << "[Node][" << subDomain()->parallelMng()->commRank() << "]"; - subDomain()->parallelMng()->barrier(); } /*---------------------------------------------------------------------------*/ @@ -1428,22 +1431,20 @@ _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, I /*---------------------------------------------------------------------------*/ void MeshCutService:: -_fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_plan_pos) +_fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) { // Cet algo est repris de celui traitant les noeuds. IParallelMng* pm = subDomain()->parallelMng(); Int32 my_proc = pm->commRank(); UniqueArray> requested_faces(subDomain()->nbSubDomain()); - Span current_plan_new_faces = new_faces.subView(current_plan_pos, new_faces.size() - current_plan_pos); - { Int32 iter = -1; UniqueArray> request_uid(subDomain()->nbSubDomain()); info() << "[Face][" << my_proc << "] Step 1"; - for (auto& elem : current_plan_new_faces) { + for (auto& elem : new_faces) { iter++; if (elem.m_uid_new_face >= 0) { continue; @@ -1512,7 +1513,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ UniqueArray requests(subDomain()->nbSubDomain() * 2); // On envoie les requêtes. - info() << "[Face][" << my_proc << "] Step 2"; + info() << "[Face][" << my_proc << "] Step 1.2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -1528,101 +1529,105 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ } } - UniqueArray> answers_uid(subDomain()->nbSubDomain()); + { + UniqueArray> answers_uid(subDomain()->nbSubDomain()); + { + UniqueArray unknown_face; + info() << "[Face][" << my_proc << "] Step 2"; - UniqueArray unknown_face; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + Int32 size = 0; + pm->recv(ArrayView{ 1, &size }, sr); - // On reçoit et traite les demandes. - info() << "[Face][" << my_proc << "] Step 3"; + UniqueArray requested_uid(size); + pm->recv(requested_uid, sr); - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; - } - Int32 size = 0; - pm->recv(ArrayView{ 1, &size }, sr); - UniqueArray requested_uid(size); - pm->recv(requested_uid, sr); - - answers_uid[sr].add(0); - - for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { - std::optional pos = _find(new_faces, requested_uid[ipair_uid], requested_uid[ipair_uid + 1]); - if (pos) { - answers_uid[sr].add(new_faces[pos.value()].m_uid_new_face); - info() << "[Face][" << my_proc << " <- " << sr << "] Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1] - << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; - } + answers_uid[sr].add(0); - // Il peut arriver que l'on nous demande une face que nous n'avons pas. - // Par exemple, si un plan arrive pile sur une des arêtes de nos mailles. - // Par contre, on sait qui en a besoin, donc qui possède une maille avec - // la face en question. - // Pour donner cette information, on va ajouter "-1" puis, à la fin de - // la réponse, on va placer les processus en question. - else { - answers_uid[sr].add(-1); - unknown_face.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr }); - info() << "[Face][" << my_proc << " <- " << sr << "] NOT Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1]; + for (Int32 ipair_uid = 0; ipair_uid < requested_uid.size(); ipair_uid += 2) { + std::optional pos = _find(new_faces, requested_uid[ipair_uid], requested_uid[ipair_uid + 1]); + if (pos) { + answers_uid[sr].add(new_faces[pos.value()].m_uid_new_face); + info() << "[Face][" << my_proc << " <- " << sr << "] Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1] + << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; + } + + // Il peut arriver que l'on nous demande une face que nous n'avons pas. + // Par exemple, si un plan arrive pile sur une des arêtes de nos mailles. + // Par contre, on sait qui en a besoin, donc qui possède une maille avec + // la face en question. + // Pour donner cette information, on va ajouter "-1" puis, à la fin de + // la réponse, on va placer les processus en question. + else { + answers_uid[sr].add(-1); + unknown_face.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr }); + info() << "[Face][" << my_proc << " <- " << sr << "] NOT Found" + << " -- UID0 : " << requested_uid[ipair_uid] + << " -- UID1 : " << requested_uid[ipair_uid + 1]; + } + } + answers_uid[sr][0] = answers_uid[sr].size() - 1; } - } - answers_uid[sr][0] = answers_uid[sr].size() - 1; - } - UniqueArray who; - for (Int32 i = 0; i < unknown_face.size(); ++i) { - if (unknown_face[i].null()) - continue; - who.clear(); - who.add(unknown_face[i].m_who); - unknown_face[i].m_who = -1; - for (Int32 j = i + 1; j < unknown_face.size(); ++j) { - if (unknown_face[j].null()) - continue; - if (unknown_face[j] == unknown_face[i]) { - who.add(unknown_face[j].m_who); - unknown_face[j].m_who = -1; + UniqueArray who; + info() << "[Face][" << my_proc << "] Step 2.2"; + + for (Int32 i = 0; i < unknown_face.size(); ++i) { + if (unknown_face[i].null()) + continue; + who.clear(); + who.add(unknown_face[i].m_who); + unknown_face[i].m_who = -1; + for (Int32 j = i + 1; j < unknown_face.size(); ++j) { + if (unknown_face[j].null()) + continue; + if (unknown_face[j] == unknown_face[i]) { + who.add(unknown_face[j].m_who); + unknown_face[j].m_who = -1; + } + } + info() << "[Face] Additionnal infos -- Node0UID : " << unknown_face[i].m_node0_uid << " -- Node1UID : " << unknown_face[i].m_node1_uid << " -- Who : " << who; + for (auto proc : who) { + answers_uid[proc].add(unknown_face[i].m_node0_uid); + answers_uid[proc].add(unknown_face[i].m_node1_uid); + answers_uid[proc].add(who.size()); + answers_uid[proc].addRange(who); + } } } - info() << "[Face] Additionnal infos -- Node0UID : " << unknown_face[i].m_node0_uid << " -- Node1UID : " << unknown_face[i].m_node1_uid << " -- Who : " << who; - for (auto proc : who) { - answers_uid[proc].add(unknown_face[i].m_node0_uid); - answers_uid[proc].add(unknown_face[i].m_node1_uid); - answers_uid[proc].add(who.size()); - answers_uid[proc].addRange(who); - } - } - { - UniqueArray requests(subDomain()->nbSubDomain() * 2); + { + UniqueArray requests(subDomain()->nbSubDomain() * 2); - // On envoie les réponses. - info() << "[Face][" << my_proc << "] Step 4"; - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; + // On envoie les réponses. + info() << "[Face][" << my_proc << "] Step 2.3"; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; + } + + Int32 size = answers_uid[sr].size(); + requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); + requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); } - Int32 size = answers_uid[sr].size(); - requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); - requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); + pm->waitAllRequests(requests); } - - pm->waitAllRequests(requests); } UniqueArray> request_uid(subDomain()->nbSubDomain()); UniqueArray> requested_faces2(subDomain()->nbSubDomain()); // On reçoit et traite les réponses. - info() << "[Face][" << my_proc << "] Step 5"; + info() << "[Face][" << my_proc << "] Step 3"; - Int32 iter_requested_faces = 0; bool need_more_comm = false; + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; @@ -1634,7 +1639,11 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ UniqueArray answered_uid(total_size); pm->recv(answered_uid, sr); - Int32 answer_to_request_size = answered_uid[0]; + if (total_size == 1) { + continue; + } + + Int32 answer_to_request_size = static_cast(answered_uid[0]); Span answer_to_request = answered_uid.subView(1, answer_to_request_size); Span additionnal_answer = answered_uid.subView(answer_to_request_size + 1, answered_uid.size() - (answer_to_request_size + 1)); @@ -1654,56 +1663,72 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ << " -- New UID : " << face_lite.m_uid_new_face; } else { - need_more_comm = true; - Span sub_additionnal_answer; - - Int32 pos_sort = 0; Int64 pos = 0; while (pos < additionnal_answer.size()) { - Int64 uid0 = additionnal_answer[pos++]; + Int64& uid0 = additionnal_answer[pos++]; Int64 uid1 = additionnal_answer[pos++]; Int64 decal = additionnal_answer[pos++]; if (uid0 == face_lite.m_node0->m_uid_new_node && uid1 == face_lite.m_node1->m_uid_new_node) { - sub_additionnal_answer = additionnal_answer.subSpan(pos, decal); + uid0 = answer; break; } pos += decal; - pos_sort++; } - if (sub_additionnal_answer.data() == nullptr) { + if (pos >= additionnal_answer.size()) { ARCANE_FATAL("Unknown face -- UID0 : {0} -- UID1 : {1}", face_lite.m_node0->m_uid_new_node, face_lite.m_node1->m_uid_new_node); } + } + } - info() << "[Face][" << my_proc << " <- " << sr << "] Sub" - << " -- sub_additionnal_answer : " << sub_additionnal_answer; + Int64 pos = 0; + Span sub_additionnal_answer; - Node node00 = face_lite.m_node0->m_node0; - Node node01 = face_lite.m_node0->m_node1; - Node node10 = face_lite.m_node1->m_node0; - Node node11 = face_lite.m_node1->m_node1; + while (pos < additionnal_answer.size()) { + Int64 pos_node_in_array = additionnal_answer[pos++]; + pos++; + Int64 decal = additionnal_answer[pos++]; - Int64 min_uid = INT64_MAX; - Int32 owner_min = -1; + FaceLite& face_lite = new_faces[requested_faces[sr][pos_node_in_array]]; + sub_additionnal_answer = additionnal_answer.subSpan(pos, decal); - // TODO AH : C'est quand même TURBO moche - for (Cell cell00 : node00.cells()) { - for (Cell cell01 : node01.cells()) { - for (Cell cell10 : node10.cells()) { - for (Cell cell11 : node11.cells()) { - if (cell00 == cell01 && cell00 == cell10 && cell00 == cell11) { - if (cell00.uniqueId() < min_uid && sub_additionnal_answer.contains(cell00.owner())) { - min_uid = cell00.uniqueId(); - owner_min = cell00.owner(); - } + pos += decal; + + + info() << "[Face][" << my_proc << " <- " << sr << "] Sub" + << " -- sub_additionnal_answer : " << sub_additionnal_answer; + + Node node00 = face_lite.m_node0->m_node0; + Node node01 = face_lite.m_node0->m_node1; + Node node10 = face_lite.m_node1->m_node0; + Node node11 = face_lite.m_node1->m_node1; + + Int64 min_uid = INT64_MAX; + Int32 owner_min = -1; + + // TODO AH : C'est quand même TURBO moche + for (Cell cell00 : node00.cells()) { + for (Cell cell01 : node01.cells()) { + for (Cell cell10 : node10.cells()) { + for (Cell cell11 : node11.cells()) { + if (cell00 == cell01 && cell00 == cell10 && cell00 == cell11) { + if (cell00.uniqueId() < min_uid && sub_additionnal_answer.contains(cell00.owner())) { + min_uid = cell00.uniqueId(); + owner_min = cell00.owner(); } } } } } + } - if (owner_min == subDomain()->subDomainId()) { - face_lite.m_owner_new_face = subDomain()->subDomainId(); - face_lite.m_uid_new_face = sd_nb_face++; + // S'il l'on est le proprio, on peut définir le uid du noeud. + if (owner_min == subDomain()->subDomainId()) { + face_lite.m_owner_new_face = subDomain()->subDomainId(); + face_lite.m_uid_new_face = sd_nb_face++; + + // On enregistre le UID à envoyer. + if (sub_additionnal_answer.size() > 1) { + need_more_comm = true; info() << "[Face][" << my_proc << "] Send" << " -- UID : " << face_lite.m_uid_new_face @@ -1717,32 +1742,35 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ request_uid[proc].add(face_lite.m_uid_new_face); } } + } - // Sinon, on doit aller demander le uid au proprio. - else { - face_lite.m_owner_new_face = owner_min; - face_lite.m_uid_new_face = -2; + // Sinon, on doit aller demander le uid au proprio. + else { + need_more_comm = true; + face_lite.m_owner_new_face = owner_min; + face_lite.m_uid_new_face = -2; - request_uid[my_proc].add(owner_min); - // request_uid[my_proc].add(iter_requested_faces); - request_uid[my_proc].add(pos_sort); + if (request_uid[my_proc].empty()) { + request_uid[my_proc].resize(subDomain()->nbSubDomain(), 0); + } - requested_faces2[owner_min].add(requested_faces[sr][answer]); + request_uid[my_proc][owner_min]++; - info() << "[Face][" << my_proc << " -> " << face_lite.m_owner_new_face << "] Recv UID for Node" - << " -- UID0 : " << face_lite.m_node0->m_uid_new_node - << " -- UID1 : " << face_lite.m_node1->m_uid_new_node; - } + requested_faces2[owner_min].add(requested_faces[sr][pos_node_in_array]); + + info() << "[Face][" << my_proc << " -> " << face_lite.m_owner_new_face << "] Recv UID for Node" + << " -- UID0 : " << face_lite.m_node0->m_uid_new_node + << " -- UID1 : " << face_lite.m_node1->m_uid_new_node; } - iter_requested_faces++; } } if (need_more_comm) { { UniqueArray requests(subDomain()->nbSubDomain()); + // On envoie les UID complémentaires. - info() << "[Face][" << my_proc << "] Step 6"; + info() << "[Face][" << my_proc << "] Step 3.2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -1760,31 +1788,24 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ // On reçoit et traite les UID complémentaires. info() << "[Face][" << my_proc << "] Step 7"; - for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { - if (sr == subDomain()->subDomainId()) { - continue; - } - - Int32 size = 0; - - for (Int32 i = 0; i < request_uid[my_proc].size(); i += 2) { - if (request_uid[my_proc][i] == sr) { - size++; + if (!request_uid[my_proc].empty()) { + for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { + if (sr == subDomain()->subDomainId()) { + continue; } - } - - if (size == 0) continue; - info() << "[Face][" << my_proc << " -> " << sr << "] Size recv : " << size; + Int64 size = request_uid[my_proc][sr]; + if (size == 0) continue; - UniqueArray requested_uid(size); - pm->recv(requested_uid, sr); + info() << "[Face][" << my_proc << " -> " << sr << "] Size recv : " << size; - for (Int32 i = 0, ii = 0; i < request_uid[my_proc].size(); i += 2, ++ii) { - if (request_uid[my_proc][i] == sr) { - FaceLite& face_lite = new_faces[requested_faces2[sr][ii]]; - face_lite.m_uid_new_face = requested_uid[request_uid[my_proc][i+1]]; + UniqueArray requested_uid(size); + pm->recv(requested_uid, sr); + + for (Int32 i = 0; i < size; ++i) { + FaceLite& face_lite = new_faces[requested_faces2[sr][i]]; + face_lite.m_uid_new_face = requested_uid[i]; info() << "[Face][" << my_proc << "] Apply2" << " -- UID0 : " << face_lite.m_node0->m_uid_new_node << " -- UID1 : " << face_lite.m_node1->m_uid_new_node @@ -1793,9 +1814,6 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces, Int32 current_ } } } - - info() << "[Face][" << subDomain()->parallelMng()->commRank() << "]"; - subDomain()->parallelMng()->barrier(); } /*---------------------------------------------------------------------------*/ @@ -1869,7 +1887,7 @@ _compute() } info() << "[" << subDomain()->parallelMng()->commRank() << "] _fillNodeUID"; - _fillNodeUID(g_nb_node, plan_new_nodes, 0); + _fillNodeUID(g_nb_node, plan_new_nodes); nb_node_for_this_plan = g_nb_node - nb_node_for_this_plan; nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, plan_new_nodes, 0); @@ -1895,7 +1913,7 @@ _compute() << " -- Node10 : " << elem.m_node1->m_uid_node0 << " -- Node11 : " << elem.m_node1->m_uid_node1; } - _fillFaceUID(g_nb_face, plan_new_faces, 0); + _fillFaceUID(g_nb_face, plan_new_faces); nb_face_for_this_plan = g_nb_face - nb_face_for_this_plan; nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, plan_new_faces, 0); From 1f3a4191c2a5493ac3684be5e25d260c785c6f70 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Fri, 31 Jul 2026 10:37:36 +0200 Subject: [PATCH 14/17] [arcane:std] Reorganize the rather ugly 'for' loop to optimize it --- arcane/src/arcane/std/MeshCutService.cc | 32 +++++++++++++++---------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index 7266066120..d7a2fe2b70 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -1462,12 +1462,16 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) // TODO AH : C'est quand même TURBO moche for (Cell cell00 : node00.cells()) { for (Cell cell01 : node01.cells()) { - for (Cell cell10 : node10.cells()) { - for (Cell cell11 : node11.cells()) { - if (cell00 == cell01 && cell00 == cell10 && cell00 == cell11) { - if (cell00.uniqueId() < min_uid) { - min_uid = cell00.uniqueId(); - owner_min = cell00.owner(); + if (cell00 == cell01) { + for (Cell cell10 : node10.cells()) { + if (cell01 == cell10 ) { + for (Cell cell11 : node11.cells()) { + if (cell10 == cell11) { + if (cell11.uniqueId() < min_uid) { + min_uid = cell11.uniqueId(); + owner_min = cell11.owner(); + } + } } } } @@ -1708,12 +1712,16 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) // TODO AH : C'est quand même TURBO moche for (Cell cell00 : node00.cells()) { for (Cell cell01 : node01.cells()) { - for (Cell cell10 : node10.cells()) { - for (Cell cell11 : node11.cells()) { - if (cell00 == cell01 && cell00 == cell10 && cell00 == cell11) { - if (cell00.uniqueId() < min_uid && sub_additionnal_answer.contains(cell00.owner())) { - min_uid = cell00.uniqueId(); - owner_min = cell00.owner(); + if (cell00 == cell01) { + for (Cell cell10 : node10.cells()) { + if (cell01 == cell10) { + for (Cell cell11 : node11.cells()) { + if (cell10 == cell11) { + if (cell11.uniqueId() < min_uid && sub_additionnal_answer.contains(cell11.owner())) { + min_uid = cell11.uniqueId(); + owner_min = cell11.owner(); + } + } } } } From 88fdadf060bdf4a1f81eac01fb08c6d4e34c9a0d Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Fri, 31 Jul 2026 10:48:37 +0200 Subject: [PATCH 15/17] [arcane:tests] Add some iterations in MeshCutTest --- arcane/src/arcane/tests/CMakeLists.txt | 3 +- arcane/src/arcane/tests/MeshCutTest.axl | 38 +++-- arcane/src/arcane/tests/MeshCutTest.cc | 159 ++++++++++++++++++-- arcane/src/arcane/tests/MeshSectionTest.axl | 2 + arcane/src/arcane/tests/MeshSectionTest.cc | 58 ++++++- arcane/tests/testMeshCut-1.arc | 31 ++-- arcane/tests/testMeshCut-2.arc | 27 ++++ 7 files changed, 273 insertions(+), 45 deletions(-) create mode 100644 arcane/tests/testMeshCut-2.arc diff --git a/arcane/src/arcane/tests/CMakeLists.txt b/arcane/src/arcane/tests/CMakeLists.txt index ed934aad00..fc4f48cf37 100644 --- a/arcane/src/arcane/tests/CMakeLists.txt +++ b/arcane/src/arcane/tests/CMakeLists.txt @@ -1422,7 +1422,8 @@ endif () # ---------------------------------------------------------------------------- -arcane_add_test(meshcut1 testMeshCut-1.arc) +arcane_add_test(meshcut1 testMeshCut-1.arc "-m 1") +arcane_add_test(meshcut2 testMeshCut-2.arc "-m 20") arcane_add_test(meshsection1 testMeshSection-1.arc) # ---------------------------------------------------------------------------- diff --git a/arcane/src/arcane/tests/MeshCutTest.axl b/arcane/src/arcane/tests/MeshCutTest.axl index f2100fc036..23d2976c97 100644 --- a/arcane/src/arcane/tests/MeshCutTest.axl +++ b/arcane/src/arcane/tests/MeshCutTest.axl @@ -1,14 +1,26 @@ - - - + + + + Test module + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/arcane/src/arcane/tests/MeshCutTest.cc b/arcane/src/arcane/tests/MeshCutTest.cc index 8ad5d5ec52..a7aad16f32 100644 --- a/arcane/src/arcane/tests/MeshCutTest.cc +++ b/arcane/src/arcane/tests/MeshCutTest.cc @@ -11,9 +11,17 @@ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -#include "arcane/core/BasicUnitTest.h" +#include "arcane/utils/List.h" +#include "arcane/utils/Real3.h" + +#include "arcane/core/Directory.h" #include "arcane/core/IMeshSection.h" +#include "arcane/core/IPostProcessorWriter.h" +#include "arcane/core/ITimeLoop.h" +#include "arcane/core/ITimeLoopMng.h" +#include "arcane/core/IVariableMng.h" #include "arcane/core/ServiceBuilder.h" +#include "arcane/core/TimeLoopEntryPointInfo.h" #include "arcane/tests/MeshCutTest_axl.h" @@ -36,52 +44,171 @@ class MeshCutTest { public: - explicit MeshCutTest(const ServiceBuildInfo& sbi); + explicit MeshCutTest(const ModuleBuildInfo& mbi); ~MeshCutTest() override = default; +public: + + static void staticInitialize(ISubDomain* sd); + public: - void initializeTest() override; - void executeTest() override; + void compute() override; + + private: + + UniqueArray times; }; /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -ARCANE_REGISTER_SERVICE_MESHCUTTEST(MeshCutTest, MeshCutTest); +ARCANE_REGISTER_MODULE_MESHCUTTEST(MeshCutTest); /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ MeshCutTest:: -MeshCutTest(const ServiceBuildInfo& sbi) -: ArcaneMeshCutTestObject(sbi) +MeshCutTest(const ModuleBuildInfo& mbi) +: ArcaneMeshCutTestObject(mbi) {} /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void MeshCutTest:: -initializeTest() +staticInitialize(ISubDomain* sd) { + String time_loop_name("MeshCutTestLoop"); + + ITimeLoopMng* tlm = sd->timeLoopMng(); + ITimeLoop* time_loop = tlm->createTimeLoop(time_loop_name); + + { + List clist; + clist.add(TimeLoopEntryPointInfo("MeshCutTest.Compute")); + time_loop->setEntryPoints(ITimeLoop::WComputeLoop, clist); + } + + { + StringList clist; + clist.add("MeshCutTest"); + time_loop->setRequiredModulesName(clist); + clist.clear(); + clist.add("ArcanePostProcessing"); + clist.add("ArcaneCheckpoint"); + time_loop->setOptionalModulesName(clist); + } + + tlm->registerTimeLoop(time_loop); } /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void MeshCutTest:: -executeTest() +compute() { - ServiceBuilder spp0(mesh()->handle()); - Ref pp0 = spp0.createReference("MeshCutService"); + { + m_global_time = globalIteration(); + times.add(m_global_time()); + } - for (auto plane : options()->plane()) { - pp0->addPlane(plane->p0(), plane->normal()); + // + // MeshHandle meshhsection; + // { + // ServiceBuilder spp0(mesh()->handle()); + // Ref pp0 = spp0.createReference("MeshSectionService"); + // + // pp0->addPlane({0.95, 0, 0}, {1, 0, 0}); + // pp0->addPlane({0.97, 0, 0}, {-1, 0, 0}); + // + // pp0->updateSection(); + // meshhsection = pp0->meshSection(); + // } + // IMesh* meshsection = meshhsection.mesh(); + // + // if (options()->enablePostProcessing()) + // { + // ServiceBuilder spp(meshhsection); + // Ref pp = spp.createReference("VtkHdfV2PostProcessor"); + // Directory output_directory = Directory(subDomain()->exportDirectory(), "amrtestpost1"); + // pp->setBaseDirectoryName(output_directory.path()); + // IPostProcessorWriter* post_processor = pp.get(); + // post_processor->setTimes(times); + // + // VariableList variables; + // variables.add(meshsection->nodesCoordinates().variable()); + // post_processor->setVariables(variables); + // + // ItemGroupList groups; + // groups.add(meshsection->allNodes()); + // post_processor->setGroups(groups); + // + // IVariableMng* vm = meshsection->variableMng(); + // vm->writePostProcessing(post_processor); + // } + + + MeshHandle meshhcut; + { + ServiceBuilder spp0(mesh()->handle()); + // ServiceBuilder spp0(meshhsection); + Ref pp0 = spp0.createReference("MeshCutService"); + + for (auto plane : options()->plane()) { + pp0->addPlane(plane->p0() + (plane->p0Velocity() * globalIteration()), plane->normal()); + } + + pp0->updateSection(); + meshhcut = pp0->meshSection(); } + IMesh* meshcut = meshhcut.mesh(); + + + if (options()->enablePostProcessing()) + { + ServiceBuilder spp(meshhcut); + Ref pp = spp.createReference("VtkHdfV2PostProcessor"); + Directory output_directory = Directory(subDomain()->exportDirectory(), "amrtestpost1"); + output_directory.createDirectory(); + pp->setBaseDirectoryName(output_directory.path()); + IPostProcessorWriter* post_processor = pp.get(); + post_processor->setTimes(times); + + VariableList variables; + variables.add(meshcut->nodesCoordinates().variable()); + post_processor->setVariables(variables); - pp0->updateSection(); - MeshHandle meshsh = pp0->meshSection(); - IMesh* meshs = meshsh.mesh(); + ItemGroupList groups; + groups.add(meshcut->allNodes()); + post_processor->setGroups(groups); + + IVariableMng* vm = meshcut->variableMng(); + vm->writePostProcessing(post_processor); + } + + if (options()->enablePostProcessing()) + { + ServiceBuilder spp(mesh()->handle()); + Ref pp = spp.createReference("VtkHdfV2PostProcessor"); + Directory output_directory = Directory(subDomain()->exportDirectory(), "amrtestpost1"); + output_directory.createDirectory(); + pp->setBaseDirectoryName(output_directory.path()); + IPostProcessorWriter* post_processor = pp.get(); + post_processor->setTimes(times); + + VariableList variables; + variables.add(mesh()->nodesCoordinates().variable()); + post_processor->setVariables(variables); + + ItemGroupList groups; + groups.add(mesh()->allNodes()); + post_processor->setGroups(groups); + + IVariableMng* vm = mesh()->variableMng(); + vm->writePostProcessing(post_processor); + } } /*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/tests/MeshSectionTest.axl b/arcane/src/arcane/tests/MeshSectionTest.axl index 26e3d6b642..95386ad386 100644 --- a/arcane/src/arcane/tests/MeshSectionTest.axl +++ b/arcane/src/arcane/tests/MeshSectionTest.axl @@ -4,6 +4,8 @@ + + diff --git a/arcane/src/arcane/tests/MeshSectionTest.cc b/arcane/src/arcane/tests/MeshSectionTest.cc index bb62ea9a78..46421e5226 100644 --- a/arcane/src/arcane/tests/MeshSectionTest.cc +++ b/arcane/src/arcane/tests/MeshSectionTest.cc @@ -11,9 +11,14 @@ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +#include "arcane/utils/List.h" + #include "arcane/core/BasicUnitTest.h" -#include "arcane/core/ServiceBuilder.h" +#include "arcane/core/Directory.h" #include "arcane/core/IMeshSection.h" +#include "arcane/core/IPostProcessorWriter.h" +#include "arcane/core/IVariableMng.h" +#include "arcane/core/ServiceBuilder.h" #include "arcane/tests/MeshSectionTest_axl.h" @@ -44,6 +49,10 @@ class MeshSectionTest void initializeTest() override; void executeTest() override; + +private: + + UniqueArray times; }; /*---------------------------------------------------------------------------*/ @@ -74,6 +83,8 @@ initializeTest() void MeshSectionTest:: executeTest() { + times.add(m_global_time()); + ServiceBuilder spp0(mesh()->handle()); Ref pp0 = spp0.createReference("MeshSectionService"); @@ -84,6 +95,51 @@ executeTest() pp0->updateSection(); MeshHandle meshsh = pp0->meshSection(); IMesh* meshs = meshsh.mesh(); + + + if (options()->enablePostProcessing()) + { + ServiceBuilder spp(meshsh); + Ref pp = spp.createReference("VtkHdfV2PostProcessor"); + Directory output_directory = Directory(subDomain()->exportDirectory(), "amrtestpost1"); + output_directory.createDirectory(); + pp->setBaseDirectoryName(output_directory.path()); + IPostProcessorWriter* post_processor = pp.get(); + post_processor->setTimes(times); + + VariableList variables; + variables.add(meshs->nodesCoordinates().variable()); + post_processor->setVariables(variables); + + ItemGroupList groups; + groups.add(meshs->allNodes()); + post_processor->setGroups(groups); + + IVariableMng* vm = meshs->variableMng(); + vm->writePostProcessing(post_processor); + } + + if (options()->enablePostProcessing()) + { + ServiceBuilder spp(mesh()->handle()); + Ref pp = spp.createReference("VtkHdfV2PostProcessor"); + Directory output_directory = Directory(subDomain()->exportDirectory(), "amrtestpost1"); + output_directory.createDirectory(); + pp->setBaseDirectoryName(output_directory.path()); + IPostProcessorWriter* post_processor = pp.get(); + post_processor->setTimes(times); + + VariableList variables; + variables.add(mesh()->nodesCoordinates().variable()); + post_processor->setVariables(variables); + + ItemGroupList groups; + groups.add(mesh()->allNodes()); + post_processor->setGroups(groups); + + IVariableMng* vm = mesh()->variableMng(); + vm->writePostProcessing(post_processor); + } } /*---------------------------------------------------------------------------*/ diff --git a/arcane/tests/testMeshCut-1.arc b/arcane/tests/testMeshCut-1.arc index d4bd7472e8..9434d6330a 100644 --- a/arcane/tests/testMeshCut-1.arc +++ b/arcane/tests/testMeshCut-1.arc @@ -3,12 +3,12 @@ Test MeshCut 1 Test MeshCut 1 - UnitTest + MeshCutTestLoop - + 2 2 1 @@ -20,16 +20,19 @@ - - - - 1 0 0 - 1 0 0 - - - 1.6 0 0 - 1 0.5 0.1 - - - + + false + + 1 1 1 + 1 0 0 + + + 1 1 1 + 1 0.5 0 + + + 1.6 0 0 + 1 0.5 0.1 + + diff --git a/arcane/tests/testMeshCut-2.arc b/arcane/tests/testMeshCut-2.arc new file mode 100644 index 0000000000..154b5c418f --- /dev/null +++ b/arcane/tests/testMeshCut-2.arc @@ -0,0 +1,27 @@ + + + + Test MeshCut 1 + Test MeshCut 1 + MeshCutTestLoop + + + + + sod3d-misc.msh + + + + + false + + 0 0.05 0 + 0 1 0 + + + 0.98 0 0 + 0 -0.1 0 + 1 0.5 0.1 + + + From 8d8ea925d48bf902242d51cb8a7cfe4863ab2273 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Fri, 31 Jul 2026 12:52:55 +0200 Subject: [PATCH 16/17] [arcane:std] Remove useless logs --- arcane/src/arcane/std/MeshCutService.cc | 330 ++++++++++++------------ 1 file changed, 164 insertions(+), 166 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index d7a2fe2b70..cecf88acbb 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -191,11 +191,14 @@ struct NodeIntersection Real3 m_intersection_pos{ -1 }; }; -struct UnknownNode +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +struct UnknownNodeOrFace { - UnknownNode(Int64 node0_uid, Int64 node1_uid, Int32 who) : m_node0_uid(node0_uid), m_node1_uid(node1_uid), m_who(who){} + UnknownNodeOrFace(Int64 node0_uid, Int64 node1_uid, Int32 who) : m_node0_uid(node0_uid), m_node1_uid(node1_uid), m_who(who){} bool null() const {return m_who == -1;} - bool operator==(const UnknownNode& other) const{return m_node0_uid == other.m_node0_uid && m_node1_uid == other.m_node1_uid;} + bool operator==(const UnknownNodeOrFace& other) const{return m_node0_uid == other.m_node0_uid && m_node1_uid == other.m_node1_uid;} Int64 m_node0_uid; Int64 m_node1_uid; Int32 m_who; @@ -249,9 +252,9 @@ class MeshCutService void _makeUniqueCellUID(Int32 sd_nb_cell, UniqueArray& new_cells, UniqueArray& new_nodes); void _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes); - Int32 _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, Int32 current_plan); + Int32 _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes); void _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces); - Int32 _makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces, Int32 current_plan); + Int32 _makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces); void _compute(); std::optional _find(Span new_faces, Int64 node_uid0, Int64 node_uid1); @@ -814,7 +817,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) { UniqueArray> request_uid(subDomain()->nbSubDomain()); - info() << "[Node][" << my_proc << "] Step 1"; + debug() << "[Node][" << my_proc << "] Step 1"; for (auto& elem : new_nodes) { // Si le uid est déjà mis, pas besoin de le rechercher... @@ -850,10 +853,10 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) elem.m_new_node->m_owner_new_node = subDomain()->subDomainId(); elem.m_new_node->m_uid_new_node = sd_nb_node++; - info() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Set UID" - << " -- UID0 : " << elem.m_new_node->m_uid_node0 - << " -- UID1 : " << elem.m_new_node->m_uid_node1 - << " -- New UID : " << elem.m_new_node->m_uid_new_node; + // debug() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Set UID" + // << " -- UID0 : " << elem.m_new_node->m_uid_node0 + // << " -- UID1 : " << elem.m_new_node->m_uid_node1 + // << " -- New UID : " << elem.m_new_node->m_uid_new_node; } // Sinon, on doit aller demander le uid au proprio. @@ -870,9 +873,9 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) requested_nodes[elem.m_new_node->m_owner_new_node].add(elem.m_new_node); - info() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Ask1" - << " -- UID0 : " << elem.m_new_node->m_uid_node0 - << " -- UID1 : " << elem.m_new_node->m_uid_node1; + // debug() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Ask1" + // << " -- UID0 : " << elem.m_new_node->m_uid_node0 + // << " -- UID1 : " << elem.m_new_node->m_uid_node1; } } @@ -883,9 +886,9 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) requested_nodes[elem.m_new_node->m_owner_new_node].add(elem.m_new_node); - info() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Ask2" - << " -- UID0 : " << elem.m_new_node->m_uid_node0 - << " -- UID1 : " << elem.m_new_node->m_uid_node1; + // debug() << "[Node][" << my_proc << " -> " << elem.m_new_node->m_owner_new_node << "] Ask2" + // << " -- UID0 : " << elem.m_new_node->m_uid_node0 + // << " -- UID1 : " << elem.m_new_node->m_uid_node1; } } @@ -893,7 +896,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) { UniqueArray requests(subDomain()->nbSubDomain() * 2); - info() << "[Node][" << my_proc << "] Step 1.2"; + debug() << "[Node][" << my_proc << "] Step 1.2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -902,7 +905,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) Int32 size = request_uid[sr].size(); requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); - info() << "[Node][" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; + // debug() << "[Node][" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; } pm->waitAllRequests(requests); @@ -978,8 +981,8 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) { UniqueArray> answers_uid(subDomain()->nbSubDomain()); { - UniqueArray unknown_node; - info() << "[Node][" << my_proc << "] Step 2"; + UniqueArray unknown_node; + debug() << "[Node][" << my_proc << "] Step 2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -1000,10 +1003,10 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) std::optional pos = new_nodes.span().findFirst(NodeIntersection{ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], Real3{ 0 } }); if (pos) { answers_uid[sr].add(new_nodes[pos.value()].m_new_node->m_uid_new_node); - info() << "[Node][" << my_proc << " <- " << sr << "] Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1] - << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; + // debug() << "[Node][" << my_proc << " <- " << sr << "] Found" + // << " -- UID0 : " << requested_uid[ipair_uid] + // << " -- UID1 : " << requested_uid[ipair_uid + 1] + // << " -- New UID : " << new_nodes[pos.value()].m_new_node->m_uid_new_node; } // Il peut arriver que l'on nous demande un noeud que nous n'avons pas. @@ -1015,16 +1018,16 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) else { answers_uid[sr].add(-1); unknown_node.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr }); - info() << "[Node][" << my_proc << " <- " << sr << "] NOT Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1]; + // debug() << "[Node][" << my_proc << " <- " << sr << "] NOT Found" + // << " -- UID0 : " << requested_uid[ipair_uid] + // << " -- UID1 : " << requested_uid[ipair_uid + 1]; } } answers_uid[sr][0] = answers_uid[sr].size() - 1; } UniqueArray who; - info() << "[Node][" << my_proc << "] Step 2.2"; + debug() << "[Node][" << my_proc << "] Step 2.2"; // Dès qu'il y a eu une paire de noeuds inconnus dans une requête, il y // a eu un enregistrement de fait dans le tableau unknown_node. @@ -1044,7 +1047,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) unknown_node[j].m_who = -1; } } - info() << "[Node] Additionnal infos -- Node0UID : " << unknown_node[i].m_node0_uid << " -- Node1UID : " << unknown_node[i].m_node1_uid << " -- Who : " << who; + // debug() << "[Node] Additionnal infos -- Node0UID : " << unknown_node[i].m_node0_uid << " -- Node1UID : " << unknown_node[i].m_node1_uid << " -- Who : " << who; for (auto proc : who) { answers_uid[proc].add(unknown_node[i].m_node0_uid); answers_uid[proc].add(unknown_node[i].m_node1_uid); @@ -1058,7 +1061,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) UniqueArray requests(subDomain()->nbSubDomain() * 2); // On envoie les réponses. - info() << "[Node][" << my_proc << "] Step 2.3"; + debug() << "[Node][" << my_proc << "] Step 2.3"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; @@ -1068,7 +1071,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); requests[sr * 2 + 1] = pm->send(answers_uid[sr], sr, false); - info() << "[Node][" << my_proc << " -> " << sr << "] Send " << answers_uid[sr]; + // debug() << "[Node][" << my_proc << " -> " << sr << "] Send " << answers_uid[sr]; } pm->waitAllRequests(requests); @@ -1194,7 +1197,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) UniqueArray>> requested_nodes2(subDomain()->nbSubDomain()); // On reçoit et traite les réponses. - info() << "[Node][" << my_proc << "] Step 3"; + debug() << "[Node][" << my_proc << "] Step 3"; // Permet de savoir si les prochaines étapes sont utiles. bool need_more_comm = false; @@ -1219,9 +1222,9 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) Span answer_to_request = answered_uid.subView(1, answer_to_request_size); Span additionnal_answer = answered_uid.subView(answer_to_request_size+1, answered_uid.size() - (answer_to_request_size+1)); - info() << "[Node][" << my_proc << " <- " << sr << "] Decoupe" - << " -- answer_to_request : " << answer_to_request - << " -- additionnal_answer : " << additionnal_answer; + // debug() << "[Node][" << my_proc << " <- " << sr << "] Decoupe" + // << " -- answer_to_request : " << answer_to_request + // << " -- additionnal_answer : " << additionnal_answer; for (Int32 answer = 0; answer < answer_to_request.size(); ++answer) { @@ -1229,10 +1232,10 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) if (answer_to_request[answer] != -1) { node_on_edge->m_uid_new_node = answer_to_request[answer]; - info() << "[Node][" << my_proc << "] Apply" - << " -- UID0 : " << node_on_edge->m_uid_node0 - << " -- UID1 : " << node_on_edge->m_uid_node1 - << " -- New UID : " << node_on_edge->m_uid_new_node; + // debug() << "[Node][" << my_proc << "] Apply" + // << " -- UID0 : " << node_on_edge->m_uid_node0 + // << " -- UID1 : " << node_on_edge->m_uid_node1 + // << " -- New UID : " << node_on_edge->m_uid_new_node; } else { Int64 pos = 0; @@ -1265,8 +1268,8 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) pos += decal; - info() << "[Node][" << my_proc << " <- " << sr << "] Sub" - << " -- sub_additionnal_answer : " << sub_additionnal_answer; + // debug() << "[Node][" << my_proc << " <- " << sr << "] Sub" + // << " -- sub_additionnal_answer : " << sub_additionnal_answer; Node node0 = node_on_edge->m_node0; Node node1 = node_on_edge->m_node1; @@ -1297,11 +1300,11 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) if (sub_additionnal_answer.size() > 1) { need_more_comm = true; - info() << "[Node][" << my_proc << "] Send" - << " -- UID : " << node_on_edge->m_uid_new_node - << " -- for Node UID0 : " << node_on_edge->m_uid_node0 - << " -- UID1 : " << node_on_edge->m_uid_node1 - << " -- to : " << sub_additionnal_answer; + // debug() << "[Node][" << my_proc << "] Send" + // << " -- UID : " << node_on_edge->m_uid_new_node + // << " -- for Node UID0 : " << node_on_edge->m_uid_node0 + // << " -- UID1 : " << node_on_edge->m_uid_node1 + // << " -- to : " << sub_additionnal_answer; for (auto proc : sub_additionnal_answer) { if (proc == my_proc) @@ -1325,9 +1328,9 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) requested_nodes2[owner_min].add(node_on_edge); - info() << "[Node][" << my_proc << " -> " << node_on_edge->m_owner_new_node << "] Recv UID for Node" - << " -- UID0 : " << node_on_edge->m_uid_node0 - << " -- UID1 : " << node_on_edge->m_uid_node1; + // debug() << "[Node][" << my_proc << " -> " << node_on_edge->m_owner_new_node << "] Recv UID for Node" + // << " -- UID0 : " << node_on_edge->m_uid_node0 + // << " -- UID1 : " << node_on_edge->m_uid_node1; } } } @@ -1340,16 +1343,16 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) UniqueArray requests(subDomain()->nbSubDomain()); // On envoie les UID complémentaires. - info() << "[Node][" << my_proc << "] Step 3.2"; + debug() << "[Node][" << my_proc << "] Step 3.2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { - info() << "[Node][" << my_proc << " -> " << sr << "] My RequestsC : " << request_uid[sr]; + // debug() << "[Node][" << my_proc << " -> " << sr << "] My RequestsC : " << request_uid[sr]; continue; } if (request_uid[sr].empty()) continue; requests[sr] = pm->send(request_uid[sr], sr, false); - info() << "[Node][" << my_proc << " -> " << sr << "] RequestsC : " << request_uid[sr]; + // debug() << "[Node][" << my_proc << " -> " << sr << "] RequestsC : " << request_uid[sr]; } pm->waitAllRequests(requests); @@ -1369,7 +1372,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) if (!request_uid[my_proc].empty()) { // On reçoit et traite les UID complémentaires. - info() << "[Node][" << my_proc << "] Step 4"; + debug() << "[Node][" << my_proc << "] Step 4"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -1379,7 +1382,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) Int64 size = request_uid[my_proc][sr]; if (size == 0) continue; - info() << "[Node][" << my_proc << " -> " << sr << "] Size recv : " << size; + // debug() << "[Node][" << my_proc << " -> " << sr << "] Size recv : " << size; UniqueArray requested_uid(size); @@ -1388,10 +1391,10 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) for (Int32 i = 0; i < size; ++i) { Ref node_on_edge = requested_nodes2[sr][i]; node_on_edge->m_uid_new_node = requested_uid[i]; - info() << "[Node][" << my_proc << "] Apply2" - << " -- UID0 : " << node_on_edge->m_uid_node0 - << " -- UID1 : " << node_on_edge->m_uid_node1 - << " -- New UID : " << node_on_edge->m_uid_new_node; + // debug() << "[Node][" << my_proc << "] Apply2" + // << " -- UID0 : " << node_on_edge->m_uid_node0 + // << " -- UID1 : " << node_on_edge->m_uid_node1 + // << " -- New UID : " << node_on_edge->m_uid_new_node; } } } @@ -1402,7 +1405,7 @@ _fillNodeUID(Int32& sd_nb_node, UniqueArray& new_nodes) /*---------------------------------------------------------------------------*/ Int32 MeshCutService:: -_makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, Int32 current_plan) +_makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes) { IParallelMng* pm = subDomain()->parallelMng(); @@ -1418,10 +1421,7 @@ _makeUniqueNodeUID(Int32 sd_nb_node, UniqueArray& new_nodes, I // info() << "[" << pm->commRank() << "] Gather result (rectified) : " << all_nb_node; - // On ne doit traiter que les nouveaux noeuds. - Span current_plan_new_nodes = new_nodes.subView(current_plan, new_nodes.size() - current_plan); - - for (auto& elem : current_plan_new_nodes) { + for (auto& elem : new_nodes) { elem.m_new_node->m_uid_new_node += all_nb_node[elem.m_new_node->m_owner_new_node]; } return sum; @@ -1442,7 +1442,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) Int32 iter = -1; UniqueArray> request_uid(subDomain()->nbSubDomain()); - info() << "[Face][" << my_proc << "] Step 1"; + debug() << "[Face][" << my_proc << "] Step 1"; for (auto& elem : new_faces) { iter++; @@ -1483,10 +1483,10 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) elem.m_owner_new_face = subDomain()->subDomainId(); elem.m_uid_new_face = sd_nb_face++; - info() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Set UID" - << " -- UID0 : " << elem.m_node0->m_uid_new_node - << " -- UID1 : " << elem.m_node1->m_uid_new_node - << " -- New UID : " << elem.m_uid_new_face; + // debug() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Set UID" + // << " -- UID0 : " << elem.m_node0->m_uid_new_node + // << " -- UID1 : " << elem.m_node1->m_uid_new_node + // << " -- New UID : " << elem.m_uid_new_face; } else { elem.m_owner_new_face = owner_min; @@ -1496,9 +1496,9 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) requested_faces[elem.m_owner_new_face].add(iter); - info() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Ask1" - << " -- UID0 : " << elem.m_node0->m_uid_new_node - << " -- UID1 : " << elem.m_node1->m_uid_new_node; + // debug() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Ask1" + // << " -- UID0 : " << elem.m_node0->m_uid_new_node + // << " -- UID1 : " << elem.m_node1->m_uid_new_node; } } else { @@ -1507,9 +1507,9 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) requested_faces[elem.m_owner_new_face].add(iter); - info() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Ask2" - << " -- UID0 : " << elem.m_node0->m_uid_new_node - << " -- UID1 : " << elem.m_node1->m_uid_new_node; + // debug() << "[Face][" << my_proc << " -> " << elem.m_owner_new_face << "] Ask2" + // << " -- UID0 : " << elem.m_node0->m_uid_new_node + // << " -- UID1 : " << elem.m_node1->m_uid_new_node; } } @@ -1517,7 +1517,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) UniqueArray requests(subDomain()->nbSubDomain() * 2); // On envoie les requêtes. - info() << "[Face][" << my_proc << "] Step 1.2"; + debug() << "[Face][" << my_proc << "] Step 1.2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -1526,7 +1526,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) Int32 size = request_uid[sr].size(); requests[sr * 2] = pm->send(ArrayView{ 1, &size }, sr, false); requests[sr * 2 + 1] = pm->send(request_uid[sr], sr, false); - info() << "[Face][" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; + // debug() << "[Face][" << my_proc << " -> " << sr << "] Requests : " << request_uid[sr]; } pm->waitAllRequests(requests); @@ -1536,8 +1536,8 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) { UniqueArray> answers_uid(subDomain()->nbSubDomain()); { - UniqueArray unknown_face; - info() << "[Face][" << my_proc << "] Step 2"; + UniqueArray unknown_face; + debug() << "[Face][" << my_proc << "] Step 2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { @@ -1555,10 +1555,10 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) std::optional pos = _find(new_faces, requested_uid[ipair_uid], requested_uid[ipair_uid + 1]); if (pos) { answers_uid[sr].add(new_faces[pos.value()].m_uid_new_face); - info() << "[Face][" << my_proc << " <- " << sr << "] Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1] - << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; + // debug() << "[Face][" << my_proc << " <- " << sr << "] Found" + // << " -- UID0 : " << requested_uid[ipair_uid] + // << " -- UID1 : " << requested_uid[ipair_uid + 1] + // << " -- New UID : " << new_faces[pos.value()].m_uid_new_face; } // Il peut arriver que l'on nous demande une face que nous n'avons pas. @@ -1570,16 +1570,16 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) else { answers_uid[sr].add(-1); unknown_face.add({ requested_uid[ipair_uid], requested_uid[ipair_uid + 1], sr }); - info() << "[Face][" << my_proc << " <- " << sr << "] NOT Found" - << " -- UID0 : " << requested_uid[ipair_uid] - << " -- UID1 : " << requested_uid[ipair_uid + 1]; + // debug() << "[Face][" << my_proc << " <- " << sr << "] NOT Found" + // << " -- UID0 : " << requested_uid[ipair_uid] + // << " -- UID1 : " << requested_uid[ipair_uid + 1]; } } answers_uid[sr][0] = answers_uid[sr].size() - 1; } UniqueArray who; - info() << "[Face][" << my_proc << "] Step 2.2"; + debug() << "[Face][" << my_proc << "] Step 2.2"; for (Int32 i = 0; i < unknown_face.size(); ++i) { if (unknown_face[i].null()) @@ -1595,7 +1595,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) unknown_face[j].m_who = -1; } } - info() << "[Face] Additionnal infos -- Node0UID : " << unknown_face[i].m_node0_uid << " -- Node1UID : " << unknown_face[i].m_node1_uid << " -- Who : " << who; + // debug() << "[Face] Additionnal infos -- Node0UID : " << unknown_face[i].m_node0_uid << " -- Node1UID : " << unknown_face[i].m_node1_uid << " -- Who : " << who; for (auto proc : who) { answers_uid[proc].add(unknown_face[i].m_node0_uid); answers_uid[proc].add(unknown_face[i].m_node1_uid); @@ -1609,7 +1609,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) UniqueArray requests(subDomain()->nbSubDomain() * 2); // On envoie les réponses. - info() << "[Face][" << my_proc << "] Step 2.3"; + debug() << "[Face][" << my_proc << "] Step 2.3"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { continue; @@ -1628,7 +1628,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) UniqueArray> requested_faces2(subDomain()->nbSubDomain()); // On reçoit et traite les réponses. - info() << "[Face][" << my_proc << "] Step 3"; + debug() << "[Face][" << my_proc << "] Step 3"; bool need_more_comm = false; @@ -1652,19 +1652,19 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) Span answer_to_request = answered_uid.subView(1, answer_to_request_size); Span additionnal_answer = answered_uid.subView(answer_to_request_size + 1, answered_uid.size() - (answer_to_request_size + 1)); - info() << "[Face][" << my_proc << " <- " << sr << "] Decoupe" - << " -- answer_to_request : " << answer_to_request - << " -- additionnal_answer : " << additionnal_answer; + // debug() << "[Face][" << my_proc << " <- " << sr << "] Decoupe" + // << " -- answer_to_request : " << answer_to_request + // << " -- additionnal_answer : " << additionnal_answer; for (Int32 answer = 0; answer < answer_to_request.size(); ++answer) { FaceLite& face_lite = new_faces[requested_faces[sr][answer]]; if (answer_to_request[answer] != -1) { face_lite.m_uid_new_face = answer_to_request[answer]; - info() << "[Face][" << my_proc << "] Apply" - << " -- UID0 : " << face_lite.m_node0->m_uid_new_node - << " -- UID1 : " << face_lite.m_node1->m_uid_new_node - << " -- New UID : " << face_lite.m_uid_new_face; + // debug() << "[Face][" << my_proc << "] Apply" + // << " -- UID0 : " << face_lite.m_node0->m_uid_new_node + // << " -- UID1 : " << face_lite.m_node1->m_uid_new_node + // << " -- New UID : " << face_lite.m_uid_new_face; } else { Int64 pos = 0; @@ -1698,8 +1698,8 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) pos += decal; - info() << "[Face][" << my_proc << " <- " << sr << "] Sub" - << " -- sub_additionnal_answer : " << sub_additionnal_answer; + // debug() << "[Face][" << my_proc << " <- " << sr << "] Sub" + // << " -- sub_additionnal_answer : " << sub_additionnal_answer; Node node00 = face_lite.m_node0->m_node0; Node node01 = face_lite.m_node0->m_node1; @@ -1738,11 +1738,11 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) if (sub_additionnal_answer.size() > 1) { need_more_comm = true; - info() << "[Face][" << my_proc << "] Send" - << " -- UID : " << face_lite.m_uid_new_face - << " -- for Node UID0 : " << face_lite.m_node0->m_uid_new_node - << " -- UID1 : " << face_lite.m_node1->m_uid_new_node - << " -- to : " << sub_additionnal_answer; + // debug() << "[Face][" << my_proc << "] Send" + // << " -- UID : " << face_lite.m_uid_new_face + // << " -- for Node UID0 : " << face_lite.m_node0->m_uid_new_node + // << " -- UID1 : " << face_lite.m_node1->m_uid_new_node + // << " -- to : " << sub_additionnal_answer; for (auto proc : sub_additionnal_answer) { if (proc == my_proc) @@ -1766,9 +1766,9 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) requested_faces2[owner_min].add(requested_faces[sr][pos_node_in_array]); - info() << "[Face][" << my_proc << " -> " << face_lite.m_owner_new_face << "] Recv UID for Node" - << " -- UID0 : " << face_lite.m_node0->m_uid_new_node - << " -- UID1 : " << face_lite.m_node1->m_uid_new_node; + // debug() << "[Face][" << my_proc << " -> " << face_lite.m_owner_new_face << "] Recv UID for Node" + // << " -- UID0 : " << face_lite.m_node0->m_uid_new_node + // << " -- UID1 : " << face_lite.m_node1->m_uid_new_node; } } } @@ -1778,23 +1778,23 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) UniqueArray requests(subDomain()->nbSubDomain()); // On envoie les UID complémentaires. - info() << "[Face][" << my_proc << "] Step 3.2"; + debug() << "[Face][" << my_proc << "] Step 3.2"; for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { if (sr == subDomain()->subDomainId()) { - info() << "[Face][" << my_proc << " -> " << sr << "] My RequestsC : " << request_uid[sr]; + // debug() << "[Face][" << my_proc << " -> " << sr << "] My RequestsC : " << request_uid[sr]; continue; } if (request_uid[sr].empty()) continue; requests[sr] = pm->send(request_uid[sr], sr, false); - info() << "[Face][" << my_proc << " -> " << sr << "] RequestsC : " << request_uid[sr]; + // debug() << "[Face][" << my_proc << " -> " << sr << "] RequestsC : " << request_uid[sr]; } pm->waitAllRequests(requests); } // On reçoit et traite les UID complémentaires. - info() << "[Face][" << my_proc << "] Step 7"; + debug() << "[Face][" << my_proc << "] Step 7"; if (!request_uid[my_proc].empty()) { for (Int32 sr = 0; sr < subDomain()->nbSubDomain(); ++sr) { @@ -1805,7 +1805,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) Int64 size = request_uid[my_proc][sr]; if (size == 0) continue; - info() << "[Face][" << my_proc << " -> " << sr << "] Size recv : " << size; + // debug() << "[Face][" << my_proc << " -> " << sr << "] Size recv : " << size; UniqueArray requested_uid(size); @@ -1814,10 +1814,10 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) for (Int32 i = 0; i < size; ++i) { FaceLite& face_lite = new_faces[requested_faces2[sr][i]]; face_lite.m_uid_new_face = requested_uid[i]; - info() << "[Face][" << my_proc << "] Apply2" - << " -- UID0 : " << face_lite.m_node0->m_uid_new_node - << " -- UID1 : " << face_lite.m_node1->m_uid_new_node - << " -- New UID : " << face_lite.m_uid_new_face; + // debug() << "[Face][" << my_proc << "] Apply2" + // << " -- UID0 : " << face_lite.m_node0->m_uid_new_node + // << " -- UID1 : " << face_lite.m_node1->m_uid_new_node + // << " -- New UID : " << face_lite.m_uid_new_face; } } } @@ -1828,7 +1828,7 @@ _fillFaceUID(Int32& sd_nb_face, UniqueArray& new_faces) /*---------------------------------------------------------------------------*/ Int32 MeshCutService:: -_makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces, Int32 current_plan) +_makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces) { IParallelMng* pm = subDomain()->parallelMng(); @@ -1844,9 +1844,7 @@ _makeUniqueFaceUID(Int32 sd_nb_face, UniqueArray& new_faces, Int32 cur // info() << "[" << pm->commRank() << "] Gather result (rectified) : " << all_nb_node; - Span current_plan_new_faces = new_faces.subView(current_plan, new_faces.size() - current_plan); - - for (auto& elem : current_plan_new_faces) { + for (auto& elem : new_faces) { elem.m_uid_new_face += all_nb_node[elem.m_owner_new_face]; } return sum; @@ -1869,7 +1867,7 @@ _compute() for (Int32 i = 0; i < m_plans.size(); ++i) { - info() << "Plan : " << m_plans[i].first << ", " << m_plans[i].second; + debug() << "Plan : " << m_plans[i].first << ", " << m_plans[i].second; UniqueArray plan_new_nodes; UniqueArray plan_new_faces; @@ -1882,62 +1880,62 @@ _compute() Int32 nb_node_for_this_plan = g_nb_node; Int32 nb_face_for_this_plan = g_nb_face; - info() << "[" << subDomain()->parallelMng()->commRank() << "] _createNodesAndCells"; + debug() << "[" << subDomain()->parallelMng()->commRank() << "] _createNodesAndCells"; _createNodesAndCells(i, g_nb_node, plan_new_nodes, ajust, nb_cell, new_cells, g_nb_face, plan_new_faces); - for (auto& elem : plan_new_nodes) { - info() << "New node" - << " -- UID : " << elem.m_new_node->m_uid_new_node - << " -- Owner : " << elem.m_new_node->m_owner_new_node - << " -- Pos : " << elem.m_intersection_pos - << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 - << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; - } + // for (auto& elem : plan_new_nodes) { + // debug() << "New node" + // << " -- UID : " << elem.m_new_node->m_uid_new_node + // << " -- Owner : " << elem.m_new_node->m_owner_new_node + // << " -- Pos : " << elem.m_intersection_pos + // << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 + // << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; + // } - info() << "[" << subDomain()->parallelMng()->commRank() << "] _fillNodeUID"; + debug() << "[" << subDomain()->parallelMng()->commRank() << "] _fillNodeUID"; _fillNodeUID(g_nb_node, plan_new_nodes); nb_node_for_this_plan = g_nb_node - nb_node_for_this_plan; - nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, plan_new_nodes, 0); + nb_node_for_this_plan = _makeUniqueNodeUID(nb_node_for_this_plan, plan_new_nodes); g_nb_node = previous_g_nb_node + nb_node_for_this_plan; - for (auto& elem : plan_new_nodes) { - info() << "Fix node" - << " -- UID : " << elem.m_new_node->m_uid_new_node - << " -- Owner : " << elem.m_new_node->m_owner_new_node - << " -- Pos : " << elem.m_intersection_pos - << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 - << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; - } - - for (auto& elem : plan_new_faces) { - info() << "New face" - << " -- UID : " << elem.m_uid_new_face - << " -- Owner : " << elem.m_owner_new_face - << " -- Node0 : " << elem.m_node0->m_uid_new_node - << " -- Node00 : " << elem.m_node0->m_uid_node0 - << " -- Node01 : " << elem.m_node0->m_uid_node1 - << " -- Node1 : " << elem.m_node1->m_uid_new_node - << " -- Node10 : " << elem.m_node1->m_uid_node0 - << " -- Node11 : " << elem.m_node1->m_uid_node1; - } + // for (auto& elem : plan_new_nodes) { + // debug() << "Fix node" + // << " -- UID : " << elem.m_new_node->m_uid_new_node + // << " -- Owner : " << elem.m_new_node->m_owner_new_node + // << " -- Pos : " << elem.m_intersection_pos + // << " -- Edge node0 : " << elem.m_new_node->m_uid_node0 + // << " -- Edge node1 : " << elem.m_new_node->m_uid_node1; + // } + // + // for (auto& elem : plan_new_faces) { + // debug() << "New face" + // << " -- UID : " << elem.m_uid_new_face + // << " -- Owner : " << elem.m_owner_new_face + // << " -- Node0 : " << elem.m_node0->m_uid_new_node + // << " -- Node00 : " << elem.m_node0->m_uid_node0 + // << " -- Node01 : " << elem.m_node0->m_uid_node1 + // << " -- Node1 : " << elem.m_node1->m_uid_new_node + // << " -- Node10 : " << elem.m_node1->m_uid_node0 + // << " -- Node11 : " << elem.m_node1->m_uid_node1; + // } _fillFaceUID(g_nb_face, plan_new_faces); nb_face_for_this_plan = g_nb_face - nb_face_for_this_plan; - nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, plan_new_faces, 0); + nb_face_for_this_plan = _makeUniqueFaceUID(nb_face_for_this_plan, plan_new_faces); g_nb_face = previous_g_nb_face + nb_face_for_this_plan; - for (auto& elem : plan_new_faces) { - info() << "Fix face" - << " -- UID : " << elem.m_uid_new_face - << " -- Owner : " << elem.m_owner_new_face - << " -- Node0 : " << elem.m_node0->m_uid_new_node - << " -- Node00 : " << elem.m_node0->m_uid_node0 - << " -- Node01 : " << elem.m_node0->m_uid_node1 - << " -- Node1 : " << elem.m_node1->m_uid_new_node - << " -- Node10 : " << elem.m_node1->m_uid_node0 - << " -- Node11 : " << elem.m_node1->m_uid_node1; - } + // for (auto& elem : plan_new_faces) { + // debug() << "Fix face" + // << " -- UID : " << elem.m_uid_new_face + // << " -- Owner : " << elem.m_owner_new_face + // << " -- Node0 : " << elem.m_node0->m_uid_new_node + // << " -- Node00 : " << elem.m_node0->m_uid_node0 + // << " -- Node01 : " << elem.m_node0->m_uid_node1 + // << " -- Node1 : " << elem.m_node1->m_uid_new_node + // << " -- Node10 : " << elem.m_node1->m_uid_node0 + // << " -- Node11 : " << elem.m_node1->m_uid_node1; + // } new_nodes.addRange(plan_new_nodes); new_faces.addRange(plan_new_faces); @@ -1961,7 +1959,7 @@ _compute() // logs += " : "; // logs += new_cells[pos0++]; // } - // info() << logs; + // debug() << logs; // } } @@ -1974,7 +1972,7 @@ _compute() m_cloned_mesh->nodeFamily()->notifyItemsOwnerChanged(); m_cloned_mesh->faceFamily()->notifyItemsOwnerChanged(); - info() << "New mesh -- NbNode : " << m_cloned_mesh->nbNode() << " -- NbCells : " << m_cloned_mesh->nbCell(); + info() << "New mesh : " << m_cloned_mesh->name() << " -- NbNode : " << m_cloned_mesh->nbNode() << " -- NbCells : " << m_cloned_mesh->nbCell(); } /*---------------------------------------------------------------------------*/ @@ -2057,7 +2055,7 @@ _setCoordNodesAndOwner(UniqueArray& new_nodes) if (elem.m_new_node->m_uid_new_node == uid) { node_coords[inode] = elem.m_intersection_pos; inode->mutableItemBase().setOwner(elem.m_new_node->m_owner_new_node, subDomain()->subDomainId()); - // info() << "NodeUID : " << uid << " -- Coord : " << node_coords[inode]; + // debug() << "NodeUID : " << uid << " -- Coord : " << node_coords[inode]; } } } From f9bc45c16105e277fa765a0b13f27d39680a23e0 Mon Sep 17 00:00:00 2001 From: Alexandre l'Heritier Date: Fri, 31 Jul 2026 15:09:25 +0200 Subject: [PATCH 17/17] [arcane:std] Fix build with windows --- arcane/src/arcane/std/MeshCutService.cc | 4 +++- arcane/src/arcane/std/MeshSectionService.cc | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arcane/src/arcane/std/MeshCutService.cc b/arcane/src/arcane/std/MeshCutService.cc index cecf88acbb..7e3888b425 100644 --- a/arcane/src/arcane/std/MeshCutService.cc +++ b/arcane/src/arcane/std/MeshCutService.cc @@ -228,6 +228,8 @@ class MeshCutService , m_creation_type(sbi.creationType()) {} + ~MeshCutService() override = default; + public: void addPlane(const Real3& p0, const Real3& normal) override; @@ -276,7 +278,7 @@ class MeshCutService /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -ARCANE_REGISTER_SERVICE_MESHCUT(MeshCutService, MeshCutService); +ARCANE_REGISTER_SERVICE_MESHCUT(MeshCut, MeshCutService); /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/std/MeshSectionService.cc b/arcane/src/arcane/std/MeshSectionService.cc index 7e6e949f0f..5ac1cb8d6d 100644 --- a/arcane/src/arcane/std/MeshSectionService.cc +++ b/arcane/src/arcane/std/MeshSectionService.cc @@ -49,6 +49,8 @@ class MeshSectionService , m_creation_type(sbi.creationType()) {} + ~MeshSectionService() override = default; + public: void addPlane(const Real3& p0, const Real3& normal) override; @@ -81,7 +83,7 @@ class MeshSectionService /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -ARCANE_REGISTER_SERVICE_MESHSECTION(MeshSectionService, MeshSectionService); +ARCANE_REGISTER_SERVICE_MESHSECTION(MeshSection, MeshSectionService); /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/