From 359a377c4a36be9c6b70a8d6a8255b6980501e68 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Sun, 20 Sep 2026 20:55:13 +0200 Subject: [PATCH 1/4] Group CGNS boundary sections into markers using the ZoneBC of the file The CGNS mesh reader made one marker per boundary section, named after the section. Meshers that split a boundary by element type (e.g. sections tri_wall and quad_wall) therefore gave two markers, and the same boundary conditions had to be set twice in the config file. Name each boundary section after the boundary condition of the zone (ZoneBC) that covers its elements: the family name of that BC if it has one, otherwise the name of the BC. Sections sharing a name become one marker, and their connectivity is concatenated. Sections that no BC covers, and files without a ZoneBC node, keep the previous behaviour of one marker named after the section. A BC given by points instead of elements is ignored, since it cannot be matched to a section. The sections grouped into a marker are printed to the console. Co-Authored-By: Claude Opus 5 (1M context) --- .../meshreader/CCGNSMeshReaderBase.hpp | 12 +++ .../meshreader/CCGNSMeshReaderBase.cpp | 58 ++++++++++++++ .../meshreader/CCGNSMeshReaderFVM.cpp | 75 ++++++++++++------- 3 files changed, 116 insertions(+), 29 deletions(-) diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp index a49c3493f78f..2a71af78ab90 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp @@ -58,6 +58,10 @@ class CCGNSMeshReaderBase : public CMeshReaderBase { CGNS section. First index is the section, second contains the connectivity in format [globalID VTK n1 n2 n3 n4 n5 n6 n7 n8] for each element. */ vector > sectionNames; /*!< \brief Vector for storing the names of each boundary section (marker). */ + vector sectionStart; /*!< \brief First element index of each CGNS section. */ + vector sectionEnd; /*!< \brief Last element index of each CGNS section. */ + vector sectionMarkerNames; /*!< \brief Marker name of each boundary section, several sections can share + one name, e.g. one with triangles and one with quadrilaterals. */ /*! * \brief Open the CGNS file and checks for errors. @@ -86,6 +90,14 @@ class CCGNSMeshReaderBase : public CMeshReaderBase { */ void ReadCGNSSectionMetadata(); + /*! + * \brief Assign a marker name to each boundary section. The name of a section covered by a boundary condition of + * the zone (ZoneBC) is the family name of that boundary condition, or its name if it has no family. Sections that + * are not covered by any boundary condition keep the name of the section, which is the only option for files + * written without a ZoneBC node. + */ + void ReadCGNSBoundaryMarkerNames(); + /*! * \brief Get the VTK type and string name for a CGNS element type. * \param[in] val_elem_type - CGNS element type. diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp index ee56074898f5..b377fad5434a 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp @@ -262,6 +262,8 @@ void CCGNSMeshReaderBase::ReadCGNSSectionMetadata() { elemOffset[0] = 0; connElems.resize(nSections); sectionNames.resize(nSections, vector(CGNS_STRING_SIZE)); + sectionStart.resize(nSections, 0); + sectionEnd.resize(nSections, 0); numberOfGlobalElements = 0; for (int s = 0; s < nSections; s++) { @@ -277,6 +279,8 @@ void CCGNSMeshReaderBase::ReadCGNSSectionMetadata() { /*--- Compute the total element count in this section (global). ---*/ unsigned long element_count = (endE - startE + 1); + sectionStart[s] = startE; + sectionEnd[s] = endE; /* Get the details for the CGNS element type in this section. */ @@ -373,6 +377,60 @@ void CCGNSMeshReaderBase::ReadCGNSSectionMetadata() { } } +void CCGNSMeshReaderBase::ReadCGNSBoundaryMarkerNames() { + /*--- Without a matching boundary condition a section is a marker of its own, named after the section. ---*/ + + sectionMarkerNames.resize(nSections); + for (int s = 0; s < nSections; s++) sectionMarkerNames[s] = string(sectionNames[s].data()); + + int nBocos = 0; + if (cg_nbocos(cgnsFileID, cgnsBase, cgnsZone, &nBocos)) cg_error_exit(); + + for (int iBoco = 1; iBoco <= nBocos; iBoco++) { + char bocoName[CGNS_STRING_SIZE]; + BCType_t bocoType; + PointSetType_t pointSetType; + cgsize_t nPoints, normalListSize; + int normalIndex, nDataset; + DataType_t normalDataType; + + if (cg_boco_info(cgnsFileID, cgnsBase, cgnsZone, iBoco, bocoName, &bocoType, &pointSetType, &nPoints, &normalIndex, + &normalListSize, &normalDataType, &nDataset)) + cg_error_exit(); + + /*--- Only a boundary condition given by elements can be matched to a section, one given by points cannot. ---*/ + + GridLocation_t location = Vertex; + cg_boco_gridlocation_read(cgnsFileID, cgnsBase, cgnsZone, iBoco, &location); + if (location != FaceCenter && location != EdgeCenter && location != CellCenter) continue; + + /*--- The marker takes the name of the family of the boundary condition, if it has one. ---*/ + + string markerName = string(bocoName); + if (cg_goto(cgnsFileID, cgnsBase, "Zone_t", cgnsZone, "ZoneBC_t", 1, "BC_t", iBoco, "end") == CG_OK) { + char familyName[CGNS_STRING_SIZE]; + if (cg_famname_read(familyName) == CG_OK) markerName = string(familyName); + } + + /*--- Give that name to every boundary section holding elements of this boundary condition. ---*/ + + vector points(nPoints); + if (cg_boco_read(cgnsFileID, cgnsBase, cgnsZone, iBoco, points.data(), nullptr)) cg_error_exit(); + + for (int s = 0; s < nSections; s++) { + if (isInterior[s]) continue; + + bool covered = false; + if (pointSetType == PointRange || pointSetType == ElementRange) { + covered = (points[0] <= sectionEnd[s]) && (points[1] >= sectionStart[s]); + } else { + for (auto point : points) covered = covered || ((point >= sectionStart[s]) && (point <= sectionEnd[s])); + } + if (covered) sectionMarkerNames[s] = markerName; + } + } +} + string CCGNSMeshReaderBase::GetCGNSElementType(ElementType_t val_elem_type, int& val_vtk_type) { /* Check the CGNS element type and return the string name for the element and the associated VTK type index. */ diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp index 501e188e40cd..0e33c9ffff0a 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp @@ -48,12 +48,11 @@ CCGNSMeshReaderFVM::CCGNSMeshReaderFVM(const CConfig* val_config, unsigned short section together), the master node reads the boundary section. Otherwise, all ranks read and communicate the interior sections. ---*/ ReadCGNSSectionMetadata(); - numberOfMarkers = 0; + ReadCGNSBoundaryMarkerNames(); for (int s = 0; s < nSections; s++) { if (isInterior[s]) { ReadCGNSVolumeSection(s); } else { - numberOfMarkers++; ReadCGNSSurfaceSection(s); } } @@ -619,39 +618,57 @@ void CCGNSMeshReaderFVM::ReformatCGNSVolumeConnectivity() { } void CCGNSMeshReaderFVM::ReformatCGNSSurfaceConnectivity() { - /*--- Prepare the class data for the marker names and connectivity. ---*/ + /*--- Group the boundary sections by marker name, a marker can be split over several sections, for example one + with triangles and one with quadrilaterals. Remove any whitespaces from the names to avoid any issues. ---*/ - markerNames.resize(numberOfMarkers); - surfaceElementConnectivity.resize(numberOfMarkers); + markerNames.clear(); + vector markerOfSection(nSections, -1); - int markerCount = 0; - int elementCount = 0; for (int s = 0; s < nSections; s++) { - if (!isInterior[s]) { - /*--- Store the tag for this marker. Remove any whitespaces from - the marker names found in the CGNS file to avoid any issues. ---*/ - - string Marker_Tag = string(sectionNames[s].data()); - Marker_Tag.erase(remove(Marker_Tag.begin(), Marker_Tag.end(), ' '), Marker_Tag.end()); - markerNames[markerCount] = Marker_Tag; - - /*--- The master node alone stores the connectivity. ---*/ - - if (rank == MASTER_NODE) { - surfaceElementConnectivity[markerCount].resize(nElems[s] * SU2_CONN_SIZE); - elementCount = 0; - for (unsigned long iElem = 0; iElem < nElems[s]; iElem++) { - for (unsigned long iNode = 0; iNode < SU2_CONN_SIZE; iNode++) { - unsigned long nn = iElem * SU2_CONN_SIZE + iNode; - surfaceElementConnectivity[markerCount][elementCount] = static_cast(connElems[s][nn]); - elementCount++; - } - } - vector().swap(connElems[s]); + if (isInterior[s]) continue; + + string Marker_Tag = sectionMarkerNames[s]; + Marker_Tag.erase(remove(Marker_Tag.begin(), Marker_Tag.end(), ' '), Marker_Tag.end()); + + const auto it = find(markerNames.begin(), markerNames.end(), Marker_Tag); + markerOfSection[s] = static_cast(distance(markerNames.begin(), it)); + if (it == markerNames.end()) markerNames.push_back(Marker_Tag); + } + + numberOfMarkers = markerNames.size(); + + /*--- Tell the user which sections were merged into one marker. ---*/ + + if (rank == MASTER_NODE) { + for (unsigned short iMarker = 0; iMarker < numberOfMarkers; iMarker++) { + vector sections; + for (int s = 0; s < nSections; s++) + if (markerOfSection[s] == iMarker) sections.push_back(string(sectionNames[s].data())); + + if (sections.size() > 1) { + cout << "Marker " << markerNames[iMarker] << " groups the sections"; + for (const auto& section : sections) cout << " " << section; + cout << "." << endl; } - markerCount++; } } + + /*--- Prepare the class data for the connectivity. The master node alone stores it. ---*/ + + surfaceElementConnectivity.clear(); + surfaceElementConnectivity.resize(numberOfMarkers); + + if (rank != MASTER_NODE) return; + + for (int s = 0; s < nSections; s++) { + if (isInterior[s]) continue; + + auto& markerConnectivity = surfaceElementConnectivity[markerOfSection[s]]; + for (unsigned long iNode = 0; iNode < nElems[s] * SU2_CONN_SIZE; iNode++) + markerConnectivity.push_back(static_cast(connElems[s][iNode])); + + vector().swap(connElems[s]); + } } #endif From 79321efae7e95448e365dc928a644c7503cca358 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 14 Oct 2026 07:47:22 +0200 Subject: [PATCH 2/4] Add a regression test for the CGNS reader with boundaries split in sections The mesh (su2code/TestCases, cgns_reader/) is a small 3D channel whose boundaries are split in sections by element type and by block, grouped by the ZoneBC. The markers of the config file are the names of the BCs, so the case only runs if the reader groups the sections into markers. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01L7oxzVir4zENrpy3K3W6Fm --- TestCases/cgns_reader/channel_sections.cfg | 61 ++++++++++++++++++++++ TestCases/parallel_regression.py | 8 +++ TestCases/serial_regression.py | 8 +++ 3 files changed, 77 insertions(+) create mode 100644 TestCases/cgns_reader/channel_sections.cfg diff --git a/TestCases/cgns_reader/channel_sections.cfg b/TestCases/cgns_reader/channel_sections.cfg new file mode 100644 index 000000000000..f67194284c45 --- /dev/null +++ b/TestCases/cgns_reader/channel_sections.cfg @@ -0,0 +1,61 @@ +% Test of the CGNS mesh reader with boundaries split in several sections, as meshers write them. +% The mesh is a small 3D channel, with hexahedra in the first half and prisms in the second half. +% The CGNS file has 9 boundary sections and a ZoneBC with 5 boundary conditions (BC): +% inlet : no BC covers it, the marker is named after the section ("inlet") +% upper_side : BC "upper" without family, the marker is named after the BC ("upper") +% lower_1, lower_2 : BC "lower_wall" of family "lower", one marker "lower" +% quad_back, tri_back : BC "back" of family "back", one marker "back" with quadrilaterals and triangles +% quad_front, tri_front : BC "front" of family "front", one marker "front" +% outlet : BC "outlet" of family "outlet", marker "outlet" +% The markers of this config file are the names above, so the case only runs if the reader +% groups the sections into markers through the ZoneBC. +% +% ------------- DIRECT, ADJOINT, AND LINEARIZED PROBLEM DEFINITION ------------% +SOLVER= EULER +MATH_PROBLEM= DIRECT +RESTART_SOL= NO +% +% ----------- COMPRESSIBLE AND INCOMPRESSIBLE FREE-STREAM DEFINITION ----------% +MACH_NUMBER= 0.3 +AOA= 0.0 +SIDESLIP_ANGLE= 0.0 +FREESTREAM_PRESSURE= 101325.0 +FREESTREAM_TEMPERATURE= 288.15 +% +% ---------------------- REFERENCE VALUE DEFINITION ---------------------------% +REF_ORIGIN_MOMENT_X= 0.0 +REF_ORIGIN_MOMENT_Y= 0.0 +REF_ORIGIN_MOMENT_Z= 0.0 +REF_LENGTH= 1.0 +REF_AREA= 1.0 +% +% -------------------- BOUNDARY CONDITION DEFINITION --------------------------% +MARKER_EULER= ( lower, upper ) +MARKER_SYM= ( back, front ) +MARKER_INLET= ( inlet, 293.336, 107822.0, 1.0, 0.0, 0.0 ) +MARKER_OUTLET= ( outlet, 101325.0 ) +% +% ------------- COMMON PARAMETERS DEFINING THE NUMERICAL METHOD ---------------% +NUM_METHOD_GRAD= GREEN_GAUSS +CFL_NUMBER= 10.0 +CFL_ADAPT= NO +ITER= 10 +% +% ------------------------ LINEAR SOLVER DEFINITION ---------------------------% +LINEAR_SOLVER= FGMRES +LINEAR_SOLVER_PREC= ILU +LINEAR_SOLVER_ERROR= 1E-6 +LINEAR_SOLVER_ITER= 10 +% +% ----------------------- FLOW NUMERICAL METHOD DEFINITION --------------------% +CONV_NUM_METHOD_FLOW= ROE +MUSCL_FLOW= YES +SLOPE_LIMITER_FLOW= NONE +TIME_DISCRE_FLOW= EULER_IMPLICIT +% +% ------------------------- INPUT/OUTPUT INFORMATION --------------------------% +MESH_FILENAME= mesh_channel_sections.cgns +MESH_FORMAT= CGNS +SCREEN_OUTPUT= INNER_ITER RMS_DENSITY RMS_MOMENTUM-X RMS_MOMENTUM-Y RMS_ENERGY +HISTORY_OUTPUT= ITER RMS_RES +OUTPUT_FILES= NONE diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 54569d389d50..c9cb917cfb6a 100755 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -2004,6 +2004,14 @@ def main(): cgns_mesh_readback_bend.test_vals = [-3.256728, -2.769844, -3.007840, -3.567315, 4.318459] test_list.append(cgns_mesh_readback_bend) + # CGNS mesh whose boundaries are split in several sections, grouped into markers by the ZoneBC. + cgns_reader_sections = TestCase('cgns_reader_sections') + cgns_reader_sections.cfg_dir = "cgns_reader" + cgns_reader_sections.cfg_file = "channel_sections.cfg" + cgns_reader_sections.test_iter = 9 + cgns_reader_sections.test_vals = [-4.344863, -1.284117, -3.081432, 0.924734] + test_list.append(cgns_reader_sections) + ###################################### ### RUN CHT TEST WITH FILEDIFF ### ###################################### diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 88b5f25ca44a..977495831f54 100755 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -1331,6 +1331,14 @@ def main(): cgns_mesh_readback_bend.test_vals = [-3.254168, -2.756564, -3.006605, -3.572686, 4.308287] test_list.append(cgns_mesh_readback_bend) + # CGNS mesh whose boundaries are split in several sections, grouped into markers by the ZoneBC. + cgns_reader_sections = TestCase('cgns_reader_sections') + cgns_reader_sections.cfg_dir = "cgns_reader" + cgns_reader_sections.cfg_file = "channel_sections.cfg" + cgns_reader_sections.test_iter = 9 + cgns_reader_sections.test_vals = [-4.344864, -1.284117, -3.081432, 0.924734] + test_list.append(cgns_reader_sections) + ###################################### ### RUN TESTS ### ###################################### From 56996e9cd6a34374dcaad487a1ad4c4bd08b2874 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 14 Oct 2026 07:47:22 +0200 Subject: [PATCH 3/4] Run the regression tests with the cgnsReaderMarkers branch of TestCases Temporary, for the mesh of the TestCases PR. To be reverted to develop before merging. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01L7oxzVir4zENrpy3K3W6Fm --- .github/workflows/regression.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 5c2157eb2277..004bb5690537 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -233,7 +233,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2:261011-1107 with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} + args: -b ${{github.ref}} -t develop -c cgnsReaderMarkers -s ${{matrix.testscript}} - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2:261011-1107 with: @@ -282,7 +282,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2:261011-1107 with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--tapetests" + args: -b ${{github.ref}} -t develop -c cgnsReaderMarkers -s ${{matrix.testscript}} -a "--tapetests" - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2:261011-1107 with: @@ -330,7 +330,7 @@ jobs: PMIX_MCA_gds: hash with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--tsan" + args: -b ${{github.ref}} -t develop -c cgnsReaderMarkers -s ${{matrix.testscript}} -a "--tsan" - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2-tsan:261011-1107 with: @@ -375,7 +375,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2-asan:261011-1107 with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--asan" + args: -b ${{github.ref}} -t develop -c cgnsReaderMarkers -s ${{matrix.testscript}} -a "--asan" - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2-asan:261011-1107 with: From aec964bcebbec28ebc8fe3880c1ca81aa87abf87 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 14 Oct 2026 08:18:32 +0200 Subject: [PATCH 4/4] Fix the CGNS family name buffer, keep sections not fully covered by one BC - cg_famname_read copies the whole family name, which can be longer than 32 characters (a path in the family tree of CGNS 4): use a buffer of the maximum size, and keep only the last part of a path. - A section partly covered by a boundary condition, or covered by boundary conditions with different names, took the name of the last one. It is now kept as one marker named after the section, with a warning, since a section cannot be split. - Boundary conditions given by ElementRange or ElementList without a GridLocation (older files) are also matched to the sections. - The loop index of the markers has the type of their number (CodeQL). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01L7oxzVir4zENrpy3K3W6Fm --- .../meshreader/CCGNSMeshReaderBase.cpp | 69 +++++++++++++++---- .../meshreader/CCGNSMeshReaderFVM.cpp | 2 +- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp index b377fad5434a..7207d1e11261 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp @@ -383,6 +383,12 @@ void CCGNSMeshReaderBase::ReadCGNSBoundaryMarkerNames() { sectionMarkerNames.resize(nSections); for (int s = 0; s < nSections; s++) sectionMarkerNames[s] = string(sectionNames[s].data()); + /*--- Name given by the boundary conditions to each section, and number of its elements they cover. ---*/ + + vector bocoNames(nSections); + vector nCovered(nSections, 0); + vector severalNames(nSections, false); + int nBocos = 0; if (cg_nbocos(cgnsFileID, cgnsBase, cgnsZone, &nBocos)) cg_error_exit(); @@ -398,36 +404,71 @@ void CCGNSMeshReaderBase::ReadCGNSBoundaryMarkerNames() { &normalListSize, &normalDataType, &nDataset)) cg_error_exit(); - /*--- Only a boundary condition given by elements can be matched to a section, one given by points cannot. ---*/ + /*--- Only a boundary condition given by elements can be matched to a section, one given by points cannot. + Older files give the elements with ElementRange or ElementList, without a GridLocation. ---*/ GridLocation_t location = Vertex; cg_boco_gridlocation_read(cgnsFileID, cgnsBase, cgnsZone, iBoco, &location); - if (location != FaceCenter && location != EdgeCenter && location != CellCenter) continue; + const bool byRange = (pointSetType == PointRange || pointSetType == ElementRange); + const bool byElements = (pointSetType == ElementRange || pointSetType == ElementList || location == FaceCenter || + location == EdgeCenter || location == CellCenter); + if (!byElements || (byRange && nPoints != 2)) continue; - /*--- The marker takes the name of the family of the boundary condition, if it has one. ---*/ + /*--- The marker takes the name of the family of the boundary condition, if it has one. The family name can be + a path in the family tree of the file (CGNS 4), in which case only its last part is kept. ---*/ string markerName = string(bocoName); if (cg_goto(cgnsFileID, cgnsBase, "Zone_t", cgnsZone, "ZoneBC_t", 1, "BC_t", iBoco, "end") == CG_OK) { - char familyName[CGNS_STRING_SIZE]; - if (cg_famname_read(familyName) == CG_OK) markerName = string(familyName); + char familyName[CG_MAX_GOTO_DEPTH * (CGNS_STRING_SIZE + 1) + 1] = {}; + if (cg_famname_read(familyName) == CG_OK) { + markerName = string(familyName); + const auto slash = markerName.find_last_of('/'); + if (slash != string::npos) markerName = markerName.substr(slash + 1); + } } - /*--- Give that name to every boundary section holding elements of this boundary condition. ---*/ + /*--- Count the elements of each boundary section that belong to this boundary condition. ---*/ vector points(nPoints); if (cg_boco_read(cgnsFileID, cgnsBase, cgnsZone, iBoco, points.data(), nullptr)) cg_error_exit(); + vector nInSection(nSections, 0); + if (byRange) { + for (int s = 0; s < nSections; s++) + if (!isInterior[s]) + nInSection[s] = max(0, min(points[1], sectionEnd[s]) - max(points[0], sectionStart[s]) + 1); + } else { + for (const auto point : points) { + for (int s = 0; s < nSections; s++) { + if (!isInterior[s] && point >= sectionStart[s] && point <= sectionEnd[s]) { + nInSection[s]++; + break; + } + } + } + } + for (int s = 0; s < nSections; s++) { - if (isInterior[s]) continue; + if (nInSection[s] == 0) continue; + if (!bocoNames[s].empty() && bocoNames[s] != markerName) severalNames[s] = true; + bocoNames[s] = markerName; + nCovered[s] += nInSection[s]; + } + } - bool covered = false; - if (pointSetType == PointRange || pointSetType == ElementRange) { - covered = (points[0] <= sectionEnd[s]) && (points[1] >= sectionStart[s]); - } else { - for (auto point : points) covered = covered || ((point >= sectionStart[s]) && (point <= sectionEnd[s])); - } - if (covered) sectionMarkerNames[s] = markerName; + /*--- A section takes the name of its boundary condition only if all its elements belong to boundary conditions + with that name. Otherwise it is kept as one marker named after the section, since a section cannot be split. ---*/ + + for (int s = 0; s < nSections; s++) { + if (isInterior[s] || bocoNames[s].empty()) continue; + + if (severalNames[s] || nCovered[s] < sectionEnd[s] - sectionStart[s] + 1) { + if (rank == MASTER_NODE) + cout << "WARNING: the boundary conditions of the file do not cover all elements of the section " + << sectionMarkerNames[s] << " with one name, the section is a marker named after the section." << endl; + continue; } + sectionMarkerNames[s] = bocoNames[s]; } } diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp index 0e33c9ffff0a..b67e41d319a1 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp @@ -640,7 +640,7 @@ void CCGNSMeshReaderFVM::ReformatCGNSSurfaceConnectivity() { /*--- Tell the user which sections were merged into one marker. ---*/ if (rank == MASTER_NODE) { - for (unsigned short iMarker = 0; iMarker < numberOfMarkers; iMarker++) { + for (int iMarker = 0; iMarker < static_cast(markerNames.size()); iMarker++) { vector sections; for (int s = 0; s < nSections; s++) if (markerOfSection[s] == iMarker) sections.push_back(string(sectionNames[s].data()));