Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ jobs:
uses: docker://ghcr.io/su2code/su2/test-su2:261011-1107
with:
# -t <Tutorials-branch> -c <Testcases-branch>
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:
Expand Down Expand Up @@ -284,7 +284,7 @@ jobs:
uses: docker://ghcr.io/su2code/su2/test-su2:261011-1107
with:
# -t <Tutorials-branch> -c <Testcases-branch>
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:
Expand Down Expand Up @@ -334,7 +334,7 @@ jobs:
PMIX_MCA_gds: hash
with:
# -t <Tutorials-branch> -c <Testcases-branch>
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:
Expand Down Expand Up @@ -379,7 +379,7 @@ jobs:
uses: docker://ghcr.io/su2code/su2/test-su2-asan:261011-1107
with:
# -t <Tutorials-branch> -c <Testcases-branch>
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:
Expand Down
12 changes: 12 additions & 0 deletions Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<vector<char> > sectionNames; /*!< \brief Vector for storing the names of each boundary section (marker). */
vector<cgsize_t> sectionStart; /*!< \brief First element index of each CGNS section. */
vector<cgsize_t> sectionEnd; /*!< \brief Last element index of each CGNS section. */
vector<string> 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.
Expand Down Expand Up @@ -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.
Expand Down
99 changes: 99 additions & 0 deletions Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ void CCGNSMeshReaderBase::ReadCGNSSectionMetadata() {
elemOffset[0] = 0;
connElems.resize(nSections);
sectionNames.resize(nSections, vector<char>(CGNS_STRING_SIZE));
sectionStart.resize(nSections, 0);
sectionEnd.resize(nSections, 0);
numberOfGlobalElements = 0;

for (int s = 0; s < nSections; s++) {
Expand All @@ -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. */

Expand Down Expand Up @@ -373,6 +377,101 @@ 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());

/*--- Name given by the boundary conditions to each section, and number of its elements they cover. ---*/

vector<string> bocoNames(nSections);
vector<cgsize_t> nCovered(nSections, 0);
vector<bool> severalNames(nSections, false);

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.
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);
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 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[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);
}
}

/*--- Count the elements of each boundary section that belong to this boundary condition. ---*/

vector<cgsize_t> points(nPoints);
if (cg_boco_read(cgnsFileID, cgnsBase, cgnsZone, iBoco, points.data(), nullptr)) cg_error_exit();

vector<cgsize_t> nInSection(nSections, 0);
if (byRange) {
for (int s = 0; s < nSections; s++)
if (!isInterior[s])
nInSection[s] = max<cgsize_t>(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 (nInSection[s] == 0) continue;
if (!bocoNames[s].empty() && bocoNames[s] != markerName) severalNames[s] = true;
bocoNames[s] = markerName;
nCovered[s] += nInSection[s];
}
}

/*--- 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];
}
}

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. */
Expand Down
75 changes: 46 additions & 29 deletions Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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<int> 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<unsigned long>(connElems[s][nn]);
elementCount++;
}
}
vector<cgsize_t>().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<int>(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 (int iMarker = 0; iMarker < static_cast<int>(markerNames.size()); iMarker++) {
vector<string> 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<unsigned long>(connElems[s][iNode]));

vector<cgsize_t>().swap(connElems[s]);
}
}
#endif

Expand Down
61 changes: 61 additions & 0 deletions TestCases/cgns_reader/channel_sections.cfg
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions TestCases/parallel_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -2026,6 +2026,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 ###
######################################
Expand Down
8 changes: 8 additions & 0 deletions TestCases/serial_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 ###
######################################
Expand Down
Loading