From 838cd964be1e048bc85296d11f942690ac0e08e2 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 31 Oct 2024 22:50:55 +0100 Subject: [PATCH 001/129] initial idea --- Common/include/CConfig.hpp | 7 +++++++ Common/src/CConfig.cpp | 2 ++ SU2_CFD/include/output/COutput.hpp | 11 +++++++--- .../output/filewriter/CParallelDataSorter.hpp | 19 +++++++++++++++++- SU2_CFD/src/output/COutput.cpp | 20 ++++++++++++++++++- .../src/output/filewriter/CSU2FileWriter.cpp | 3 ++- config_template.cfg | 3 +++ 7 files changed, 59 insertions(+), 6 deletions(-) diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index 0c32f044288..b5a595ce5c6 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -700,6 +700,7 @@ class CConfig { unsigned long StartConv_Iter; /*!< \brief Start convergence criteria at iteration. */ su2double Cauchy_Eps; /*!< \brief Epsilon used for the convergence. */ bool Restart, /*!< \brief Restart solution (for direct, adjoint, and linearized problems).*/ + Wrt_Restart_Compact, /*!< \brief Write compact restart files with minimum nr. of variables. */ Read_Binary_Restart, /*!< \brief Read binary SU2 native restart files.*/ Wrt_Restart_Overwrite, /*!< \brief Overwrite restart files or append iteration number.*/ Wrt_Surface_Overwrite, /*!< \brief Overwrite surface output files or append iteration number.*/ @@ -5490,6 +5491,12 @@ class CConfig { */ bool GetRead_Binary_Restart(void) const { return Read_Binary_Restart; } + /*! + * \brief Flag for whether restart files contain only necessary variables. + * \return Flag TRUE then the code will write compact restart files. + */ + bool GetWrt_Restart_Compact(void) const { return Wrt_Restart_Compact; } + /*! * \brief Flag for whether restart solution files are overwritten. * \return Flag for overwriting. If Flag=false, iteration nr is appended to filename diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 8a60579189c..be10298e348 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -1169,6 +1169,8 @@ void CConfig::SetConfig_Options() { /*!\brief RESTART_SOL \n DESCRIPTION: Restart solution from native solution file \n Options: NO, YES \ingroup Config */ addBoolOption("RESTART_SOL", Restart, false); + /*!\brief WRT_RESTART_COMPACT \n DESCRIPTION: Minimize the size of restart files \n Options: NO, YES \ingroup Config */ + addBoolOption("WRT_RESTART_COMPACT", Wrt_Restart_Compact, true); /*!\brief BINARY_RESTART \n DESCRIPTION: Read binary SU2 native restart files. \n Options: YES, NO \ingroup Config */ addBoolOption("READ_BINARY_RESTART", Read_Binary_Restart, true); /*!\brief WRT_RESTART_OVERWRITE \n DESCRIPTION: overwrite restart files or append iteration number. \n Options: YES, NO \ingroup Config */ diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index a549a6c5541..146a2d6bc0c 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -293,6 +293,11 @@ class COutput { /*! \brief Number of requested volume field names in the config file. */ unsigned short nRequestedVolumeFields; + /*! \brief Minimum required volume fields for restart file. */ + std::vector requiredVolumeFields; + /*! \brief Minimum required volume fields for restart file. */ + unsigned short nRequiredVolumeFields; + /*----------------------------- Convergence monitoring ----------------------------*/ su2double cauchyValue, /*!< \brief Summed value of the convergence indicator. */ @@ -959,14 +964,14 @@ class COutput { /*! * \brief Sets the turboperformance screen output - * \param[in] TurboPerf - Turboperformance class + * \param[in] TurboPerf - Turboperformance class * \param[in] config - Definition of the particular problem * \param[in] TimeIter - Index of the current time-step * \param[in] OuterIter - Index of current outer iteration * \param[in] InnerIter - Index of current inner iteration */ inline virtual void SetTurboPerformance_Output(std::shared_ptr TurboPerf, CConfig *config, unsigned long TimeIter, unsigned long OuterIter, unsigned long InnerIter) {} - + /*! * \brief Sets the multizone turboperformacne screen output * \param[in] TurboStagePerf - Stage turboperformance class @@ -982,7 +987,7 @@ class COutput { * \param[in] config - Definition of the particular problem */ inline virtual void LoadTurboHistoryData(std::shared_ptr TurboStagePerf, std::shared_ptr TurboPerf, CConfig *config) {} - + /*! * \brief Write the kinematic and thermodynamic variables at each spanwise division * \param[in] solver - The container hold all solution data diff --git a/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp b/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp index da2f6a1f3bf..fc7418c09ad 100644 --- a/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp +++ b/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp @@ -108,7 +108,8 @@ class CParallelDataSorter{ int nSends, //!< Number of sends nRecvs; //!< Number of receives - vector fieldNames; //!< Vector with names of the output fields + vector fieldNames; //!< Vector with names of the all output fields + vector requiredFieldNames; //!< Vector with names of the required output fields that we write to file unsigned short nDim; //!< Spatial dimension of the data @@ -340,6 +341,22 @@ class CParallelDataSorter{ return fieldNames; } + /*! + * \brief Get the vector containing the names of the required output fields + * \return Vector of strings containing the required field names + */ + const vector& GetRequiredFieldNames() const{ + return requiredFieldNames; + } + + /*! + * \brief Set the vector of required output fields. + * \return None. + */ + void SetRequiredFieldNames(vector req_field_names) { + requiredFieldNames = req_field_names; + } + /*! * \brief Get the spatial dimension * \return The spatial dimension diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index adc6f942145..58763f238f5 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -123,6 +123,8 @@ COutput::COutput(const CConfig *config, unsigned short ndim, bool fem_output): requestedVolumeFields.push_back(config->GetVolumeOutput_Field(iField)); } + nRequiredVolumeFields = 0; + /*--- Default is to write history to file and screen --- */ noWriting = false; @@ -430,6 +432,9 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form if (!config->GetWrt_Restart_Overwrite()) filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); + volumeDataSorter->SetRequiredFieldNames(requiredVolumeFields); + + LogOutputFiles("SU2 ASCII restart"); fileWriter = new CSU2FileWriter(volumeDataSorter); @@ -836,6 +841,7 @@ bool COutput::SetResultFiles(CGeometry *geometry, CConfig *config, CSolver** sol /*--- Loop through all requested output files and write * the partitioned and sorted data stored in the data sorters. ---*/ + WriteToFile(config, geometry, VolumeFiles[iFile]); /*--- Write any additonal files defined in the child class ----*/ @@ -1513,6 +1519,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ requestedVolumeFields.emplace_back("COORDINATES"); nRequestedVolumeFields++; } + auto itSol = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "SOLUTION"); if (itSol == requestedVolumeFields.end()){ @@ -1520,6 +1527,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ nRequestedVolumeFields++; } + nVolumeFields = 0; string RequestedField; @@ -1548,13 +1556,23 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ Field.offset = nVolumeFields; volumeFieldNames.push_back(Field.fieldName); nVolumeFields++; - FoundField[iReqField] = true; + + /*--- If we want compact solution, then required field contains only SOLUTION and COORDINATES, + else the required fields is all requested fields. ---*/ + if ( ((config->GetWrt_Restart_Compact() == true) && + ((Field.outputGroup == "SOLUTION") || (Field.outputGroup == "COORDINATES"))) || + (config->GetWrt_Restart_Compact() == false) + ) { + requiredVolumeFields.push_back(Field.fieldName); + nRequiredVolumeFields++; + } } } } } + for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ if (!FoundField[iReqField]){ FieldsToRemove.push_back(requestedVolumeFields[iReqField]); diff --git a/SU2_CFD/src/output/filewriter/CSU2FileWriter.cpp b/SU2_CFD/src/output/filewriter/CSU2FileWriter.cpp index 4c04cf0e70d..ff498b1d357 100644 --- a/SU2_CFD/src/output/filewriter/CSU2FileWriter.cpp +++ b/SU2_CFD/src/output/filewriter/CSU2FileWriter.cpp @@ -35,7 +35,8 @@ CSU2FileWriter::CSU2FileWriter(CParallelDataSorter *valDataSorter) : void CSU2FileWriter::WriteData(string val_filename){ ofstream restart_file; - const vector fieldNames = dataSorter->GetFieldNames(); + const vector fieldNames = dataSorter->GetRequiredFieldNames(); + /*--- We append the pre-defined suffix (extension) to the filename (prefix) ---*/ val_filename.append(fileExt); diff --git a/config_template.cfg b/config_template.cfg index 8a953b7be78..c28d1ed40de 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -60,6 +60,9 @@ GRAVITY_FORCE= NO % Restart solution (NO, YES) RESTART_SOL= NO % +% Only save minimum required variables for restart to minimize the restart file size. +WRT_RESTART_COMPACT= YES +% % Discard the data storaged in the solution and geometry files % e.g. AOA, dCL/dAoA, dCD/dCL, iter, etc. % Note that AoA in the solution and geometry files is critical From 4fdc8b425cecbe8d42b78ab5339ab590f6f0c77e Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 31 Oct 2024 22:58:59 +0100 Subject: [PATCH 002/129] do not write SOLUTION by default --- SU2_CFD/src/output/COutput.cpp | 3 ++- SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 58763f238f5..9c1bb808b28 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1520,13 +1520,14 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ nRequestedVolumeFields++; } + /* auto itSol = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "SOLUTION"); if (itSol == requestedVolumeFields.end()){ requestedVolumeFields.emplace_back("SOLUTION"); nRequestedVolumeFields++; } - + */ nVolumeFields = 0; diff --git a/SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp b/SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp index 8e7a869f1bf..fb8c660c740 100644 --- a/SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp +++ b/SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp @@ -41,7 +41,7 @@ void CSU2BinaryFileWriter::WriteData(string val_filename){ unsigned short iVar; - const vector& fieldNames = dataSorter->GetFieldNames(); + const vector& fieldNames = dataSorter->GetRequiredFieldNames(); unsigned short nVar = fieldNames.size(); unsigned long nParallel_Poin = dataSorter->GetnPoints(); unsigned long nPoint_Global = dataSorter->GetnPointsGlobal(); From de9ce794c3d9ea7caf299aee38e5b07411edeb1c Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 31 Oct 2024 23:22:51 +0100 Subject: [PATCH 003/129] small cleanup --- .../include/output/filewriter/CParallelDataSorter.hpp | 2 +- SU2_CFD/src/output/COutput.cpp | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp b/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp index fc7418c09ad..cfe7929b69f 100644 --- a/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp +++ b/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp @@ -108,7 +108,7 @@ class CParallelDataSorter{ int nSends, //!< Number of sends nRecvs; //!< Number of receives - vector fieldNames; //!< Vector with names of the all output fields + vector fieldNames; //!< Vector with names of all the output fields vector requiredFieldNames; //!< Vector with names of the required output fields that we write to file unsigned short nDim; //!< Spatial dimension of the data diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 9c1bb808b28..fd8045365de 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -841,7 +841,6 @@ bool COutput::SetResultFiles(CGeometry *geometry, CConfig *config, CSolver** sol /*--- Loop through all requested output files and write * the partitioned and sorted data stored in the data sorters. ---*/ - WriteToFile(config, geometry, VolumeFiles[iFile]); /*--- Write any additonal files defined in the child class ----*/ @@ -1520,15 +1519,6 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ nRequestedVolumeFields++; } - /* - auto itSol = std::find(requestedVolumeFields.begin(), - requestedVolumeFields.end(), "SOLUTION"); - if (itSol == requestedVolumeFields.end()){ - requestedVolumeFields.emplace_back("SOLUTION"); - nRequestedVolumeFields++; - } - */ - nVolumeFields = 0; string RequestedField; From 2992d7cb38a84b02cdb28bbcff4e22446fcd4839 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 1 Nov 2024 09:15:02 +0100 Subject: [PATCH 004/129] change default to false --- Common/src/CConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index be10298e348..1af4a36b1f1 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -1170,7 +1170,7 @@ void CConfig::SetConfig_Options() { /*!\brief RESTART_SOL \n DESCRIPTION: Restart solution from native solution file \n Options: NO, YES \ingroup Config */ addBoolOption("RESTART_SOL", Restart, false); /*!\brief WRT_RESTART_COMPACT \n DESCRIPTION: Minimize the size of restart files \n Options: NO, YES \ingroup Config */ - addBoolOption("WRT_RESTART_COMPACT", Wrt_Restart_Compact, true); + addBoolOption("WRT_RESTART_COMPACT", Wrt_Restart_Compact, false); /*!\brief BINARY_RESTART \n DESCRIPTION: Read binary SU2 native restart files. \n Options: YES, NO \ingroup Config */ addBoolOption("READ_BINARY_RESTART", Read_Binary_Restart, true); /*!\brief WRT_RESTART_OVERWRITE \n DESCRIPTION: overwrite restart files or append iteration number. \n Options: YES, NO \ingroup Config */ From af2fd4f7f87667fe63ae4898d7d47ba7fa18ac6a Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 6 Nov 2024 11:29:49 +0100 Subject: [PATCH 005/129] fixed --- SU2_CFD/include/output/COutput.hpp | 7 ++- SU2_CFD/src/output/COutput.cpp | 74 +++++++++++++++++++++--------- 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 146a2d6bc0c..55e335be036 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -247,6 +247,9 @@ class COutput { vector volumeFieldNames; //!< Vector containing the volume field names unsigned short nVolumeFields; //!< Number of fields in the volume output + vector requiredVolumeFieldNames; //!< Vector containing the minimum required volume field names. + //unsigned short nrequiredVolumeFields; //!< Number of fields in the minimum required volume output. + string volumeFilename, //!< Volume output filename surfaceFilename, //!< Surface output filename restartFilename; //!< Restart output filename @@ -294,9 +297,9 @@ class COutput { unsigned short nRequestedVolumeFields; /*! \brief Minimum required volume fields for restart file. */ - std::vector requiredVolumeFields; + std::vector requiredVolumeFields = {"COORDINATES", "SOLUTION"}; /*! \brief Minimum required volume fields for restart file. */ - unsigned short nRequiredVolumeFields; + unsigned short nRequiredVolumeFields = 2; /*----------------------------- Convergence monitoring ----------------------------*/ diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index fd8045365de..5d9b83eebe7 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -123,7 +123,7 @@ COutput::COutput(const CConfig *config, unsigned short ndim, bool fem_output): requestedVolumeFields.push_back(config->GetVolumeOutput_Field(iField)); } - nRequiredVolumeFields = 0; + //nRequiredVolumeFields = 0; /*--- Default is to write history to file and screen --- */ @@ -432,8 +432,12 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form if (!config->GetWrt_Restart_Overwrite()) filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); - volumeDataSorter->SetRequiredFieldNames(requiredVolumeFields); + /*--- If we have compact restarts, we use only the required fields. ---*/ + if (config->GetWrt_Restart_Compact() == true) + volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); + else + volumeDataSorter->SetRequiredFieldNames(volumeDataSorter->GetFieldNames()); LogOutputFiles("SU2 ASCII restart"); fileWriter = new CSU2FileWriter(volumeDataSorter); @@ -450,6 +454,12 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form if (!config->GetWrt_Restart_Overwrite()) filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); + /*--- If we have compact restarts, we use only the required fields. ---*/ + if (config->GetWrt_Restart_Compact() == true) + volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); + else + volumeDataSorter->SetRequiredFieldNames(volumeDataSorter->GetFieldNames()); + LogOutputFiles("SU2 binary restart"); fileWriter = new CSU2BinaryFileWriter(volumeDataSorter); @@ -1509,61 +1519,81 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ SetVolumeOutputFields(config); - /*---Coordinates and solution groups must be always in the output. - * If they are not requested, add them here. ---*/ + /*--- Coordinates must be always in the output. + * If they are not requested, add them here. + * SOLUTION is only required for restart files. ---*/ auto itCoord = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COORDINATES"); - if (itCoord == requestedVolumeFields.end()){ + if (itCoord == requestedVolumeFields.end()) { requestedVolumeFields.emplace_back("COORDINATES"); nRequestedVolumeFields++; } + /*--- If no volume fields were requested, we add the entire SOLUTION field. + * We also add the solution field if we are not using the compact formulation. + This is for backwards compatibility. ---*/ + if ((config->GetWrt_Restart_Compact() == false) || (nRequestedVolumeFields == 1)) { + requestedVolumeFields.emplace_back("SOLUTION"); + nRequestedVolumeFields++; + } + nVolumeFields = 0; string RequestedField; + string RequiredField; std::vector FoundField(nRequestedVolumeFields, false); vector FieldsToRemove; /*--- Loop through all fields defined in the corresponding SetVolumeOutputFields(). - * If it is also defined in the config (either as part of a group or a single field), the field - * object gets an offset so that we know where to find the data in the Local_Data() array. - * Note that the default offset is -1. An index !=-1 defines this field as part of the output. ---*/ + * If it is also defined in the config (either as part of a group or a single field), the field + * object gets an offset so that we know where to find the data in the Local_Data() array. + * Note that the default offset is -1. An index !=-1 defines this field as part of the output. ---*/ + + for (unsigned short iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { + + const string &fieldReference1 = volumeOutput_List[iField_Output]; + if (volumeOutput_Map.count(fieldReference1) > 0) { + + VolumeOutputField &Field1 = volumeOutput_Map.at(fieldReference1); + /*--- Loop through all fields specified in the config ---*/ + for (unsigned short iReqField = 0; iReqField < nRequiredVolumeFields; iReqField++) { + + RequiredField = requiredVolumeFields[iReqField]; + if (((RequiredField == Field1.outputGroup) || (RequiredField == fieldReference1)) && (Field1.offset == -1)) { + requiredVolumeFieldNames.push_back(Field1.fieldName); + } + } + } + } + nVolumeFields = 0; - for (unsigned short iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++){ + for (unsigned short iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { const string &fieldReference = volumeOutput_List[iField_Output]; if (volumeOutput_Map.count(fieldReference) > 0){ VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); /*--- Loop through all fields specified in the config ---*/ - - for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ + for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++) { RequestedField = requestedVolumeFields[iReqField]; + if (((RequestedField == Field.outputGroup) || (RequestedField == fieldReference)) && (Field.offset == -1)) { - if (((RequestedField == Field.outputGroup) || (RequestedField == fieldReference)) && (Field.offset == -1)){ Field.offset = nVolumeFields; volumeFieldNames.push_back(Field.fieldName); nVolumeFields++; FoundField[iReqField] = true; - - /*--- If we want compact solution, then required field contains only SOLUTION and COORDINATES, - else the required fields is all requested fields. ---*/ - if ( ((config->GetWrt_Restart_Compact() == true) && - ((Field.outputGroup == "SOLUTION") || (Field.outputGroup == "COORDINATES"))) || - (config->GetWrt_Restart_Compact() == false) - ) { - requiredVolumeFields.push_back(Field.fieldName); - nRequiredVolumeFields++; - } } } } } + + + for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ if (!FoundField[iReqField]){ FieldsToRemove.push_back(requestedVolumeFields[iReqField]); From 1f4390238e074d684fed304e5390e002ccad824f Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 6 Nov 2024 11:39:25 +0100 Subject: [PATCH 006/129] cleanup --- SU2_CFD/include/output/COutput.hpp | 1 - SU2_CFD/src/output/COutput.cpp | 11 +++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 55e335be036..9d3d9685a98 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -248,7 +248,6 @@ class COutput { unsigned short nVolumeFields; //!< Number of fields in the volume output vector requiredVolumeFieldNames; //!< Vector containing the minimum required volume field names. - //unsigned short nrequiredVolumeFields; //!< Number of fields in the minimum required volume output. string volumeFilename, //!< Volume output filename surfaceFilename, //!< Surface output filename diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 5d9b83eebe7..94a359142a9 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -123,8 +123,6 @@ COutput::COutput(const CConfig *config, unsigned short ndim, bool fem_output): requestedVolumeFields.push_back(config->GetVolumeOutput_Field(iField)); } - //nRequiredVolumeFields = 0; - /*--- Default is to write history to file and screen --- */ noWriting = false; @@ -1521,7 +1519,6 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ /*--- Coordinates must be always in the output. * If they are not requested, add them here. - * SOLUTION is only required for restart files. ---*/ auto itCoord = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COORDINATES"); @@ -1532,7 +1529,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ /*--- If no volume fields were requested, we add the entire SOLUTION field. * We also add the solution field if we are not using the compact formulation. - This is for backwards compatibility. ---*/ + * This is for backwards compatibility. ---*/ if ((config->GetWrt_Restart_Compact() == false) || (nRequestedVolumeFields == 1)) { requestedVolumeFields.emplace_back("SOLUTION"); nRequestedVolumeFields++; @@ -1576,9 +1573,11 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); /*--- Loop through all fields specified in the config ---*/ + for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++) { RequestedField = requestedVolumeFields[iReqField]; + if (((RequestedField == Field.outputGroup) || (RequestedField == fieldReference)) && (Field.offset == -1)) { Field.offset = nVolumeFields; @@ -1590,10 +1589,6 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ } } - - - - for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ if (!FoundField[iReqField]){ FieldsToRemove.push_back(requestedVolumeFields[iReqField]); From f9687803e7bae8e0197c8d94ad4b6746ced674c4 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 6 Nov 2024 11:48:00 +0100 Subject: [PATCH 007/129] variable renaming --- SU2_CFD/src/output/COutput.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 94a359142a9..bebf54cef5e 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1550,16 +1550,16 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ for (unsigned short iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { - const string &fieldReference1 = volumeOutput_List[iField_Output]; - if (volumeOutput_Map.count(fieldReference1) > 0) { + const string &fieldReference = volumeOutput_List[iField_Output]; + if (volumeOutput_Map.count(fieldReference) > 0) { - VolumeOutputField &Field1 = volumeOutput_Map.at(fieldReference1); + VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); /*--- Loop through all fields specified in the config ---*/ for (unsigned short iReqField = 0; iReqField < nRequiredVolumeFields; iReqField++) { RequiredField = requiredVolumeFields[iReqField]; - if (((RequiredField == Field1.outputGroup) || (RequiredField == fieldReference1)) && (Field1.offset == -1)) { - requiredVolumeFieldNames.push_back(Field1.fieldName); + if (((RequiredField == Field.outputGroup) || (RequiredField == fieldReference)) && (Field.offset == -1)) { + requiredVolumeFieldNames.push_back(Field.fieldName); } } } From ecfca082d9c6bbe714eb84916a5c1631e571fccc Mon Sep 17 00:00:00 2001 From: Nijso Date: Wed, 20 Nov 2024 23:02:37 +0100 Subject: [PATCH 008/129] Fix code scanning alert no. 625: Comparison of narrow type with wide type in loop condition Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index bebf54cef5e..f35624b7630 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1548,7 +1548,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ * object gets an offset so that we know where to find the data in the Local_Data() array. * Note that the default offset is -1. An index !=-1 defines this field as part of the output. ---*/ - for (unsigned short iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { + for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { const string &fieldReference = volumeOutput_List[iField_Output]; if (volumeOutput_Map.count(fieldReference) > 0) { From 202cc3c006ef6a84ec116aed663373e6419c181c Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 21 Nov 2024 15:27:02 +0100 Subject: [PATCH 009/129] include surface csv --- SU2_CFD/src/output/COutput.cpp | 7 +++++++ config_template.cfg | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index f35624b7630..86684bf66d4 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -412,6 +412,13 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form if (!config->GetWrt_Surface_Overwrite()) filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); + /*--- If we have compact restarts, we use only the required fields. ---*/ + if (config->GetWrt_Restart_Compact() == true) + surfaceDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); + else + surfaceDataSorter->SetRequiredFieldNames(surfaceDataSorter->GetFieldNames()); + + surfaceDataSorter->SortConnectivity(config, geometry); surfaceDataSorter->SortOutputData(); diff --git a/config_template.cfg b/config_template.cfg index c28d1ed40de..f21ced6fd46 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -61,7 +61,7 @@ GRAVITY_FORCE= NO RESTART_SOL= NO % % Only save minimum required variables for restart to minimize the restart file size. -WRT_RESTART_COMPACT= YES +WRT_RESTART_COMPACT= NO % % Discard the data storaged in the solution and geometry files % e.g. AOA, dCL/dAoA, dCD/dCL, iter, etc. From 8fbc8258e542ac25e7b9f044cbb02286c49b50b2 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 21 Nov 2024 15:35:32 +0100 Subject: [PATCH 010/129] change to size_t --- SU2_CFD/src/output/COutput.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 86684bf66d4..2d82b1fecf0 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1573,7 +1573,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ } nVolumeFields = 0; - for (unsigned short iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { + for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { const string &fieldReference = volumeOutput_List[iField_Output]; if (volumeOutput_Map.count(fieldReference) > 0){ @@ -1596,7 +1596,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ } } - for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ + for (size_t iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ if (!FoundField[iReqField]){ FieldsToRemove.push_back(requestedVolumeFields[iReqField]); } @@ -1604,7 +1604,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ /*--- Remove fields which are not defined --- */ - for (unsigned short iReqField = 0; iReqField < FieldsToRemove.size(); iReqField++){ + for (size_t iReqField = 0; iReqField < FieldsToRemove.size(); iReqField++){ if (rank == MASTER_NODE) { if (iReqField == 0){ cout << " Info: Ignoring the following volume output fields/groups:" << endl; From 9307d7d645127d6e7bb9e8447c3f33380dfe34e7 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 21 Nov 2024 15:49:10 +0100 Subject: [PATCH 011/129] remove variable --- SU2_CFD/include/output/COutput.hpp | 1 - SU2_CFD/src/output/COutput.cpp | 15 ++++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 9d3d9685a98..0f5dddf43e3 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -245,7 +245,6 @@ class COutput { CParallelDataSorter* surfaceDataSorter; //!< Surface data sorter vector volumeFieldNames; //!< Vector containing the volume field names - unsigned short nVolumeFields; //!< Number of fields in the volume output vector requiredVolumeFieldNames; //!< Vector containing the minimum required volume field names. diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 2d82b1fecf0..ac0d893ae96 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1542,9 +1542,6 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ nRequestedVolumeFields++; } - nVolumeFields = 0; - - string RequestedField; string RequiredField; std::vector FoundField(nRequestedVolumeFields, false); vector FieldsToRemove; @@ -1562,7 +1559,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); /*--- Loop through all fields specified in the config ---*/ - for (unsigned short iReqField = 0; iReqField < nRequiredVolumeFields; iReqField++) { + for (size_t iReqField = 0; iReqField < nRequiredVolumeFields; iReqField++) { RequiredField = requiredVolumeFields[iReqField]; if (((RequiredField == Field.outputGroup) || (RequiredField == fieldReference)) && (Field.offset == -1)) { @@ -1571,7 +1568,8 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ } } } - nVolumeFields = 0; + + unsigned short nVolumeFields = 0; for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { @@ -1581,9 +1579,9 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ /*--- Loop through all fields specified in the config ---*/ - for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++) { + for (size_t iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++) { - RequestedField = requestedVolumeFields[iReqField]; + const string &RequestedField = requestedVolumeFields[iReqField]; if (((RequestedField == Field.outputGroup) || (RequestedField == fieldReference)) && (Field.offset == -1)) { @@ -1625,8 +1623,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ if (rank == MASTER_NODE){ cout <<"Volume output fields: "; - for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ - RequestedField = requestedVolumeFields[iReqField]; + for (size_t iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ cout << requestedVolumeFields[iReqField]; if (iReqField != nRequestedVolumeFields - 1) cout << ", "; } From 3db06276c65dcf115bcdc5257b5121c112e1385a Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 21 Nov 2024 22:41:36 +0100 Subject: [PATCH 012/129] change to size_t --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index ac0d893ae96..321054a8083 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1623,7 +1623,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ if (rank == MASTER_NODE){ cout <<"Volume output fields: "; - for (size_t iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ + for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){ cout << requestedVolumeFields[iReqField]; if (iReqField != nRequestedVolumeFields - 1) cout << ", "; } From 4c2ba55f52ede40a5ce766d0c7aec7d34ce61d01 Mon Sep 17 00:00:00 2001 From: Nijso Date: Mon, 25 Nov 2024 08:00:31 +0100 Subject: [PATCH 013/129] Update SU2_CFD/src/output/COutput.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 321054a8083..be2b9b848c3 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -413,7 +413,7 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); /*--- If we have compact restarts, we use only the required fields. ---*/ - if (config->GetWrt_Restart_Compact() == true) + if (config->GetWrt_Restart_Compact()) surfaceDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); else surfaceDataSorter->SetRequiredFieldNames(surfaceDataSorter->GetFieldNames()); From fb8e8956ed14d373eef55f11335f73efc0e888d3 Mon Sep 17 00:00:00 2001 From: Nijso Date: Mon, 25 Nov 2024 08:00:39 +0100 Subject: [PATCH 014/129] Update SU2_CFD/src/output/COutput.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index be2b9b848c3..974447e4e13 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -439,7 +439,7 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form /*--- If we have compact restarts, we use only the required fields. ---*/ - if (config->GetWrt_Restart_Compact() == true) + if (config->GetWrt_Restart_Compact()) volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); else volumeDataSorter->SetRequiredFieldNames(volumeDataSorter->GetFieldNames()); From 6dc6724a48a328ae2f08cd61dce3e0186c3f999c Mon Sep 17 00:00:00 2001 From: Nijso Date: Mon, 25 Nov 2024 08:00:48 +0100 Subject: [PATCH 015/129] Update SU2_CFD/src/output/COutput.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 974447e4e13..d98933d24e6 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -460,7 +460,7 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); /*--- If we have compact restarts, we use only the required fields. ---*/ - if (config->GetWrt_Restart_Compact() == true) + if (config->GetWrt_Restart_Compact()) volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); else volumeDataSorter->SetRequiredFieldNames(volumeDataSorter->GetFieldNames()); From bb0a5685eae91f024e6e1589190083d8e3ef0853 Mon Sep 17 00:00:00 2001 From: Nijso Date: Mon, 25 Nov 2024 08:00:55 +0100 Subject: [PATCH 016/129] Update Common/src/CConfig.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- Common/src/CConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index b5f6bc05194..31f29697aee 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -1170,7 +1170,7 @@ void CConfig::SetConfig_Options() { /*!\brief RESTART_SOL \n DESCRIPTION: Restart solution from native solution file \n Options: NO, YES \ingroup Config */ addBoolOption("RESTART_SOL", Restart, false); /*!\brief WRT_RESTART_COMPACT \n DESCRIPTION: Minimize the size of restart files \n Options: NO, YES \ingroup Config */ - addBoolOption("WRT_RESTART_COMPACT", Wrt_Restart_Compact, false); + addBoolOption("WRT_RESTART_COMPACT", Wrt_Restart_Compact, true); /*!\brief BINARY_RESTART \n DESCRIPTION: Read binary SU2 native restart files. \n Options: YES, NO \ingroup Config */ addBoolOption("READ_BINARY_RESTART", Read_Binary_Restart, true); /*!\brief WRT_RESTART_OVERWRITE \n DESCRIPTION: overwrite restart files or append iteration number. \n Options: YES, NO \ingroup Config */ From a5d27b3aaa34c8bffe542303a1d979b57f8b86da Mon Sep 17 00:00:00 2001 From: Nijso Date: Mon, 25 Nov 2024 08:01:02 +0100 Subject: [PATCH 017/129] Update config_template.cfg Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- config_template.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_template.cfg b/config_template.cfg index f21ced6fd46..c28d1ed40de 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -61,7 +61,7 @@ GRAVITY_FORCE= NO RESTART_SOL= NO % % Only save minimum required variables for restart to minimize the restart file size. -WRT_RESTART_COMPACT= NO +WRT_RESTART_COMPACT= YES % % Discard the data storaged in the solution and geometry files % e.g. AOA, dCL/dAoA, dCD/dCL, iter, etc. From b18b92db2ce775f24ab20a05ceb922e576a35430 Mon Sep 17 00:00:00 2001 From: Nijso Date: Mon, 25 Nov 2024 08:01:09 +0100 Subject: [PATCH 018/129] Update SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp b/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp index cfe7929b69f..4882165a770 100644 --- a/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp +++ b/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp @@ -353,7 +353,7 @@ class CParallelDataSorter{ * \brief Set the vector of required output fields. * \return None. */ - void SetRequiredFieldNames(vector req_field_names) { + void SetRequiredFieldNames(const vector& req_field_names) { requiredFieldNames = req_field_names; } From b6f23c3c701d0d35533c6f8e5caecc3e8648c51a Mon Sep 17 00:00:00 2001 From: Nijso Date: Mon, 25 Nov 2024 08:04:33 +0100 Subject: [PATCH 019/129] Update SU2_CFD/include/output/COutput.hpp --- SU2_CFD/include/output/COutput.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 0f5dddf43e3..1d34312ce00 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -295,7 +295,7 @@ class COutput { unsigned short nRequestedVolumeFields; /*! \brief Minimum required volume fields for restart file. */ - std::vector requiredVolumeFields = {"COORDINATES", "SOLUTION"}; + std::vector requiredVolumeFields = {"COORDINATES", "SOLUTION", "GRID_VELOCITY"}; /*! \brief Minimum required volume fields for restart file. */ unsigned short nRequiredVolumeFields = 2; From c5a6c5e28d09ff74b7579573ae5153d107d7ec27 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 00:34:05 +0100 Subject: [PATCH 020/129] introduce COMPACT keyword --- SU2_CFD/include/output/COutput.hpp | 2 +- SU2_CFD/src/output/COutput.cpp | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 1d34312ce00..710f7df9dd6 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -297,7 +297,7 @@ class COutput { /*! \brief Minimum required volume fields for restart file. */ std::vector requiredVolumeFields = {"COORDINATES", "SOLUTION", "GRID_VELOCITY"}; /*! \brief Minimum required volume fields for restart file. */ - unsigned short nRequiredVolumeFields = 2; + unsigned short nRequiredVolumeFields = requiredVolumeFields.size(); /*----------------------------- Convergence monitoring ----------------------------*/ diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index d98933d24e6..e8144363127 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -414,9 +414,9 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form /*--- If we have compact restarts, we use only the required fields. ---*/ if (config->GetWrt_Restart_Compact()) - surfaceDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); - else surfaceDataSorter->SetRequiredFieldNames(surfaceDataSorter->GetFieldNames()); + else + surfaceDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); surfaceDataSorter->SortConnectivity(config, geometry); @@ -1537,16 +1537,21 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ /*--- If no volume fields were requested, we add the entire SOLUTION field. * We also add the solution field if we are not using the compact formulation. * This is for backwards compatibility. ---*/ - if ((config->GetWrt_Restart_Compact() == false) || (nRequestedVolumeFields == 1)) { - requestedVolumeFields.emplace_back("SOLUTION"); - nRequestedVolumeFields++; + itCoord = std::find(requestedVolumeFields.begin(), + requestedVolumeFields.end(), "SOLUTION"); + if (itCoord == requestedVolumeFields.end()) { + auto itCoordCompact = std::find(requestedVolumeFields.begin(), + requestedVolumeFields.end(), "COMPACT"); + if (itCoordCompact == requestedVolumeFields.end()) { + requestedVolumeFields.emplace_back("SOLUTION"); + nRequestedVolumeFields++; + } } string RequiredField; std::vector FoundField(nRequestedVolumeFields, false); vector FieldsToRemove; - /*--- Loop through all fields defined in the corresponding SetVolumeOutputFields(). * If it is also defined in the config (either as part of a group or a single field), the field * object gets an offset so that we know where to find the data in the Local_Data() array. @@ -1555,6 +1560,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { const string &fieldReference = volumeOutput_List[iField_Output]; + if (volumeOutput_Map.count(fieldReference) > 0) { VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); @@ -2452,7 +2458,7 @@ void COutput::PrintVolumeFields(){ } cout << "Available volume output fields for the current configuration in " << multiZoneHeaderString << ":" << endl; - cout << "Note: COORDINATES and SOLUTION groups are always in the volume output." << endl; + cout << "Note: COORDINATES and SOLUTION groups are always in the volume output unless WRT_COMPACT_RESTART=YES." << endl; VolumeFieldTable.AddColumn("Name", NameSize); VolumeFieldTable.AddColumn("Group Name", GroupSize); VolumeFieldTable.AddColumn("Description", DescrSize); From 8cd04b00c6f9c7ec589711efa0fb9b7c7b6efc35 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 00:38:45 +0100 Subject: [PATCH 021/129] update dry-run text --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index e8144363127..eeb2174961c 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -2458,7 +2458,7 @@ void COutput::PrintVolumeFields(){ } cout << "Available volume output fields for the current configuration in " << multiZoneHeaderString << ":" << endl; - cout << "Note: COORDINATES and SOLUTION groups are always in the volume output unless WRT_COMPACT_RESTART=YES." << endl; + cout << "Note: COORDINATES and SOLUTION groups are always in the volume output unless you add the keyword COMPACT." << endl; VolumeFieldTable.AddColumn("Name", NameSize); VolumeFieldTable.AddColumn("Group Name", GroupSize); VolumeFieldTable.AddColumn("Description", DescrSize); From 4d6f92e019263cf5bce65374c7d7b17b24123db8 Mon Sep 17 00:00:00 2001 From: Nijso Date: Wed, 27 Nov 2024 07:24:30 +0100 Subject: [PATCH 022/129] Update SU2_CFD/include/output/COutput.hpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/include/output/COutput.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 710f7df9dd6..726b170b7d7 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -295,9 +295,7 @@ class COutput { unsigned short nRequestedVolumeFields; /*! \brief Minimum required volume fields for restart file. */ - std::vector requiredVolumeFields = {"COORDINATES", "SOLUTION", "GRID_VELOCITY"}; - /*! \brief Minimum required volume fields for restart file. */ - unsigned short nRequiredVolumeFields = requiredVolumeFields.size(); + const std::vector restartVolumeFields = {"COORDINATES", "SOLUTION", "GRID_VELOCITY"}; /*----------------------------- Convergence monitoring ----------------------------*/ From 1ba790c737a9e967e5e7f3d74bdf43070853b156 Mon Sep 17 00:00:00 2001 From: Nijso Date: Wed, 27 Nov 2024 07:24:46 +0100 Subject: [PATCH 023/129] Update SU2_CFD/src/output/COutput.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index eeb2174961c..7525f430706 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1565,7 +1565,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); /*--- Loop through all fields specified in the config ---*/ - for (size_t iReqField = 0; iReqField < nRequiredVolumeFields; iReqField++) { + for (size_t iReqField = 0; iReqField < requiredVolumeFields.size(); iReqField++) { RequiredField = requiredVolumeFields[iReqField]; if (((RequiredField == Field.outputGroup) || (RequiredField == fieldReference)) && (Field.offset == -1)) { From d9ec9931add7196e3a91ab8f8da2df27927cff56 Mon Sep 17 00:00:00 2001 From: Nijso Date: Wed, 27 Nov 2024 07:24:59 +0100 Subject: [PATCH 024/129] Update SU2_CFD/src/output/COutput.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 7525f430706..05b07d71c38 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1540,7 +1540,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ itCoord = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "SOLUTION"); if (itCoord == requestedVolumeFields.end()) { - auto itCoordCompact = std::find(requestedVolumeFields.begin(), + auto itCompact = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COMPACT"); if (itCoordCompact == requestedVolumeFields.end()) { requestedVolumeFields.emplace_back("SOLUTION"); From e48c22a61be0c5d125631edcdb2d800cb55337ae Mon Sep 17 00:00:00 2001 From: Nijso Date: Wed, 27 Nov 2024 07:25:09 +0100 Subject: [PATCH 025/129] Update SU2_CFD/src/output/COutput.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 05b07d71c38..c95d90a992f 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1537,7 +1537,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ /*--- If no volume fields were requested, we add the entire SOLUTION field. * We also add the solution field if we are not using the compact formulation. * This is for backwards compatibility. ---*/ - itCoord = std::find(requestedVolumeFields.begin(), + auto itSol = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "SOLUTION"); if (itCoord == requestedVolumeFields.end()) { auto itCompact = std::find(requestedVolumeFields.begin(), From 6e6c70e0227d4c47e0625a11082a67d4e272edbf Mon Sep 17 00:00:00 2001 From: Nijso Date: Wed, 27 Nov 2024 07:25:25 +0100 Subject: [PATCH 026/129] Update SU2_CFD/src/output/COutput.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index c95d90a992f..9602c5bfb85 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1525,8 +1525,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ SetVolumeOutputFields(config); /*--- Coordinates must be always in the output. - * If they are not requested, add them here. - * SOLUTION is only required for restart files. ---*/ + * If they are not requested, add them here. ---*/ auto itCoord = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COORDINATES"); if (itCoord == requestedVolumeFields.end()) { From 9134d8b1edf19b21c926792b1f8f7f5e65f58f6a Mon Sep 17 00:00:00 2001 From: Nijso Date: Wed, 27 Nov 2024 07:25:41 +0100 Subject: [PATCH 027/129] Update SU2_CFD/src/output/COutput.cpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/src/output/COutput.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 9602c5bfb85..c0f9756affa 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1533,9 +1533,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ nRequestedVolumeFields++; } - /*--- If no volume fields were requested, we add the entire SOLUTION field. - * We also add the solution field if we are not using the compact formulation. - * This is for backwards compatibility. ---*/ + /*--- Add the solution if it was not requested for backwards compatibility, unless the COMPACT keyword was used to request exclusively the specified fields. ---*/ auto itSol = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "SOLUTION"); if (itCoord == requestedVolumeFields.end()) { From 1a0aef878a28ee1838bcabdee07f67c1c04155d0 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 07:34:00 +0100 Subject: [PATCH 028/129] add better config_template description --- config_template.cfg | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/config_template.cfg b/config_template.cfg index c28d1ed40de..d75f8932cef 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -51,7 +51,7 @@ KIND_VERIFICATION_SOLUTION= NO_VERIFICATION_SOLUTION % Defaults to DISCRETE_ADJOINT for the SU2_*_AD codes, and to DIRECT otherwise. MATH_PROBLEM= DIRECT % -% Axisymmetric simulation, only compressible flows (NO, YES) +% Axisymmetric simulation for 2D problems. (NO, YES) AXISYMMETRIC= NO % % Gravity force @@ -60,7 +60,10 @@ GRAVITY_FORCE= NO % Restart solution (NO, YES) RESTART_SOL= NO % -% Only save minimum required variables for restart to minimize the restart file size. +% Only save minimum required variables to restart files (NO, YES). +% If this option is set to NO, then the SOLUTION fields will be written to all output +% files by default. If you would also like to have minimum output files +% (e.g. paraview, tecplot), then add the keyword COMPACT to VOLUME_OUTPUT. WRT_RESTART_COMPACT= YES % % Discard the data storaged in the solution and geometry files From da4c87e4787dde717d04c850ec4146dd5631c88a Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 08:15:47 +0100 Subject: [PATCH 029/129] update variable name --- SU2_CFD/src/output/COutput.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index c0f9756affa..d3dc4cc64cb 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1562,9 +1562,9 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); /*--- Loop through all fields specified in the config ---*/ - for (size_t iReqField = 0; iReqField < requiredVolumeFields.size(); iReqField++) { + for (size_t iReqField = 0; iReqField < restartVolumeFields.size(); iReqField++) { - RequiredField = requiredVolumeFields[iReqField]; + RequiredField = restartVolumeFields[iReqField]; if (((RequiredField == Field.outputGroup) || (RequiredField == fieldReference)) && (Field.offset == -1)) { requiredVolumeFieldNames.push_back(Field.fieldName); } From d54eb64abd83dc309431a8d6d3911a30c7fc4607 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 08:34:00 +0100 Subject: [PATCH 030/129] update variable name --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index d3dc4cc64cb..fe1b7d9dc74 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1539,7 +1539,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ if (itCoord == requestedVolumeFields.end()) { auto itCompact = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COMPACT"); - if (itCoordCompact == requestedVolumeFields.end()) { + if (itCompact == requestedVolumeFields.end()) { requestedVolumeFields.emplace_back("SOLUTION"); nRequestedVolumeFields++; } From 915fa30246844cd230b6b9cfacd16d453514d11d Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 08:51:59 +0100 Subject: [PATCH 031/129] update variable name --- SU2_CFD/src/output/COutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index fe1b7d9dc74..08e3c633217 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1536,7 +1536,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ /*--- Add the solution if it was not requested for backwards compatibility, unless the COMPACT keyword was used to request exclusively the specified fields. ---*/ auto itSol = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "SOLUTION"); - if (itCoord == requestedVolumeFields.end()) { + if (itSol == requestedVolumeFields.end()) { auto itCompact = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COMPACT"); if (itCompact == requestedVolumeFields.end()) { From 2ece849afe9ab5819a85f8e90864df361bfe95a0 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 13:27:46 +0100 Subject: [PATCH 032/129] do not use compact to pass regressions --- .../02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg | 2 +- .../lam_prem_ch4_cht_cfd_fluid.cfg | 2 ++ TestCases/radiation/p1adjoint/configp1adjoint.cfg | 2 +- TestCases/rans/oneram6/turb_ONERAM6.cfg | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg b/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg index ff52e8d58b6..b79c1f3b367 100644 --- a/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg +++ b/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg @@ -128,7 +128,7 @@ MARKER_ANALYZE_AVERAGE= MASSFLUX OUTPUT_FILES= RESTART, RESTART_ASCII, PARAVIEW VOLUME_OUTPUT= RESIDUAL, PRIMITIVE VOLUME_ADJ_FILENAME= ch4_flame_hx_ad - +WRT_RESTART_COMPACT = NO OUTPUT_WRT_FREQ= 100 % GRAD_OBJFUNC_FILENAME= of_grad.csv diff --git a/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg b/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg index adf9a65020f..af8e562b0cd 100644 --- a/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg +++ b/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg @@ -19,6 +19,8 @@ HISTORY_OUTPUT= RMS_RES AERO_COEFF FLOW_COEFF FLOW_COEFF_SURF VOLUME_OUTPUT= SOLUTION PRIMITIVE SOURCE RESIDUAL LOOKUP +WRT_RESTART_COMPACT = NO + OUTPUT_FILES= (RESTART_ASCII, PARAVIEW) INNER_ITER= 1 diff --git a/TestCases/radiation/p1adjoint/configp1adjoint.cfg b/TestCases/radiation/p1adjoint/configp1adjoint.cfg index 93740e5ea95..cdbad6937b7 100644 --- a/TestCases/radiation/p1adjoint/configp1adjoint.cfg +++ b/TestCases/radiation/p1adjoint/configp1adjoint.cfg @@ -131,7 +131,7 @@ FFD_CONTINUITY = 2ND_DERIVATIVE %%%%%%%%%%%%%%%%%%%%%%% OUTPUT_FILES = (RESTART, PARAVIEW) - +WRT_RESTART_COMPACT = NO SOLUTION_FILENAME = solution_rht RESTART_FILENAME = restart_rht VOLUME_FILENAME = volume_rht diff --git a/TestCases/rans/oneram6/turb_ONERAM6.cfg b/TestCases/rans/oneram6/turb_ONERAM6.cfg index a43f3974459..d38d71b3287 100644 --- a/TestCases/rans/oneram6/turb_ONERAM6.cfg +++ b/TestCases/rans/oneram6/turb_ONERAM6.cfg @@ -110,6 +110,7 @@ MESH_OUT_FILENAME= mesh_out.su2 SOLUTION_FILENAME= restart_flow.dat SOLUTION_ADJ_FILENAME= solution_adj.dat OUTPUT_FILES=(RESTART, STL_ASCII, PARAVIEW, SURFACE_PARAVIEW) +WRT_RESTART_COMPACT = NO TABULAR_FORMAT= CSV CONV_FILENAME= history RESTART_FILENAME= restart_flow.dat From 605d42ded11b2d99e808a403f73c5d2b9fdcf165 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 15:05:42 +0100 Subject: [PATCH 033/129] update naca0012 cfg --- TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg b/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg index 7a63c1ff189..1911bdef3b7 100644 --- a/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg +++ b/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg @@ -127,6 +127,7 @@ SURFACE_ADJ_FILENAME= surface_adjoint OUTPUT_WRT_FREQ= 250 SCREEN_OUTPUT = (INNER_ITER, RMS_ADJ_DENSITY, RMS_ADJ_ENERGY, SENS_GEO, SENS_AOA, RMS_DENSITY, RMS_ENERGY, LIFT, DRAG) HISTORY_OUTPUT= (ITER, RMS_RES, AERO_COEFF, SENSITIVITY) +WRT_RESTART_COMPACT = NO VOLUME_OUTPUT= (COORDINATES, SOLUTION, PRESSURE, TEMPERATURE, SENSITIVITY) OUTPUT_FILES=(RESTART_ASCII, PARAVIEW, SURFACE_CSV) From cb748fd6a9c8bc3c755b20a3189e3515e82f8f88 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 21:19:28 +0100 Subject: [PATCH 034/129] fix writing surface csv --- SU2_CFD/src/output/COutput.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 08e3c633217..3fb9fbb5582 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -414,9 +414,9 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form /*--- If we have compact restarts, we use only the required fields. ---*/ if (config->GetWrt_Restart_Compact()) - surfaceDataSorter->SetRequiredFieldNames(surfaceDataSorter->GetFieldNames()); - else surfaceDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); + else + surfaceDataSorter->SetRequiredFieldNames(surfaceDataSorter->GetFieldNames()); surfaceDataSorter->SortConnectivity(config, geometry); From 452d5893d39cd673d5cafc90ab13fadaa6b4a5c1 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 27 Nov 2024 22:16:13 +0100 Subject: [PATCH 035/129] add SENSITIVITY to required restart fields --- SU2_CFD/include/output/COutput.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 726b170b7d7..a3a222dff40 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -295,7 +295,7 @@ class COutput { unsigned short nRequestedVolumeFields; /*! \brief Minimum required volume fields for restart file. */ - const std::vector restartVolumeFields = {"COORDINATES", "SOLUTION", "GRID_VELOCITY"}; + const std::vector restartVolumeFields = {"COORDINATES", "SOLUTION", "SENSITIVITY", "GRID_VELOCITY"}; /*----------------------------- Convergence monitoring ----------------------------*/ From dc99d6f672d45521609aaf8b69b3042fd1b390aa Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 28 Nov 2024 00:03:28 +0100 Subject: [PATCH 036/129] fix regression tests --- TestCases/disc_adj_rans/naca0012/naca0012.cfg | 1 + .../lam_prem_ch4_cht_ad_fluid.cfg | 2 ++ 2 files changed, 3 insertions(+) diff --git a/TestCases/disc_adj_rans/naca0012/naca0012.cfg b/TestCases/disc_adj_rans/naca0012/naca0012.cfg index 9a84427b263..6a722eead1c 100644 --- a/TestCases/disc_adj_rans/naca0012/naca0012.cfg +++ b/TestCases/disc_adj_rans/naca0012/naca0012.cfg @@ -105,6 +105,7 @@ CONV_FILENAME= 0_history RESTART_FILENAME= restart_flow.dat RESTART_ADJ_FILENAME= restart_adj.dat VOLUME_FILENAME= flow +WRT_RESTART_COMPACT= NO SURFACE_FILENAME= surface_flow OUTPUT_WRT_FREQ= 1 % diff --git a/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg b/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg index 7824d6780fd..b251e54182a 100644 --- a/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg +++ b/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg @@ -23,6 +23,8 @@ VOLUME_OUTPUT= SOLUTION PRIMITIVE SOURCE RESIDUAL LOOKUP OUTPUT_FILES= ( RESTART_ASCII) +WRT_RESTART_COMPACT= NO + INNER_ITER= 1 % -------------------- BOUNDARY CONDITION DEFINITION --------------------------% From 145018b0213f2818450c554ad8413fe54eedc1bb Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 29 Nov 2024 10:31:33 +0100 Subject: [PATCH 037/129] add compact=no to pywrapper regressions --- TestCases/py_wrapper/custom_load_fea/run_ad.py | 1 + TestCases/py_wrapper/wavy_wall/run_steady.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/TestCases/py_wrapper/custom_load_fea/run_ad.py b/TestCases/py_wrapper/custom_load_fea/run_ad.py index dfb9fab4fab..59e4ec03c07 100644 --- a/TestCases/py_wrapper/custom_load_fea/run_ad.py +++ b/TestCases/py_wrapper/custom_load_fea/run_ad.py @@ -61,6 +61,7 @@ OUTPUT_WRT_FREQ= 1 OBJECTIVE_FUNCTION= STRESS_PENALTY STRESS_PENALTY_PARAM= ( 500, 20 ) +WRT_RESTART_CUSTOM= NO INNER_ITER= 20 CONV_RESIDUAL_MINVAL= -4 diff --git a/TestCases/py_wrapper/wavy_wall/run_steady.py b/TestCases/py_wrapper/wavy_wall/run_steady.py index 511aa585827..db40659c68b 100644 --- a/TestCases/py_wrapper/wavy_wall/run_steady.py +++ b/TestCases/py_wrapper/wavy_wall/run_steady.py @@ -93,7 +93,7 @@ primal_settings = """ MATH_PROBLEM= DIRECT RESTART_SOL= YES - +WRT_RESTART_COMPACT= NO CFL_NUMBER= 1000 LINEAR_SOLVER= FGMRES LINEAR_SOLVER_PREC= ILU From b61e7cec2e9c402b11aca3c723a4268111bb49ab Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 29 Nov 2024 21:26:47 +0100 Subject: [PATCH 038/129] add compact=no to pywrapper regressions --- TestCases/py_wrapper/custom_load_fea/run_ad.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/py_wrapper/custom_load_fea/run_ad.py b/TestCases/py_wrapper/custom_load_fea/run_ad.py index 59e4ec03c07..dc643ad67a1 100644 --- a/TestCases/py_wrapper/custom_load_fea/run_ad.py +++ b/TestCases/py_wrapper/custom_load_fea/run_ad.py @@ -61,7 +61,7 @@ OUTPUT_WRT_FREQ= 1 OBJECTIVE_FUNCTION= STRESS_PENALTY STRESS_PENALTY_PARAM= ( 500, 20 ) -WRT_RESTART_CUSTOM= NO +WRT_RESTART_COMPACT= NO INNER_ITER= 20 CONV_RESIDUAL_MINVAL= -4 From 864512001d116948cad8d0d9cab3991cd54c6491 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 29 Nov 2024 22:31:59 +0100 Subject: [PATCH 039/129] add compact=no to pywrapper regressions --- TestCases/optimization_rans/naca0012/naca0012.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/TestCases/optimization_rans/naca0012/naca0012.cfg b/TestCases/optimization_rans/naca0012/naca0012.cfg index 763109d820a..a9d0b530419 100644 --- a/TestCases/optimization_rans/naca0012/naca0012.cfg +++ b/TestCases/optimization_rans/naca0012/naca0012.cfg @@ -107,6 +107,7 @@ RESTART_ADJ_FILENAME= restart_adj.dat VOLUME_FILENAME= flow SURFACE_FILENAME= surface_flow OUTPUT_WRT_FREQ= 1 +WRT_RESTART_COMPACT= NO % % ----------------------- DESIGN VARIABLE PARAMETERS --------------------------% % From a9682ac22e01857fb9cd82aa1312aaecaa1b42f6 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sun, 1 Dec 2024 16:22:44 +0100 Subject: [PATCH 040/129] stl writer - change SU2_SOL to SU2_CFD --- TestCases/parallel_regression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 66aa66fb805..8537e636c12 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -1660,7 +1660,7 @@ def main(): stl_writer_test.cfg_dir = "rans/oneram6" stl_writer_test.cfg_file = "turb_ONERAM6.cfg" stl_writer_test.test_iter = 1 - stl_writer_test.command = TestCase.Command("mpirun -n 2", "SU2_SOL") + stl_writer_test.command = TestCase.Command("mpirun -n 2", "SU2_CFD") stl_writer_test.timeout = 1600 stl_writer_test.reference_file = "surface_flow.stl.ref" stl_writer_test.test_file = "surface_flow.stl" From bef2a1e63e171cce88f780ba972fda88fe05c438 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sun, 8 Dec 2024 14:08:44 -0800 Subject: [PATCH 041/129] measure the heat flux used in BCs instead of computing from the normal gradient --- .../include/solvers/CFVMFlowSolverBase.inl | 46 ++++++++++++++++--- SU2_CFD/src/solvers/CIncNSSolver.cpp | 18 ++++---- SU2_CFD/src/solvers/CNSSolver.cpp | 16 ++++--- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl b/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl index 4797293529f..10166b18978 100644 --- a/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl +++ b/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl @@ -2363,6 +2363,7 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr const su2double Beta = config->GetAoS() * PI_NUMBER / 180.0; const su2double RefLength = config->GetRefLength(); const su2double RefHeatFlux = config->GetHeat_Flux_Ref(); + const su2double RefTemperature = config->GetTemperature_Ref(); const su2double Gas_Constant = config->GetGas_ConstantND(); auto Origin = config->GetRefOriginMoment(0); @@ -2396,6 +2397,8 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr Marker_Tag = config->GetMarker_All_TagBound(iMarker); if (!config->GetViscous_Wall(iMarker)) continue; + const bool py_custom = config->GetMarker_All_PyCustom(iMarker); + /*--- Obtain the origin for the moment computation for a particular marker ---*/ const auto Monitoring = config->GetMarker_All_Monitoring(iMarker); @@ -2506,26 +2509,55 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr /*--- Compute total and maximum heat flux on the wall ---*/ - su2double dTdn = -GeometryToolbox::DotProduct(nDim, Grad_Temp, UnitNormal); - - if (!nemo){ - + if (!nemo) { if (FlowRegime == ENUM_REGIME::COMPRESSIBLE) { - Cp = (Gamma / Gamma_Minus_One) * Gas_Constant; thermal_conductivity = Cp * Viscosity / Prandtl_Lam; } if (FlowRegime == ENUM_REGIME::INCOMPRESSIBLE) { - if (!energy) dTdn = 0.0; thermal_conductivity = nodes->GetThermalConductivity(iPoint); } - HeatFlux[iMarker][iVertex] = -thermal_conductivity * dTdn * RefHeatFlux; + if (config->GetMarker_All_KindBC(iMarker) == BC_TYPE::HEAT_FLUX) { + if (py_custom) { + HeatFlux[iMarker][iVertex] = geometry->GetCustomBoundaryHeatFlux(iMarker, iVertex); + } else { + HeatFlux[iMarker][iVertex] = config->GetWall_HeatFlux(Marker_Tag); + if (config->GetIntegrated_HeatFlux()) { + HeatFlux[iMarker][iVertex] /= geometry->GetSurfaceArea(config, iMarker); + } + } + } else if (config->GetMarker_All_KindBC(iMarker) == BC_TYPE::ISOTHERMAL) { + su2double Twall = 0.0; + if (py_custom) { + Twall = geometry->GetCustomBoundaryTemperature(iMarker, iVertex) / RefTemperature; + } else { + Twall = config->GetIsothermal_Temperature(Marker_Tag) / RefTemperature; + } + iPointNormal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); + Coord_Normal = geometry->nodes->GetCoord(iPointNormal); + su2double Vec_ij[MAXNDIM] = {0.0}; + GeometryToolbox::Distance(nDim, Coord, Coord_Normal, Vec_ij); + + /*--- Prevent divisions by 0 by limiting the normal projection. ---*/ + const su2double dist_ij = fmax( + fabs(GeometryToolbox::DotProduct(int(MAXNDIM), Vec_ij, UnitNormal)), + fmax(0.05 * GeometryToolbox::Norm(int(MAXNDIM), Vec_ij), EPS)); + + const su2double There = nodes->GetTemperature(iPointNormal); + + HeatFlux[iMarker][iVertex] = -thermal_conductivity * (There - Twall) / dist_ij * RefHeatFlux; + } else { + su2double dTdn = -GeometryToolbox::DotProduct(nDim, Grad_Temp, UnitNormal); + if (FlowRegime == ENUM_REGIME::INCOMPRESSIBLE && !energy) dTdn = 0.0; + HeatFlux[iMarker][iVertex] = -thermal_conductivity * dTdn * RefHeatFlux; + } } else { const auto& thermal_conductivity_tr = nodes->GetThermalConductivity(iPoint); const auto& thermal_conductivity_ve = nodes->GetThermalConductivity_ve(iPoint); + const su2double dTdn = -GeometryToolbox::DotProduct(nDim, Grad_Temp, UnitNormal); const su2double dTvedn = -GeometryToolbox::DotProduct(nDim, Grad_Temp_ve, UnitNormal); /*--- Surface energy balance: trans-rot heat flux, vib-el heat flux ---*/ diff --git a/SU2_CFD/src/solvers/CIncNSSolver.cpp b/SU2_CFD/src/solvers/CIncNSSolver.cpp index 41cedcdb5f5..67b8ed863c4 100644 --- a/SU2_CFD/src/solvers/CIncNSSolver.cpp +++ b/SU2_CFD/src/solvers/CIncNSSolver.cpp @@ -472,18 +472,21 @@ void CIncNSSolver::BC_Wall_Generic(const CGeometry *geometry, const CConfig *con const auto Coord_i = geometry->nodes->GetCoord(iPoint); const auto Coord_j = geometry->nodes->GetCoord(Point_Normal); - su2double Edge_Vector[MAXNDIM]; + su2double Edge_Vector[MAXNDIM] = {0.0}; GeometryToolbox::Distance(nDim, Coord_j, Coord_i, Edge_Vector); - su2double dist_ij_2 = GeometryToolbox::SquaredNorm(nDim, Edge_Vector); - su2double dist_ij = sqrt(dist_ij_2); + + /*--- Prevent divisions by 0 by limiting the normal projection. ---*/ + const su2double dist_ij = fmax( + fabs(GeometryToolbox::DotProduct(int(MAXNDIM), Edge_Vector, Normal)) / Area, + fmax(0.05 * GeometryToolbox::Norm(int(MAXNDIM), Edge_Vector), EPS)); /*--- Compute the normal gradient in temperature using Twall ---*/ - su2double dTdn = -(nodes->GetTemperature(Point_Normal) - Twall)/dist_ij; + const su2double dTdn = -(nodes->GetTemperature(Point_Normal) - Twall)/dist_ij; /*--- Get thermal conductivity ---*/ - su2double thermal_conductivity = nodes->GetThermalConductivity(iPoint); + const su2double thermal_conductivity = nodes->GetThermalConductivity(iPoint); /*--- Apply a weak boundary condition for the energy equation. Compute the residual due to the prescribed heat flux. ---*/ @@ -493,10 +496,7 @@ void CIncNSSolver::BC_Wall_Generic(const CGeometry *geometry, const CConfig *con /*--- Jacobian contribution for temperature equation. ---*/ if (implicit) { - su2double proj_vector_ij = 0.0; - if (dist_ij_2 > 0.0) - proj_vector_ij = GeometryToolbox::DotProduct(nDim, Edge_Vector, Normal) / dist_ij_2; - Jacobian.AddVal2Diag(iPoint, nDim+1, thermal_conductivity*proj_vector_ij); + Jacobian.AddVal2Diag(iPoint, nDim+1, thermal_conductivity * Area / dist_ij); } break; } // switch diff --git a/SU2_CFD/src/solvers/CNSSolver.cpp b/SU2_CFD/src/solvers/CNSSolver.cpp index 127ff3f5b08..3d6c6609e3b 100644 --- a/SU2_CFD/src/solvers/CNSSolver.cpp +++ b/SU2_CFD/src/solvers/CNSSolver.cpp @@ -672,22 +672,25 @@ void CNSSolver::BC_Isothermal_Wall_Generic(CGeometry *geometry, CSolver **solver const auto Coord_i = geometry->nodes->GetCoord(iPoint); const auto Coord_j = geometry->nodes->GetCoord(Point_Normal); + su2double Vec_ij[MAXNDIM] = {0.0}; + GeometryToolbox::Distance(nDim, Coord_i, Coord_j, Vec_ij); - su2double dist_ij = GeometryToolbox::Distance(nDim, Coord_i, Coord_j); + /*--- Prevent divisions by 0 by limiting the normal projection. ---*/ + const su2double dist_ij = fmax( + fabs(GeometryToolbox::DotProduct(int(MAXNDIM), Vec_ij, UnitNormal)), + fmax(0.05 * GeometryToolbox::Norm(int(MAXNDIM), Vec_ij), EPS)); /*--- Store the corrected velocity at the wall which will be zero (v = 0), unless there is grid motion (v = u_wall)---*/ if (dynamic_grid) { nodes->SetVelocity_Old(iPoint, geometry->nodes->GetGridVel(iPoint)); - } - else { + } else { su2double zero[MAXNDIM] = {0.0}; nodes->SetVelocity_Old(iPoint, zero); } - for (auto iDim = 0u; iDim < nDim; iDim++) - LinSysRes(iPoint, iDim+1) = 0.0; + for (auto iDim = 0u; iDim < nDim; iDim++) LinSysRes(iPoint, iDim+1) = 0.0; nodes->SetVel_ResTruncError_Zero(iPoint); /*--- Get transport coefficients ---*/ @@ -708,8 +711,7 @@ void CNSSolver::BC_Isothermal_Wall_Generic(CGeometry *geometry, CSolver **solver if (cht_mode) { Twall = GetCHTWallTemperature(config, val_marker, iVertex, dist_ij, thermal_conductivity, There, Temperature_Ref); - } - else if (config->GetMarker_All_PyCustom(val_marker)) { + } else if (config->GetMarker_All_PyCustom(val_marker)) { Twall = geometry->GetCustomBoundaryTemperature(val_marker, iVertex) / Temperature_Ref; } From 43cb5f23d68b14f6f773d2130ef7a52d907ada40 Mon Sep 17 00:00:00 2001 From: emaberman Date: Mon, 9 Dec 2024 17:30:56 +0200 Subject: [PATCH 042/129] fix bug with dshat for SA jacobian --- SU2_CFD/include/numerics/turbulent/turb_sources.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index c9464b1dfc3..0614e451714 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -347,16 +347,18 @@ struct Bsl { * Note 1 option c in https://turbmodels.larc.nasa.gov/spalart.html ---*/ if (Sbar >= - c2 * var.Omega) { var.Shat = var.Omega + Sbar; + var.d_Shat = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; } else { const su2double Num = var.Omega * (c2 * c2 * var.Omega + c3 * Sbar); const su2double Den = (c3 - 2 * c2) * var.Omega - Sbar; var.Shat = var.Omega + Num / Den; + + const su2double d_SB =var.d_Shat = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; + var.d_Shat = d_SB * (c3 * var.Omega + Num / Den) / Den; } if (var.Shat <= 1e-10) { var.Shat = 1e-10; var.d_Shat = 0.0; - } else { - var.d_Shat = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; } } }; From fefd2d343eb98a6abec7da6464d332915256fe29 Mon Sep 17 00:00:00 2001 From: emaberman Date: Mon, 9 Dec 2024 17:38:21 +0200 Subject: [PATCH 043/129] fix bug with dshat for SA jacobian --- SU2_CFD/include/numerics/turbulent/turb_sources.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index 0614e451714..5a173f6aeea 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -353,7 +353,7 @@ struct Bsl { const su2double Den = (c3 - 2 * c2) * var.Omega - Sbar; var.Shat = var.Omega + Num / Den; - const su2double d_SB =var.d_Shat = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; + const su2double d_SB = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; var.d_Shat = d_SB * (c3 * var.Omega + Num / Den) / Den; } if (var.Shat <= 1e-10) { From 147da5d4eda752f84512a7b260b2f2594d7042a7 Mon Sep 17 00:00:00 2001 From: Eitan Aberman <139676851+emaberman@users.noreply.github.com> Date: Tue, 10 Dec 2024 08:02:44 +0200 Subject: [PATCH 044/129] Update SU2_CFD/include/numerics/turbulent/turb_sources.hpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/include/numerics/turbulent/turb_sources.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index 5a173f6aeea..8698e2822c7 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -345,6 +345,7 @@ struct Bsl { /*--- Limiting of \hat{S} based on "Modifications and Clarifications for the Implementation of the Spalart-Allmaras Turbulence Model" * Note 1 option c in https://turbmodels.larc.nasa.gov/spalart.html ---*/ + const su2double d_Sbar = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; if (Sbar >= - c2 * var.Omega) { var.Shat = var.Omega + Sbar; var.d_Shat = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; From b6ebcc5c725b6c72f13141626d115937e239b297 Mon Sep 17 00:00:00 2001 From: Eitan Aberman <139676851+emaberman@users.noreply.github.com> Date: Tue, 10 Dec 2024 08:02:52 +0200 Subject: [PATCH 045/129] Update SU2_CFD/include/numerics/turbulent/turb_sources.hpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/include/numerics/turbulent/turb_sources.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index 8698e2822c7..f2e3d1c3809 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -348,7 +348,7 @@ struct Bsl { const su2double d_Sbar = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; if (Sbar >= - c2 * var.Omega) { var.Shat = var.Omega + Sbar; - var.d_Shat = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; + var.d_Shat = d_Sbar; } else { const su2double Num = var.Omega * (c2 * c2 * var.Omega + c3 * Sbar); const su2double Den = (c3 - 2 * c2) * var.Omega - Sbar; From 8214318f56150b3e9c7648e13aef1689fef4b628 Mon Sep 17 00:00:00 2001 From: Eitan Aberman <139676851+emaberman@users.noreply.github.com> Date: Tue, 10 Dec 2024 08:02:58 +0200 Subject: [PATCH 046/129] Update SU2_CFD/include/numerics/turbulent/turb_sources.hpp Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- SU2_CFD/include/numerics/turbulent/turb_sources.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index f2e3d1c3809..4e5f1cd51f3 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -353,9 +353,7 @@ struct Bsl { const su2double Num = var.Omega * (c2 * c2 * var.Omega + c3 * Sbar); const su2double Den = (c3 - 2 * c2) * var.Omega - Sbar; var.Shat = var.Omega + Num / Den; - - const su2double d_SB = (var.fv2 + nue * var.d_fv2) * var.inv_k2_d2; - var.d_Shat = d_SB * (c3 * var.Omega + Num / Den) / Den; + var.d_Shat = d_Sbar * (c3 * var.Omega + Num / Den) / Den; } if (var.Shat <= 1e-10) { var.Shat = 1e-10; From 397c22819d41b7669d7fb234db5115917acd05ef Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sun, 15 Dec 2024 11:48:21 -0800 Subject: [PATCH 047/129] recover old sign convention and use helper function --- Common/include/toolboxes/geometry_toolbox.hpp | 8 ++++++++ .../include/solvers/CFVMFlowSolverBase.inl | 20 ++++++------------- SU2_CFD/src/solvers/CIncNSSolver.cpp | 10 +++------- SU2_CFD/src/solvers/CNSSolver.cpp | 8 +------- 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/Common/include/toolboxes/geometry_toolbox.hpp b/Common/include/toolboxes/geometry_toolbox.hpp index 773f1d553dc..ddc2fd4434a 100644 --- a/Common/include/toolboxes/geometry_toolbox.hpp +++ b/Common/include/toolboxes/geometry_toolbox.hpp @@ -79,6 +79,14 @@ inline T Norm(Int nDim, const T* a) { return sqrt(SquaredNorm(nDim, a)); } +/*! \brief dn = max(abs(n.(a-b)), 0.05 * ||a-b|| */ +template +inline T NormalDistance(Int nDim, const T* n, const T* a, const T* b) { + T d[3] = {0}; + Distance(nDim, a, b, d); + return fmax(fabs(DotProduct(nDim, n, d)), 0.05 * Norm(nDim, d)); +} + /*! \brief c = a x b */ template inline void CrossProduct(const T* a, const T* b, T* c) { diff --git a/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl b/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl index 10166b18978..40206768e4c 100644 --- a/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl +++ b/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl @@ -2520,9 +2520,9 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr if (config->GetMarker_All_KindBC(iMarker) == BC_TYPE::HEAT_FLUX) { if (py_custom) { - HeatFlux[iMarker][iVertex] = geometry->GetCustomBoundaryHeatFlux(iMarker, iVertex); + HeatFlux[iMarker][iVertex] = -geometry->GetCustomBoundaryHeatFlux(iMarker, iVertex); } else { - HeatFlux[iMarker][iVertex] = config->GetWall_HeatFlux(Marker_Tag); + HeatFlux[iMarker][iVertex] = -config->GetWall_HeatFlux(Marker_Tag); if (config->GetIntegrated_HeatFlux()) { HeatFlux[iMarker][iVertex] /= geometry->GetSurfaceArea(config, iMarker); } @@ -2536,21 +2536,13 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr } iPointNormal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); Coord_Normal = geometry->nodes->GetCoord(iPointNormal); - su2double Vec_ij[MAXNDIM] = {0.0}; - GeometryToolbox::Distance(nDim, Coord, Coord_Normal, Vec_ij); - - /*--- Prevent divisions by 0 by limiting the normal projection. ---*/ - const su2double dist_ij = fmax( - fabs(GeometryToolbox::DotProduct(int(MAXNDIM), Vec_ij, UnitNormal)), - fmax(0.05 * GeometryToolbox::Norm(int(MAXNDIM), Vec_ij), EPS)); - + const su2double dist_ij = GeometryToolbox::NormalDistance(nDim, UnitNormal, Coord, Coord_Normal); const su2double There = nodes->GetTemperature(iPointNormal); - - HeatFlux[iMarker][iVertex] = -thermal_conductivity * (There - Twall) / dist_ij * RefHeatFlux; + HeatFlux[iMarker][iVertex] = thermal_conductivity * (There - Twall) / dist_ij * RefHeatFlux; } else { - su2double dTdn = -GeometryToolbox::DotProduct(nDim, Grad_Temp, UnitNormal); + su2double dTdn = GeometryToolbox::DotProduct(nDim, Grad_Temp, UnitNormal); if (FlowRegime == ENUM_REGIME::INCOMPRESSIBLE && !energy) dTdn = 0.0; - HeatFlux[iMarker][iVertex] = -thermal_conductivity * dTdn * RefHeatFlux; + HeatFlux[iMarker][iVertex] = thermal_conductivity * dTdn * RefHeatFlux; } } else { diff --git a/SU2_CFD/src/solvers/CIncNSSolver.cpp b/SU2_CFD/src/solvers/CIncNSSolver.cpp index 67b8ed863c4..8db972191c3 100644 --- a/SU2_CFD/src/solvers/CIncNSSolver.cpp +++ b/SU2_CFD/src/solvers/CIncNSSolver.cpp @@ -472,13 +472,9 @@ void CIncNSSolver::BC_Wall_Generic(const CGeometry *geometry, const CConfig *con const auto Coord_i = geometry->nodes->GetCoord(iPoint); const auto Coord_j = geometry->nodes->GetCoord(Point_Normal); - su2double Edge_Vector[MAXNDIM] = {0.0}; - GeometryToolbox::Distance(nDim, Coord_j, Coord_i, Edge_Vector); - - /*--- Prevent divisions by 0 by limiting the normal projection. ---*/ - const su2double dist_ij = fmax( - fabs(GeometryToolbox::DotProduct(int(MAXNDIM), Edge_Vector, Normal)) / Area, - fmax(0.05 * GeometryToolbox::Norm(int(MAXNDIM), Edge_Vector), EPS)); + su2double UnitNormal[MAXNDIM] = {0.0}; + for (auto iDim = 0u; iDim < nDim; ++iDim) UnitNormal[iDim] = Normal[iDim] / Area; + const su2double dist_ij = GeometryToolbox::NormalDistance(nDim, UnitNormal, Coord_i, Coord_j); /*--- Compute the normal gradient in temperature using Twall ---*/ diff --git a/SU2_CFD/src/solvers/CNSSolver.cpp b/SU2_CFD/src/solvers/CNSSolver.cpp index 3d6c6609e3b..50f243c7f0c 100644 --- a/SU2_CFD/src/solvers/CNSSolver.cpp +++ b/SU2_CFD/src/solvers/CNSSolver.cpp @@ -672,13 +672,7 @@ void CNSSolver::BC_Isothermal_Wall_Generic(CGeometry *geometry, CSolver **solver const auto Coord_i = geometry->nodes->GetCoord(iPoint); const auto Coord_j = geometry->nodes->GetCoord(Point_Normal); - su2double Vec_ij[MAXNDIM] = {0.0}; - GeometryToolbox::Distance(nDim, Coord_i, Coord_j, Vec_ij); - - /*--- Prevent divisions by 0 by limiting the normal projection. ---*/ - const su2double dist_ij = fmax( - fabs(GeometryToolbox::DotProduct(int(MAXNDIM), Vec_ij, UnitNormal)), - fmax(0.05 * GeometryToolbox::Norm(int(MAXNDIM), Vec_ij), EPS)); + const su2double dist_ij = GeometryToolbox::NormalDistance(nDim, UnitNormal, Coord_i, Coord_j); /*--- Store the corrected velocity at the wall which will be zero (v = 0), unless there is grid motion (v = u_wall)---*/ From 82ac79102671c041c339668316ff2177f1419ecd Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sun, 15 Dec 2024 13:40:19 -0800 Subject: [PATCH 048/129] update tests --- TestCases/hybrid_regression.py | 34 +++++++++++----------- TestCases/hybrid_regression_AD.py | 4 +-- TestCases/parallel_regression.py | 44 ++++++++++++++--------------- TestCases/parallel_regression_AD.py | 4 +-- TestCases/serial_regression.py | 42 +++++++++++++-------------- TestCases/serial_regression_AD.py | 4 +-- 6 files changed, 66 insertions(+), 66 deletions(-) diff --git a/TestCases/hybrid_regression.py b/TestCases/hybrid_regression.py index fe2634fb2a5..a5fbd5961b6 100644 --- a/TestCases/hybrid_regression.py +++ b/TestCases/hybrid_regression.py @@ -103,7 +103,7 @@ def main(): flatplate.cfg_dir = "navierstokes/flatplate" flatplate.cfg_file = "lam_flatplate.cfg" flatplate.test_iter = 100 - flatplate.test_vals = [-7.679131, -2.206953, 0.001084, 0.036233, 2.361500, -2.325300, -1.984700, -1.984700] + flatplate.test_vals = [-7.679131, -2.206953, 0.001084, 0.036233, 2.361500, -2.325300, 0, 0] test_list.append(flatplate) # Laminar cylinder (steady) @@ -111,7 +111,7 @@ def main(): cylinder.cfg_dir = "navierstokes/cylinder" cylinder.cfg_file = "lam_cylinder.cfg" cylinder.test_iter = 25 - cylinder.test_vals = [-8.266513, -2.783904, -0.019899, 1.615668, -0.010207] + cylinder.test_vals = [-8.266513, -2.783904, -0.019899, 1.615668, 0] test_list.append(cylinder) # Laminar cylinder (low Mach correction) @@ -119,8 +119,8 @@ def main(): cylinder_lowmach.cfg_dir = "navierstokes/cylinder" cylinder_lowmach.cfg_file = "cylinder_lowmach.cfg" cylinder_lowmach.test_iter = 25 - cylinder_lowmach.test_vals = [-6.830996, -1.368850, -0.143956, 73.963354, 0.002457] - cylinder_lowmach.test_vals_aarch64 = [-6.830996, -1.368850, -0.143956, 73.963354, 0.002457] + cylinder_lowmach.test_vals = [-6.830996, -1.368850, -0.143956, 73.963354, 0] + cylinder_lowmach.test_vals_aarch64 = [-6.830996, -1.368850, -0.143956, 73.963354, 0] test_list.append(cylinder_lowmach) # 2D Poiseuille flow (body force driven with periodic inlet / outlet) @@ -128,7 +128,7 @@ def main(): poiseuille.cfg_dir = "navierstokes/poiseuille" poiseuille.cfg_file = "lam_poiseuille.cfg" poiseuille.test_iter = 10 - poiseuille.test_vals = [-5.046131, 0.652984, 0.008355, 13.735818, -2.142500] + poiseuille.test_vals = [-5.046131, 0.652984, 0.008355, 13.735818, 0] test_list.append(poiseuille) # 2D Poiseuille flow (inlet profile file) @@ -157,7 +157,7 @@ def main(): rae2822_sa.cfg_dir = "rans/rae2822" rae2822_sa.cfg_file = "turb_SA_RAE2822.cfg" rae2822_sa.test_iter = 20 - rae2822_sa.test_vals = [-2.020123, -5.269324, 0.807147, 0.060499, -80602.000000] + rae2822_sa.test_vals = [-2.020123, -5.269324, 0.807147, 0.060499, 0] test_list.append(rae2822_sa) # RAE2822 SST @@ -165,7 +165,7 @@ def main(): rae2822_sst.cfg_dir = "rans/rae2822" rae2822_sst.cfg_file = "turb_SST_RAE2822.cfg" rae2822_sst.test_iter = 20 - rae2822_sst.test_vals = [-0.510363, 4.872736, 0.815617, 0.060920, -73391.000000] + rae2822_sst.test_vals = [-0.510363, 4.872736, 0.815617, 0.060920, 0] test_list.append(rae2822_sst) # RAE2822 SST_SUST @@ -189,7 +189,7 @@ def main(): turb_oneram6.cfg_dir = "rans/oneram6" turb_oneram6.cfg_file = "turb_ONERAM6.cfg" turb_oneram6.test_iter = 10 - turb_oneram6.test_vals = [-2.408523, -6.662833, 0.238333, 0.158910, -52718] + turb_oneram6.test_vals = [-2.408523, -6.662833, 0.238333, 0.158910, 0] test_list.append(turb_oneram6) # NACA0012 (SA, FUN3D finest grid results: CL=1.0983, CD=0.01242) @@ -197,8 +197,8 @@ def main(): turb_naca0012_sa.cfg_dir = "rans/naca0012" turb_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" turb_naca0012_sa.test_iter = 5 - turb_naca0012_sa.test_vals = [-12.098325, -14.149988, 1.057665, 0.022971, 20.000000, -2.292707, 0.000000, -12.068169, -44.871000] - turb_naca0012_sa.test_vals_aarch64 = [-12.098325, -14.149988, 1.057665, 0.022971, 20.000000, -2.292707, 0.000000, -12.068169, -44.871000] + turb_naca0012_sa.test_vals = [-12.098325, -14.149988, 1.057665, 0.022971, 20.000000, -2.292707, 0.000000, -12.068169, 0] + turb_naca0012_sa.test_vals_aarch64 = [-12.098325, -14.149988, 1.057665, 0.022971, 20.000000, -2.292707, 0.000000, -12.068169, 0] test_list.append(turb_naca0012_sa) # NACA0012 (SST, FUN3D finest grid results: CL=1.0840, CD=0.01253) @@ -206,7 +206,7 @@ def main(): turb_naca0012_sst.cfg_dir = "rans/naca0012" turb_naca0012_sst.cfg_file = "turb_NACA0012_sst.cfg" turb_naca0012_sst.test_iter = 10 - turb_naca0012_sst.test_vals = [-12.105781, -15.277738, -6.210248, 1.049757, 0.019249, -2.807857, -38.976000] + turb_naca0012_sst.test_vals = [-12.105781, -15.277738, -6.210248, 1.049757, 0.019249, -2.807857, 0] test_list.append(turb_naca0012_sst) # NACA0012 (SST_SUST, FUN3D finest grid results: CL=1.0840, CD=0.01253) @@ -250,7 +250,7 @@ def main(): axi_rans_air_nozzle_restart.cfg_dir = "axisymmetric_rans/air_nozzle" axi_rans_air_nozzle_restart.cfg_file = "air_nozzle_restart.cfg" axi_rans_air_nozzle_restart.test_iter = 10 - axi_rans_air_nozzle_restart.test_vals = [-12.070954, -7.407644, -8.698118, -4.008751, -3572.100000] + axi_rans_air_nozzle_restart.test_vals = [-12.070954, -7.407644, -8.698118, -4.008751, 0] test_list.append(axi_rans_air_nozzle_restart) ################################# @@ -381,8 +381,8 @@ def main(): inc_poly_cylinder.cfg_dir = "incomp_navierstokes/cylinder" inc_poly_cylinder.cfg_file = "poly_cylinder.cfg" inc_poly_cylinder.test_iter = 20 - inc_poly_cylinder.test_vals = [-7.851512, -2.093420, 0.029974, 1.921595, -175.300000] - inc_poly_cylinder.test_vals_aarch64 = [-7.851510, -2.093419, 0.029974, 1.921595, -175.300000] + inc_poly_cylinder.test_vals = [-7.827942, -2.061513, 0.029525, 1.953498, -174.780000] + inc_poly_cylinder.test_vals_aarch64 = [-7.827942, -2.061513, 0.029525, 1.953498, -174.780000] test_list.append(inc_poly_cylinder) # X-coarse laminar bend as a mixed element CGNS test @@ -452,8 +452,8 @@ def main(): square_cylinder.cfg_dir = "unsteady/square_cylinder" square_cylinder.cfg_file = "turb_square.cfg" square_cylinder.test_iter = 3 - square_cylinder.test_vals = [-2.560839, -1.173497, 0.061188, 1.399403, 2.220575, 1.399351, 2.218781, -0.584690] - square_cylinder.test_vals_aarch64 = [-2.557902, -1.173574, 0.058050, 1.399794, 2.220402, 1.399748, 2.218604, -0.453270] + square_cylinder.test_vals = [-2.560839, -1.173497, 0.061188, 1.399403, 2.220575, 1.399351, 2.218781, 0] + square_cylinder.test_vals_aarch64 = [-2.557902, -1.173574, 0.058050, 1.399794, 2.220402, 1.399748, 2.218604, 0] square_cylinder.unsteady = True test_list.append(square_cylinder) @@ -503,7 +503,7 @@ def main(): ddes_flatplate.cfg_dir = "ddes/flatplate" ddes_flatplate.cfg_file = "ddes_flatplate.cfg" ddes_flatplate.test_iter = 10 - ddes_flatplate.test_vals = [-2.714785, -5.882681, -0.215041, 0.023758, -617.440000] + ddes_flatplate.test_vals = [-2.714785, -5.882681, -0.215041, 0.023758, 0] ddes_flatplate.unsteady = True test_list.append(ddes_flatplate) diff --git a/TestCases/hybrid_regression_AD.py b/TestCases/hybrid_regression_AD.py index a0e29d54c84..3cc8adf1a68 100644 --- a/TestCases/hybrid_regression_AD.py +++ b/TestCases/hybrid_regression_AD.py @@ -110,8 +110,8 @@ def main(): discadj_incomp_cylinder.cfg_dir = "disc_adj_incomp_navierstokes/cylinder" discadj_incomp_cylinder.cfg_file = "heated_cylinder.cfg" discadj_incomp_cylinder.test_iter = 20 - discadj_incomp_cylinder.test_vals = [20.000000, -2.705921, -2.837904, 0.000000] - discadj_incomp_cylinder.test_vals_aarch64 = [20.000000, -2.705918, -2.837766, 0.000000] + discadj_incomp_cylinder.test_vals = [20.000000, -2.746353, -2.934792, 0.000000] + discadj_incomp_cylinder.test_vals_aarch64 = [20.000000, -2.746353, -2.934792, 0.000000] test_list.append(discadj_incomp_cylinder) ###################################### diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 5462560119e..e5f3f7ae029 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -303,7 +303,7 @@ def main(): flatplate.cfg_dir = "navierstokes/flatplate" flatplate.cfg_file = "lam_flatplate.cfg" flatplate.test_iter = 100 - flatplate.test_vals = [-7.613122, -2.140941, 0.001084, 0.036230, 2.361500, -2.325300, -1.975600, -1.975600] + flatplate.test_vals = [-7.613122, -2.140941, 0.001084, 0.036230, 2.361500, -2.325300, 0.000000, 0.000000] test_list.append(flatplate) # Custom objective function @@ -319,7 +319,7 @@ def main(): cylinder.cfg_dir = "navierstokes/cylinder" cylinder.cfg_file = "lam_cylinder.cfg" cylinder.test_iter = 25 - cylinder.test_vals = [-8.422091, -2.930561, -0.003396, 1.608418, -0.009920] + cylinder.test_vals = [-8.422091, -2.930561, -0.003396, 1.608418, 0.000000] test_list.append(cylinder) # Laminar cylinder (low Mach correction) @@ -327,7 +327,7 @@ def main(): cylinder_lowmach.cfg_dir = "navierstokes/cylinder" cylinder_lowmach.cfg_file = "cylinder_lowmach.cfg" cylinder_lowmach.test_iter = 25 - cylinder_lowmach.test_vals = [-6.841604, -1.379532, -1.266739, 76.118218, 0.000274] + cylinder_lowmach.test_vals = [-6.841604, -1.379532, -1.266739, 76.118218, 0.000000] test_list.append(cylinder_lowmach) # 2D Poiseuille flow (body force driven with periodic inlet / outlet) @@ -335,7 +335,7 @@ def main(): poiseuille.cfg_dir = "navierstokes/poiseuille" poiseuille.cfg_file = "lam_poiseuille.cfg" poiseuille.test_iter = 10 - poiseuille.test_vals = [-5.050889, 0.648196, 0.000199, 13.639173, -2.114500] + poiseuille.test_vals = [-5.050889, 0.648196, 0.000199, 13.639173, 0.000000] poiseuille.tol = 0.001 test_list.append(poiseuille) @@ -357,7 +357,7 @@ def main(): rae2822_sa.cfg_dir = "rans/rae2822" rae2822_sa.cfg_file = "turb_SA_RAE2822.cfg" rae2822_sa.test_iter = 20 - rae2822_sa.test_vals = [-2.004689, -5.265782, 0.809463, 0.062016, -80576.000000] + rae2822_sa.test_vals = [-2.004689, -5.265782, 0.809463, 0.062016, 0.000000] test_list.append(rae2822_sa) # RAE2822 SST @@ -365,7 +365,7 @@ def main(): rae2822_sst.cfg_dir = "rans/rae2822" rae2822_sst.cfg_file = "turb_SST_RAE2822.cfg" rae2822_sst.test_iter = 20 - rae2822_sst.test_vals = [-0.510369, 4.870643, 0.816647, 0.061833, -71779.000000] + rae2822_sst.test_vals = [-0.510369, 4.870643, 0.816647, 0.061833, 0.000000] test_list.append(rae2822_sst) # RAE2822 SST_SUST @@ -413,7 +413,7 @@ def main(): turb_oneram6.cfg_dir = "rans/oneram6" turb_oneram6.cfg_file = "turb_ONERAM6.cfg" turb_oneram6.test_iter = 10 - turb_oneram6.test_vals = [-2.408532, -6.662836, 0.238334, 0.158910, -52718] + turb_oneram6.test_vals = [-2.408532, -6.662836, 0.238334, 0.158910, 0] turb_oneram6.timeout = 3200 test_list.append(turb_oneram6) @@ -422,7 +422,7 @@ def main(): turb_oneram6_vc.cfg_dir = "rans/oneram6" turb_oneram6_vc.cfg_file = "turb_ONERAM6_vc.cfg" turb_oneram6_vc.test_iter = 15 - turb_oneram6_vc.test_vals = [-2.281896, -6.614616, 0.233785, 0.142861, -47942] + turb_oneram6_vc.test_vals = [-2.281896, -6.614616, 0.233785, 0.142861, 0] turb_oneram6_vc.timeout = 3200 test_list.append(turb_oneram6_vc) @@ -441,7 +441,7 @@ def main(): turb_naca0012_sa.cfg_dir = "rans/naca0012" turb_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" turb_naca0012_sa.test_iter = 5 - turb_naca0012_sa.test_vals = [-12.094721, -14.685268, 1.057665, 0.022971, 20.000000, -1.692925, 20.000000, -4.037672, -44.871000] + turb_naca0012_sa.test_vals = [-12.094721, -14.685268, 1.057665, 0.022971, 20.000000, -1.692925, 20.000000, -4.037672, 0] turb_naca0012_sa.timeout = 3200 test_list.append(turb_naca0012_sa) @@ -450,8 +450,8 @@ def main(): turb_naca0012_sst.cfg_dir = "rans/naca0012" turb_naca0012_sst.cfg_file = "turb_NACA0012_sst.cfg" turb_naca0012_sst.test_iter = 10 - turb_naca0012_sst.test_vals = [-12.107692, -15.277743, -6.210238, 1.049757, 0.019249, -2.357984, -38.976000] - turb_naca0012_sst.test_vals_aarch64 = [-12.107692, -15.277743, -6.210238, 1.049757, 0.019249, -2.357984, -38.976000] + turb_naca0012_sst.test_vals = [-12.107692, -15.277743, -6.210238, 1.049757, 0.019249, -2.357984, 0] + turb_naca0012_sst.test_vals_aarch64 = [-12.107692, -15.277743, -6.210238, 1.049757, 0.019249, -2.357984, 0] turb_naca0012_sst.timeout = 3200 test_list.append(turb_naca0012_sst) @@ -530,7 +530,7 @@ def main(): axi_rans_air_nozzle_restart.cfg_dir = "axisymmetric_rans/air_nozzle" axi_rans_air_nozzle_restart.cfg_file = "air_nozzle_restart.cfg" axi_rans_air_nozzle_restart.test_iter = 10 - axi_rans_air_nozzle_restart.test_vals = [-12.071395, -7.467871, -8.649076, -3.995810, -3572.100000] + axi_rans_air_nozzle_restart.test_vals = [-12.071395, -7.467871, -8.649076, -3.995810, 0] axi_rans_air_nozzle_restart.tol = 0.0001 test_list.append(axi_rans_air_nozzle_restart) @@ -602,7 +602,7 @@ def main(): inc_poly_cylinder.cfg_dir = "incomp_navierstokes/cylinder" inc_poly_cylinder.cfg_file = "poly_cylinder.cfg" inc_poly_cylinder.test_iter = 20 - inc_poly_cylinder.test_vals = [-7.791831, -2.062292, 0.013040, 1.913997, -171.120000] + inc_poly_cylinder.test_vals = [-7.786564, -2.036735, 0.012980, 1.944887, -170.930000] test_list.append(inc_poly_cylinder) # X-coarse laminar bend as a mixed element CGNS test @@ -732,8 +732,8 @@ def main(): turbmod_sa_neg_rae2822.cfg_dir = "turbulence_models/sa/rae2822" turbmod_sa_neg_rae2822.cfg_file = "turb_SA_NEG_RAE2822.cfg" turbmod_sa_neg_rae2822.test_iter = 10 - turbmod_sa_neg_rae2822.test_vals = [-1.466238, 3.169232, 2.756518, 4.722767, 1.120253, 0.378675, -83444.000000] - turbmod_sa_neg_rae2822.test_vals_aarch64 = [-1.359612, 1.493629, 1.218367, -1.441703, 1.248499, 0.457987, -86467.000000] + turbmod_sa_neg_rae2822.test_vals = [-1.466238, 3.169232, 2.756518, 4.722767, 1.120253, 0.378675, 0] + turbmod_sa_neg_rae2822.test_vals_aarch64 = [-1.359612, 1.493629, 1.218367, -1.441703, 1.248499, 0.457987, 0] test_list.append(turbmod_sa_neg_rae2822) # SA Compressibility Correction @@ -974,7 +974,7 @@ def main(): square_cylinder.cfg_dir = "unsteady/square_cylinder" square_cylinder.cfg_file = "turb_square.cfg" square_cylinder.test_iter = 3 - square_cylinder.test_vals = [-1.173495, 0.061186, 1.399404, 2.220578, 1.399352, 2.218783, -0.584750] + square_cylinder.test_vals = [-1.173495, 0.061186, 1.399404, 2.220578, 1.399352, 2.218783, 0] square_cylinder.unsteady = True test_list.append(square_cylinder) @@ -1001,7 +1001,7 @@ def main(): ddes_flatplate.cfg_dir = "ddes/flatplate" ddes_flatplate.cfg_file = "ddes_flatplate.cfg" ddes_flatplate.test_iter = 10 - ddes_flatplate.test_vals = [-2.714785, -5.882679, -0.215041, 0.023758, -617.450000] + ddes_flatplate.test_vals = [-2.714785, -5.882679, -0.215041, 0.023758, 0] ddes_flatplate.unsteady = True test_list.append(ddes_flatplate) @@ -1282,7 +1282,7 @@ def main(): p1rad.cfg_dir = "radiation/p1model" p1rad.cfg_file = "configp1.cfg" p1rad.test_iter = 100 - p1rad.test_vals = [-7.743666, -7.921411, -2.111848, 0.098302, -45.023000] + p1rad.test_vals = [-7.743666, -7.921411, -2.111848, 0.098302, -47.897000] test_list.append(p1rad) @@ -1359,8 +1359,8 @@ def main(): pywrapper_turb_naca0012_sst.cfg_dir = "rans/naca0012" pywrapper_turb_naca0012_sst.cfg_file = "turb_NACA0012_sst.cfg" pywrapper_turb_naca0012_sst.test_iter = 10 - pywrapper_turb_naca0012_sst.test_vals = [-12.107692, -15.277743, -6.210238, 1.049757, 0.019249, -2.357984, -38.976000] - pywrapper_turb_naca0012_sst.test_vals_aarch64 = [-12.107692, -15.277743, -6.210238, 1.049757, 0.019249, -2.357984, -38.976000] + pywrapper_turb_naca0012_sst.test_vals = [-12.107692, -15.277743, -6.210238, 1.049757, 0.019249, -2.357984, 0] + pywrapper_turb_naca0012_sst.test_vals_aarch64 = [-12.107692, -15.277743, -6.210238, 1.049757, 0.019249, -2.357984, 0] pywrapper_turb_naca0012_sst.command = TestCase.Command("mpirun -np 2", "SU2_CFD.py", "--parallel -f") pywrapper_turb_naca0012_sst.timeout = 3200 test_list.append(pywrapper_turb_naca0012_sst) @@ -1370,7 +1370,7 @@ def main(): pywrapper_square_cylinder.cfg_dir = "unsteady/square_cylinder" pywrapper_square_cylinder.cfg_file = "turb_square.cfg" pywrapper_square_cylinder.test_iter = 10 - pywrapper_square_cylinder.test_vals = [-1.176405, -0.354027, 1.407859, 2.360784, 1.404715, 2.302615, -0.394750] + pywrapper_square_cylinder.test_vals = [-1.176405, -0.354027, 1.407859, 2.360784, 1.404715, 2.302615, 0] pywrapper_square_cylinder.command = TestCase.Command("mpirun -np 2", "SU2_CFD.py", "--parallel -f") pywrapper_square_cylinder.unsteady = True test_list.append(pywrapper_square_cylinder) @@ -1422,7 +1422,7 @@ def main(): pywrapper_unsteadyCHT.cfg_dir = "py_wrapper/flatPlate_unsteady_CHT" pywrapper_unsteadyCHT.cfg_file = "unsteady_CHT_FlatPlate_Conf.cfg" pywrapper_unsteadyCHT.test_iter = 5 - pywrapper_unsteadyCHT.test_vals = [-1.614167, 2.240663, -0.001316, 0.177491] + pywrapper_unsteadyCHT.test_vals = [-1.614167, 2.240663, -0.001392, 0.177499] pywrapper_unsteadyCHT.command = TestCase.Command("mpirun -np 2", "python", "launch_unsteady_CHT_FlatPlate.py --parallel -f") pywrapper_unsteadyCHT.unsteady = True test_list.append(pywrapper_unsteadyCHT) diff --git a/TestCases/parallel_regression_AD.py b/TestCases/parallel_regression_AD.py index 7d0f0d10049..dbc1ee9bd9b 100644 --- a/TestCases/parallel_regression_AD.py +++ b/TestCases/parallel_regression_AD.py @@ -116,7 +116,7 @@ def main(): discadj_incomp_cylinder.cfg_dir = "disc_adj_incomp_navierstokes/cylinder" discadj_incomp_cylinder.cfg_file = "heated_cylinder.cfg" discadj_incomp_cylinder.test_iter = 20 - discadj_incomp_cylinder.test_vals = [20.000000, -2.195581, -2.162081, 0.000000] + discadj_incomp_cylinder.test_vals = [20.000000, -2.082673, -2.013587, 0.000000] test_list.append(discadj_incomp_cylinder) ###################################### @@ -256,7 +256,7 @@ def main(): discadj_heat.cfg_dir = "disc_adj_heat" discadj_heat.cfg_file = "disc_adj_heat.cfg" discadj_heat.test_iter = 10 - discadj_heat.test_vals = [-2.117791, 0.784475, 0.000000, -0.574700] + discadj_heat.test_vals = [-1.840132, 0.751835, 0.000000, 0.006760] discadj_heat.test_vals_aarch64 = [-2.226539, 0.605868, 0.000000, -6.256400] test_list.append(discadj_heat) diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 10312c92cc3..0ea5038cfc5 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -166,7 +166,7 @@ def main(): flatplate.cfg_dir = "navierstokes/flatplate" flatplate.cfg_file = "lam_flatplate.cfg" flatplate.test_iter = 20 - flatplate.test_vals = [-5.097707, 0.381809, 0.001324, 0.027932, 2.361600, -2.333600, -2.845200, -2.845200] + flatplate.test_vals = [-5.097707, 0.381809, 0.001324, 0.027932, 2.361600, -2.333600, 0, 0] test_list.append(flatplate) # Laminar cylinder (steady) @@ -174,7 +174,7 @@ def main(): cylinder.cfg_dir = "navierstokes/cylinder" cylinder.cfg_file = "lam_cylinder.cfg" cylinder.test_iter = 25 - cylinder.test_vals = [-8.363995, -2.882536, -0.017780, 1.607979, -0.010080] + cylinder.test_vals = [-8.363995, -2.882536, -0.017780, 1.607979, 0] test_list.append(cylinder) # Laminar cylinder (low Mach correction) @@ -182,7 +182,7 @@ def main(): cylinder_lowmach.cfg_dir = "navierstokes/cylinder" cylinder_lowmach.cfg_file = "cylinder_lowmach.cfg" cylinder_lowmach.test_iter = 25 - cylinder_lowmach.test_vals = [-6.830989, -1.368842, -0.143838, 73.962440, 0.002454] + cylinder_lowmach.test_vals = [-6.830989, -1.368842, -0.143838, 73.962440, 0] test_list.append(cylinder_lowmach) # 2D Poiseuille flow (body force driven with periodic inlet / outlet) @@ -190,7 +190,7 @@ def main(): poiseuille.cfg_dir = "navierstokes/poiseuille" poiseuille.cfg_file = "lam_poiseuille.cfg" poiseuille.test_iter = 10 - poiseuille.test_vals = [-5.050753, 0.648333, 0.012273, 13.643141, -2.114700] + poiseuille.test_vals = [-5.050753, 0.648333, 0.012273, 13.643141, 0] test_list.append(poiseuille) # 2D Poiseuille flow (inlet profile file) @@ -218,7 +218,7 @@ def main(): rae2822_sa.cfg_dir = "rans/rae2822" rae2822_sa.cfg_file = "turb_SA_RAE2822.cfg" rae2822_sa.test_iter = 20 - rae2822_sa.test_vals = [-2.020123, -5.269324, 0.807147, 0.060499, -80602.000000] + rae2822_sa.test_vals = [-2.020123, -5.269324, 0.807147, 0.060499, 0] test_list.append(rae2822_sa) # RAE2822 SST @@ -226,7 +226,7 @@ def main(): rae2822_sst.cfg_dir = "rans/rae2822" rae2822_sst.cfg_file = "turb_SST_RAE2822.cfg" rae2822_sst.test_iter = 20 - rae2822_sst.test_vals = [-0.510376, 4.873617, 0.816197, 0.060504, -71886.000000] + rae2822_sst.test_vals = [-0.510376, 4.873617, 0.816197, 0.060504, 0] test_list.append(rae2822_sst) # RAE2822 SST_SUST @@ -266,7 +266,7 @@ def main(): turb_oneram6.cfg_dir = "rans/oneram6" turb_oneram6.cfg_file = "turb_ONERAM6.cfg" turb_oneram6.test_iter = 10 - turb_oneram6.test_vals = [-2.408533, -6.662837, 0.238334, 0.158910, -52718] + turb_oneram6.test_vals = [-2.408533, -6.662837, 0.238334, 0.158910, 0] turb_oneram6.timeout = 3200 test_list.append(turb_oneram6) @@ -275,7 +275,7 @@ def main(): turb_naca0012_sa.cfg_dir = "rans/naca0012" turb_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" turb_naca0012_sa.test_iter = 5 - turb_naca0012_sa.test_vals = [-12.091696, -14.685322, 1.057665, 0.022971, 20.000000, -2.686306, 20.000000, -4.459916, -44.871000] + turb_naca0012_sa.test_vals = [-12.091696, -14.685322, 1.057665, 0.022971, 20.000000, -2.686306, 20.000000, -4.459916, 0] turb_naca0012_sa.timeout = 3200 test_list.append(turb_naca0012_sa) @@ -284,8 +284,8 @@ def main(): turb_naca0012_sst.cfg_dir = "rans/naca0012" turb_naca0012_sst.cfg_file = "turb_NACA0012_sst.cfg" turb_naca0012_sst.test_iter = 10 - turb_naca0012_sst.test_vals = [-12.107132, -15.277740, -6.210248, 1.049757, 0.019249, -3.173936, -38.97600] - turb_naca0012_sst.test_vals_aarch64 = [-12.107132, -15.277740, -6.210248, 1.049757, 0.019249, -3.173936, -38.97600] + turb_naca0012_sst.test_vals = [-12.107132, -15.277740, -6.210248, 1.049757, 0.019249, -3.173936, 0] + turb_naca0012_sst.test_vals_aarch64 = [-12.107132, -15.277740, -6.210248, 1.049757, 0.019249, -3.173936, 0] turb_naca0012_sst.timeout = 3200 test_list.append(turb_naca0012_sst) @@ -294,7 +294,7 @@ def main(): turb_naca0012_sst_2003m.cfg_dir = "rans/naca0012" turb_naca0012_sst_2003m.cfg_file = "turb_NACA0012_sst_2003m.cfg" turb_naca0012_sst_2003m.test_iter = 10 - turb_naca0012_sst_2003m.test_vals = [-7.688139, -10.046053, -3.410061, 1.048970, 0.019798, -2.208236, -45.678000] + turb_naca0012_sst_2003m.test_vals = [-7.688139, -10.046053, -3.410061, 1.048970, 0.019798, -2.208236, 0] turb_naca0012_sst_2003m.timeout = 3200 test_list.append(turb_naca0012_sst_2003m) @@ -335,8 +335,8 @@ def main(): axi_rans_air_nozzle_restart.cfg_dir = "axisymmetric_rans/air_nozzle" axi_rans_air_nozzle_restart.cfg_file = "air_nozzle_restart.cfg" axi_rans_air_nozzle_restart.test_iter = 10 - axi_rans_air_nozzle_restart.test_vals = [-12.071702, -7.474599, -8.646498, -3.988633, -3572.100000] - axi_rans_air_nozzle_restart.test_vals_aarch64 = [-12.071702, -7.474599, -8.646498, -3.988633, -3572.100000] + axi_rans_air_nozzle_restart.test_vals = [-12.071702, -7.474599, -8.646498, -3.988633, 0] + axi_rans_air_nozzle_restart.test_vals_aarch64 = [-12.071702, -7.474599, -8.646498, -3.988633, 0] axi_rans_air_nozzle_restart.tol = 0.0001 test_list.append(axi_rans_air_nozzle_restart) @@ -414,7 +414,7 @@ def main(): inc_poly_cylinder.cfg_dir = "incomp_navierstokes/cylinder" inc_poly_cylinder.cfg_file = "poly_cylinder.cfg" inc_poly_cylinder.test_iter = 20 - inc_poly_cylinder.test_vals = [-8.106741, -2.160042, 0.019225, 1.902421, -172.750000] + inc_poly_cylinder.test_vals = [-8.083556, -2.134369, 0.018999, 1.932938, -173.730000] test_list.append(inc_poly_cylinder) # X-coarse laminar bend as a mixed element CGNS test @@ -457,7 +457,7 @@ def main(): inc_turb_wallfunction_flatplate_sst.cfg_dir = "wallfunctions/flatplate/incompressible_SST" inc_turb_wallfunction_flatplate_sst.cfg_file = "turb_SST_flatplate.cfg" inc_turb_wallfunction_flatplate_sst.test_iter = 10 - inc_turb_wallfunction_flatplate_sst.test_vals = [-6.507362, -5.693894, -6.434063, -4.223774, -7.008049, -1.954102, 10.000000, -3.047554, 0.001081, 0.003644, 0.618140] + inc_turb_wallfunction_flatplate_sst.test_vals = [-6.507362, -5.693894, -6.434063, -4.223774, -7.008049, -1.954102, 10.000000, -3.047554, 0.001081, 0.003644, 0] test_list.append(inc_turb_wallfunction_flatplate_sst) # FLAT PLATE, WALL FUNCTIONS, INCOMPRESSIBLE SA @@ -769,7 +769,7 @@ def main(): square_cylinder.cfg_dir = "unsteady/square_cylinder" square_cylinder.cfg_file = "turb_square.cfg" square_cylinder.test_iter = 3 - square_cylinder.test_vals = [-2.560840, -1.173495, 0.061186, 1.399403, 2.220585, 1.399351, 2.218790, -0.584750] + square_cylinder.test_vals = [-2.560840, -1.173495, 0.061186, 1.399403, 2.220585, 1.399351, 2.218790, 0] square_cylinder.unsteady = True test_list.append(square_cylinder) @@ -796,7 +796,7 @@ def main(): ddes_flatplate.cfg_dir = "ddes/flatplate" ddes_flatplate.cfg_file = "ddes_flatplate.cfg" ddes_flatplate.test_iter = 10 - ddes_flatplate.test_vals = [-2.714785, -5.882680, -0.215041, 0.023758, -617.450000] + ddes_flatplate.test_vals = [-2.714785, -5.882680, -0.215041, 0.023758, 0] ddes_flatplate.unsteady = True test_list.append(ddes_flatplate) @@ -1093,7 +1093,7 @@ def main(): p1rad.cfg_dir = "radiation/p1model" p1rad.cfg_file = "configp1.cfg" p1rad.test_iter = 100 - p1rad.test_vals = [-7.751309, -7.923059, -2.119084, 0.091733, -44.537000] + p1rad.test_vals = [-7.751309, -7.923059, -2.119084, 0.091733, -47.387000] test_list.append(p1rad) # ############################### @@ -1520,8 +1520,8 @@ def main(): pywrapper_turb_naca0012_sst.cfg_dir = "rans/naca0012" pywrapper_turb_naca0012_sst.cfg_file = "turb_NACA0012_sst.cfg" pywrapper_turb_naca0012_sst.test_iter = 10 - pywrapper_turb_naca0012_sst.test_vals = [-12.107132, -15.277740, -6.210248, 1.049757, 0.019249, -3.173936, -38.976000] - pywrapper_turb_naca0012_sst.test_vals_aarch64 = [-12.107132, -15.277740, -6.210248, 1.049757, 0.019249, -3.173936, -38.976000] + pywrapper_turb_naca0012_sst.test_vals = [-12.107132, -15.277740, -6.210248, 1.049757, 0.019249, -3.173936, 0] + pywrapper_turb_naca0012_sst.test_vals_aarch64 = [-12.107132, -15.277740, -6.210248, 1.049757, 0.019249, -3.173936, 0] pywrapper_turb_naca0012_sst.command = TestCase.Command(exec = "SU2_CFD.py", param = "-f") pywrapper_turb_naca0012_sst.timeout = 3200 pywrapper_turb_naca0012_sst.tol = 0.00001 @@ -1534,7 +1534,7 @@ def main(): pywrapper_square_cylinder.cfg_dir = "unsteady/square_cylinder" pywrapper_square_cylinder.cfg_file = "turb_square.cfg" pywrapper_square_cylinder.test_iter = 3 - pywrapper_square_cylinder.test_vals = [-2.560840, -1.173495, 0.061186, 1.399403, 2.220585, 1.399351, 2.218790, -0.584750] + pywrapper_square_cylinder.test_vals = [-2.560840, -1.173495, 0.061186, 1.399403, 2.220585, 1.399351, 2.218790, 0] pywrapper_square_cylinder.command = TestCase.Command(exec = "SU2_CFD.py", param = "-f") pywrapper_square_cylinder.timeout = 1600 pywrapper_square_cylinder.tol = 0.00001 diff --git a/TestCases/serial_regression_AD.py b/TestCases/serial_regression_AD.py index 9817708b300..9bca48cd310 100644 --- a/TestCases/serial_regression_AD.py +++ b/TestCases/serial_regression_AD.py @@ -110,7 +110,7 @@ def main(): discadj_incomp_cylinder.cfg_dir = "disc_adj_incomp_navierstokes/cylinder" discadj_incomp_cylinder.cfg_file = "heated_cylinder.cfg" discadj_incomp_cylinder.test_iter = 20 - discadj_incomp_cylinder.test_vals = [20.000000, -2.373367, -2.368305, 0.000000] + discadj_incomp_cylinder.test_vals = [20.000000, -2.386480, -2.408986, 0.000000] test_list.append(discadj_incomp_cylinder) ####################################################### @@ -183,7 +183,7 @@ def main(): discadj_heat.cfg_dir = "disc_adj_heat" discadj_heat.cfg_file = "disc_adj_heat.cfg" discadj_heat.test_iter = 10 - discadj_heat.test_vals = [-2.122406, 0.693852, 0.000000, -0.869010] + discadj_heat.test_vals = [-1.956349, 0.722272, 0.000000, 0.007024] test_list.append(discadj_heat) ################################### From d476c8ba2b634dadfe39ab56667702abd9c322d5 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sun, 15 Dec 2024 20:36:26 -0800 Subject: [PATCH 049/129] update file regression --- .../include/solvers/CFVMFlowSolverBase.inl | 9 +- SU2_CFD/src/solvers/CIncNSSolver.cpp | 11 +- .../radiation/p1adjoint/of_grad_cd.csv.ref | 100 +++++++++--------- 3 files changed, 59 insertions(+), 61 deletions(-) diff --git a/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl b/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl index 40206768e4c..d7a634e8227 100644 --- a/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl +++ b/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl @@ -2357,8 +2357,6 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr const su2double *Coord = nullptr, *Coord_Normal = nullptr, *Normal = nullptr; const su2double minYPlus = config->GetwallModel_MinYPlus(); - string Marker_Tag, Monitoring_Tag; - const su2double Alpha = config->GetAoA() * PI_NUMBER / 180.0; const su2double Beta = config->GetAoS() * PI_NUMBER / 180.0; const su2double RefLength = config->GetRefLength(); @@ -2394,8 +2392,8 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr for (iMarker = 0; iMarker < nMarker; iMarker++) { - Marker_Tag = config->GetMarker_All_TagBound(iMarker); if (!config->GetViscous_Wall(iMarker)) continue; + const auto Marker_Tag = config->GetMarker_All_TagBound(iMarker); const bool py_custom = config->GetMarker_All_PyCustom(iMarker); @@ -2404,7 +2402,7 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr const auto Monitoring = config->GetMarker_All_Monitoring(iMarker); if (Monitoring == YES) { for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring); + const auto Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring); if (Marker_Tag == Monitoring_Tag) Origin = config->GetRefOriginMoment(iMarker_Monitoring); } } @@ -2677,8 +2675,7 @@ void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometr /*--- Compute the coefficients per surface ---*/ for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring); - Marker_Tag = config->GetMarker_All_TagBound(iMarker); + const auto Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring); if (Marker_Tag == Monitoring_Tag) { SurfaceViscCoeff.CL[iMarker_Monitoring] += ViscCoeff.CL[iMarker]; SurfaceViscCoeff.CD[iMarker_Monitoring] += ViscCoeff.CD[iMarker]; diff --git a/SU2_CFD/src/solvers/CIncNSSolver.cpp b/SU2_CFD/src/solvers/CIncNSSolver.cpp index 8db972191c3..e0a4fda96ef 100644 --- a/SU2_CFD/src/solvers/CIncNSSolver.cpp +++ b/SU2_CFD/src/solvers/CIncNSSolver.cpp @@ -341,7 +341,6 @@ void CIncNSSolver::BC_Wall_Generic(const CGeometry *geometry, const CConfig *con /*--- Variables for streamwise periodicity ---*/ const bool streamwise_periodic = (config->GetKind_Streamwise_Periodic() != ENUM_STREAMWISE_PERIODIC::NONE); const bool streamwise_periodic_temperature = config->GetStreamwise_Periodic_Temperature(); - su2double Cp, thermal_conductivity, dot_product, scalar_factor; /*--- Identify the boundary by string name ---*/ @@ -434,15 +433,17 @@ void CIncNSSolver::BC_Wall_Generic(const CGeometry *geometry, const CConfig *con /*--- With streamwise periodic flow and heatflux walls an additional term is introduced in the boundary formulation ---*/ if (streamwise_periodic && streamwise_periodic_temperature) { - Cp = nodes->GetSpecificHeatCp(iPoint); - thermal_conductivity = nodes->GetThermalConductivity(iPoint); + const su2double Cp = nodes->GetSpecificHeatCp(iPoint); + const su2double thermal_conductivity = nodes->GetThermalConductivity(iPoint); /*--- Scalar factor of the residual contribution ---*/ const su2double norm2_translation = GeometryToolbox::SquaredNorm(nDim, config->GetPeriodic_Translation(0)); - scalar_factor = SPvals.Streamwise_Periodic_IntegratedHeatFlow*thermal_conductivity / (SPvals.Streamwise_Periodic_MassFlow * Cp * norm2_translation); + const su2double scalar_factor = + SPvals.Streamwise_Periodic_IntegratedHeatFlow*thermal_conductivity / + (SPvals.Streamwise_Periodic_MassFlow * Cp * norm2_translation); /*--- Dot product ---*/ - dot_product = GeometryToolbox::DotProduct(nDim, config->GetPeriodic_Translation(0), Normal); + const su2double dot_product = GeometryToolbox::DotProduct(nDim, config->GetPeriodic_Translation(0), Normal); LinSysRes(iPoint, nDim+1) += scalar_factor*dot_product; } // if streamwise_periodic diff --git a/TestCases/radiation/p1adjoint/of_grad_cd.csv.ref b/TestCases/radiation/p1adjoint/of_grad_cd.csv.ref index 8c422aae719..0d3e4c92dbc 100644 --- a/TestCases/radiation/p1adjoint/of_grad_cd.csv.ref +++ b/TestCases/radiation/p1adjoint/of_grad_cd.csv.ref @@ -1,51 +1,51 @@ "VARIABLE" , "GRADIENT" , "FINDIFF_STEP" -0 , -0.000954218 , 0.001 -1 , -0.00432384 , 0.001 -2 , -0.0111485 , 0.001 -3 , -0.0214656 , 0.001 -4 , -0.0344212 , 0.001 -5 , -0.0490221 , 0.001 -6 , -0.0643278 , 0.001 -7 , -0.0792041 , 0.001 -8 , -0.0924318 , 0.001 -9 , -0.103025 , 0.001 -10 , -0.110239 , 0.001 -11 , -0.113383 , 0.001 -12 , -0.111898 , 0.001 -13 , -0.105745 , 0.001 -14 , -0.0956773 , 0.001 -15 , -0.0830288 , 0.001 -16 , -0.069201 , 0.001 -17 , -0.0553022 , 0.001 -18 , -0.0421316 , 0.001 -19 , -0.0303252 , 0.001 -20 , -0.0203976 , 0.001 -21 , -0.0126387 , 0.001 -22 , -0.00701749 , 0.001 -23 , -0.0032361 , 0.001 -24 , -0.000955756 , 0.001 -25 , 0.00128953 , 0.001 -26 , 0.00518424 , 0.001 -27 , 0.0125712 , 0.001 -28 , 0.0234942 , 0.001 -29 , 0.0370801 , 0.001 -30 , 0.052231 , 0.001 -31 , 0.06787 , 0.001 -32 , 0.0827503 , 0.001 -33 , 0.0955927 , 0.001 -34 , 0.105415 , 0.001 -35 , 0.11154 , 0.001 -36 , 0.113399 , 0.001 -37 , 0.110583 , 0.001 -38 , 0.103215 , 0.001 -39 , 0.0921957 , 0.001 -40 , 0.0789703 , 0.001 -41 , 0.0650043 , 0.001 -42 , 0.0514107 , 0.001 -43 , 0.0389322 , 0.001 -44 , 0.0280921 , 0.001 -45 , 0.0192441 , 0.001 -46 , 0.0124768 , 0.001 -47 , 0.00752972 , 0.001 -48 , 0.00391057 , 0.001 -49 , 0.00131276 , 0.001 +0 , -0.000958205 , 0.001 +1 , -0.00432733 , 0.001 +2 , -0.0111443 , 0.001 +3 , -0.0214515 , 0.001 +4 , -0.0343997 , 0.001 +5 , -0.0489968 , 0.001 +6 , -0.0643023 , 0.001 +7 , -0.0791818 , 0.001 +8 , -0.092416 , 0.001 +9 , -0.103017 , 0.001 +10 , -0.11024 , 0.001 +11 , -0.113392 , 0.001 +12 , -0.111913 , 0.001 +13 , -0.105766 , 0.001 +14 , -0.0957015 , 0.001 +15 , -0.0830517 , 0.001 +16 , -0.0692182 , 0.001 +17 , -0.0553101 , 0.001 +18 , -0.042129 , 0.001 +19 , -0.0303137 , 0.001 +20 , -0.0203813 , 0.001 +21 , -0.0126226 , 0.001 +22 , -0.00700441 , 0.001 +23 , -0.00322726 , 0.001 +24 , -0.000951904 , 0.001 +25 , 0.00128803 , 0.001 +26 , 0.0051774 , 0.001 +27 , 0.0125547 , 0.001 +28 , 0.0234674 , 0.001 +29 , 0.0370465 , 0.001 +30 , 0.0521956 , 0.001 +31 , 0.0678379 , 0.001 +32 , 0.0827257 , 0.001 +33 , 0.0955787 , 0.001 +34 , 0.105412 , 0.001 +35 , 0.111548 , 0.001 +36 , 0.113415 , 0.001 +37 , 0.110605 , 0.001 +38 , 0.103242 , 0.001 +39 , 0.0922244 , 0.001 +40 , 0.0789963 , 0.001 +41 , 0.0650234 , 0.001 +42 , 0.0514199 , 0.001 +43 , 0.0389312 , 0.001 +44 , 0.0280831 , 0.001 +45 , 0.0192316 , 0.001 +46 , 0.0124655 , 0.001 +47 , 0.00752232 , 0.001 +48 , 0.0039072 , 0.001 +49 , 0.00131195 , 0.001 From bc59826ee2a4ac70a8fbaac45a966f61d61dd949 Mon Sep 17 00:00:00 2001 From: emaberman Date: Wed, 18 Dec 2024 20:38:55 +0200 Subject: [PATCH 050/129] Fix regression testing --- TestCases/hybrid_regression.py | 10 +++++----- TestCases/parallel_regression.py | 28 ++++++++++++++-------------- TestCases/parallel_regression_AD.py | 4 ++-- TestCases/serial_regression.py | 16 ++++++++-------- TestCases/serial_regression_AD.py | 2 +- TestCases/tutorials.py | 6 +++--- TestCases/vandv.py | 4 ++-- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/TestCases/hybrid_regression.py b/TestCases/hybrid_regression.py index fe2634fb2a5..e5b0a847e61 100644 --- a/TestCases/hybrid_regression.py +++ b/TestCases/hybrid_regression.py @@ -157,7 +157,7 @@ def main(): rae2822_sa.cfg_dir = "rans/rae2822" rae2822_sa.cfg_file = "turb_SA_RAE2822.cfg" rae2822_sa.test_iter = 20 - rae2822_sa.test_vals = [-2.020123, -5.269324, 0.807147, 0.060499, -80602.000000] + rae2822_sa.test_vals = [-2.020123, -5.269339, 0.807147, 0.060499, -80603.000000] test_list.append(rae2822_sa) # RAE2822 SST @@ -181,7 +181,7 @@ def main(): turb_flatplate.cfg_dir = "rans/flatplate" turb_flatplate.cfg_file = "turb_SA_flatplate.cfg" turb_flatplate.test_iter = 20 - turb_flatplate.test_vals = [-4.312826, -6.736053, -0.187467, 0.057454] + turb_flatplate.test_vals = [-4.312725, -6.737976, -0.187467, 0.057468] test_list.append(turb_flatplate) # ONERA M6 Wing @@ -238,7 +238,7 @@ def main(): propeller.cfg_dir = "rans/propeller" propeller.cfg_file = "propeller.cfg" propeller.test_iter = 10 - propeller.test_vals = [-3.389724, -8.409223, 0.000048, 0.056344] + propeller.test_vals = [-3.389724, -8.409502, 0.000048, 0.056344] test_list.append(propeller) ####################################### @@ -403,7 +403,7 @@ def main(): inc_turb_naca0012.cfg_dir = "incomp_rans/naca0012" inc_turb_naca0012.cfg_file = "naca0012.cfg" inc_turb_naca0012.test_iter = 20 - inc_turb_naca0012.test_vals = [-4.788405, -11.039465, 0.000008, 0.309490] + inc_turb_naca0012.test_vals = [-4.788405, -11.040560, 0.000008, 0.309505] test_list.append(inc_turb_naca0012) # NACA0012, SST_SUST @@ -503,7 +503,7 @@ def main(): ddes_flatplate.cfg_dir = "ddes/flatplate" ddes_flatplate.cfg_file = "ddes_flatplate.cfg" ddes_flatplate.test_iter = 10 - ddes_flatplate.test_vals = [-2.714785, -5.882681, -0.215041, 0.023758, -617.440000] + ddes_flatplate.test_vals = [-2.714786, -5.882652, -0.215041, 0.023758, -617.470000] ddes_flatplate.unsteady = True test_list.append(ddes_flatplate) diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 5462560119e..f19b323f761 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -357,7 +357,7 @@ def main(): rae2822_sa.cfg_dir = "rans/rae2822" rae2822_sa.cfg_file = "turb_SA_RAE2822.cfg" rae2822_sa.test_iter = 20 - rae2822_sa.test_vals = [-2.004689, -5.265782, 0.809463, 0.062016, -80576.000000] + rae2822_sa.test_vals = [-2.004689, -5.265797, 0.809463, 0.062016, -80577.000000] test_list.append(rae2822_sa) # RAE2822 SST @@ -381,7 +381,7 @@ def main(): turb_flatplate.cfg_dir = "rans/flatplate" turb_flatplate.cfg_file = "turb_SA_flatplate.cfg" turb_flatplate.test_iter = 20 - turb_flatplate.test_vals = [-4.293562, -6.728390, -0.187643, 0.057686] + turb_flatplate.test_vals = [-4.293470, -6.730438, -0.187644, 0.057700] test_list.append(turb_flatplate) # Flat plate (compressible) with species inlet @@ -389,7 +389,7 @@ def main(): turb_flatplate_species.cfg_dir = "rans/flatplate" turb_flatplate_species.cfg_file = "turb_SA_flatplate_species.cfg" turb_flatplate_species.test_iter = 20 - turb_flatplate_species.test_vals = [-4.243136, -0.634954, -1.706721, 1.231179, -3.266212, 9.000000, -6.632862, 5.000000, -6.979197, 10.000000, -6.007240, 0.996237, 0.996237] + turb_flatplate_species.test_vals = [-4.243064, -0.634797, -1.706652, 1.231264, -3.266203, 9.000000, -6.632972, 5.000000, -6.985977, 10.000000, -6.007208, 0.996237, 0.996237] test_list.append(turb_flatplate_species) # Flat plate SST compressibility correction Wilcox @@ -431,7 +431,7 @@ def main(): turb_oneram6_nk.cfg_dir = "rans/oneram6" turb_oneram6_nk.cfg_file = "turb_ONERAM6_nk.cfg" turb_oneram6_nk.test_iter = 20 - turb_oneram6_nk.test_vals = [-4.843772, -4.444210, -11.473964, 0.216337, 0.049646, 5.000000, -0.613234, 23.568000] + turb_oneram6_nk.test_vals = [-4.851388, -4.457414, -11.468726, 0.217228, 0.049043, 5.000000, -0.533763, 23.567000] turb_oneram6_nk.timeout = 600 turb_oneram6_nk.tol = 0.0001 test_list.append(turb_oneram6_nk) @@ -441,7 +441,7 @@ def main(): turb_naca0012_sa.cfg_dir = "rans/naca0012" turb_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" turb_naca0012_sa.test_iter = 5 - turb_naca0012_sa.test_vals = [-12.094721, -14.685268, 1.057665, 0.022971, 20.000000, -1.692925, 20.000000, -4.037672, -44.871000] + turb_naca0012_sa.test_vals = [-12.094695, -14.685268, 1.057665, 0.022971, 20.000000, -1.692967, 20.000000, -4.037673, -44.871000] turb_naca0012_sa.timeout = 3200 test_list.append(turb_naca0012_sa) @@ -507,7 +507,7 @@ def main(): propeller.cfg_dir = "rans/propeller" propeller.cfg_file = "propeller.cfg" propeller.test_iter = 10 - propeller.test_vals = [-3.389724, -8.409223, 0.000048, 0.056344] + propeller.test_vals = [-3.389724, -8.409502, 0.000048, 0.056344] propeller.timeout = 3200 test_list.append(propeller) @@ -638,7 +638,7 @@ def main(): inc_turb_naca0012.cfg_dir = "incomp_rans/naca0012" inc_turb_naca0012.cfg_file = "naca0012.cfg" inc_turb_naca0012.test_iter = 20 - inc_turb_naca0012.test_vals = [-4.788596, -11.039529, -0.000002, 0.309504] + inc_turb_naca0012.test_vals = [-4.788595, -11.040625, -0.000002, 0.309519] test_list.append(inc_turb_naca0012) # NACA0012, SST_SUST @@ -724,7 +724,7 @@ def main(): turbmod_sa_bsl_rae2822.cfg_dir = "turbulence_models/sa/rae2822" turbmod_sa_bsl_rae2822.cfg_file = "turb_SA_BSL_RAE2822.cfg" turbmod_sa_bsl_rae2822.test_iter = 20 - turbmod_sa_bsl_rae2822.test_vals = [-2.004689, 0.742306, 0.497308, -5.265782, 0.809463, 0.062016] + turbmod_sa_bsl_rae2822.test_vals = [-2.004689, 0.742306, 0.497308, -5.265797, 0.809463, 0.062016] test_list.append(turbmod_sa_bsl_rae2822) # SA Negative @@ -732,7 +732,7 @@ def main(): turbmod_sa_neg_rae2822.cfg_dir = "turbulence_models/sa/rae2822" turbmod_sa_neg_rae2822.cfg_file = "turb_SA_NEG_RAE2822.cfg" turbmod_sa_neg_rae2822.test_iter = 10 - turbmod_sa_neg_rae2822.test_vals = [-1.466238, 3.169232, 2.756518, 4.722767, 1.120253, 0.378675, -83444.000000] + turbmod_sa_neg_rae2822.test_vals = [-1.204800, 1.611685, 1.349330, 1.489602, 1.263603, 0.466487, -83309.000000] turbmod_sa_neg_rae2822.test_vals_aarch64 = [-1.359612, 1.493629, 1.218367, -1.441703, 1.248499, 0.457987, -86467.000000] test_list.append(turbmod_sa_neg_rae2822) @@ -741,7 +741,7 @@ def main(): turbmod_sa_comp_rae2822.cfg_dir = "turbulence_models/sa/rae2822" turbmod_sa_comp_rae2822.cfg_file = "turb_SA_COMP_RAE2822.cfg" turbmod_sa_comp_rae2822.test_iter = 20 - turbmod_sa_comp_rae2822.test_vals = [-2.004687, 0.742304, 0.497309, -5.266067, 0.809467, 0.062029] + turbmod_sa_comp_rae2822.test_vals = [-2.004687, 0.742304, 0.497309, -5.266084, 0.809467, 0.062029] test_list.append(turbmod_sa_comp_rae2822) # SA Edwards @@ -765,7 +765,7 @@ def main(): turbmod_sa_qcr_rae2822.cfg_dir = "turbulence_models/sa/rae2822" turbmod_sa_qcr_rae2822.cfg_file = "turb_SA_QCR_RAE2822.cfg" turbmod_sa_qcr_rae2822.test_iter = 20 - turbmod_sa_qcr_rae2822.test_vals = [-2.004793, 0.742353, 0.497315, -5.265962, 0.807841, 0.062027] + turbmod_sa_qcr_rae2822.test_vals = [-2.004793, 0.742353, 0.497315, -5.265977, 0.807841, 0.062027] test_list.append(turbmod_sa_qcr_rae2822) ############################ @@ -1001,7 +1001,7 @@ def main(): ddes_flatplate.cfg_dir = "ddes/flatplate" ddes_flatplate.cfg_file = "ddes_flatplate.cfg" ddes_flatplate.test_iter = 10 - ddes_flatplate.test_vals = [-2.714785, -5.882679, -0.215041, 0.023758, -617.450000] + ddes_flatplate.test_vals = [-2.714786, -5.882637, -0.215041, 0.023758, -617.470000] ddes_flatplate.unsteady = True test_list.append(ddes_flatplate) @@ -1010,7 +1010,7 @@ def main(): unst_inc_turb_naca0015_sa.cfg_dir = "unsteady/pitching_naca0015_rans_inc" unst_inc_turb_naca0015_sa.cfg_file = "config_incomp_turb_sa.cfg" unst_inc_turb_naca0015_sa.test_iter = 1 - unst_inc_turb_naca0015_sa.test_vals = [-3.004012, -6.876220, 1.487882, 0.421861] + unst_inc_turb_naca0015_sa.test_vals = [-3.004011, -6.876250, 1.487888, 0.421869] unst_inc_turb_naca0015_sa.unsteady = True test_list.append(unst_inc_turb_naca0015_sa) @@ -1530,7 +1530,7 @@ def main(): species2_primitiveVenturi_mixingmodel_viscosity.cfg_dir = "species_transport/venturi_primitive_3species" species2_primitiveVenturi_mixingmodel_viscosity.cfg_file = "species2_primitiveVenturi_mixingmodel_viscosity.cfg" species2_primitiveVenturi_mixingmodel_viscosity.test_iter = 50 - species2_primitiveVenturi_mixingmodel_viscosity.test_vals = [-4.857397, -3.646605, -3.737462, -7.602922, -5.008846, 5.000000, -1.756226, 5.000000, -3.163353, 5.000000, -2.189723, 2.476808, 0.976999, 0.609280, 0.890529] + species2_primitiveVenturi_mixingmodel_viscosity.test_vals = [-4.857405, -3.646534, -3.737422, -7.602756, -5.008835, 5.000000, -1.756256, 5.000000, -3.163548, 5.000000, -2.189690, 2.476807, 0.977000, 0.609279, 0.890528] test_list.append(species2_primitiveVenturi_mixingmodel_viscosity) # 2 species (1 eq) primitive venturi mixing using mixing model including heat capacity and mass diffusivity diff --git a/TestCases/parallel_regression_AD.py b/TestCases/parallel_regression_AD.py index 7d0f0d10049..c549f753c0f 100644 --- a/TestCases/parallel_regression_AD.py +++ b/TestCases/parallel_regression_AD.py @@ -83,7 +83,7 @@ def main(): discadj_rans_naca0012_sa.cfg_dir = "disc_adj_rans/naca0012" discadj_rans_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" discadj_rans_naca0012_sa.test_iter = 10 - discadj_rans_naca0012_sa.test_vals = [-2.996963, -0.196020, 0.000004, -0.000000, 5.000000, -3.430615, 5.000000, -7.411396] + discadj_rans_naca0012_sa.test_vals = [-2.996963, -0.196020, 0.000004, -0.000000, 5.000000, -3.430615, 5.000000, -7.411381] test_list.append(discadj_rans_naca0012_sa) # Adjoint turbulent NACA0012 SST @@ -256,7 +256,7 @@ def main(): discadj_heat.cfg_dir = "disc_adj_heat" discadj_heat.cfg_file = "disc_adj_heat.cfg" discadj_heat.test_iter = 10 - discadj_heat.test_vals = [-2.117791, 0.784475, 0.000000, -0.574700] + discadj_heat.test_vals = [-2.117792, 0.784117, 0.000000, -0.574700] discadj_heat.test_vals_aarch64 = [-2.226539, 0.605868, 0.000000, -6.256400] test_list.append(discadj_heat) diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 10312c92cc3..4aa5f883481 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -218,7 +218,7 @@ def main(): rae2822_sa.cfg_dir = "rans/rae2822" rae2822_sa.cfg_file = "turb_SA_RAE2822.cfg" rae2822_sa.test_iter = 20 - rae2822_sa.test_vals = [-2.020123, -5.269324, 0.807147, 0.060499, -80602.000000] + rae2822_sa.test_vals = [-2.020123, -5.269339, 0.807147, 0.060499, -80603.000000] test_list.append(rae2822_sa) # RAE2822 SST @@ -242,7 +242,7 @@ def main(): turb_flatplate.cfg_dir = "rans/flatplate" turb_flatplate.cfg_file = "turb_SA_flatplate.cfg" turb_flatplate.test_iter = 20 - turb_flatplate.test_vals = [-4.312826, -6.736053, -0.187467, 0.057454] + turb_flatplate.test_vals = [-4.312724, -6.737976, -0.187467, 0.057468] test_list.append(turb_flatplate) # FLAT PLATE, WALL FUNCTIONS, COMPRESSIBLE SST @@ -258,7 +258,7 @@ def main(): turb_wallfunction_flatplate_sa.cfg_dir = "wallfunctions/flatplate/compressible_SA" turb_wallfunction_flatplate_sa.cfg_file = "turb_SA_flatplate.cfg" turb_wallfunction_flatplate_sa.test_iter = 10 - turb_wallfunction_flatplate_sa.test_vals = [-4.460537, -2.033605, -2.117564, 0.889626, -5.381903, 10.000000, -1.517487, 0.034212, 0.002636] + turb_wallfunction_flatplate_sa.test_vals = [-4.460657, -2.033641, -2.118149, 0.889562, -5.382249, 10.000000, -1.517453, 0.034213, 0.002636] test_list.append(turb_wallfunction_flatplate_sa) # ONERA M6 Wing @@ -275,7 +275,7 @@ def main(): turb_naca0012_sa.cfg_dir = "rans/naca0012" turb_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" turb_naca0012_sa.test_iter = 5 - turb_naca0012_sa.test_vals = [-12.091696, -14.685322, 1.057665, 0.022971, 20.000000, -2.686306, 20.000000, -4.459916, -44.871000] + turb_naca0012_sa.test_vals = [-12.091778, -14.685322, 1.057665, 0.022971, 20.000000, -2.686203, 20.000000, -4.459916, -44.871000] turb_naca0012_sa.timeout = 3200 test_list.append(turb_naca0012_sa) @@ -322,7 +322,7 @@ def main(): propeller.cfg_dir = "rans/propeller" propeller.cfg_file = "propeller.cfg" propeller.test_iter = 10 - propeller.test_vals = [-3.389724, -8.409223, 0.000048, 0.056344] + propeller.test_vals = [-3.389724, -8.409502, 0.000048, 0.056344] propeller.timeout = 3200 test_list.append(propeller) @@ -441,7 +441,7 @@ def main(): inc_turb_naca0012.cfg_dir = "incomp_rans/naca0012" inc_turb_naca0012.cfg_file = "naca0012.cfg" inc_turb_naca0012.test_iter = 20 - inc_turb_naca0012.test_vals = [-4.788496, -11.039482, 0.000023, 0.309488] + inc_turb_naca0012.test_vals = [-4.788495, -11.040578, 0.000023, 0.309503] test_list.append(inc_turb_naca0012) # NACA0012, SST_SUST @@ -796,7 +796,7 @@ def main(): ddes_flatplate.cfg_dir = "ddes/flatplate" ddes_flatplate.cfg_file = "ddes_flatplate.cfg" ddes_flatplate.test_iter = 10 - ddes_flatplate.test_vals = [-2.714785, -5.882680, -0.215041, 0.023758, -617.450000] + ddes_flatplate.test_vals = [-2.714786, -5.882646, -0.215041, 0.023758, -617.470000] ddes_flatplate.unsteady = True test_list.append(ddes_flatplate) @@ -805,7 +805,7 @@ def main(): unst_inc_turb_naca0015_sa.cfg_dir = "unsteady/pitching_naca0015_rans_inc" unst_inc_turb_naca0015_sa.cfg_file = "config_incomp_turb_sa.cfg" unst_inc_turb_naca0015_sa.test_iter = 1 - unst_inc_turb_naca0015_sa.test_vals = [-3.007635, -6.879778, 1.445293, 0.419274] + unst_inc_turb_naca0015_sa.test_vals = [-3.007635, -6.879809, 1.445300, 0.419281] unst_inc_turb_naca0015_sa.unsteady = True test_list.append(unst_inc_turb_naca0015_sa) diff --git a/TestCases/serial_regression_AD.py b/TestCases/serial_regression_AD.py index 9817708b300..8dc7ca3704c 100644 --- a/TestCases/serial_regression_AD.py +++ b/TestCases/serial_regression_AD.py @@ -183,7 +183,7 @@ def main(): discadj_heat.cfg_dir = "disc_adj_heat" discadj_heat.cfg_file = "disc_adj_heat.cfg" discadj_heat.test_iter = 10 - discadj_heat.test_vals = [-2.122406, 0.693852, 0.000000, -0.869010] + discadj_heat.test_vals = [-2.122406, 0.693159, 0.000000, -0.869010] test_list.append(discadj_heat) ################################### diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index eb018f65e73..e819ff246c1 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -228,7 +228,7 @@ def main(): tutorial_trans_e387_sa.cfg_dir = "../Tutorials/compressible_flow/Transitional_Airfoil/Langtry_and_Menter/E387" tutorial_trans_e387_sa.cfg_file = "transitional_SA_LM_model_ConfigFile.cfg" tutorial_trans_e387_sa.test_iter = 20 - tutorial_trans_e387_sa.test_vals = [-6.527027, -5.081558, -0.795261, 1.022606, 0.150125, 2.000000, -9.580659] + tutorial_trans_e387_sa.test_vals = [-6.527027, -5.081541, -0.795261, 1.022607, 0.150175, 2.000000, -9.580660] tutorial_trans_e387_sa.no_restart = True test_list.append(tutorial_trans_e387_sa) @@ -263,7 +263,7 @@ def main(): tutorial_unst_naca0012.cfg_dir = "../Tutorials/compressible_flow/Unsteady_NACA0012" tutorial_unst_naca0012.cfg_file = "unsteady_naca0012.cfg" tutorial_unst_naca0012.test_iter = 520 - tutorial_unst_naca0012.test_vals = [520.000000, 0.000000, -5.291711, 0.000000, 0.305248, 0.810326, 0.001814, 0.006573] + tutorial_unst_naca0012.test_vals = [520.000000, 0.000000, -5.290694, 0.000000, 0.317272, 0.820972, 0.002144, 0.012805] tutorial_unst_naca0012.test_vals_aarch64 = [520.000000, 0.000000, -5.298777, 0.000000, 0.288956, 0.736706, 0.002419, 0.007134] tutorial_unst_naca0012.unsteady = True test_list.append(tutorial_unst_naca0012) @@ -273,7 +273,7 @@ def main(): propeller_var_load.cfg_dir = "../Tutorials/compressible_flow/ActuatorDisk_VariableLoad" propeller_var_load.cfg_file = "propeller_variable_load.cfg" propeller_var_load.test_iter = 20 - propeller_var_load.test_vals = [-1.830276, -4.535127, -0.000323, 0.171623] + propeller_var_load.test_vals = [-1.830257, -4.535041, -0.000323, 0.171647] propeller_var_load.timeout = 3200 test_list.append(propeller_var_load) diff --git a/TestCases/vandv.py b/TestCases/vandv.py index 01359163885..f9da6969994 100644 --- a/TestCases/vandv.py +++ b/TestCases/vandv.py @@ -45,8 +45,8 @@ def main(): p30n30.cfg_dir = "vandv/rans/30p30n" p30n30.cfg_file = "config.cfg" p30n30.test_iter = 20 - p30n30.test_vals = [-10.582171, -10.106603, -10.474926, -10.182536, -12.679336, 0.052181, 2.829820, 1.318613, -0.221214] - p30n30.test_vals_aarch64 = [-10.582171, -10.106603, -10.474926, -10.182536, -12.679336, 0.052181, 2.829820, 1.318613, -0.221214] + p30n30.test_vals = [-10.582183, -10.106601, -10.474910, -10.182549, -12.679336, 0.052181, 2.829820, 1.318613, -0.221374] + p30n30.test_vals_aarch64 = [-10.582183, -10.106601, -10.474910, -10.182549, -12.679336, 0.052181, 2.829820, 1.318613, -0.221374] test_list.append(p30n30) # flat plate - sst-v1994m From 1b8fad3391a687f748507b5fe017d42f529d9867 Mon Sep 17 00:00:00 2001 From: emaberman Date: Wed, 18 Dec 2024 21:57:19 +0200 Subject: [PATCH 051/129] fixes --- TestCases/serial_regression_AD.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/serial_regression_AD.py b/TestCases/serial_regression_AD.py index 8dc7ca3704c..71d4ccf90ea 100644 --- a/TestCases/serial_regression_AD.py +++ b/TestCases/serial_regression_AD.py @@ -78,7 +78,7 @@ def main(): discadj_rans_naca0012_sa.cfg_dir = "disc_adj_rans/naca0012" discadj_rans_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" discadj_rans_naca0012_sa.test_iter = 10 - discadj_rans_naca0012_sa.test_vals = [-2.996976, -0.196055, 0.000004, -0.000000, 5.000000, -3.971736, 5.000000, -10.464337] + discadj_rans_naca0012_sa.test_vals = [-2.996976, -0.196055, 0.000004, -0.000000, 5.000000, -3.971736, 5.000000, -10.464319v] test_list.append(discadj_rans_naca0012_sa) # Adjoint turbulent NACA0012 SST From cea32627c0e7476b2c9688ea12c07d66e36667fa Mon Sep 17 00:00:00 2001 From: emaberman Date: Wed, 18 Dec 2024 22:03:53 +0200 Subject: [PATCH 052/129] fixes --- TestCases/serial_regression_AD.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/serial_regression_AD.py b/TestCases/serial_regression_AD.py index 71d4ccf90ea..47cb87fc98e 100644 --- a/TestCases/serial_regression_AD.py +++ b/TestCases/serial_regression_AD.py @@ -78,7 +78,7 @@ def main(): discadj_rans_naca0012_sa.cfg_dir = "disc_adj_rans/naca0012" discadj_rans_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" discadj_rans_naca0012_sa.test_iter = 10 - discadj_rans_naca0012_sa.test_vals = [-2.996976, -0.196055, 0.000004, -0.000000, 5.000000, -3.971736, 5.000000, -10.464319v] + discadj_rans_naca0012_sa.test_vals = [-2.996976, -0.196055, 0.000004, -0.000000, 5.000000, -3.971736, 5.000000, -10.464319] test_list.append(discadj_rans_naca0012_sa) # Adjoint turbulent NACA0012 SST From 46405cdd5ef8dab7ac6676052c7a38d6b4263423 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 21 Dec 2024 14:48:10 -0800 Subject: [PATCH 053/129] add thermal expansion to CConfig --- Common/include/CConfig.hpp | 11 +++++++++-- Common/src/CConfig.cpp | 14 +++++++++++--- .../numerics/elasticity/CFEAElasticity.hpp | 2 ++ .../src/numerics/elasticity/CFEAElasticity.cpp | 13 ++++++------- .../numerics/elasticity/CFEALinearElasticity.cpp | 7 +++++++ .../src/numerics/elasticity/nonlinear_models.cpp | 2 +- TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg | 16 ++++++++-------- 7 files changed, 44 insertions(+), 21 deletions(-) diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index 0c32f044288..9eb6ef74e71 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -1013,10 +1013,12 @@ class CConfig { su2double *Int_Coeffs; /*!< \brief Time integration coefficients for structural method. */ unsigned short nElasticityMod, /*!< \brief Number of different values for the elasticity modulus. */ nPoissonRatio, /*!< \brief Number of different values for the Poisson ratio modulus. */ - nMaterialDensity; /*!< \brief Number of different values for the Material density. */ + nMaterialDensity, /*!< \brief Number of different values for the Material density. */ + nMaterialThermalExpansion; /*!< \brief Number of different values for thermal expansion coefficient. */ su2double *ElasticityMod, /*!< \brief Value of the elasticity moduli. */ *PoissonRatio, /*!< \brief Value of the Poisson ratios. */ - *MaterialDensity; /*!< \brief Value of the Material densities. */ + *MaterialDensity, /*!< \brief Value of the Material densities. */ + *MaterialThermalExpansion; /*!< \brief Value of the thermal expansion coefficients. */ unsigned short nElectric_Field, /*!< \brief Number of different values for the electric field in the membrane. */ nDim_Electric_Field; /*!< \brief Dimensionality of the problem. */ unsigned short nDim_RefNode; /*!< \brief Dimensionality of the vector . */ @@ -2389,6 +2391,11 @@ class CConfig { */ su2double GetMaterialDensity(unsigned short id_val) const { return MaterialDensity[id_val]; } + /*! + * \brief Get the thermal expansion coefficient. + */ + su2double GetMaterialThermalExpansion(unsigned short id_val) const { return MaterialThermalExpansion[id_val]; } + /*! * \brief Compressibility/incompressibility of the solids analysed using the structural solver. * \return Compressible or incompressible. diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index c5bd653b04a..90af5948d25 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -2440,6 +2440,8 @@ void CConfig::SetConfig_Options() { addDoubleListOption("POISSON_RATIO", nPoissonRatio, PoissonRatio); /* DESCRIPTION: Material density */ addDoubleListOption("MATERIAL_DENSITY", nMaterialDensity, MaterialDensity); + /* DESCRIPTION: Material thermal expansion coefficient */ + addDoubleListOption("MATERIAL_THERMAL_EXPANSION_COEFF", nMaterialThermalExpansion, MaterialThermalExpansion); /* DESCRIPTION: Knowles B constant */ addDoubleOption("KNOWLES_B", Knowles_B, 1.0); /* DESCRIPTION: Knowles N constant */ @@ -4834,9 +4836,15 @@ void CConfig::SetPostprocessing(SU2_COMPONENT val_software, unsigned short val_i MaterialDensity = new su2double[1]; MaterialDensity[0] = 7854; } - if (nElasticityMod != nPoissonRatio || nElasticityMod != nMaterialDensity) { - SU2_MPI::Error("ELASTICITY_MODULUS, POISSON_RATIO, and MATERIAL_DENSITY need to have the same number " - "of entries (the number of materials).", CURRENT_FUNCTION); + if (nMaterialThermalExpansion == 0) { + nMaterialThermalExpansion = 1; + MaterialThermalExpansion = new su2double[1](); + } + + if (nElasticityMod != nPoissonRatio || nElasticityMod != nMaterialDensity || + nElasticityMod != nMaterialThermalExpansion) { + SU2_MPI::Error("ELASTICITY_MODULUS, POISSON_RATIO, MATERIAL_DENSITY, and THERMAL_EXPANSION_COEFF need " + "to have the same number of entries (the number of materials).", CURRENT_FUNCTION); } if (nElectric_Constant == 0) { diff --git a/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp b/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp index 11470fd0fba..43d5ebd5a63 100644 --- a/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp +++ b/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp @@ -54,6 +54,7 @@ class CFEAElasticity : public CNumerics { su2double Nu = 0.0; /*!< \brief Aux. variable, Poisson's ratio. */ su2double Rho_s = 0.0; /*!< \brief Aux. variable, Structural density. */ su2double Rho_s_DL = 0.0; /*!< \brief Aux. variable, Structural density (for dead loads). */ + su2double Alpha = 0.0; /*!< \brief Aux. variable, thermal expansion coefficient. */ su2double Mu = 0.0; /*!< \brief Aux. variable, Lame's coeficient. */ su2double Lambda = 0.0; /*!< \brief Aux. variable, Lame's coeficient. */ @@ -63,6 +64,7 @@ class CFEAElasticity : public CNumerics { su2double *Nu_i = nullptr; /*!< \brief Poisson's ratio. */ su2double *Rho_s_i = nullptr; /*!< \brief Structural density. */ su2double *Rho_s_DL_i = nullptr; /*!< \brief Structural density (for dead loads). */ + su2double *Alpha_i = nullptr; /*!< \brief Thermal expansion coefficient. */ su2double **Ba_Mat = nullptr; /*!< \brief Matrix B for node a - Auxiliary. */ su2double **Bb_Mat = nullptr; /*!< \brief Matrix B for node b - Auxiliary. */ diff --git a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp index 44014591204..b91be37223e 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp @@ -44,19 +44,16 @@ CFEAElasticity::CFEAElasticity(unsigned short val_nDim, unsigned short val_nVar, const auto nProp = config->GetnElasticityMat(); E_i = new su2double[nProp]; - for (iVar = 0; iVar < nProp; iVar++) - E_i[iVar] = config->GetElasticyMod(iVar); - Nu_i = new su2double[nProp]; - for (iVar = 0; iVar < nProp; iVar++) - Nu_i[iVar] = config->GetPoissonRatio(iVar); - Rho_s_i = new su2double[nProp]; // For inertial effects Rho_s_DL_i = new su2double[nProp]; // For dead loads - + Alpha_i = new su2double[nProp]; for (iVar = 0; iVar < nProp; iVar++) { + E_i[iVar] = config->GetElasticyMod(iVar); + Nu_i[iVar] = config->GetPoissonRatio(iVar); Rho_s_DL_i[iVar] = config->GetMaterialDensity(iVar); Rho_s_i[iVar] = pseudo_static ? 0.0 : config->GetMaterialDensity(iVar); + Alpha_i[iVar] = config->GetMaterialThermalExpansion(iVar); } // Initialization @@ -64,6 +61,7 @@ CFEAElasticity::CFEAElasticity(unsigned short val_nDim, unsigned short val_nVar, Nu = Nu_i[0]; Rho_s = Rho_s_i[0]; Rho_s_DL = Rho_s_DL_i[0]; + Alpha = Alpha_i[0]; Compute_Lame_Parameters(); @@ -302,6 +300,7 @@ void CFEAElasticity::SetElement_Properties(const CElement *element, const CConfi Nu = Nu_i[element->Get_iProp()]; Rho_s = Rho_s_i[element->Get_iProp()]; Rho_s_DL = Rho_s_DL_i[element->Get_iProp()]; + Alpha = Alpha_i[element->Get_iProp()]; switch (config->GetDV_FEA()) { case YOUNG_MODULUS: diff --git a/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp index a6763bed0b8..de7ad86219f 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp @@ -99,6 +99,13 @@ void CFEALinearElasticity::Compute_Tangent_Matrix(CElement *element, const CConf for (iNode = 0; iNode < nNode; iNode++) { + su2double KAux_t_a[3] = {0.0}; + const su2double thermalStress = -E * 2e-4 / (1 - 2 * Nu); + for (iVar = 0; iVar < nDim; iVar++) { + KAux_t_a[iVar] += Weight * thermalStress * GradNi_Ref_Mat[iNode][iVar] * Jac_X; + } + element->Add_Kt_a(iNode, KAux_t_a); + if (nDim == 2) { Ba_Mat[0][0] = GradNi_Ref_Mat[iNode][0]; Ba_Mat[1][1] = GradNi_Ref_Mat[iNode][1]; diff --git a/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp b/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp index d21fc228300..55d48a29010 100644 --- a/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp +++ b/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp @@ -112,7 +112,7 @@ void CFEM_NeoHookean_Comp::Compute_Stress_Tensor(CElement *element, const CConfi for (iVar = 0; iVar < 3; iVar++) { for (jVar = 0; jVar < 3; jVar++) { su2double dij = deltaij(iVar,jVar); - Stress_Tensor[iVar][jVar] = Mu_J * (b_Mat[iVar][jVar] - dij) + Lambda_J * log(J_F) * dij; + Stress_Tensor[iVar][jVar] = Mu_J * (b_Mat[iVar][jVar] - dij) + (Lambda_J * log(J_F) - E * 2e-4 / (1 - 2 * Nu)) * dij; } } diff --git a/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg b/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg index a6c9cde3c84..128958ecb19 100644 --- a/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg +++ b/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg @@ -15,13 +15,13 @@ MESH_FILENAME= meshBeam_3d.su2 ELASTICITY_MODULUS=3E7 POISSON_RATIO=0.3 MATERIAL_DENSITY=7854 -MARKER_CLAMPED = ( left , right ) -MARKER_PRESSURE= ( lower, 0 , symleft, 0, symright, 0) -MARKER_LOAD= ( upper, 1, 1000, 0, -1, 0) -LINEAR_SOLVER= FGMRES -LINEAR_SOLVER_PREC= LU_SGS -LINEAR_SOLVER_ERROR= 1E-8 -LINEAR_SOLVER_ITER= 500 +MARKER_CLAMPED = ( left ) +MARKER_PRESSURE= ( lower, 0 , symleft, 0, symright, 0, upper, 0, right, 0) +%MARKER_LOAD= ( upper, 1, 1000, 0, -1, 0) +LINEAR_SOLVER= CONJUGATE_GRADIENT +LINEAR_SOLVER_PREC= ILU +LINEAR_SOLVER_ERROR= 1E-9 +LINEAR_SOLVER_ITER= 1000 MESH_FORMAT= SU2 TABULAR_FORMAT= CSV CONV_FILENAME= history_beam @@ -29,4 +29,4 @@ VOLUME_FILENAME= beam RESTART_FILENAME= restart_beam.dat SOLUTION_FILENAME= restart_beam.dat OUTPUT_WRT_FREQ= 1 -INNER_ITER=1 +INNER_ITER=10 From aa88aba520bae2858f6980d9cd01430d8131fdc1 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 21 Dec 2024 14:49:05 -0800 Subject: [PATCH 054/129] error if interpolating takes too long --- SU2_CFD/src/solvers/CSolver.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/SU2_CFD/src/solvers/CSolver.cpp b/SU2_CFD/src/solvers/CSolver.cpp index e446c3f1133..2c6322392c7 100644 --- a/SU2_CFD/src/solvers/CSolver.cpp +++ b/SU2_CFD/src/solvers/CSolver.cpp @@ -3163,7 +3163,8 @@ void CSolver::InterpolateRestartData(const CGeometry *geometry, const CConfig *c const unsigned long nFields = Restart_Vars[1]; const unsigned long nPointFile = Restart_Vars[2]; const auto t0 = SU2_MPI::Wtime(); - auto nRecurse = 0; + int nRecurse = 0; + const int maxNRecurse = 128; if (rank == MASTER_NODE) { cout << "\nThe number of points in the restart file (" << nPointFile << ") does not match " @@ -3262,7 +3263,7 @@ void CSolver::InterpolateRestartData(const CGeometry *geometry, const CConfig *c bool done = false; SU2_OMP_PARALLEL - while (!done) { + while (!done && nRecurse < maxNRecurse) { SU2_OMP_FOR_DYN(roundUpDiv(nPointDomain,2*omp_get_num_threads())) for (auto iPoint = 0ul; iPoint < nPointDomain; ++iPoint) { /*--- Do not change points that are already interpolated. ---*/ @@ -3273,7 +3274,8 @@ void CSolver::InterpolateRestartData(const CGeometry *geometry, const CConfig *c for (const auto jPoint : geometry->nodes->GetPoints(iPoint)) { if (!isMapped[jPoint]) continue; - if (boundary_i != geometry->nodes->GetSolidBoundary(jPoint)) continue; + /*--- Take data from anywhere if we are looping too many times. ---*/ + if (boundary_i != geometry->nodes->GetSolidBoundary(jPoint) && nRecurse < 8) continue; nDonor[iPoint]++; @@ -3315,6 +3317,10 @@ void CSolver::InterpolateRestartData(const CGeometry *geometry, const CConfig *c } // everything goes out of scope except "localVars" + if (nRecurse == maxNRecurse) { + SU2_MPI::Error("Limit number of recursions reached, the meshes may be too different.", CURRENT_FUNCTION); + } + /*--- Move to Restart_Data in ascending order of global index, which is how a matching restart would have been read. ---*/ Restart_Data.resize(nPointDomain*nFields); @@ -3329,9 +3335,11 @@ void CSolver::InterpolateRestartData(const CGeometry *geometry, const CConfig *c counter++; } } + int nRecurseMax = 0; + SU2_MPI::Reduce(&nRecurse, &nRecurseMax, 1, MPI_INT, MPI_MAX, MASTER_NODE, SU2_MPI::GetComm()); if (rank == MASTER_NODE) { - cout << "Number of recursions: " << nRecurse << ".\n" + cout << "Number of recursions: " << nRecurseMax << ".\n" "Elapsed time: " << SU2_MPI::Wtime()-t0 << "s.\n" << endl; } } From 0fc99e944651233ba6ffb75fd2ca860c660f4bb6 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 21 Dec 2024 18:17:59 -0800 Subject: [PATCH 055/129] re-update --- TestCases/parallel_regression_AD.py | 2 +- TestCases/serial_regression_AD.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TestCases/parallel_regression_AD.py b/TestCases/parallel_regression_AD.py index 0cb0d452d57..f54849610f4 100644 --- a/TestCases/parallel_regression_AD.py +++ b/TestCases/parallel_regression_AD.py @@ -256,7 +256,7 @@ def main(): discadj_heat.cfg_dir = "disc_adj_heat" discadj_heat.cfg_file = "disc_adj_heat.cfg" discadj_heat.test_iter = 10 - discadj_heat.test_vals = [-2.117792, 0.784117, 0.000000, -0.574700] + discadj_heat.test_vals = [-1.840134, 0.750337, 0.000000, 0.006760] discadj_heat.test_vals_aarch64 = [-2.226539, 0.605868, 0.000000, -6.256400] test_list.append(discadj_heat) diff --git a/TestCases/serial_regression_AD.py b/TestCases/serial_regression_AD.py index 1a1267e7306..620a3b20e8f 100644 --- a/TestCases/serial_regression_AD.py +++ b/TestCases/serial_regression_AD.py @@ -183,7 +183,7 @@ def main(): discadj_heat.cfg_dir = "disc_adj_heat" discadj_heat.cfg_file = "disc_adj_heat.cfg" discadj_heat.test_iter = 10 - discadj_heat.test_vals = [-1.956349, 0.722272, 0.000000, 0.007024] + discadj_heat.test_vals = [-1.956346, 0.721746, 0.000000, 0.007024] test_list.append(discadj_heat) ################################### From e22089fd79062de05511feeaf92e7a6d64ba0b3f Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sun, 22 Dec 2024 13:55:22 +0100 Subject: [PATCH 056/129] fixing binary restart --- SU2_CFD/include/output/COutput.hpp | 15 ++++++---- SU2_CFD/src/output/COutput.cpp | 48 +++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index a3a222dff40..eea8188ed46 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -242,6 +242,7 @@ class COutput { /*----------------------------- Volume output ----------------------------*/ CParallelDataSorter* volumeDataSorter; //!< Volume data sorter + CParallelDataSorter* volumeDataSorterCompact; //!< Volume data sorter CParallelDataSorter* surfaceDataSorter; //!< Surface data sorter vector volumeFieldNames; //!< Vector containing the volume field names @@ -260,10 +261,12 @@ class COutput { /*! \brief The name of the field, i.e. the name that is printed in the file header.*/ string fieldName; /*! \brief This value identifies the position of the values of this field at each node in the ::Local_Data array. */ - short offset; + short offset; + /*! \brief This offset is used for the compact formulation. */ + short offsetCompact; /*! \brief The group this field belongs to. */ string outputGroup; - /*! \brief String containing the description of the field */ + /*! \brief String containing the description of the field. */ string description; /*! \brief Default constructor. */ VolumeOutputField () {} @@ -278,15 +281,15 @@ class COutput { /*! \brief Vector that contains the keys of the ::volumeOutput_Map in the order of their insertion. */ std::vector volumeOutput_List; - /*! \brief Vector to cache the positions of the field in the data array */ + /*! \brief Vector to cache the positions of the field in the data array. */ std::vector fieldIndexCache; - /*! \brief Current value of the cache index */ + /*! \brief Current value of the cache index. */ unsigned short cachePosition; /*! \brief Boolean to store whether the field index cache should be build. */ bool buildFieldIndexCache; - /*! \brief Vector to cache the positions of the field in the data array */ + /*! \brief Vector to cache the positions of the field in the data array. */ std::vector fieldGetIndexCache; - /*! \brief Current value of the cache index */ + /*! \brief Current value of the cache index. */ unsigned short curGetFieldIndex; /*! \brief Requested volume field names in the config file. */ diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 3fb9fbb5582..1400e6378ba 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -179,6 +179,7 @@ COutput::COutput(const CConfig *config, unsigned short ndim, bool fem_output): curTimeIter = 0; volumeDataSorter = nullptr; + volumeDataSorterCompact = nullptr; surfaceDataSorter = nullptr; headerNeeded = false; @@ -195,6 +196,7 @@ COutput::~COutput() { delete fileWritingTable; delete historyFileTable; delete volumeDataSorter; + delete volumeDataSorterCompact; delete surfaceDataSorter; } @@ -343,6 +345,9 @@ void COutput::AllocateDataSorters(CConfig *config, CGeometry *geometry){ if (volumeDataSorter == nullptr) volumeDataSorter = new CFEMDataSorter(config, geometry, volumeFieldNames); + if (volumeDataSorterCompact == nullptr) + volumeDataSorterCompact = new CFEMDataSorter(config, geometry, requiredVolumeFieldNames); + if (surfaceDataSorter == nullptr) surfaceDataSorter = new CSurfaceFEMDataSorter(config, geometry, dynamic_cast(volumeDataSorter)); @@ -352,6 +357,9 @@ void COutput::AllocateDataSorters(CConfig *config, CGeometry *geometry){ if (volumeDataSorter == nullptr) volumeDataSorter = new CFVMDataSorter(config, geometry, volumeFieldNames); + if (volumeDataSorterCompact == nullptr) + volumeDataSorterCompact = new CFVMDataSorter(config, geometry, requiredVolumeFieldNames); + if (surfaceDataSorter == nullptr) surfaceDataSorter = new CSurfaceFVMDataSorter(config, geometry, dynamic_cast(volumeDataSorter)); @@ -461,12 +469,15 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form /*--- If we have compact restarts, we use only the required fields. ---*/ if (config->GetWrt_Restart_Compact()) - volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); + volumeDataSorterCompact->SetRequiredFieldNames(requiredVolumeFieldNames); else volumeDataSorter->SetRequiredFieldNames(volumeDataSorter->GetFieldNames()); LogOutputFiles("SU2 binary restart"); - fileWriter = new CSU2BinaryFileWriter(volumeDataSorter); + if (config->GetWrt_Restart_Compact()) + fileWriter = new CSU2BinaryFileWriter(volumeDataSorterCompact); + else + fileWriter = new CSU2BinaryFileWriter(volumeDataSorter); break; @@ -846,6 +857,7 @@ bool COutput::SetResultFiles(CGeometry *geometry, CConfig *config, CSolver** sol /*--- Partition and sort the data --- */ volumeDataSorter->SortOutputData(); + volumeDataSorterCompact->SortOutputData(); if (rank == MASTER_NODE && !isFileWrite) { fileWritingTable->SetAlign(PrintingToolbox::CTablePrinter::CENTER); @@ -1554,24 +1566,32 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ * object gets an offset so that we know where to find the data in the Local_Data() array. * Note that the default offset is -1. An index !=-1 defines this field as part of the output. ---*/ + unsigned short nVolumeFieldsCompact = 0; + for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { const string &fieldReference = volumeOutput_List[iField_Output]; - if (volumeOutput_Map.count(fieldReference) > 0) { - VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); + /*--- Loop through all fields specified in the config ---*/ + for (size_t iReqField = 0; iReqField < restartVolumeFields.size(); iReqField++) { + // minimum required fields for restarts RequiredField = restartVolumeFields[iReqField]; + if (((RequiredField == Field.outputGroup) || (RequiredField == fieldReference)) && (Field.offset == -1)) { + Field.offsetCompact = nVolumeFieldsCompact; requiredVolumeFieldNames.push_back(Field.fieldName); + nVolumeFieldsCompact++; } } } } + //volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); + unsigned short nVolumeFields = 0; for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { @@ -1716,16 +1736,25 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver** void COutput::SetVolumeOutputValue(const string& name, unsigned long iPoint, su2double value){ - if (buildFieldIndexCache){ + const vector reqFieldNames = requiredVolumeFieldNames; + string fieldname = volumeOutput_Map.at(name).fieldName; + bool contains = std::any_of(requiredVolumeFieldNames.begin(), requiredVolumeFieldNames.end(), + [fieldname](string n) { return n == fieldname; }); + if (buildFieldIndexCache) { /*--- Build up the offset cache to speed up subsequent * calls of this routine since the order of calls is * the same for every value of iPoint --- */ - if (volumeOutput_Map.count(name) > 0){ + if (volumeOutput_Map.count(name) > 0) { const short Offset = volumeOutput_Map.at(name).offset; fieldIndexCache.push_back(Offset); if (Offset != -1){ + // note that the compact fields are a subset of the full fields + if (contains == true) { + const short OffsetCompact = volumeOutput_Map.at(name).offsetCompact; + volumeDataSorterCompact->SetUnsortedData(iPoint, OffsetCompact, value); + } volumeDataSorter->SetUnsortedData(iPoint, Offset, value); } } else { @@ -1734,9 +1763,12 @@ void COutput::SetVolumeOutputValue(const string& name, unsigned long iPoint, su2 } else { /*--- Use the offset cache for the access ---*/ - const short Offset = fieldIndexCache[cachePosition++]; - if (Offset != -1){ + if (Offset != -1) { + if (contains == true) { + const short OffsetCompact = volumeOutput_Map.at(name).offsetCompact; + volumeDataSorterCompact->SetUnsortedData(iPoint, OffsetCompact, value); + } volumeDataSorter->SetUnsortedData(iPoint, Offset, value); } if (cachePosition == fieldIndexCache.size()){ From 458e73224ccdee72f99d79635745197b879c4973 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sun, 22 Dec 2024 18:00:05 -0800 Subject: [PATCH 057/129] thermal stress term, not coupled to heat solver --- Common/include/CConfig.hpp | 8 +++- Common/include/geometry/elements/CElement.hpp | 41 ++++++++++++++--- Common/src/CConfig.cpp | 2 + Common/src/geometry/elements/CElement.cpp | 2 + Common/src/geometry/elements/CQUAD4.cpp | 1 - .../numerics/elasticity/CFEAElasticity.hpp | 11 +++-- .../elasticity/CFEANonlinearElasticity.hpp | 3 +- .../numerics/elasticity/nonlinear_models.hpp | 8 ++-- .../numerics/elasticity/CFEAElasticity.cpp | 46 ++++++------------- .../elasticity/CFEALinearElasticity.cpp | 10 ++-- .../elasticity/CFEANonlinearElasticity.cpp | 6 +-- .../numerics/elasticity/nonlinear_models.cpp | 26 ++++++----- SU2_CFD/src/solvers/CFEASolver.cpp | 8 ++++ .../fea_fsi/StatBeam_3d/configBeam_3d.cfg | 8 ++-- 14 files changed, 110 insertions(+), 70 deletions(-) diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index 9eb6ef74e71..d91a6011611 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -1018,7 +1018,8 @@ class CConfig { su2double *ElasticityMod, /*!< \brief Value of the elasticity moduli. */ *PoissonRatio, /*!< \brief Value of the Poisson ratios. */ *MaterialDensity, /*!< \brief Value of the Material densities. */ - *MaterialThermalExpansion; /*!< \brief Value of the thermal expansion coefficients. */ + *MaterialThermalExpansion, /*!< \brief Value of the thermal expansion coefficients. */ + MaterialReferenceTemperature; /*!< \brief Value of the reference temperature for thermal expansion. */ unsigned short nElectric_Field, /*!< \brief Number of different values for the electric field in the membrane. */ nDim_Electric_Field; /*!< \brief Dimensionality of the problem. */ unsigned short nDim_RefNode; /*!< \brief Dimensionality of the vector . */ @@ -2396,6 +2397,11 @@ class CConfig { */ su2double GetMaterialThermalExpansion(unsigned short id_val) const { return MaterialThermalExpansion[id_val]; } + /*! + * \brief Temperature at which there is no stress from thermal expansion. + */ + su2double GetMaterialReferenceTemperature() const { return MaterialReferenceTemperature; } + /*! * \brief Compressibility/incompressibility of the solids analysed using the structural solver. * \return Compressible or incompressible. diff --git a/Common/include/geometry/elements/CElement.hpp b/Common/include/geometry/elements/CElement.hpp index 535323ec0c0..6f7bd435560 100644 --- a/Common/include/geometry/elements/CElement.hpp +++ b/Common/include/geometry/elements/CElement.hpp @@ -67,6 +67,8 @@ class CElement { su2activematrix NodalExtrap; /*!< \brief Coordinates of the nodal points for Gaussian extrapolation. */ su2activematrix NodalStress; /*!< \brief Stress at the nodes. */ + su2activevector NodalTemperature; /*!< \brief Temperature at the nodes. */ + /*--- Stiffness and load matrices. ---*/ std::vector Kab; /*!< \brief Structure for the constitutive component of the tangent matrix. */ su2activematrix Mab; /*!< \brief Structure for the nodal components of the mass matrix. */ @@ -151,7 +153,7 @@ class CElement { * \param[in] iDim - Dimension. * \param[in] val_CoordRef - Value of the coordinate. */ - inline void SetRef_Coord(unsigned short iNode, unsigned short iDim, su2double val_CoordRef) { + inline void SetRef_Coord(unsigned short iNode, unsigned short iDim, const su2double& val_CoordRef) { RefCoord(iNode, iDim) = val_CoordRef; } @@ -161,10 +163,22 @@ class CElement { * \param[in] iDim - Dimension. * \param[in] val_CoordRef - Value of the coordinate. */ - inline void SetCurr_Coord(unsigned short iNode, unsigned short iDim, su2double val_CoordCurr) { + inline void SetCurr_Coord(unsigned short iNode, unsigned short iDim, const su2double& val_CoordCurr) { CurrentCoord(iNode, iDim) = val_CoordCurr; } + /*! + * \brief Set the value of the temperature of a node. + */ + inline void SetTemperature(unsigned short iNode, const su2double& val_Temperature) { + NodalTemperature[iNode] = val_Temperature; + } + + /*! + * \brief Set the value of the temperature of all nodes. + */ + inline void SetTemperature(const su2double& val_Temperature) { NodalTemperature = val_Temperature; } + /*! * \brief Get the value of the coordinate of the nodes in the reference configuration. * \param[in] iNode - Index of node. @@ -181,6 +195,17 @@ class CElement { */ inline su2double GetCurr_Coord(unsigned short iNode, unsigned short iDim) const { return CurrentCoord(iNode, iDim); } + /*! + * \brief Get the value of the temperature at a Gaussian integration point. + */ + inline su2double GetTemperature(unsigned short iGauss) const { + su2double Temperature = 0; + for (auto iNode = 0u; iNode < nNodes; ++iNode) { + Temperature += GetNi(iNode, iGauss) * NodalTemperature[iNode]; + } + return Temperature; + } + /*! * \brief Get the weight of the corresponding Gaussian Point. * \param[in] iGauss - index of the Gaussian point. @@ -214,7 +239,9 @@ class CElement { * \param[in] nodeB - index of Node b. * \param[in] val_Ks_ab - value of the term that will constitute the diagonal of the stress contribution. */ - inline void Add_Mab(unsigned short nodeA, unsigned short nodeB, su2double val_Mab) { Mab(nodeA, nodeB) += val_Mab; } + inline void Add_Mab(unsigned short nodeA, unsigned short nodeB, const su2double& val_Mab) { + Mab(nodeA, nodeB) += val_Mab; + } /*! * \brief Add the value of a submatrix K relating nodes a and b, for the constitutive term. @@ -243,7 +270,7 @@ class CElement { * \param[in] nodeB - index of Node b. * \param[in] val_Ks_ab - value of the term that will constitute the diagonal of the stress contribution. */ - inline void Add_Ks_ab(unsigned short nodeA, unsigned short nodeB, su2double val_Ks_ab) { + inline void Add_Ks_ab(unsigned short nodeA, unsigned short nodeB, const su2double& val_Ks_ab) { Ks_ab(nodeA, nodeB) += val_Ks_ab; } @@ -354,7 +381,7 @@ class CElement { * \param[in] iVar - Variable index. * \param[in] val_Stress - Value of the stress added. */ - inline void Add_NodalStress(unsigned short iNode, unsigned short iVar, su2double val_Stress) { + inline void Add_NodalStress(unsigned short iNode, unsigned short iVar, const su2double& val_Stress) { NodalStress(iNode, iVar) += val_Stress; } @@ -789,7 +816,7 @@ class CQUAD4 final : public CElementWithKnownSizes<4, 4, 2> { /*! * \brief Shape functions (Ni) evaluated at point Xi,Eta. */ - inline static void ShapeFunctions(su2double Xi, su2double Eta, su2double* Ni) { + inline static void ShapeFunctions(const su2double& Xi, const su2double& Eta, su2double* Ni) { Ni[0] = 0.25 * (1.0 - Xi) * (1.0 - Eta); Ni[1] = 0.25 * (1.0 + Xi) * (1.0 - Eta); Ni[2] = 0.25 * (1.0 + Xi) * (1.0 + Eta); @@ -799,7 +826,7 @@ class CQUAD4 final : public CElementWithKnownSizes<4, 4, 2> { /*! * \brief Shape function Jacobian (dNi) evaluated at point Xi,Eta. */ - inline static void ShapeFunctionJacobian(su2double Xi, su2double Eta, su2double dNi[][2]) { + inline static void ShapeFunctionJacobian(const su2double& Xi, const su2double& Eta, su2double dNi[][2]) { dNi[0][0] = -0.25 * (1.0 - Eta); dNi[0][1] = -0.25 * (1.0 - Xi); dNi[1][0] = 0.25 * (1.0 - Eta); diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 90af5948d25..5c220686271 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -2442,6 +2442,8 @@ void CConfig::SetConfig_Options() { addDoubleListOption("MATERIAL_DENSITY", nMaterialDensity, MaterialDensity); /* DESCRIPTION: Material thermal expansion coefficient */ addDoubleListOption("MATERIAL_THERMAL_EXPANSION_COEFF", nMaterialThermalExpansion, MaterialThermalExpansion); + /* DESCRIPTION: Temperature at which there is no stress from thermal expansion */ + addDoubleOption("MATERIAL_REFERENCE_TEMPERATURE", MaterialReferenceTemperature, 288.15); /* DESCRIPTION: Knowles B constant */ addDoubleOption("KNOWLES_B", Knowles_B, 1.0); /* DESCRIPTION: Knowles N constant */ diff --git a/Common/src/geometry/elements/CElement.cpp b/Common/src/geometry/elements/CElement.cpp index c42a3707562..5acf96a3ac9 100644 --- a/Common/src/geometry/elements/CElement.cpp +++ b/Common/src/geometry/elements/CElement.cpp @@ -47,6 +47,8 @@ CElement::CElement(unsigned short ngauss, unsigned short nnodes, unsigned short NodalStress.resize(nNodes, 6) = su2double(0.0); + NodalTemperature.resize(nNodes) = su2double(0.0); + Mab.resize(nNodes, nNodes); Ks_ab.resize(nNodes, nNodes); Kab.resize(nNodes); diff --git a/Common/src/geometry/elements/CQUAD4.cpp b/Common/src/geometry/elements/CQUAD4.cpp index 07725a3af19..29d3a621281 100644 --- a/Common/src/geometry/elements/CQUAD4.cpp +++ b/Common/src/geometry/elements/CQUAD4.cpp @@ -67,7 +67,6 @@ CQUAD4::CQUAD4() : CElementWithKnownSizes() { /*--- Store the extrapolation functions (used to compute nodal stresses) ---*/ su2double ExtrapCoord[4][2], sqrt3 = 1.732050807568877; - ; ExtrapCoord[0][0] = -sqrt3; ExtrapCoord[0][1] = -sqrt3; diff --git a/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp b/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp index 43d5ebd5a63..bbaa805e046 100644 --- a/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp +++ b/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp @@ -59,6 +59,7 @@ class CFEAElasticity : public CNumerics { su2double Mu = 0.0; /*!< \brief Aux. variable, Lame's coeficient. */ su2double Lambda = 0.0; /*!< \brief Aux. variable, Lame's coeficient. */ su2double Kappa = 0.0; /*!< \brief Aux. variable, Compressibility constant. */ + su2double ThermalStressTerm = 0.0; /*!< \brief Aux. variable, Relationship between stress and delta T. */ su2double *E_i = nullptr; /*!< \brief Young's modulus of elasticity. */ su2double *Nu_i = nullptr; /*!< \brief Poisson's ratio. */ @@ -66,6 +67,8 @@ class CFEAElasticity : public CNumerics { su2double *Rho_s_DL_i = nullptr; /*!< \brief Structural density (for dead loads). */ su2double *Alpha_i = nullptr; /*!< \brief Thermal expansion coefficient. */ + su2double ReferenceTemperature = 0.0; /*!< \brief Reference temperature for thermal expansion. */ + su2double **Ba_Mat = nullptr; /*!< \brief Matrix B for node a - Auxiliary. */ su2double **Bb_Mat = nullptr; /*!< \brief Matrix B for node b - Auxiliary. */ su2double *Ni_Vec = nullptr; /*!< \brief Vector of shape functions - Auxiliary. */ @@ -74,8 +77,6 @@ class CFEAElasticity : public CNumerics { su2double **GradNi_Ref_Mat = nullptr; /*!< \brief Gradients of Ni - Auxiliary. */ su2double **GradNi_Curr_Mat = nullptr; /*!< \brief Gradients of Ni - Auxiliary. */ - su2double *FAux_Dead_Load = nullptr; /*!< \brief Auxiliar vector for the dead loads */ - su2double *DV_Val = nullptr; /*!< \brief For optimization cases, value of the design variables. */ unsigned short n_DV = 0; /*!< \brief For optimization cases, number of design variables. */ @@ -232,6 +233,8 @@ class CFEAElasticity : public CNumerics { Mu = E / (2.0*(1.0 + Nu)); Lambda = Nu*E/((1.0+Nu)*(1.0-2.0*Nu)); Kappa = Lambda + (2/3)*Mu; + /*--- https://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php ---*/ + ThermalStressTerm = -Alpha * E / (1 - (plane_stress ? 1 : 2) * Nu); } /*! @@ -240,8 +243,8 @@ class CFEAElasticity : public CNumerics { * \param[in] jVar - Index j. * \return 1 if i=j, 0 otherwise. */ - inline static su2double deltaij(unsigned short iVar, unsigned short jVar) { - return su2double(iVar==jVar); + inline static passivedouble deltaij(unsigned short iVar, unsigned short jVar) { + return static_cast(iVar == jVar); } }; diff --git a/SU2_CFD/include/numerics/elasticity/CFEANonlinearElasticity.hpp b/SU2_CFD/include/numerics/elasticity/CFEANonlinearElasticity.hpp index 0e57f54e529..49ba78c09a2 100644 --- a/SU2_CFD/include/numerics/elasticity/CFEANonlinearElasticity.hpp +++ b/SU2_CFD/include/numerics/elasticity/CFEANonlinearElasticity.hpp @@ -141,8 +141,9 @@ class CFEANonlinearElasticity : public CFEAElasticity { * \brief Compute the stress tensor. * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. + * \param[in] iGauss - Index of Gaussian integration point. */ - virtual void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) = 0; + virtual void Compute_Stress_Tensor(CElement *element_container, const CConfig *config, unsigned short iGauss) = 0; /*! * \brief Update an element with Maxwell's stress. diff --git a/SU2_CFD/include/numerics/elasticity/nonlinear_models.hpp b/SU2_CFD/include/numerics/elasticity/nonlinear_models.hpp index a36eee0a67d..dbd7b4db422 100644 --- a/SU2_CFD/include/numerics/elasticity/nonlinear_models.hpp +++ b/SU2_CFD/include/numerics/elasticity/nonlinear_models.hpp @@ -73,7 +73,7 @@ class CFEM_NeoHookean_Comp final : public CFEANonlinearElasticity { * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) override; + void Compute_Stress_Tensor(CElement *element_container, const CConfig *config, unsigned short iGauss) override; }; @@ -124,7 +124,7 @@ class CFEM_Knowles_NearInc final : public CFEANonlinearElasticity { * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) override; + void Compute_Stress_Tensor(CElement *element_container, const CConfig *config, unsigned short iGauss) override; }; @@ -172,7 +172,7 @@ class CFEM_DielectricElastomer final : public CFEANonlinearElasticity { * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) override; + void Compute_Stress_Tensor(CElement *element_container, const CConfig *config, unsigned short iGauss) override; }; @@ -222,6 +222,6 @@ class CFEM_IdealDE final : public CFEANonlinearElasticity { * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) override; + void Compute_Stress_Tensor(CElement *element_container, const CConfig *config, unsigned short iGauss) override; }; diff --git a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp index b91be37223e..73df569ff26 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp @@ -35,7 +35,6 @@ CFEAElasticity::CFEAElasticity(unsigned short val_nDim, unsigned short val_nVar, nDim = val_nDim; nVar = val_nVar; - bool body_forces = config->GetDeadLoad(); // Body forces (dead loads). bool pseudo_static = config->GetPseudoStatic(); unsigned short iVar; @@ -62,14 +61,11 @@ CFEAElasticity::CFEAElasticity(unsigned short val_nDim, unsigned short val_nVar, Rho_s = Rho_s_i[0]; Rho_s_DL = Rho_s_DL_i[0]; Alpha = Alpha_i[0]; + ReferenceTemperature = config->GetMaterialReferenceTemperature(); Compute_Lame_Parameters(); - // Auxiliary vector for body forces (dead load) - FAux_Dead_Load = nullptr; - if (body_forces) FAux_Dead_Load = new su2double [nDim]; - - plane_stress = (config->GetElas2D_Formulation() == STRUCT_2DFORM::PLANE_STRESS); + plane_stress = (nDim == 2) && (config->GetElas2D_Formulation() == STRUCT_2DFORM::PLANE_STRESS); KAux_ab = new su2double* [nDim]; for (iVar = 0; iVar < nDim; iVar++) { @@ -162,12 +158,11 @@ CFEAElasticity::~CFEAElasticity() { delete[] DV_Val; - delete [] FAux_Dead_Load; - delete [] E_i; delete [] Nu_i; delete [] Rho_s_i; delete [] Rho_s_DL_i; + delete [] Alpha_i; delete [] Ni_Vec; } @@ -242,43 +237,32 @@ void CFEAElasticity::Compute_Dead_Load(CElement *element, const CConfig *config) AD::SetPreaccIn(Rho_s_DL); element->SetPreaccIn_Coords(false); - unsigned short iGauss, nGauss; - unsigned short iNode, iDim, nNode; - - su2double Weight, Jac_X; - /* -- Gravity directionality: * -- For 2D problems, we assume the direction for gravity is -y * -- For 3D problems, we assume the direction for gravity is -z */ su2double g_force[3] = {0.0,0.0,0.0}; - - if (nDim == 2) g_force[1] = -1*STANDARD_GRAVITY; - else if (nDim == 3) g_force[2] = -1*STANDARD_GRAVITY; + g_force[nDim - 1] = -STANDARD_GRAVITY; element->ClearElement(); /*--- Restart the element to avoid adding over previous results. --*/ element->ComputeGrad_Linear(); /*--- Need to compute the gradients to obtain the Jacobian. ---*/ - nNode = element->GetnNodes(); - nGauss = element->GetnGaussPoints(); - - for (iGauss = 0; iGauss < nGauss; iGauss++) { + const auto nNode = element->GetnNodes(); + const auto nGauss = element->GetnGaussPoints(); - Weight = element->GetWeight(iGauss); - Jac_X = element->GetJ_X(iGauss); /*--- The dead load is computed in the reference configuration ---*/ + for (auto iGauss = 0u; iGauss < nGauss; iGauss++) { - /*--- Retrieve the values of the shape functions for each node ---*/ - /*--- This avoids repeated operations ---*/ - for (iNode = 0; iNode < nNode; iNode++) { - Ni_Vec[iNode] = element->GetNi(iNode,iGauss); - } + const auto Weight = element->GetWeight(iGauss); + /*--- The dead load is computed in the reference configuration ---*/ + const auto Jac_X = element->GetJ_X(iGauss); - for (iNode = 0; iNode < nNode; iNode++) { + for (auto iNode = 0; iNode < nNode; iNode++) { + const auto Ni = element->GetNi(iNode,iGauss); - for (iDim = 0; iDim < nDim; iDim++) { - FAux_Dead_Load[iDim] = Weight * Ni_Vec[iNode] * Jac_X * Rho_s_DL * g_force[iDim]; + su2double FAux_Dead_Load[3] = {0.0,0.0,0.0}; + for (auto iDim = 0u; iDim < nDim; iDim++) { + FAux_Dead_Load[iDim] = Weight * Ni * Jac_X * Rho_s_DL * g_force[iDim]; } - element->Add_FDL_a(iNode, FAux_Dead_Load); } diff --git a/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp index de7ad86219f..8e15ed0cf6b 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp @@ -97,10 +97,11 @@ void CFEALinearElasticity::Compute_Tangent_Matrix(CElement *element, const CConf } } + const su2double thermalStress = ThermalStressTerm * (element->GetTemperature(iGauss) - ReferenceTemperature); + for (iNode = 0; iNode < nNode; iNode++) { su2double KAux_t_a[3] = {0.0}; - const su2double thermalStress = -E * 2e-4 / (1 - 2 * Nu); for (iVar = 0; iVar < nDim; iVar++) { KAux_t_a[iVar] += Weight * thermalStress * GradNi_Ref_Mat[iNode][iVar] * Jac_X; } @@ -321,14 +322,17 @@ su2double CFEALinearElasticity::Compute_Averaged_NodalStress(CElement *element, } - /*--- Compute the Stress Vector as D*epsilon ---*/ + /*--- Compute the Stress Vector as D*epsilon + thermal stress ---*/ su2double Stress[DIM_STRAIN_3D] = {0.0}; + const su2double thermalStress = ThermalStressTerm * (element->GetTemperature(iGauss) - ReferenceTemperature); + for (iVar = 0; iVar < bDim; iVar++) { for (jVar = 0; jVar < bDim; jVar++) { Stress[iVar] += D_Mat[iVar][jVar]*Strain[jVar]; } + if (iVar < nDim) Stress[iVar] += thermalStress; avgStress[iVar] += Stress[iVar] / nGauss; } @@ -370,10 +374,10 @@ CFEAMeshElasticity::CFEAMeshElasticity(unsigned short val_nDim, unsigned short v unsigned long val_nElem, const CConfig *config) : CFEALinearElasticity() { DV_Val = nullptr; - FAux_Dead_Load = nullptr; Rho_s_i = nullptr; Rho_s_DL_i = nullptr; Nu_i = nullptr; + Alpha_i = nullptr; nDim = val_nDim; nVar = val_nVar; diff --git a/SU2_CFD/src/numerics/elasticity/CFEANonlinearElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEANonlinearElasticity.cpp index 0b8ed7cb855..8f74c164dd6 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEANonlinearElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEANonlinearElasticity.cpp @@ -349,7 +349,7 @@ void CFEANonlinearElasticity::Compute_Tangent_Matrix(CElement *element, const CC /*--- Compute the constitutive matrix ---*/ - Compute_Stress_Tensor(element, config); + Compute_Stress_Tensor(element, config, iGauss); // if (maxwell_stress) Add_MaxwellStress(element, config); Compute_Constitutive_Matrix(element, config); @@ -571,7 +571,7 @@ void CFEANonlinearElasticity::Compute_NodalStress_Term(CElement *element, const /*--- Compute the stress tensor ---*/ - Compute_Stress_Tensor(element, config); + Compute_Stress_Tensor(element, config, iGauss); // if (maxwell_stress) Add_MaxwellStress(element, config); for (iNode = 0; iNode < nNode; iNode++) { @@ -850,7 +850,7 @@ su2double CFEANonlinearElasticity::Compute_Averaged_NodalStress(CElement *elemen /*--- Compute the stress tensor ---*/ - Compute_Stress_Tensor(element, config); + Compute_Stress_Tensor(element, config, iGauss); if (maxwell_stress) Add_MaxwellStress(element, config); avgStress[0] += Stress_Tensor[0][0] / nGauss; diff --git a/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp b/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp index 55d48a29010..4b787db3416 100644 --- a/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp +++ b/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp @@ -98,7 +98,7 @@ void CFEM_NeoHookean_Comp::Compute_Constitutive_Matrix(CElement *element, const } -void CFEM_NeoHookean_Comp::Compute_Stress_Tensor(CElement *element, const CConfig *config) { +void CFEM_NeoHookean_Comp::Compute_Stress_Tensor(CElement *element, const CConfig *config, unsigned short iGauss) { unsigned short iVar,jVar; su2double Mu_J = 0.0, Lambda_J = 0.0; @@ -109,10 +109,12 @@ void CFEM_NeoHookean_Comp::Compute_Stress_Tensor(CElement *element, const CConfi Lambda_J = Lambda/J_F; } + const su2double thermalStress = ThermalStressTerm * (element->GetTemperature(iGauss) - ReferenceTemperature); + for (iVar = 0; iVar < 3; iVar++) { for (jVar = 0; jVar < 3; jVar++) { su2double dij = deltaij(iVar,jVar); - Stress_Tensor[iVar][jVar] = Mu_J * (b_Mat[iVar][jVar] - dij) + (Lambda_J * log(J_F) - E * 2e-4 / (1 - 2 * Nu)) * dij; + Stress_Tensor[iVar][jVar] = Mu_J * (b_Mat[iVar][jVar] - dij) + (Lambda_J * log(J_F) + thermalStress) * dij; } } @@ -182,7 +184,7 @@ void CFEM_Knowles_NearInc::Compute_Constitutive_Matrix(CElement *element, const } -void CFEM_Knowles_NearInc::Compute_Stress_Tensor(CElement *element, const CConfig *config) { +void CFEM_Knowles_NearInc::Compute_Stress_Tensor(CElement *element, const CConfig *config, unsigned short iGauss) { /* -- Suchocki (2011) (full reference in class constructor). ---*/ @@ -199,10 +201,12 @@ void CFEM_Knowles_NearInc::Compute_Stress_Tensor(CElement *element, const CConfi Ek = Kappa * (2.0 * J_F - 1.0); Pr = Kappa * (J_F - 1.0); + const su2double thermalStress = ThermalStressTerm * (element->GetTemperature(iGauss) - ReferenceTemperature); + for (iVar = 0; iVar < 3; iVar++){ for (jVar = 0; jVar < 3; jVar++){ Stress_Tensor[iVar][jVar] = term1 * (b_Mat_Iso[iVar][jVar] - deltaij(iVar,jVar)*trbbar) + - deltaij(iVar,jVar) * Pr; + deltaij(iVar,jVar) * (Pr + thermalStress); } } @@ -234,7 +238,7 @@ void CFEM_DielectricElastomer::Compute_Constitutive_Matrix(CElement *element, co } -void CFEM_DielectricElastomer::Compute_Stress_Tensor(CElement *element, const CConfig *config) { +void CFEM_DielectricElastomer::Compute_Stress_Tensor(CElement *element, const CConfig *config, unsigned short iGauss) { unsigned short iDim, jDim; @@ -315,12 +319,11 @@ void CFEM_IdealDE::Compute_Constitutive_Matrix(CElement *element, const CConfig } -void CFEM_IdealDE::Compute_Stress_Tensor(CElement *element, const CConfig *config) { +void CFEM_IdealDE::Compute_Stress_Tensor(CElement *element, const CConfig *config, unsigned short iGauss) { /* -- Zhao, X. and Suo, Z. (2008) (full reference in class constructor). ---*/ unsigned short iVar, jVar; - su2double dij = 0.0; /*--- Compute the isochoric deformation gradient Fbar and left Cauchy-Green tensor bbar ---*/ Compute_Isochoric_F_b(); @@ -333,13 +336,12 @@ void CFEM_IdealDE::Compute_Stress_Tensor(CElement *element, const CConfig *confi Pr = Kappa * (J_F - 1.0); Eg23 = 2.0 * Eg / 3.0; - // Stress tensor + const su2double thermalStress = ThermalStressTerm * (element->GetTemperature(iGauss) - ReferenceTemperature); for (iVar = 0; iVar < 3; iVar++){ - for (jVar = 0; jVar < 3; jVar++){ - if (iVar == jVar) dij = 1.0; - else if (iVar != jVar) dij = 0.0; - Stress_Tensor[iVar][jVar] = Eg * ( b_Mat_Iso[iVar][jVar] - dij * trbbar) + dij * Pr ; + for (jVar = 0; jVar < 3; jVar++) { + const su2double dij = deltaij(iVar, jVar); + Stress_Tensor[iVar][jVar] = Eg * ( b_Mat_Iso[iVar][jVar] - dij * trbbar) + dij * (Pr + thermalStress); } } diff --git a/SU2_CFD/src/solvers/CFEASolver.cpp b/SU2_CFD/src/solvers/CFEASolver.cpp index 4cd718d6ce1..44a19e1421a 100644 --- a/SU2_CFD/src/solvers/CFEASolver.cpp +++ b/SU2_CFD/src/solvers/CFEASolver.cpp @@ -71,6 +71,10 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CFEASolverBase(ge element_container[FEA_TERM][EL_TRIA+offset] = new CTRIA1(); element_container[FEA_TERM][EL_QUAD+offset] = new CQUAD4(); + /*--- Initialize temperature ---*/ + element_container[FEA_TERM][EL_TRIA+offset]->SetTemperature(config->GetTemperature_FreeStream()); + element_container[FEA_TERM][EL_QUAD+offset]->SetTemperature(config->GetTemperature_FreeStream()); + if (de_effects) { element_container[DE_TERM][EL_TRIA+offset] = new CTRIA1(); element_container[DE_TERM][EL_QUAD+offset] = new CQUAD4(); @@ -82,6 +86,10 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CFEASolverBase(ge element_container[FEA_TERM][EL_PYRAM+offset] = new CPYRAM5(); element_container[FEA_TERM][EL_PRISM+offset] = new CPRISM6(); + for (const auto el : {EL_TETRA, EL_HEXA, EL_PYRAM, EL_PRISM}) { + element_container[FEA_TERM][el+offset]->SetTemperature(config->GetTemperature_FreeStream()); + } + if (de_effects) { element_container[DE_TERM][EL_TETRA+offset] = new CTETRA1(); element_container[DE_TERM][EL_HEXA +offset] = new CHEXA8 (); diff --git a/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg b/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg index 128958ecb19..b08a38181d6 100644 --- a/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg +++ b/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg @@ -14,13 +14,15 @@ MATERIAL_MODEL= LINEAR_ELASTIC MESH_FILENAME= meshBeam_3d.su2 ELASTICITY_MODULUS=3E7 POISSON_RATIO=0.3 +MATERIAL_THERMAL_EXPANSION_COEFF= 2e-5 +MATERIAL_REFERENCE_TEMPERATURE= 288.15 +FREESTREAM_TEMPERATURE= 350 MATERIAL_DENSITY=7854 MARKER_CLAMPED = ( left ) MARKER_PRESSURE= ( lower, 0 , symleft, 0, symright, 0, upper, 0, right, 0) -%MARKER_LOAD= ( upper, 1, 1000, 0, -1, 0) LINEAR_SOLVER= CONJUGATE_GRADIENT LINEAR_SOLVER_PREC= ILU -LINEAR_SOLVER_ERROR= 1E-9 +LINEAR_SOLVER_ERROR= 1E-8 LINEAR_SOLVER_ITER= 1000 MESH_FORMAT= SU2 TABULAR_FORMAT= CSV @@ -29,4 +31,4 @@ VOLUME_FILENAME= beam RESTART_FILENAME= restart_beam.dat SOLUTION_FILENAME= restart_beam.dat OUTPUT_WRT_FREQ= 1 -INNER_ITER=10 +INNER_ITER=1 From bac0e067fe3169496b1484346be42d0d2177497a Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sun, 22 Dec 2024 18:15:30 -0800 Subject: [PATCH 058/129] update testcase --- TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg | 5 +++-- config_template.cfg | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg b/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg index b08a38181d6..56b57777a55 100644 --- a/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg +++ b/TestCases/fea_fsi/StatBeam_3d/configBeam_3d.cfg @@ -18,8 +18,9 @@ MATERIAL_THERMAL_EXPANSION_COEFF= 2e-5 MATERIAL_REFERENCE_TEMPERATURE= 288.15 FREESTREAM_TEMPERATURE= 350 MATERIAL_DENSITY=7854 -MARKER_CLAMPED = ( left ) -MARKER_PRESSURE= ( lower, 0 , symleft, 0, symright, 0, upper, 0, right, 0) +MARKER_CLAMPED = ( left, right ) +MARKER_PRESSURE= ( lower, 0 , symleft, 0, symright, 0 ) +MARKER_LOAD= ( upper, 1, 1000, 0, -1, 0 ) LINEAR_SOLVER= CONJUGATE_GRADIENT LINEAR_SOLVER_PREC= ILU LINEAR_SOLVER_ERROR= 1E-8 diff --git a/config_template.cfg b/config_template.cfg index 8a953b7be78..2ecb8ca03b2 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -1727,6 +1727,12 @@ ELASTICITY_MODULUS= 1000.0 % Poisson ratio POISSON_RATIO= 0.35 % +% Thermal expansion coefficient +MATERIAL_THERMAL_EXPANSION_COEFF= 0 +% +% Freestream temperature at which there is no stress from thermal expansion +MATERIAL_REFERENCE_TEMPERATURE= 288.15 +% % Knowles B constant KNOWLES_B= 1.0 % From f0808bd7dc0a7109b6f823ce1b854b0c18d73bad Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Mon, 23 Dec 2024 18:28:26 -0800 Subject: [PATCH 059/129] update cases --- Common/src/CConfig.cpp | 5 ++++- TestCases/hybrid_regression.py | 4 ++-- TestCases/parallel_regression.py | 4 ++-- TestCases/serial_regression.py | 4 ++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 5c220686271..ba2f975c699 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -914,7 +914,10 @@ void CConfig::SetPointersNull() { Inlet_Velocity = nullptr; Inflow_Mach = nullptr; Inflow_Pressure = nullptr; Outlet_Pressure = nullptr; Isothermal_Temperature = nullptr; - ElasticityMod = nullptr; PoissonRatio = nullptr; MaterialDensity = nullptr; + ElasticityMod = nullptr; + PoissonRatio = nullptr; + MaterialDensity = nullptr; + MaterialThermalExpansion = nullptr; Load_Dir = nullptr; Load_Dir_Value = nullptr; Load_Dir_Multiplier = nullptr; Disp_Dir = nullptr; Disp_Dir_Value = nullptr; Disp_Dir_Multiplier = nullptr; diff --git a/TestCases/hybrid_regression.py b/TestCases/hybrid_regression.py index e5b0a847e61..fb05c2513db 100644 --- a/TestCases/hybrid_regression.py +++ b/TestCases/hybrid_regression.py @@ -680,8 +680,8 @@ def main(): statbeam3d.cfg_dir = "fea_fsi/StatBeam_3d" statbeam3d.cfg_file = "configBeam_3d.cfg" statbeam3d.test_iter = 0 - statbeam3d.test_vals = [-2.378370, -1.585252, -2.028505, 64359.000000] - statbeam3d.test_vals_aarch64 = [-2.382650, -1.561882, -2.045083, 64433.000000] + statbeam3d.test_vals = [-2.787802, -1.721974, -2.438436, 110350] + statbeam3d.test_vals_aarch64 = [-2.787802, -1.721974, -2.438436, 110350] test_list.append(statbeam3d) # Dynamic beam, 2d diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index f19b323f761..4a86a6fcc00 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -1220,8 +1220,8 @@ def main(): statbeam3d.cfg_dir = "fea_fsi/StatBeam_3d" statbeam3d.cfg_file = "configBeam_3d.cfg" statbeam3d.test_iter = 0 - statbeam3d.test_vals = [-8.396797, -8.162206, -8.156102, 64095.000000] - statbeam3d.test_vals_aarch64 = [-8.396793, -8.162255, -8.156118, 64095.0] #last 4 columns + statbeam3d.test_vals = [-6.058758, -5.750933, -5.892188, 110190] + statbeam3d.test_vals_aarch64 = [-6.058758, -5.750933, -5.892188, 110190] statbeam3d.command = TestCase.Command(exec = "parallel_computation_fsi.py", param = "-f") test_list.append(statbeam3d) diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 4aa5f883481..a0d531353f6 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -1012,8 +1012,8 @@ def main(): statbeam3d.cfg_dir = "fea_fsi/StatBeam_3d" statbeam3d.cfg_file = "configBeam_3d.cfg" statbeam3d.test_iter = 0 - statbeam3d.test_vals = [-8.498245, -8.230816, -8.123810, 64095.000000] - statbeam3d.test_vals_aarch64 = [-8.498254, -8.230683, -8.123819, 64095.0] #last 4 columns + statbeam3d.test_vals = [-6.168640, -5.939035, -6.071159, 110190] + statbeam3d.test_vals_aarch64 = [-6.168640, -5.939035, -6.071159, 110190] #last 4 columns test_list.append(statbeam3d) # Mix elem, 3d beam, Knowles From 2cda5ec8ff45ea99466ceb59187f031cba654b41 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Tue, 24 Dec 2024 14:10:28 -0800 Subject: [PATCH 060/129] generalize body force for FEA solver and add centrifugal loads --- Common/include/CConfig.hpp | 7 ++- Common/src/CConfig.cpp | 10 ++-- SU2_CFD/include/numerics/CNumerics.hpp | 4 +- .../numerics/elasticity/CFEAElasticity.hpp | 6 +-- SU2_CFD/include/solvers/CFEASolver.hpp | 9 ++-- SU2_CFD/include/solvers/CSolver.hpp | 6 +-- .../numerics/elasticity/CFEAElasticity.cpp | 51 ++++++++++++++----- SU2_CFD/src/output/CAdjElasticityOutput.cpp | 4 +- SU2_CFD/src/solvers/CFEASolver.cpp | 26 +++------- SU2_CFD/src/variables/CFEAVariable.cpp | 2 +- TestCases/disc_adj_fea/configAD_fem.cfg | 3 +- .../flow_load_sens/configAD_fem.cfg | 1 - config_template.cfg | 5 +- 13 files changed, 73 insertions(+), 61 deletions(-) diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index d91a6011611..b5407e71eeb 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -1004,7 +1004,7 @@ class CConfig { bool ExtraOutput; /*!< \brief Check if extra output need. */ bool Wall_Functions; /*!< \brief Use wall functions with the turbulence model */ long ExtraHeatOutputZone; /*!< \brief Heat solver zone with extra screen output */ - bool DeadLoad; /*!< \brief Application of dead loads to the FE analysis */ + bool CentrifugalForce; /*!< \brief Application of centrifugal forces to the FE analysis */ bool PseudoStatic; /*!< \brief Application of dead loads to the FE analysis */ bool SteadyRestart; /*!< \brief Restart from a steady state for FSI problems. */ su2double Newmark_beta, /*!< \brief Parameter alpha for Newmark method. */ @@ -8942,10 +8942,9 @@ class CConfig { su2double GetAitkenDynMinInit(void) const { return AitkenDynMinInit; } /*! - * \brief Decide whether to apply dead loads to the model. - * \return TRUE if the dead loads are to be applied, FALSE otherwise. + * \brief Decide whether to apply centrifugal forces to the model. */ - bool GetDeadLoad(void) const { return DeadLoad; } + bool GetCentrifugalForce(void) const { return CentrifugalForce; } /*! * \brief Identifies if the mesh is matching or not (temporary, while implementing interpolation procedures). diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index ba2f975c699..757388c9cc8 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -2507,11 +2507,11 @@ void CConfig::SetConfig_Options() { addEnumOption("NONLINEAR_FEM_SOLUTION_METHOD", Kind_SpaceIteScheme_FEA, Space_Ite_Map_FEA, STRUCT_SPACE_ITE::NEWTON); /* DESCRIPTION: Formulation for bidimensional elasticity solver */ addEnumOption("FORMULATION_ELASTICITY_2D", Kind_2DElasForm, ElasForm_2D, STRUCT_2DFORM::PLANE_STRAIN); - /* DESCRIPTION: Apply dead loads - * Options: NO, YES \ingroup Config */ - addBoolOption("DEAD_LOAD", DeadLoad, false); + /* DESCRIPTION: Apply centrifugal forces + * Options: NO, YES \ingroup Config */ + addBoolOption("CENTRIFUGAL_FORCE", CentrifugalForce, false); /* DESCRIPTION: Temporary: pseudo static analysis (no density in dynamic analysis) - * Options: NO, YES \ingroup Config */ + * Options: NO, YES \ingroup Config */ addBoolOption("PSEUDO_STATIC", PseudoStatic, false); /* DESCRIPTION: Parameter alpha for Newmark scheme (s) */ addDoubleOption("NEWMARK_BETA", Newmark_beta, 0.25); @@ -3070,6 +3070,8 @@ void CConfig::SetConfig_Parsing(istream& config_buffer){ newString.append("DYNAMIC_ANALYSIS is deprecated. Use TIME_DOMAIN instead.\n\n"); else if (!option_name.compare("SPECIES_USE_STRONG_BC")) newString.append("SPECIES_USE_STRONG_BC is deprecated. Use MARKER_SPECIES_STRONG_BC= (marker1, ...) instead.\n\n"); + else if (!option_name.compare("DEAD_LOAD")) + newString.append("DEAD_LOAD is deprecated. Use GRAVITY_FORCE or BODY_FORCE instead.\n\n"); else { /*--- Find the most likely candidate for the unrecognized option, based on the length of start and end character sequences shared by candidates and the option. ---*/ diff --git a/SU2_CFD/include/numerics/CNumerics.hpp b/SU2_CFD/include/numerics/CNumerics.hpp index 535335947ca..2e45916edb1 100644 --- a/SU2_CFD/include/numerics/CNumerics.hpp +++ b/SU2_CFD/include/numerics/CNumerics.hpp @@ -1483,10 +1483,10 @@ class CNumerics { inline virtual void Compute_Mass_Matrix(CElement *element_container, const CConfig* config) { } /*! - * \brief A virtual member to compute the residual component due to dead loads + * \brief A virtual member to compute the residual component due to body forces. * \param[in] element_container - Element structure for the particular element integrated. */ - inline virtual void Compute_Dead_Load(CElement *element_container, const CConfig* config) { } + inline virtual void Compute_Body_Forces(CElement *element_container, const CConfig* config) { } /*! * \brief A virtual member to compute the averaged nodal stresses diff --git a/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp b/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp index bbaa805e046..a1395fdf130 100644 --- a/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp +++ b/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp @@ -159,11 +159,11 @@ class CFEAElasticity : public CNumerics { void Compute_Mass_Matrix(CElement *element_container, const CConfig *config) final; /*! - * \brief Compute the nodal gravity loads for an element. - * \param[in,out] element_container - The element for which the dead loads are computed. + * \brief Compute the nodal inertial loads for an element. + * \param[in,out] element_container - The element for which the inertial loads are computed. * \param[in] config - Definition of the problem. */ - void Compute_Dead_Load(CElement *element_container, const CConfig *config) final; + void Compute_Body_Forces(CElement *element_container, const CConfig *config) final; /*! * \brief Build the tangent stiffness matrix of an element. diff --git a/SU2_CFD/include/solvers/CFEASolver.hpp b/SU2_CFD/include/solvers/CFEASolver.hpp index 4d8bf74be8e..9442fa190d7 100644 --- a/SU2_CFD/include/solvers/CFEASolver.hpp +++ b/SU2_CFD/include/solvers/CFEASolver.hpp @@ -98,6 +98,7 @@ class CFEASolver : public CFEASolverBase { bool element_based; /*!< \brief Bool to determine if an element-based file is used. */ bool topol_filter_applied; /*!< \brief True if density filtering has been performed. */ bool initial_calc = true; /*!< \brief Becomes false after first call to Preprocessing. */ + bool body_forces = false; /*!< \brief Whether any body force is active. */ /*! * \brief The highest level in the variable hierarchy this solver can safely use, @@ -335,14 +336,14 @@ class CFEASolver : public CFEASolverBase { const CConfig *config); /*! - * \brief Compute the dead loads. + * \brief Compute the inertial loads. * \param[in] geometry - Geometrical definition of the problem. * \param[in] numerics - Description of the numerical method. * \param[in] config - Definition of the particular problem. */ - void Compute_DeadLoad(CGeometry *geometry, - CNumerics **numerics, - const CConfig *config) final; + void Compute_BodyForces(CGeometry *geometry, + CNumerics **numerics, + const CConfig *config) final; /*! * \brief Clamped boundary conditions. diff --git a/SU2_CFD/include/solvers/CSolver.hpp b/SU2_CFD/include/solvers/CSolver.hpp index b6c0d45d219..2ed78a78a9b 100644 --- a/SU2_CFD/include/solvers/CSolver.hpp +++ b/SU2_CFD/include/solvers/CSolver.hpp @@ -3645,9 +3645,9 @@ class CSolver { * \param[in] numerics - Description of the numerical method. * \param[in] config - Definition of the particular problem. */ - inline virtual void Compute_DeadLoad(CGeometry *geometry, - CNumerics **numerics, - const CConfig *config) { } + inline virtual void Compute_BodyForces(CGeometry *geometry, + CNumerics **numerics, + const CConfig *config) { } /*! * \brief A virtual member. Set the volumetric heat source diff --git a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp index 73df569ff26..ca3da2b26ae 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp @@ -27,6 +27,7 @@ #include "../../../include/numerics/elasticity/CFEAElasticity.hpp" #include "../../../../Common/include/parallelization/omp_structure.hpp" +#include "../../../../Common/include/toolboxes/geometry_toolbox.hpp" CFEAElasticity::CFEAElasticity(unsigned short val_nDim, unsigned short val_nVar, @@ -226,7 +227,11 @@ void CFEAElasticity::Compute_Mass_Matrix(CElement *element, const CConfig *confi } -void CFEAElasticity::Compute_Dead_Load(CElement *element, const CConfig *config) { +void CFEAElasticity::Compute_Body_Forces(CElement *element, const CConfig *config) { + + const bool gravity = config->GetGravityForce(); + const bool body_force = config->GetBody_Force(); + const bool centrifugal = config->GetCentrifugalForce(); /*--- Initialize values for the material model considered ---*/ SetElement_Properties(element, config); @@ -237,13 +242,24 @@ void CFEAElasticity::Compute_Dead_Load(CElement *element, const CConfig *config) AD::SetPreaccIn(Rho_s_DL); element->SetPreaccIn_Coords(false); - /* -- Gravity directionality: - * -- For 2D problems, we assume the direction for gravity is -y - * -- For 3D problems, we assume the direction for gravity is -z - */ - su2double g_force[3] = {0.0,0.0,0.0}; - g_force[nDim - 1] = -STANDARD_GRAVITY; + std::array acceleration{}; + if (gravity) { + /*--- For 2D problems, we assume gravity is in the -y direction, + * and for 3D problems in the -z direction. ---*/ + acceleration[nDim - 1] = -STANDARD_GRAVITY; + } else if (body_force) { + for (auto iDim = 0u; iDim < nDim; iDim++) { + acceleration[iDim] = config->GetBody_Force_Vector()[iDim]; + } + } + std::array center{}, omega{}; + if (centrifugal) { + for (auto iDim = 0u; iDim < nDim; iDim++) { + center[iDim] = config->GetMotion_Origin(iDim); + omega[iDim] = config->GetRotation_Rate(iDim); + } + } element->ClearElement(); /*--- Restart the element to avoid adding over previous results. --*/ element->ComputeGrad_Linear(); /*--- Need to compute the gradients to obtain the Jacobian. ---*/ @@ -256,15 +272,26 @@ void CFEAElasticity::Compute_Dead_Load(CElement *element, const CConfig *config) /*--- The dead load is computed in the reference configuration ---*/ const auto Jac_X = element->GetJ_X(iGauss); - for (auto iNode = 0; iNode < nNode; iNode++) { + for (auto iNode = 0u; iNode < nNode; iNode++) { const auto Ni = element->GetNi(iNode,iGauss); - su2double FAux_Dead_Load[3] = {0.0,0.0,0.0}; + auto total_accel = acceleration; + if (centrifugal) { + /*--- For nonlinear this should probably use the current (deformed) + * coordinates, but it should not make a big difference. ---*/ + std::array r{}, wr{}, w2r{}; + for (auto iDim = 0u; iDim < nDim; iDim++) { + r[iDim] = element->GetRef_Coord(iNode, iDim) - center[iDim]; + } + GeometryToolbox::CrossProduct(omega.data(), r.data(), wr.data()); + GeometryToolbox::CrossProduct(omega.data(), wr.data(), w2r.data()); + for (auto iDim = 0; iDim < 3; ++iDim) total_accel[iDim] += w2r[iDim]; + } + std::array force{}; for (auto iDim = 0u; iDim < nDim; iDim++) { - FAux_Dead_Load[iDim] = Weight * Ni * Jac_X * Rho_s_DL * g_force[iDim]; + force[iDim] = Weight * Ni * Jac_X * Rho_s_DL * total_accel[iDim]; } - element->Add_FDL_a(iNode, FAux_Dead_Load); - + element->Add_FDL_a(iNode, force.data()); } } diff --git a/SU2_CFD/src/output/CAdjElasticityOutput.cpp b/SU2_CFD/src/output/CAdjElasticityOutput.cpp index 7466b506d60..add084006ea 100644 --- a/SU2_CFD/src/output/CAdjElasticityOutput.cpp +++ b/SU2_CFD/src/output/CAdjElasticityOutput.cpp @@ -113,7 +113,7 @@ void CAdjElasticityOutput::SetHistoryOutputFields(CConfig *config){ if (config->GetTime_Domain() && !config->GetPseudoStatic()) { AddHistoryOutput("SENS_RHO_" + iVarS, "Sens[Rho" + iVarS + ']', ScreenOutputFormat::SCIENTIFIC, "SENSITIVITY", "d Objective / d Material density"); } - if (config->GetDeadLoad()) { + if (config->GetGravityForce() || config->GetBody_Force() || config->GetCentrifugalForce()) { AddHistoryOutput("SENS_RHO_DL_" + iVarS, "Sens[RhoDL" + iVarS + ']', ScreenOutputFormat::SCIENTIFIC, "SENSITIVITY", "d Objective / d Dead load density"); } } @@ -151,7 +151,7 @@ inline void CAdjElasticityOutput::LoadHistoryData(CConfig *config, CGeometry *ge if (config->GetTime_Domain() && !config->GetPseudoStatic()) { SetHistoryOutputValue("SENS_RHO_" + iVarS, solver[ADJFEA_SOL]->GetTotal_Sens_Rho(iVar)); } - if (config->GetDeadLoad()) { + if (config->GetGravityForce() || config->GetBody_Force() || config->GetCentrifugalForce()) { SetHistoryOutputValue("SENS_RHO_DL_" + iVarS, solver[ADJFEA_SOL]->GetTotal_Sens_Rho_DL(iVar)); } } diff --git a/SU2_CFD/src/solvers/CFEASolver.cpp b/SU2_CFD/src/solvers/CFEASolver.cpp index 44a19e1421a..23bad36a8a4 100644 --- a/SU2_CFD/src/solvers/CFEASolver.cpp +++ b/SU2_CFD/src/solvers/CFEASolver.cpp @@ -49,7 +49,7 @@ CFEASolver::CFEASolver(LINEAR_SOLVER_MODE mesh_deform_mode) : CFEASolverBase(mes CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CFEASolverBase(geometry, config) { - bool dynamic = (config->GetTime_Domain()); + bool dynamic = config->GetTime_Domain(); config->SetDelta_UnstTimeND(config->GetDelta_UnstTime()); /*--- Test whether we consider dielectric elastomers ---*/ @@ -59,6 +59,7 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CFEASolverBase(ge element_based = false; topol_filter_applied = false; initial_calc = true; + body_forces = config->GetGravityForce() || config->GetBody_Force() || config->GetCentrifugalForce(); /*--- Here is where we assign the kind of each element ---*/ @@ -121,22 +122,15 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CFEASolverBase(ge /*--- The length of the solution vector depends on whether the problem is static or dynamic ---*/ - unsigned short nSolVar; string text_line, filename; ifstream restart_file; - if (dynamic) nSolVar = 3 * nVar; - else nSolVar = nVar; - - auto* SolInit = new su2double[nSolVar](); - /*--- Initialize from zero everywhere ---*/ - nodes = new CFEABoundVariable(SolInit, nPoint, nDim, nVar, config); + std::array zeros{}; + nodes = new CFEABoundVariable(zeros.data(), nPoint, nDim, nVar, config); SetBaseClassPointerToNodes(); - delete [] SolInit; - /*--- Set which points are vertices and allocate boundary data. ---*/ for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++) @@ -567,7 +561,6 @@ void CFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, const bool dynamic = config->GetTime_Domain(); const bool disc_adj_fem = (config->GetKind_Solver() == MAIN_SOLVER::DISC_ADJ_FEM); - const bool body_forces = config->GetDeadLoad(); const bool topology_mode = config->GetTopology_Optimization(); /* @@ -602,7 +595,7 @@ void CFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, * Only initialized once, at the first iteration of the first time step. */ if (body_forces && (initial_calc || disc_adj_fem)) - Compute_DeadLoad(geometry, numerics, config); + Compute_BodyForces(geometry, numerics, config); /*--- Clear the linear system solution. ---*/ SU2_OMP_PARALLEL @@ -1415,7 +1408,7 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, } -void CFEASolver::Compute_DeadLoad(CGeometry *geometry, CNumerics **numerics, const CConfig *config) { +void CFEASolver::Compute_BodyForces(CGeometry *geometry, CNumerics **numerics, const CConfig *config) { /*--- Start OpenMP parallel region. ---*/ @@ -1465,7 +1458,7 @@ void CFEASolver::Compute_DeadLoad(CGeometry *geometry, CNumerics **numerics, con /*--- Set the properties of the element and compute its mass matrix. ---*/ element->Set_ElProperties(element_properties[iElem]); - numerics[FEA_TERM + thread*MAX_TERMS]->Compute_Dead_Load(element, config); + numerics[FEA_TERM + thread*MAX_TERMS]->Compute_Body_Forces(element, config); /*--- Add contributions of this element to the mass matrix. ---*/ for (iNode = 0; iNode < nNodes; iNode++) { @@ -2113,7 +2106,6 @@ void CFEASolver::ImplicitNewmark_Iteration(const CGeometry *geometry, CNumerics const bool linear_analysis = (config->GetGeometricConditions() == STRUCT_DEFORMATION::SMALL); const bool nonlinear_analysis = (config->GetGeometricConditions() == STRUCT_DEFORMATION::LARGE); const bool newton_raphson = (config->GetKind_SpaceIteScheme_FEA() == STRUCT_SPACE_ITE::NEWTON); - const bool body_forces = config->GetDeadLoad(); /*--- For simplicity, no incremental loading is handled with increment of 1. ---*/ const su2double loadIncr = config->GetIncrementalLoad()? loadIncrement : su2double(1.0); @@ -2301,7 +2293,6 @@ void CFEASolver::GeneralizedAlpha_Iteration(const CGeometry *geometry, CNumerics const bool linear_analysis = (config->GetGeometricConditions() == STRUCT_DEFORMATION::SMALL); const bool nonlinear_analysis = (config->GetGeometricConditions() == STRUCT_DEFORMATION::LARGE); const bool newton_raphson = (config->GetKind_SpaceIteScheme_FEA() == STRUCT_SPACE_ITE::NEWTON); - const bool body_forces = config->GetDeadLoad(); /*--- Blend between previous and current timestep. ---*/ const su2double alpha_f = config->Get_Int_Coeffs(2); @@ -2925,9 +2916,6 @@ void CFEASolver::Compute_OFVolFrac(CGeometry *geometry, const CConfig *config) void CFEASolver::Compute_OFCompliance(CGeometry *geometry, const CConfig *config) { - /*--- Types of loads to consider ---*/ - const bool body_forces = config->GetDeadLoad(); - /*--- If the loads are being applied incrementaly ---*/ const bool incremental_load = config->GetIncrementalLoad(); diff --git a/SU2_CFD/src/variables/CFEAVariable.cpp b/SU2_CFD/src/variables/CFEAVariable.cpp index 7e486af3a21..4760706a814 100644 --- a/SU2_CFD/src/variables/CFEAVariable.cpp +++ b/SU2_CFD/src/variables/CFEAVariable.cpp @@ -46,7 +46,7 @@ CFEAVariable::CFEAVariable(const su2double *val_fea, unsigned long npoint, unsig * still work as expected for the primal solver). ---*/ const bool dynamic_analysis = config->GetTime_Domain(); - const bool body_forces = config->GetDeadLoad(); + const bool body_forces = config->GetGravityForce() || config->GetBody_Force() || config->GetCentrifugalForce(); const bool prestretch_fem = config->GetPrestretch(); // Structure is prestretched const bool discrete_adjoint = config->GetDiscrete_Adjoint(); const bool refgeom = config->GetRefGeom(); // Reference geometry needs to be stored diff --git a/TestCases/disc_adj_fea/configAD_fem.cfg b/TestCases/disc_adj_fea/configAD_fem.cfg index 188c7e451bf..fe1d2c6c5b7 100644 --- a/TestCases/disc_adj_fea/configAD_fem.cfg +++ b/TestCases/disc_adj_fea/configAD_fem.cfg @@ -16,7 +16,7 @@ RESTART_SOL= NO ITER = 10 -OBJECTIVE_FUNCTION = REFERENCE_GEOMETRY +OBJECTIVE_FUNCTION = REFERENCE_GEOMETRY REFERENCE_GEOMETRY = YES REFERENCE_GEOMETRY_FILENAME = reference_geometry.dat @@ -39,7 +39,6 @@ MATERIAL_COMPRESSIBILITY= COMPRESSIBLE ELASTICITY_MODULUS=21000 POISSON_RATIO=0.4 MATERIAL_DENSITY=100 -DEAD_LOAD=NO FORMULATION_ELASTICITY_2D = PLANE_STRAIN NONLINEAR_FEM_SOLUTION_METHOD = NEWTON_RAPHSON diff --git a/TestCases/py_wrapper/disc_adj_fea/flow_load_sens/configAD_fem.cfg b/TestCases/py_wrapper/disc_adj_fea/flow_load_sens/configAD_fem.cfg index 63edf6869cf..b5d0f15d944 100644 --- a/TestCases/py_wrapper/disc_adj_fea/flow_load_sens/configAD_fem.cfg +++ b/TestCases/py_wrapper/disc_adj_fea/flow_load_sens/configAD_fem.cfg @@ -35,7 +35,6 @@ MATERIAL_COMPRESSIBILITY= COMPRESSIBLE ELASTICITY_MODULUS=21000 POISSON_RATIO=0.4 MATERIAL_DENSITY=100 -DEAD_LOAD=NO FORMULATION_ELASTICITY_2D = PLANE_STRAIN NONLINEAR_FEM_SOLUTION_METHOD = NEWTON_RAPHSON diff --git a/config_template.cfg b/config_template.cfg index 2ecb8ca03b2..17891c34373 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -2023,10 +2023,7 @@ NONLINEAR_FEM_SOLUTION_METHOD= NEWTON_RAPHSON % Formulation for bidimensional elasticity solver FORMULATION_ELASTICITY_2D= PLANE_STRAIN % -% Apply dead loads -DEAD_LOAD= NO -% -% pseudo static analysis (no density in dynamic analysis) +% Pseudo static analysis (no density in dynamic analysis) PSEUDO_STATIC= NO % % Dynamic or static structural analysis (deprecated -> use TIME_DOMAIN) From bee055e4f89e2f00f3c32d186ceb6a904a1287ad Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Tue, 24 Dec 2024 19:12:01 -0800 Subject: [PATCH 061/129] add verification case --- .../numerics/elasticity/CFEAElasticity.cpp | 2 +- .../fea_fsi/rotating_cylinder/config.cfg | 34 +++++++++++++++++++ TestCases/parallel_regression.py | 12 +++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 TestCases/fea_fsi/rotating_cylinder/config.cfg diff --git a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp index ca3da2b26ae..efe0e19a0b2 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp @@ -285,7 +285,7 @@ void CFEAElasticity::Compute_Body_Forces(CElement *element, const CConfig *confi } GeometryToolbox::CrossProduct(omega.data(), r.data(), wr.data()); GeometryToolbox::CrossProduct(omega.data(), wr.data(), w2r.data()); - for (auto iDim = 0; iDim < 3; ++iDim) total_accel[iDim] += w2r[iDim]; + for (auto iDim = 0; iDim < 3; ++iDim) total_accel[iDim] -= w2r[iDim]; } std::array force{}; for (auto iDim = 0u; iDim < nDim; iDim++) { diff --git a/TestCases/fea_fsi/rotating_cylinder/config.cfg b/TestCases/fea_fsi/rotating_cylinder/config.cfg new file mode 100644 index 00000000000..7a9d124da76 --- /dev/null +++ b/TestCases/fea_fsi/rotating_cylinder/config.cfg @@ -0,0 +1,34 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% SU2 configuration file % +% Case description: Spinning Cylinder % +% Author: Pedro Gomes % +% Institution: SU2 Foundation % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +SOLVER= ELASTICITY +MATH_PROBLEM= DIRECT +GEOMETRIC_CONDITIONS= SMALL_DEFORMATIONS +MATERIAL_MODEL= LINEAR_ELASTIC + +ELASTICITY_MODULUS= 2E11 +POISSON_RATIO= 0.3 +MATERIAL_DENSITY= 7854 + +MARKER_SYM= ( x_minus, per_1, per_2 ) +MARKER_PRESSURE= ( inner, 0, outer, 0, x_plus, 0 ) + +CENTRIFUGAL_FORCE= YES +ROTATION_RATE= ( 1500, 0, 0 ) +MOTION_ORIGIN= ( 0, 0, 0 ) + +LINEAR_SOLVER= CONJUGATE_GRADIENT +LINEAR_SOLVER_PREC= ILU +LINEAR_SOLVER_ERROR= 1E-8 +LINEAR_SOLVER_ITER= 1000 + +SCREEN_OUTPUT= INNER_ITER, RMS_RES, LINSOL, VMS +OUTPUT_WRT_FREQ= 1 +INNER_ITER= 1 + +MESH_FILENAME= cylinder.su2 + diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index d60bd28e07e..b0c18f755b3 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -1225,6 +1225,18 @@ def main(): statbeam3d.command = TestCase.Command(exec = "parallel_computation_fsi.py", param = "-f") test_list.append(statbeam3d) + # Rotating cylinder, 3d + rotating_cylinder_fea = TestCase('rotating_cylinder_fea') + rotating_cylinder_fea.cfg_dir = "fea_fsi/rotating_cylinder" + rotating_cylinder_fea.cfg_file = "config.cfg" + rotating_cylinder_fea.test_iter = 0 + # For a thin disk with the inner and outer radius of this geometry, from + # "Formulas for Stress, Strain, and Structural Matrices", 2nd Edition, figure 19-4, + # the maximum stress is 165.6MPa, we get a Von Misses stress very close to that. + rotating_cylinder_fea.test_vals = [-1.986097, -1.023250, -1.022700, 47, -8.101266, 1.6458e+08] + rotating_cylinder_fea.command = TestCase.Command(exec = "parallel_computation_fsi.py", param = "-f") + test_list.append(rotating_cylinder_fea) + # Dynamic beam, 2d dynbeam2d = TestCase('dynbeam2d') dynbeam2d.cfg_dir = "fea_fsi/DynBeam_2d" From 28fb23ddef1d624dbbe485f122e8cab3123cfa67 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Wed, 25 Dec 2024 10:01:45 -0800 Subject: [PATCH 062/129] update values and config template --- TestCases/parallel_regression.py | 3 +- config_template.cfg | 49 +++++++++++++++----------------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index b0c18f755b3..8bc45cb6a8b 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -1233,8 +1233,7 @@ def main(): # For a thin disk with the inner and outer radius of this geometry, from # "Formulas for Stress, Strain, and Structural Matrices", 2nd Edition, figure 19-4, # the maximum stress is 165.6MPa, we get a Von Misses stress very close to that. - rotating_cylinder_fea.test_vals = [-1.986097, -1.023250, -1.022700, 47, -8.101266, 1.6458e+08] - rotating_cylinder_fea.command = TestCase.Command(exec = "parallel_computation_fsi.py", param = "-f") + rotating_cylinder_fea.test_vals = [-6.005467, -5.615543, -5.615527, 38, -8.126591, 1.6457e8] test_list.append(rotating_cylinder_fea) # Dynamic beam, 2d diff --git a/config_template.cfg b/config_template.cfg index 17891c34373..49cca43332b 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -1742,12 +1742,17 @@ KNOWLES_N= 1.0 % ID of the region we want to compute the sensitivities using direct differentiation FEA_ID_DIRECTDIFF= 0 % -% RESTART_STEADY_STATE= NO % % Time discretization TIME_DISCRE_FEA= NEWMARK_IMPLICIT % +% Iterative method for non-linear structural analysis +NONLINEAR_FEM_SOLUTION_METHOD= NEWTON_RAPHSON +% +% Pseudo static analysis (no density in dynamic analysis) +PSEUDO_STATIC= NO +% % Parameter alpha for Newmark scheme (s) NEWMARK_BETA= 0.25 % @@ -1781,6 +1786,9 @@ MATERIAL_MODEL= LINEAR_ELASTIC % Compressibility of the material MATERIAL_COMPRESSIBILITY= COMPRESSIBLE % +% Formulation for 2-dimensional elasticity solver +FORMULATION_ELASTICITY_2D= PLANE_STRAIN +% % -------------------- Dielectric effects ------------------% % % Include DE effects @@ -1794,6 +1802,20 @@ ELECTRIC_FIELD_MOD= 20e5 % % Direction of the Electic Fields ELECTRIC_FIELD_DIR= (0.0, 1.0) +% +% ------------------------ Prestretch -----------------------% +% +% Consider a prestretch in the structural domain +PRESTRETCH= NO +% +% Filename to input for prestretching membranes +PRESTRETCH_FILENAME= prestretch_file.dat +% +% ----------------------- Body Forces -----------------------% +% +% Centrifugal forces due to ROTATION_RATE around MOTION_ORIGIN. +% GRAVITY_FORCE and BODY_FORCE can also be used with the FEA solver. +CENTRIFUGAL_FORCE= NO % -------------------- Weakly Coupled Heat ------------------% % @@ -2010,31 +2032,6 @@ STRESS_PENALTY_PARAM= (1.0, 10.0) % Preaccumulation in the AD mode. PREACC= YES -% ---------------- PRESTRETCH FOR STRUCTURES -------------------% -% Consider a prestretch in the structural domain -PRESTRETCH= NO -% -% Filename to input for prestretching membranes -PRESTRETCH_FILENAME= prestretch_file.dat -% -% Iterative method for non-linear structural analysis -NONLINEAR_FEM_SOLUTION_METHOD= NEWTON_RAPHSON -% -% Formulation for bidimensional elasticity solver -FORMULATION_ELASTICITY_2D= PLANE_STRAIN -% -% Pseudo static analysis (no density in dynamic analysis) -PSEUDO_STATIC= NO -% -% Dynamic or static structural analysis (deprecated -> use TIME_DOMAIN) -DYNAMIC_ANALYSIS= NO -% -% Time Step for dynamic analysis (s) (deprecated -> use TIME_STEP) -DYN_TIMESTEP= 0.0 -% -% Total Physical Time for dual time stepping simulations (s) (deprecated -> use MAX_TIME) -DYN_TIME= 1.0 - % ---------------- MESH DEFORMATION PARAMETERS (NEW SOLVER) -------------------% % % Use the reformatted pseudo-elastic solver for grid deformation From 64d8ff6b50d90d98eb0b2ec979634a4661d595af Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 28 Dec 2024 12:13:32 -0800 Subject: [PATCH 063/129] remove axis-aligned restriction --- Common/include/linear_algebra/CSysMatrix.hpp | 4 +- Common/src/linear_algebra/CSysMatrix.cpp | 58 ++++++++++++++------ SU2_CFD/src/solvers/CFEASolver.cpp | 53 ++++++++++++------ TestCases/parallel_regression.py | 2 +- 4 files changed, 78 insertions(+), 39 deletions(-) diff --git a/Common/include/linear_algebra/CSysMatrix.hpp b/Common/include/linear_algebra/CSysMatrix.hpp index 815d52e0708..422a2068a88 100644 --- a/Common/include/linear_algebra/CSysMatrix.hpp +++ b/Common/include/linear_algebra/CSysMatrix.hpp @@ -805,10 +805,10 @@ class CSysMatrix { void EnforceSolutionAtNode(unsigned long node_i, const OtherType* x_i, CSysVector& b); /*! - * \brief Version of EnforceSolutionAtNode for a single degree of freedom. + * \brief Similar to EnforceSolutionAtNode, but for 0 projection in a given direction. */ template - void EnforceSolutionAtDOF(unsigned long node_i, unsigned long iVar, OtherType x_i, CSysVector& b); + void EnforceZeroProjection(unsigned long node_i, const OtherType* n, CSysVector& b); /*! * \brief Sets the diagonal entries of the matrix as the sum of the blocks in the corresponding column. diff --git a/Common/src/linear_algebra/CSysMatrix.cpp b/Common/src/linear_algebra/CSysMatrix.cpp index 4196f638678..9ef0c7b88de 100644 --- a/Common/src/linear_algebra/CSysMatrix.cpp +++ b/Common/src/linear_algebra/CSysMatrix.cpp @@ -1027,36 +1027,59 @@ void CSysMatrix::EnforceSolutionAtNode(const unsigned long node_i, c template template -void CSysMatrix::EnforceSolutionAtDOF(unsigned long node_i, unsigned long iVar, OtherType x_i, - CSysVector& b) { +void CSysMatrix::EnforceZeroProjection(unsigned long node_i, const OtherType* n, CSysVector& b) { for (auto index = row_ptr[node_i]; index < row_ptr[node_i + 1]; ++index) { const auto node_j = col_ind[index]; - /*--- Delete row iVar of block j on row i (bij) and ATTEMPT - * to delete column iVar block i on row j (bji). ---*/ + /*--- Remove product components of block j on row i (bij) and ATTEMPT + * to remove solution components of block i on row j (bji). + * This is identical to symmetry correction applied to gradients + * but extended to the entire matrix. ---*/ auto bij = &matrix[index * nVar * nVar]; auto bji = GetBlock(node_j, node_i); - /*--- The "attempt" part. ---*/ + /*--- Attempt to remove solution components. ---*/ + ScalarType nbn{}; if (bji != nullptr) { - for (auto jVar = 0ul; jVar < nVar; ++jVar) { - /*--- Column product. ---*/ - b[node_j * nVar + jVar] -= bji[jVar * nVar + iVar] * x_i; - /*--- Delete entries. ---*/ - bji[jVar * nVar + iVar] = 0.0; + for (auto iVar = 0ul; iVar < nVar; ++iVar) { + ScalarType proj{}; + for (auto jVar = 0ul; jVar < nVar; ++jVar) { + proj += bji[iVar * nVar + jVar] * PassiveAssign(n[jVar]); + } + for (auto jVar = 0ul; jVar < nVar; ++jVar) { + bji[iVar * nVar + jVar] -= proj * PassiveAssign(n[jVar]); + } + nbn += proj * PassiveAssign(n[iVar]); } } - /*--- Delete row. ---*/ - for (auto jVar = 0ul; jVar < nVar; ++jVar) bij[iVar * nVar + jVar] = 0.0; + /*--- Product components. ---*/ + for (auto jVar = 0ul; jVar < nVar; ++jVar) { + ScalarType proj{}; + for (auto iVar = 0ul; iVar < nVar; ++iVar) { + proj += bij[iVar * nVar + jVar] * PassiveAssign(n[iVar]); + } + for (auto iVar = 0ul; iVar < nVar; ++iVar) { + bij[iVar * nVar + jVar] -= proj * PassiveAssign(n[iVar]); + } + } - /*--- Set the diagonal entry of the block to 1. ---*/ - if (node_j == node_i) bij[iVar * (nVar + 1)] = 1.0; + /*--- This part doesn't have the "*2" factor because the product components + * were removed from the result of removing the solution components + * instead of from the original block (bji == bij). ---*/ + if (node_i == node_j) { + for (auto iVar = 0ul; iVar < nVar; ++iVar) { + for (auto jVar = 0ul; jVar < nVar; ++jVar) { + bij[iVar * nVar + jVar] += PassiveAssign(n[iVar]) * nbn * PassiveAssign(n[jVar]); + } + } + } } - /*--- Set known solution in rhs vector. ---*/ - b(node_i, iVar) = x_i; + OtherType proj{}; + for (auto iVar = 0ul; iVar < nVar; ++iVar) proj += b(node_i, iVar) * n[iVar]; + for (auto iVar = 0ul; iVar < nVar; ++iVar) b(node_i, iVar) -= proj * n[iVar]; } template @@ -1203,8 +1226,7 @@ void CSysMatrix::ComputePastixPreconditioner(const CSysVector; \ template void CSysMatrix::EnforceSolutionAtNode(unsigned long, const su2double*, CSysVector&); \ - template void CSysMatrix::EnforceSolutionAtDOF(unsigned long, unsigned long, su2double, \ - CSysVector&); \ + template void CSysMatrix::EnforceZeroProjection(unsigned long, const su2double*, CSysVector&); \ INSTANTIATE_COMMS(TYPE) #ifdef CODI_FORWARD_TYPE diff --git a/SU2_CFD/src/solvers/CFEASolver.cpp b/SU2_CFD/src/solvers/CFEASolver.cpp index 23bad36a8a4..9d19aa7c5a0 100644 --- a/SU2_CFD/src/solvers/CFEASolver.cpp +++ b/SU2_CFD/src/solvers/CFEASolver.cpp @@ -1588,6 +1588,20 @@ void CFEASolver::BC_Clamped_Post(CGeometry *geometry, const CConfig *config, uns } +namespace { +/*--- Helper for BC_Sym_Plane ---*/ +template +void SubtractProjection(unsigned short nDim, const su2double* n, const Read& read, const Write& write) { + su2double tmp[3] = {}; + for (auto iDim = 0u; iDim < nDim; ++iDim) tmp[iDim] = read(iDim); + const su2double proj = DotProduct(nDim, tmp, n); + for (auto iDim = 0u; iDim < nDim; ++iDim) { + tmp[iDim] -= proj * n[iDim]; + write(iDim, tmp[iDim]); + } +} +} + void CFEASolver::BC_Sym_Plane(CGeometry *geometry, const CConfig *config, unsigned short val_marker) { if (geometry->GetnElem_Bound(val_marker) == 0) return; @@ -1610,14 +1624,8 @@ void CFEASolver::BC_Sym_Plane(CGeometry *geometry, const CConfig *config, unsign case 3: TriangleNormal(nodeCoord, normal); break; case 4: QuadrilateralNormal(nodeCoord, normal); break; } - - auto axis = 0u; - for (auto iDim = 1u; iDim < MAXNDIM; ++iDim) - axis = (fabs(normal[iDim]) > fabs(normal[axis]))? iDim : axis; - - if (fabs(normal[axis]) < 0.99*Norm(int(MAXNDIM),normal)) { - SU2_MPI::Error("The structural solver only supports axis-aligned symmetry planes.",CURRENT_FUNCTION); - } + const su2double area = Norm(int(MAXNDIM), normal); + for (auto iDim = 0u; iDim < MAXNDIM; ++iDim) normal[iDim] /= area; /*--- Impose zero displacement perpendicular to the symmetry plane. ---*/ @@ -1627,20 +1635,29 @@ void CFEASolver::BC_Sym_Plane(CGeometry *geometry, const CConfig *config, unsign const auto iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); /*--- Set and enforce solution at current and previous time-step ---*/ - nodes->SetSolution(iPoint, axis, 0.0); +#define SUBTRACT_PROJECTION(READ, WRITE) \ + SubtractProjection(nDim, normal, [&](unsigned short iDim) { return nodes->READ(iPoint, iDim); }, \ + [&](unsigned short iDim, const su2double& x) { nodes->WRITE(iPoint, iDim, x); }); + SUBTRACT_PROJECTION(GetSolution, SetSolution) if (dynamic) { - nodes->SetSolution_Vel(iPoint, axis, 0.0); - nodes->SetSolution_Accel(iPoint, axis, 0.0); - nodes->Set_Solution_time_n(iPoint, axis, 0.0); - nodes->SetSolution_Vel_time_n(iPoint, axis, 0.0); - nodes->SetSolution_Accel_time_n(iPoint, axis, 0.0); + SUBTRACT_PROJECTION(GetSolution_Vel, SetSolution_Vel) + SUBTRACT_PROJECTION(GetSolution_Accel, SetSolution_Accel) + SUBTRACT_PROJECTION(GetSolution_time_n, Set_Solution_time_n) + SUBTRACT_PROJECTION(GetSolution_Vel_time_n, SetSolution_Vel_time_n) + SUBTRACT_PROJECTION(GetSolution_Accel_time_n, SetSolution_Accel_time_n) } /*--- Set and enforce 0 solution for mesh deformation ---*/ - nodes->SetBound_Disp(iPoint, axis, 0.0); - LinSysSol(iPoint, axis) = 0.0; - if (LinSysReact.GetLocSize() > 0) LinSysReact(iPoint, axis) = 0.0; - Jacobian.EnforceSolutionAtDOF(iPoint, axis, su2double(0.0), LinSysRes); + SUBTRACT_PROJECTION(GetBound_Disp, SetBound_Disp) +#undef SUBTRACT_PROJECTION + + SubtractProjection(nDim, normal, [&](unsigned short iDim) { return LinSysSol(iPoint, iDim); }, + [&](unsigned short iDim, const su2double& x) { LinSysSol(iPoint, iDim) = x; }); + if (LinSysReact.GetLocSize() > 0) { + SubtractProjection(nDim, normal, [&](unsigned short iDim) { return LinSysReact(iPoint, iDim); }, + [&](unsigned short iDim, const su2double& x) { LinSysReact(iPoint, iDim) = x; }); + } + Jacobian.EnforceZeroProjection(iPoint, normal, LinSysRes); } diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 8bc45cb6a8b..530328b52a6 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -1233,7 +1233,7 @@ def main(): # For a thin disk with the inner and outer radius of this geometry, from # "Formulas for Stress, Strain, and Structural Matrices", 2nd Edition, figure 19-4, # the maximum stress is 165.6MPa, we get a Von Misses stress very close to that. - rotating_cylinder_fea.test_vals = [-6.005467, -5.615543, -5.615527, 38, -8.126591, 1.6457e8] + rotating_cylinder_fea.test_vals = [-6.861940, -6.835545, -6.895500, 22, -8.313847, 1.6502e+08] test_list.append(rotating_cylinder_fea) # Dynamic beam, 2d From dc862fd6bb76ea1dbfefdf34c00fe0a99dbd715e Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sun, 29 Dec 2024 22:24:23 +0100 Subject: [PATCH 064/129] compact restart testcases quick update --- TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg | 2 +- TestCases/disc_adj_rans/naca0012/naca0012.cfg | 2 +- .../02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg | 2 +- .../lam_prem_ch4_cht_cfd_fluid.cfg | 2 +- .../lam_prem_ch4_cht_ad_fluid.cfg | 2 +- TestCases/optimization_rans/naca0012/naca0012.cfg | 2 +- TestCases/radiation/p1adjoint/configp1adjoint.cfg | 2 +- TestCases/rans/oneram6/turb_ONERAM6.cfg | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg b/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg index 1911bdef3b7..b7f4b338875 100644 --- a/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg +++ b/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg @@ -127,7 +127,7 @@ SURFACE_ADJ_FILENAME= surface_adjoint OUTPUT_WRT_FREQ= 250 SCREEN_OUTPUT = (INNER_ITER, RMS_ADJ_DENSITY, RMS_ADJ_ENERGY, SENS_GEO, SENS_AOA, RMS_DENSITY, RMS_ENERGY, LIFT, DRAG) HISTORY_OUTPUT= (ITER, RMS_RES, AERO_COEFF, SENSITIVITY) -WRT_RESTART_COMPACT = NO +WRT_RESTART_COMPACT = YES VOLUME_OUTPUT= (COORDINATES, SOLUTION, PRESSURE, TEMPERATURE, SENSITIVITY) OUTPUT_FILES=(RESTART_ASCII, PARAVIEW, SURFACE_CSV) diff --git a/TestCases/disc_adj_rans/naca0012/naca0012.cfg b/TestCases/disc_adj_rans/naca0012/naca0012.cfg index 6a722eead1c..3af10b754e4 100644 --- a/TestCases/disc_adj_rans/naca0012/naca0012.cfg +++ b/TestCases/disc_adj_rans/naca0012/naca0012.cfg @@ -105,7 +105,7 @@ CONV_FILENAME= 0_history RESTART_FILENAME= restart_flow.dat RESTART_ADJ_FILENAME= restart_adj.dat VOLUME_FILENAME= flow -WRT_RESTART_COMPACT= NO +WRT_RESTART_COMPACT= YES SURFACE_FILENAME= surface_flow OUTPUT_WRT_FREQ= 1 % diff --git a/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg b/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg index b79c1f3b367..8df82d47a78 100644 --- a/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg +++ b/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg @@ -128,7 +128,7 @@ MARKER_ANALYZE_AVERAGE= MASSFLUX OUTPUT_FILES= RESTART, RESTART_ASCII, PARAVIEW VOLUME_OUTPUT= RESIDUAL, PRIMITIVE VOLUME_ADJ_FILENAME= ch4_flame_hx_ad -WRT_RESTART_COMPACT = NO +WRT_RESTART_COMPACT = YES OUTPUT_WRT_FREQ= 100 % GRAD_OBJFUNC_FILENAME= of_grad.csv diff --git a/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg b/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg index af8e562b0cd..6ba0b04835c 100644 --- a/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg +++ b/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg @@ -19,7 +19,7 @@ HISTORY_OUTPUT= RMS_RES AERO_COEFF FLOW_COEFF FLOW_COEFF_SURF VOLUME_OUTPUT= SOLUTION PRIMITIVE SOURCE RESIDUAL LOOKUP -WRT_RESTART_COMPACT = NO +WRT_RESTART_COMPACT = YES OUTPUT_FILES= (RESTART_ASCII, PARAVIEW) diff --git a/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg b/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg index b251e54182a..060f9be0663 100644 --- a/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg +++ b/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg @@ -23,7 +23,7 @@ VOLUME_OUTPUT= SOLUTION PRIMITIVE SOURCE RESIDUAL LOOKUP OUTPUT_FILES= ( RESTART_ASCII) -WRT_RESTART_COMPACT= NO +WRT_RESTART_COMPACT= YES INNER_ITER= 1 diff --git a/TestCases/optimization_rans/naca0012/naca0012.cfg b/TestCases/optimization_rans/naca0012/naca0012.cfg index a9d0b530419..bc277d88e48 100644 --- a/TestCases/optimization_rans/naca0012/naca0012.cfg +++ b/TestCases/optimization_rans/naca0012/naca0012.cfg @@ -107,7 +107,7 @@ RESTART_ADJ_FILENAME= restart_adj.dat VOLUME_FILENAME= flow SURFACE_FILENAME= surface_flow OUTPUT_WRT_FREQ= 1 -WRT_RESTART_COMPACT= NO +WRT_RESTART_COMPACT= YES % % ----------------------- DESIGN VARIABLE PARAMETERS --------------------------% % diff --git a/TestCases/radiation/p1adjoint/configp1adjoint.cfg b/TestCases/radiation/p1adjoint/configp1adjoint.cfg index cdbad6937b7..54d80d40a24 100644 --- a/TestCases/radiation/p1adjoint/configp1adjoint.cfg +++ b/TestCases/radiation/p1adjoint/configp1adjoint.cfg @@ -131,7 +131,7 @@ FFD_CONTINUITY = 2ND_DERIVATIVE %%%%%%%%%%%%%%%%%%%%%%% OUTPUT_FILES = (RESTART, PARAVIEW) -WRT_RESTART_COMPACT = NO +WRT_RESTART_COMPACT = YES SOLUTION_FILENAME = solution_rht RESTART_FILENAME = restart_rht VOLUME_FILENAME = volume_rht diff --git a/TestCases/rans/oneram6/turb_ONERAM6.cfg b/TestCases/rans/oneram6/turb_ONERAM6.cfg index d38d71b3287..f7a3ce88e2e 100644 --- a/TestCases/rans/oneram6/turb_ONERAM6.cfg +++ b/TestCases/rans/oneram6/turb_ONERAM6.cfg @@ -110,7 +110,7 @@ MESH_OUT_FILENAME= mesh_out.su2 SOLUTION_FILENAME= restart_flow.dat SOLUTION_ADJ_FILENAME= solution_adj.dat OUTPUT_FILES=(RESTART, STL_ASCII, PARAVIEW, SURFACE_PARAVIEW) -WRT_RESTART_COMPACT = NO +WRT_RESTART_COMPACT = YES TABULAR_FORMAT= CSV CONV_FILENAME= history RESTART_FILENAME= restart_flow.dat From 76fddc4312b156f76162d9e9c386676a8a834d08 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Tue, 31 Dec 2024 08:54:44 +0100 Subject: [PATCH 065/129] compact restart for flamelet --- .../lam_prem_ch4_cht_cfd_fluid.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg b/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg index 6ba0b04835c..af8e562b0cd 100644 --- a/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg +++ b/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg @@ -19,7 +19,7 @@ HISTORY_OUTPUT= RMS_RES AERO_COEFF FLOW_COEFF FLOW_COEFF_SURF VOLUME_OUTPUT= SOLUTION PRIMITIVE SOURCE RESIDUAL LOOKUP -WRT_RESTART_COMPACT = YES +WRT_RESTART_COMPACT = NO OUTPUT_FILES= (RESTART_ASCII, PARAVIEW) From 7a66387f461f90cc786341b4ee797341530ca75f Mon Sep 17 00:00:00 2001 From: bigfooted Date: Tue, 31 Dec 2024 13:36:39 +0100 Subject: [PATCH 066/129] remove unnecessary WRT_COMPACT_RESTART statements --- TestCases/disc_adj_rans/naca0012/naca0012.cfg | 1 - .../02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg | 2 +- .../lam_prem_ch4_cht_ad_fluid.cfg | 2 +- TestCases/optimization_rans/naca0012/naca0012.cfg | 1 - TestCases/radiation/p1adjoint/configp1adjoint.cfg | 1 - TestCases/rans/oneram6/turb_ONERAM6.cfg | 1 - 6 files changed, 2 insertions(+), 6 deletions(-) diff --git a/TestCases/disc_adj_rans/naca0012/naca0012.cfg b/TestCases/disc_adj_rans/naca0012/naca0012.cfg index 3af10b754e4..9a84427b263 100644 --- a/TestCases/disc_adj_rans/naca0012/naca0012.cfg +++ b/TestCases/disc_adj_rans/naca0012/naca0012.cfg @@ -105,7 +105,6 @@ CONV_FILENAME= 0_history RESTART_FILENAME= restart_flow.dat RESTART_ADJ_FILENAME= restart_adj.dat VOLUME_FILENAME= flow -WRT_RESTART_COMPACT= YES SURFACE_FILENAME= surface_flow OUTPUT_WRT_FREQ= 1 % diff --git a/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg b/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg index 8df82d47a78..b79c1f3b367 100644 --- a/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg +++ b/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg @@ -128,7 +128,7 @@ MARKER_ANALYZE_AVERAGE= MASSFLUX OUTPUT_FILES= RESTART, RESTART_ASCII, PARAVIEW VOLUME_OUTPUT= RESIDUAL, PRIMITIVE VOLUME_ADJ_FILENAME= ch4_flame_hx_ad -WRT_RESTART_COMPACT = YES +WRT_RESTART_COMPACT = NO OUTPUT_WRT_FREQ= 100 % GRAD_OBJFUNC_FILENAME= of_grad.csv diff --git a/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg b/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg index 060f9be0663..b251e54182a 100644 --- a/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg +++ b/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg @@ -23,7 +23,7 @@ VOLUME_OUTPUT= SOLUTION PRIMITIVE SOURCE RESIDUAL LOOKUP OUTPUT_FILES= ( RESTART_ASCII) -WRT_RESTART_COMPACT= YES +WRT_RESTART_COMPACT= NO INNER_ITER= 1 diff --git a/TestCases/optimization_rans/naca0012/naca0012.cfg b/TestCases/optimization_rans/naca0012/naca0012.cfg index bc277d88e48..763109d820a 100644 --- a/TestCases/optimization_rans/naca0012/naca0012.cfg +++ b/TestCases/optimization_rans/naca0012/naca0012.cfg @@ -107,7 +107,6 @@ RESTART_ADJ_FILENAME= restart_adj.dat VOLUME_FILENAME= flow SURFACE_FILENAME= surface_flow OUTPUT_WRT_FREQ= 1 -WRT_RESTART_COMPACT= YES % % ----------------------- DESIGN VARIABLE PARAMETERS --------------------------% % diff --git a/TestCases/radiation/p1adjoint/configp1adjoint.cfg b/TestCases/radiation/p1adjoint/configp1adjoint.cfg index 54d80d40a24..15603eea1a6 100644 --- a/TestCases/radiation/p1adjoint/configp1adjoint.cfg +++ b/TestCases/radiation/p1adjoint/configp1adjoint.cfg @@ -131,7 +131,6 @@ FFD_CONTINUITY = 2ND_DERIVATIVE %%%%%%%%%%%%%%%%%%%%%%% OUTPUT_FILES = (RESTART, PARAVIEW) -WRT_RESTART_COMPACT = YES SOLUTION_FILENAME = solution_rht RESTART_FILENAME = restart_rht VOLUME_FILENAME = volume_rht diff --git a/TestCases/rans/oneram6/turb_ONERAM6.cfg b/TestCases/rans/oneram6/turb_ONERAM6.cfg index f7a3ce88e2e..a43f3974459 100644 --- a/TestCases/rans/oneram6/turb_ONERAM6.cfg +++ b/TestCases/rans/oneram6/turb_ONERAM6.cfg @@ -110,7 +110,6 @@ MESH_OUT_FILENAME= mesh_out.su2 SOLUTION_FILENAME= restart_flow.dat SOLUTION_ADJ_FILENAME= solution_adj.dat OUTPUT_FILES=(RESTART, STL_ASCII, PARAVIEW, SURFACE_PARAVIEW) -WRT_RESTART_COMPACT = YES TABULAR_FORMAT= CSV CONV_FILENAME= history RESTART_FILENAME= restart_flow.dat From 60d7256ebc68716d26d404dfdb3121569648c766 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 1 Jan 2025 01:16:42 +0100 Subject: [PATCH 067/129] remove unnecessary WRT_COMPACT_RESTART statements --- SU2_CFD/src/output/COutput.cpp | 2 -- TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg | 1 - TestCases/py_wrapper/wavy_wall/run_steady.py | 1 - TestCases/radiation/p1adjoint/configp1adjoint.cfg | 1 + 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 1400e6378ba..4c0ce5e096f 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1590,8 +1590,6 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ } } - //volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); - unsigned short nVolumeFields = 0; for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { diff --git a/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg b/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg index b7f4b338875..7a63c1ff189 100644 --- a/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg +++ b/TestCases/cont_adj_euler/naca0012/inv_NACA0012.cfg @@ -127,7 +127,6 @@ SURFACE_ADJ_FILENAME= surface_adjoint OUTPUT_WRT_FREQ= 250 SCREEN_OUTPUT = (INNER_ITER, RMS_ADJ_DENSITY, RMS_ADJ_ENERGY, SENS_GEO, SENS_AOA, RMS_DENSITY, RMS_ENERGY, LIFT, DRAG) HISTORY_OUTPUT= (ITER, RMS_RES, AERO_COEFF, SENSITIVITY) -WRT_RESTART_COMPACT = YES VOLUME_OUTPUT= (COORDINATES, SOLUTION, PRESSURE, TEMPERATURE, SENSITIVITY) OUTPUT_FILES=(RESTART_ASCII, PARAVIEW, SURFACE_CSV) diff --git a/TestCases/py_wrapper/wavy_wall/run_steady.py b/TestCases/py_wrapper/wavy_wall/run_steady.py index db40659c68b..4a90995ace1 100644 --- a/TestCases/py_wrapper/wavy_wall/run_steady.py +++ b/TestCases/py_wrapper/wavy_wall/run_steady.py @@ -93,7 +93,6 @@ primal_settings = """ MATH_PROBLEM= DIRECT RESTART_SOL= YES -WRT_RESTART_COMPACT= NO CFL_NUMBER= 1000 LINEAR_SOLVER= FGMRES LINEAR_SOLVER_PREC= ILU diff --git a/TestCases/radiation/p1adjoint/configp1adjoint.cfg b/TestCases/radiation/p1adjoint/configp1adjoint.cfg index 15603eea1a6..93740e5ea95 100644 --- a/TestCases/radiation/p1adjoint/configp1adjoint.cfg +++ b/TestCases/radiation/p1adjoint/configp1adjoint.cfg @@ -131,6 +131,7 @@ FFD_CONTINUITY = 2ND_DERIVATIVE %%%%%%%%%%%%%%%%%%%%%%% OUTPUT_FILES = (RESTART, PARAVIEW) + SOLUTION_FILENAME = solution_rht RESTART_FILENAME = restart_rht VOLUME_FILENAME = volume_rht From e599fa10adc3bdb7d175b41d597e0acb2392cbc2 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Wed, 1 Jan 2025 13:56:44 -0800 Subject: [PATCH 068/129] index cache for compact --- SU2_CFD/include/output/COutput.hpp | 47 +++--- SU2_CFD/src/output/CElasticityOutput.cpp | 17 +- SU2_CFD/src/output/COutput.cpp | 155 +++++++----------- .../output/filewriter/CParallelDataSorter.cpp | 3 +- TestCases/parallel_regression.py | 2 +- TestCases/py_wrapper/wavy_wall/run_steady.py | 1 + config_template.cfg | 8 +- 7 files changed, 102 insertions(+), 131 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index eea8188ed46..e39b047ce82 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -241,17 +241,16 @@ class COutput { /*----------------------------- Volume output ----------------------------*/ - CParallelDataSorter* volumeDataSorter; //!< Volume data sorter - CParallelDataSorter* volumeDataSorterCompact; //!< Volume data sorter - CParallelDataSorter* surfaceDataSorter; //!< Surface data sorter + CParallelDataSorter* volumeDataSorter; //!< Volume data sorter. + CParallelDataSorter* volumeDataSorterCompact; //!< Volume data sorter for compact files. + CParallelDataSorter* surfaceDataSorter; //!< Surface data sorter. - vector volumeFieldNames; //!< Vector containing the volume field names + vector volumeFieldNames; //!< Vector containing the volume field names. + vector requiredVolumeFieldNames; //!< Vector containing the minimum required volume field names. - vector requiredVolumeFieldNames; //!< Vector containing the minimum required volume field names. - - string volumeFilename, //!< Volume output filename - surfaceFilename, //!< Surface output filename - restartFilename; //!< Restart output filename + string volumeFilename, //!< Volume output filename. + surfaceFilename, //!< Surface output filename. + restartFilename; //!< Restart output filename. /** \brief Structure to store information for a volume output field. * @@ -269,28 +268,32 @@ class COutput { /*! \brief String containing the description of the field. */ string description; /*! \brief Default constructor. */ - VolumeOutputField () {} + VolumeOutputField() = default; /*! \brief Constructor to initialize all members. */ VolumeOutputField(string fieldName_, int offset_, string volumeOutputGroup_, string description_): - fieldName(std::move(fieldName_)), offset(std::move(offset_)), - outputGroup(std::move(volumeOutputGroup_)), description(std::move(description_)){} + fieldName(std::move(fieldName_)), + offset(offset_), + outputGroup(std::move(volumeOutputGroup_)), + description(std::move(description_)) {} }; /*! \brief Associative map to access data stored in the volume output fields by a string identifier. */ - std::map volumeOutput_Map; + std::map volumeOutput_Map; /*! \brief Vector that contains the keys of the ::volumeOutput_Map in the order of their insertion. */ - std::vector volumeOutput_List; + std::vector volumeOutput_List; + + /*! \brief Whether the field index caches should be build. */ + bool buildFieldIndexCache; + + /*! \brief Vectors to cache the positions of the fields in the data array. */ + std::vector fieldIndexCache, fieldIndexCacheCompact; + /*! \brief Current value of the cache indices. */ + unsigned short cachePosition; /*! \brief Vector to cache the positions of the field in the data array. */ - std::vector fieldIndexCache; - /*! \brief Current value of the cache index. */ - unsigned short cachePosition; - /*! \brief Boolean to store whether the field index cache should be build. */ - bool buildFieldIndexCache; - /*! \brief Vector to cache the positions of the field in the data array. */ - std::vector fieldGetIndexCache; + std::vector fieldGetIndexCache; /*! \brief Current value of the cache index. */ - unsigned short curGetFieldIndex; + unsigned short curGetFieldIndex; /*! \brief Requested volume field names in the config file. */ std::vector requestedVolumeFields; diff --git a/SU2_CFD/src/output/CElasticityOutput.cpp b/SU2_CFD/src/output/CElasticityOutput.cpp index a2abc4e6d12..1af62426cce 100644 --- a/SU2_CFD/src/output/CElasticityOutput.cpp +++ b/SU2_CFD/src/output/CElasticityOutput.cpp @@ -235,21 +235,20 @@ void CElasticityOutput::SetVolumeOutputFields(CConfig *config){ // Grid coordinates AddVolumeOutput("COORD-X", "x", "COORDINATES", "x-component of the coordinate vector"); AddVolumeOutput("COORD-Y", "y", "COORDINATES", "y-component of the coordinate vector"); - if (nDim == 3) - AddVolumeOutput("COORD-Z", "z", "COORDINATES", "z-component of the coordinate vector"); + if (nDim == 3) AddVolumeOutput("COORD-Z", "z", "COORDINATES", "z-component of the coordinate vector"); AddVolumeOutput("DISPLACEMENT-X", "Displacement_x", "SOLUTION", "x-component of the displacement vector"); AddVolumeOutput("DISPLACEMENT-Y", "Displacement_y", "SOLUTION", "y-component of the displacement vector"); if (nDim == 3) AddVolumeOutput("DISPLACEMENT-Z", "Displacement_z", "SOLUTION", "z-component of the displacement vector"); - if(dynamic){ - AddVolumeOutput("VELOCITY-X", "Velocity_x", "VELOCITY", "x-component of the velocity vector"); - AddVolumeOutput("VELOCITY-Y", "Velocity_y", "VELOCITY", "y-component of the velocity vector"); - if (nDim == 3) AddVolumeOutput("VELOCITY-Z", "Velocity_z", "VELOCITY", "z-component of the velocity vector"); + if (dynamic) { + AddVolumeOutput("VELOCITY-X", "Velocity_x", "SOLUTION", "x-component of the velocity vector"); + AddVolumeOutput("VELOCITY-Y", "Velocity_y", "SOLUTION", "y-component of the velocity vector"); + if (nDim == 3) AddVolumeOutput("VELOCITY-Z", "Velocity_z", "SOLUTION", "z-component of the velocity vector"); - AddVolumeOutput("ACCELERATION-X", "Acceleration_x", "ACCELERATION", "x-component of the acceleration vector"); - AddVolumeOutput("ACCELERATION-Y", "Acceleration_y", "ACCELERATION", "y-component of the acceleration vector"); - if (nDim == 3) AddVolumeOutput("ACCELERATION-Z", "Acceleration_z", "ACCELERATION", "z-component of the acceleration vector"); + AddVolumeOutput("ACCELERATION-X", "Acceleration_x", "SOLUTION", "x-component of the acceleration vector"); + AddVolumeOutput("ACCELERATION-Y", "Acceleration_y", "SOLUTION", "y-component of the acceleration vector"); + if (nDim == 3) AddVolumeOutput("ACCELERATION-Z", "Acceleration_z", "SOLUTION", "z-component of the acceleration vector"); } AddVolumeOutput("STRESS-XX", "Sxx", "STRESS", "x-component of the normal stress vector"); diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 4c0ce5e096f..bfb0b6329c5 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -173,7 +173,6 @@ COutput::COutput(const CConfig *config, unsigned short ndim, bool fem_output): convergence = false; buildFieldIndexCache = false; - curInnerIter = 0; curOuterIter = 0; curTimeIter = 0; @@ -345,7 +344,7 @@ void COutput::AllocateDataSorters(CConfig *config, CGeometry *geometry){ if (volumeDataSorter == nullptr) volumeDataSorter = new CFEMDataSorter(config, geometry, volumeFieldNames); - if (volumeDataSorterCompact == nullptr) + if (config->GetWrt_Restart_Compact() && volumeDataSorterCompact == nullptr) volumeDataSorterCompact = new CFEMDataSorter(config, geometry, requiredVolumeFieldNames); if (surfaceDataSorter == nullptr) @@ -357,7 +356,7 @@ void COutput::AllocateDataSorters(CConfig *config, CGeometry *geometry){ if (volumeDataSorter == nullptr) volumeDataSorter = new CFVMDataSorter(config, geometry, volumeFieldNames); - if (volumeDataSorterCompact == nullptr) + if (config->GetWrt_Restart_Compact() && volumeDataSorterCompact == nullptr) volumeDataSorterCompact = new CFVMDataSorter(config, geometry, requiredVolumeFieldNames); if (surfaceDataSorter == nullptr) @@ -423,9 +422,6 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form /*--- If we have compact restarts, we use only the required fields. ---*/ if (config->GetWrt_Restart_Compact()) surfaceDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); - else - surfaceDataSorter->SetRequiredFieldNames(surfaceDataSorter->GetFieldNames()); - surfaceDataSorter->SortConnectivity(config, geometry); surfaceDataSorter->SortOutputData(); @@ -445,12 +441,9 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form if (!config->GetWrt_Restart_Overwrite()) filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); - /*--- If we have compact restarts, we use only the required fields. ---*/ if (config->GetWrt_Restart_Compact()) volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames); - else - volumeDataSorter->SetRequiredFieldNames(volumeDataSorter->GetFieldNames()); LogOutputFiles("SU2 ASCII restart"); fileWriter = new CSU2FileWriter(volumeDataSorter); @@ -467,18 +460,14 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form if (!config->GetWrt_Restart_Overwrite()) filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); - /*--- If we have compact restarts, we use only the required fields. ---*/ - if (config->GetWrt_Restart_Compact()) - volumeDataSorterCompact->SetRequiredFieldNames(requiredVolumeFieldNames); - else - volumeDataSorter->SetRequiredFieldNames(volumeDataSorter->GetFieldNames()); - LogOutputFiles("SU2 binary restart"); - if (config->GetWrt_Restart_Compact()) + if (config->GetWrt_Restart_Compact()) { + /*--- If we have compact restarts, we use only the required fields. ---*/ + volumeDataSorterCompact->SetRequiredFieldNames(requiredVolumeFieldNames); fileWriter = new CSU2BinaryFileWriter(volumeDataSorterCompact); - else + } else { fileWriter = new CSU2BinaryFileWriter(volumeDataSorter); - + } break; case OUTPUT_TYPE::MESH: @@ -857,7 +846,7 @@ bool COutput::SetResultFiles(CGeometry *geometry, CConfig *config, CSolver** sol /*--- Partition and sort the data --- */ volumeDataSorter->SortOutputData(); - volumeDataSorterCompact->SortOutputData(); + if (volumeDataSorterCompact != nullptr) volumeDataSorterCompact->SortOutputData(); if (rank == MASTER_NODE && !isFileWrite) { fileWritingTable->SetAlign(PrintingToolbox::CTablePrinter::CENTER); @@ -1536,21 +1525,17 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ SetVolumeOutputFields(config); - /*--- Coordinates must be always in the output. - * If they are not requested, add them here. ---*/ - auto itCoord = std::find(requestedVolumeFields.begin(), - requestedVolumeFields.end(), "COORDINATES"); + /*--- Coordinates must be always in the output. If they are not requested, add them here. ---*/ + auto itCoord = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COORDINATES"); if (itCoord == requestedVolumeFields.end()) { requestedVolumeFields.emplace_back("COORDINATES"); nRequestedVolumeFields++; } /*--- Add the solution if it was not requested for backwards compatibility, unless the COMPACT keyword was used to request exclusively the specified fields. ---*/ - auto itSol = std::find(requestedVolumeFields.begin(), - requestedVolumeFields.end(), "SOLUTION"); + auto itSol = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "SOLUTION"); if (itSol == requestedVolumeFields.end()) { - auto itCompact = std::find(requestedVolumeFields.begin(), - requestedVolumeFields.end(), "COMPACT"); + auto itCompact = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COMPACT"); if (itCompact == requestedVolumeFields.end()) { requestedVolumeFields.emplace_back("SOLUTION"); nRequestedVolumeFields++; @@ -1661,10 +1646,11 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver** /*--- Reset the offset cache and index --- */ cachePosition = 0; fieldIndexCache.clear(); + fieldIndexCacheCompact.clear(); curGetFieldIndex = 0; fieldGetIndexCache.clear(); - if (femOutput){ + if (femOutput) { /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary geometrical information for the FEM DG solver. ---*/ @@ -1678,33 +1664,24 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver** /*--- Access the solution by looping over the owned volume elements. ---*/ for(unsigned long l=0; lGetnPointDomain(); iPoint++) { - - /*--- Load the volume data into the data sorter. --- */ - buildFieldIndexCache = fieldIndexCache.empty(); - LoadVolumeData(config, geometry, solver, iPoint); - } /*--- Reset the offset cache and index --- */ cachePosition = 0; fieldIndexCache.clear(); + fieldIndexCacheCompact.clear(); curGetFieldIndex = 0; fieldGetIndexCache.clear(); @@ -1712,19 +1689,16 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver** /*--- We only want to have surface values on solid walls ---*/ - if (config->GetSolid_Wall(iMarker)){ - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++){ + if (config->GetSolid_Wall(iMarker)) { + for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); /*--- Load the surface data into the data sorter. --- */ - if(geometry->nodes->GetDomain(iPoint)){ - + if (geometry->nodes->GetDomain(iPoint)) { buildFieldIndexCache = fieldIndexCache.empty(); - LoadSurfaceData(config, geometry, solver, iPoint, iMarker, iVertex); - } } } @@ -1734,79 +1708,74 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver** void COutput::SetVolumeOutputValue(const string& name, unsigned long iPoint, su2double value){ - const vector reqFieldNames = requiredVolumeFieldNames; - string fieldname = volumeOutput_Map.at(name).fieldName; - bool contains = std::any_of(requiredVolumeFieldNames.begin(), requiredVolumeFieldNames.end(), - [fieldname](string n) { return n == fieldname; }); if (buildFieldIndexCache) { - /*--- Build up the offset cache to speed up subsequent * calls of this routine since the order of calls is - * the same for every value of iPoint --- */ + * the same for every value of iPoint. ---*/ - if (volumeOutput_Map.count(name) > 0) { - const short Offset = volumeOutput_Map.at(name).offset; + const auto it = volumeOutput_Map.find(name); + if (it != volumeOutput_Map.end()) { + const short Offset = it->second.offset; fieldIndexCache.push_back(Offset); - if (Offset != -1){ - // note that the compact fields are a subset of the full fields - if (contains == true) { - const short OffsetCompact = volumeOutput_Map.at(name).offsetCompact; - volumeDataSorterCompact->SetUnsortedData(iPoint, OffsetCompact, value); - } + if (Offset != -1) { volumeDataSorter->SetUnsortedData(iPoint, Offset, value); } + /*--- Note that the compact fields are a subset of the full fields. ---*/ + const short OffsetCompact = it->second.offsetCompact; + fieldIndexCacheCompact.push_back(OffsetCompact); + if (volumeDataSorterCompact != nullptr && OffsetCompact != -1) { + volumeDataSorterCompact->SetUnsortedData(iPoint, OffsetCompact, value); + } } else { - SU2_MPI::Error(string("Cannot find output field with name ") + name, CURRENT_FUNCTION); + SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION); } } else { - /*--- Use the offset cache for the access ---*/ - const short Offset = fieldIndexCache[cachePosition++]; + /*--- Use the offset caches for the access. ---*/ + const short Offset = fieldIndexCache[cachePosition]; + const short OffsetCompact = fieldIndexCacheCompact[cachePosition++]; + if (cachePosition == fieldIndexCache.size()) { + cachePosition = 0; + } if (Offset != -1) { - if (contains == true) { - const short OffsetCompact = volumeOutput_Map.at(name).offsetCompact; - volumeDataSorterCompact->SetUnsortedData(iPoint, OffsetCompact, value); - } volumeDataSorter->SetUnsortedData(iPoint, Offset, value); } - if (cachePosition == fieldIndexCache.size()){ - cachePosition = 0; + if (volumeDataSorterCompact != nullptr && OffsetCompact != -1) { + volumeDataSorterCompact->SetUnsortedData(iPoint, OffsetCompact, value); } } } -su2double COutput::GetVolumeOutputValue(const string& name, unsigned long iPoint){ - - if (buildFieldIndexCache){ +su2double COutput::GetVolumeOutputValue(const string& name, unsigned long iPoint) { + if (buildFieldIndexCache) { /*--- Build up the offset cache to speed up subsequent * calls of this routine since the order of calls is - * the same for every value of iPoint --- */ + * the same for every value of iPoint. ---*/ - if (volumeOutput_Map.count(name) > 0){ - const short Offset = volumeOutput_Map.at(name).offset; + const auto it = volumeOutput_Map.find(name); + if (it != volumeOutput_Map.end()) { + const short Offset = it->second.offset; fieldGetIndexCache.push_back(Offset); - if (Offset != -1){ + if (Offset != -1) { return volumeDataSorter->GetUnsortedData(iPoint, Offset); } } else { - SU2_MPI::Error(string("Cannot find output field with name ") + name, CURRENT_FUNCTION); + SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION); } } else { - - /*--- Use the offset cache for the access ---*/ + /*--- Use the offset cache for the access, ---*/ const short Offset = fieldGetIndexCache[curGetFieldIndex++]; - if (curGetFieldIndex == fieldGetIndexCache.size()){ + if (curGetFieldIndex == fieldGetIndexCache.size()) { curGetFieldIndex = 0; } - if (Offset != -1){ + if (Offset != -1) { return volumeDataSorter->GetUnsortedData(iPoint, Offset); } } - return 0.0; } @@ -1814,38 +1783,36 @@ void COutput::SetAvgVolumeOutputValue(const string& name, unsigned long iPoint, const su2double scaling = 1.0 / su2double(curAbsTimeIter + 1); - if (buildFieldIndexCache){ - + if (buildFieldIndexCache) { /*--- Build up the offset cache to speed up subsequent * calls of this routine since the order of calls is - * the same for every value of iPoint --- */ + * the same for every value of iPoint. ---*/ - if (volumeOutput_Map.count(name) > 0){ - const short Offset = volumeOutput_Map.at(name).offset; + const auto it = volumeOutput_Map.find(name); + if (it != volumeOutput_Map.end()) { + const short Offset = it->second.offset; fieldIndexCache.push_back(Offset); - if (Offset != -1){ - + if (Offset != -1) { const su2double old_value = volumeDataSorter->GetUnsortedData(iPoint, Offset); - const su2double new_value = value * scaling + old_value *( 1.0 - scaling); + const su2double new_value = value * scaling + old_value * (1.0 - scaling); volumeDataSorter->SetUnsortedData(iPoint, Offset, new_value); } } else { - SU2_MPI::Error(string("Cannot find output field with name ") + name, CURRENT_FUNCTION); + SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION); } } else { /*--- Use the offset cache for the access ---*/ const short Offset = fieldIndexCache[cachePosition++]; - if (Offset != -1){ - + if (Offset != -1) { const su2double old_value = volumeDataSorter->GetUnsortedData(iPoint, Offset); - const su2double new_value = value * scaling + old_value *( 1.0 - scaling); + const su2double new_value = value * scaling + old_value * (1.0 - scaling); volumeDataSorter->SetUnsortedData(iPoint, Offset, new_value); } - if (cachePosition == fieldIndexCache.size()){ + if (cachePosition == fieldIndexCache.size()) { cachePosition = 0; } } @@ -2485,7 +2452,7 @@ void COutput::PrintVolumeFields(){ } cout << "Available volume output fields for the current configuration in " << multiZoneHeaderString << ":" << endl; - cout << "Note: COORDINATES and SOLUTION groups are always in the volume output unless you add the keyword COMPACT." << endl; + cout << "Note: COORDINATES are always included, and so is SOLUTION unless you add the keyword COMPACT to the list of fields." << endl; VolumeFieldTable.AddColumn("Name", NameSize); VolumeFieldTable.AddColumn("Group Name", GroupSize); VolumeFieldTable.AddColumn("Description", DescrSize); diff --git a/SU2_CFD/src/output/filewriter/CParallelDataSorter.cpp b/SU2_CFD/src/output/filewriter/CParallelDataSorter.cpp index 0290c20b025..2bc2778ec24 100644 --- a/SU2_CFD/src/output/filewriter/CParallelDataSorter.cpp +++ b/SU2_CFD/src/output/filewriter/CParallelDataSorter.cpp @@ -32,7 +32,8 @@ CParallelDataSorter::CParallelDataSorter(CConfig *config, const vector &valFieldNames) : rank(SU2_MPI::GetRank()), size(SU2_MPI::GetSize()), - fieldNames(valFieldNames) { + fieldNames(valFieldNames), + requiredFieldNames(valFieldNames) { GlobalField_Counter = fieldNames.size(); diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 9c6cdf65373..530328b52a6 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -1671,7 +1671,7 @@ def main(): stl_writer_test.cfg_dir = "rans/oneram6" stl_writer_test.cfg_file = "turb_ONERAM6.cfg" stl_writer_test.test_iter = 1 - stl_writer_test.command = TestCase.Command("mpirun -n 2", "SU2_CFD") + stl_writer_test.command = TestCase.Command("mpirun -n 2", "SU2_SOL") stl_writer_test.timeout = 1600 stl_writer_test.reference_file = "surface_flow.stl.ref" stl_writer_test.test_file = "surface_flow.stl" diff --git a/TestCases/py_wrapper/wavy_wall/run_steady.py b/TestCases/py_wrapper/wavy_wall/run_steady.py index 4a90995ace1..511aa585827 100644 --- a/TestCases/py_wrapper/wavy_wall/run_steady.py +++ b/TestCases/py_wrapper/wavy_wall/run_steady.py @@ -93,6 +93,7 @@ primal_settings = """ MATH_PROBLEM= DIRECT RESTART_SOL= YES + CFL_NUMBER= 1000 LINEAR_SOLVER= FGMRES LINEAR_SOLVER_PREC= ILU diff --git a/config_template.cfg b/config_template.cfg index 8b6b313246d..0acf538f856 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -60,10 +60,10 @@ GRAVITY_FORCE= NO % Restart solution (NO, YES) RESTART_SOL= NO % -% Only save minimum required variables to restart files (NO, YES). -% If this option is set to NO, then the SOLUTION fields will be written to all output -% files by default. If you would also like to have minimum output files -% (e.g. paraview, tecplot), then add the keyword COMPACT to VOLUME_OUTPUT. +% Only save the minimum required variables for restarting to restart files (NO, YES). +% If this option is set to NO, then all fields will be written to all output files. +% To minimize the size of other output files (e.g. paraview, tecplot) by not including +% default restart fields in them, add the keyword COMPACT to VOLUME_OUTPUT. WRT_RESTART_COMPACT= YES % % Discard the data storaged in the solution and geometry files From cf4f6094772135c76ebd215ae8be1569639b61e2 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Wed, 1 Jan 2025 14:57:25 -0800 Subject: [PATCH 069/129] missing initialization --- SU2_CFD/include/output/COutput.hpp | 12 +++---- SU2_CFD/src/output/CAdjFlowCompOutput.cpp | 2 +- SU2_CFD/src/output/CAdjFlowIncOutput.cpp | 2 +- SU2_CFD/src/output/CAdjHeatOutput.cpp | 2 +- SU2_CFD/src/output/CFlowCompOutput.cpp | 20 +++++------ SU2_CFD/src/output/CFlowIncOutput.cpp | 2 +- SU2_CFD/src/output/CNEMOCompOutput.cpp | 2 +- SU2_CFD/src/output/COutput.cpp | 42 +++++++---------------- 8 files changed, 33 insertions(+), 51 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index e39b047ce82..14b0bbec9b6 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -260,9 +260,9 @@ class COutput { /*! \brief The name of the field, i.e. the name that is printed in the file header.*/ string fieldName; /*! \brief This value identifies the position of the values of this field at each node in the ::Local_Data array. */ - short offset; + short offset = -1; /*! \brief This offset is used for the compact formulation. */ - short offsetCompact; + short offsetCompact = -1; /*! \brief The group this field belongs to. */ string outputGroup; /*! \brief String containing the description of the field. */ @@ -270,9 +270,8 @@ class COutput { /*! \brief Default constructor. */ VolumeOutputField() = default; /*! \brief Constructor to initialize all members. */ - VolumeOutputField(string fieldName_, int offset_, string volumeOutputGroup_, string description_): + VolumeOutputField(string fieldName_, string volumeOutputGroup_, string description_): fieldName(std::move(fieldName_)), - offset(offset_), outputGroup(std::move(volumeOutputGroup_)), description(std::move(description_)) {} }; @@ -746,8 +745,9 @@ class COutput { * \param[in] groupname - The name of the group this field belongs to. * \param[in] description - Description of the volume field. */ - inline void AddVolumeOutput(string name, string field_name, string groupname, string description){ - volumeOutput_Map[name] = VolumeOutputField(field_name, -1, groupname, description); + inline void AddVolumeOutput(const string& name, const string& field_name, + const string& group_name, const string& description) { + volumeOutput_Map[name] = VolumeOutputField(field_name, group_name, description); volumeOutput_List.push_back(name); } diff --git a/SU2_CFD/src/output/CAdjFlowCompOutput.cpp b/SU2_CFD/src/output/CAdjFlowCompOutput.cpp index 108856156e7..f1e492e1a37 100644 --- a/SU2_CFD/src/output/CAdjFlowCompOutput.cpp +++ b/SU2_CFD/src/output/CAdjFlowCompOutput.cpp @@ -61,7 +61,7 @@ CAdjFlowCompOutput::CAdjFlowCompOutput(CConfig *config, unsigned short nDim) : C if (find(requestedVolumeFields.begin(), requestedVolumeFields.end(), string("SENSITIVITY")) == requestedVolumeFields.end()) { requestedVolumeFields.emplace_back("SENSITIVITY"); - nRequestedVolumeFields ++; + nRequestedVolumeFields++; } stringstream ss; diff --git a/SU2_CFD/src/output/CAdjFlowIncOutput.cpp b/SU2_CFD/src/output/CAdjFlowIncOutput.cpp index be86c12a494..3fff6de99e5 100644 --- a/SU2_CFD/src/output/CAdjFlowIncOutput.cpp +++ b/SU2_CFD/src/output/CAdjFlowIncOutput.cpp @@ -67,7 +67,7 @@ CAdjFlowIncOutput::CAdjFlowIncOutput(CConfig *config, unsigned short nDim) : CAd if (find(requestedVolumeFields.begin(), requestedVolumeFields.end(), string("SENSITIVITY")) == requestedVolumeFields.end()) { requestedVolumeFields.emplace_back("SENSITIVITY"); - nRequestedVolumeFields ++; + nRequestedVolumeFields++; } stringstream ss; diff --git a/SU2_CFD/src/output/CAdjHeatOutput.cpp b/SU2_CFD/src/output/CAdjHeatOutput.cpp index 578175fccad..9c8a85e2f5d 100644 --- a/SU2_CFD/src/output/CAdjHeatOutput.cpp +++ b/SU2_CFD/src/output/CAdjHeatOutput.cpp @@ -58,7 +58,7 @@ CAdjHeatOutput::CAdjHeatOutput(CConfig *config, unsigned short nDim) : COutput(c if (find(requestedVolumeFields.begin(), requestedVolumeFields.end(), string("SENSITIVITY")) == requestedVolumeFields.end()) { requestedVolumeFields.emplace_back("SENSITIVITY"); - nRequestedVolumeFields ++; + nRequestedVolumeFields++; } stringstream ss; diff --git a/SU2_CFD/src/output/CFlowCompOutput.cpp b/SU2_CFD/src/output/CFlowCompOutput.cpp index e460109c8b5..d3c76e75a36 100644 --- a/SU2_CFD/src/output/CFlowCompOutput.cpp +++ b/SU2_CFD/src/output/CFlowCompOutput.cpp @@ -61,7 +61,7 @@ CFlowCompOutput::CFlowCompOutput(const CConfig *config, unsigned short nDim) : C auto notFound = requestedVolumeFields.end(); if (find(requestedVolumeFields.begin(), notFound, string("GRID_VELOCITY")) == notFound) { requestedVolumeFields.emplace_back("GRID_VELOCITY"); - nRequestedVolumeFields ++; + nRequestedVolumeFields++; } } @@ -219,7 +219,7 @@ void CFlowCompOutput::SetVolumeOutputFields(CConfig *config){ AddVolumeOutput("DENSITY", "Density", "SOLUTION", "Density"); AddVolumeOutput("MOMENTUM-X", "Momentum_x", "SOLUTION", "x-component of the momentum vector"); AddVolumeOutput("MOMENTUM-Y", "Momentum_y", "SOLUTION", "y-component of the momentum vector"); - + if (nDim == 3) AddVolumeOutput("MOMENTUM-Z", "Momentum_z", "SOLUTION", "z-component of the momentum vector"); AddVolumeOutput("ENERGY", "Energy", "SOLUTION", "Energy"); @@ -241,7 +241,7 @@ void CFlowCompOutput::SetVolumeOutputFields(CConfig *config){ AddVolumeOutput("PRESSURE_COEFF", "Pressure_Coefficient", "PRIMITIVE", "Pressure coefficient"); AddVolumeOutput("VELOCITY-X", "Velocity_x", "PRIMITIVE", "x-component of the velocity vector"); AddVolumeOutput("VELOCITY-Y", "Velocity_y", "PRIMITIVE", "y-component of the velocity vector"); - + if (nDim == 3) AddVolumeOutput("VELOCITY-Z", "Velocity_z", "PRIMITIVE", "z-component of the velocity vector"); @@ -525,7 +525,7 @@ void CFlowCompOutput::SetTurboPerformance_Output(std::shared_ptr T for (unsigned short iZone = 0; iZone <= config->GetnZone()-1; iZone++) { auto nSpan = config->GetnSpan_iZones(iZone); - const auto& BladePerf = BladePerformance.at(iZone).at(nSpan); + const auto& BladePerf = BladePerformance.at(iZone).at(nSpan); TurboInOut<<" BLADE ROW INDEX "<GetInletState().GetVelocity()[iDim]*config[ZONE_0]->GetVelocity_Ref(); } file.width(30); file << BladePerf->GetInletState().GetVelocityValue()*config[ZONE_0]->GetVelocity_Ref(); - // This captures NaNs + // This captures NaNs if(isnan(BladePerf->GetInletState().GetAbsFlowAngle())){ file.width(30); file << "0.0000"; } @@ -792,11 +792,11 @@ void CFlowCompOutput::WriteTurboSpanwisePerformance(std::shared_ptr 1) { - spanwise_performance_filename.append("_" + std::to_string(val_iZone) + ".dat"); - } else { - spanwise_performance_filename.append(".dat"); - } + if (nZone > 1) { + spanwise_performance_filename.append("_" + std::to_string(val_iZone) + ".dat"); + } else { + spanwise_performance_filename.append(".dat"); + } file.open (spanwise_performance_filename.data(), ios::out | ios::trunc); file.setf(ios::scientific); file.precision(12); diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp index eeffb6a3486..1f4c0809d1b 100644 --- a/SU2_CFD/src/output/CFlowIncOutput.cpp +++ b/SU2_CFD/src/output/CFlowIncOutput.cpp @@ -70,7 +70,7 @@ CFlowIncOutput::CFlowIncOutput(CConfig *config, unsigned short nDim) : CFlowOutp auto notFound = requestedVolumeFields.end(); if (find(requestedVolumeFields.begin(), notFound, string("GRID_VELOCITY")) == notFound) { requestedVolumeFields.emplace_back("GRID_VELOCITY"); - nRequestedVolumeFields ++; + nRequestedVolumeFields++; } } diff --git a/SU2_CFD/src/output/CNEMOCompOutput.cpp b/SU2_CFD/src/output/CNEMOCompOutput.cpp index 7b75ac646d2..2994dd4345e 100644 --- a/SU2_CFD/src/output/CNEMOCompOutput.cpp +++ b/SU2_CFD/src/output/CNEMOCompOutput.cpp @@ -65,7 +65,7 @@ CNEMOCompOutput::CNEMOCompOutput(const CConfig *config, unsigned short nDim) : C auto notFound = requestedVolumeFields.end(); if (find(requestedVolumeFields.begin(), notFound, string("GRID_VELOCITY")) == notFound) { requestedVolumeFields.emplace_back("GRID_VELOCITY"); - nRequestedVolumeFields ++; + nRequestedVolumeFields++; } } diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index bfb0b6329c5..e66c1752ea9 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1542,7 +1542,6 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ } } - string RequiredField; std::vector FoundField(nRequestedVolumeFields, false); vector FieldsToRemove; @@ -1551,49 +1550,32 @@ void COutput::PreprocessVolumeOutput(CConfig *config){ * object gets an offset so that we know where to find the data in the Local_Data() array. * Note that the default offset is -1. An index !=-1 defines this field as part of the output. ---*/ - unsigned short nVolumeFieldsCompact = 0; + unsigned short nVolumeFields = 0, nVolumeFieldsCompact = 0; for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { const string &fieldReference = volumeOutput_List[iField_Output]; - if (volumeOutput_Map.count(fieldReference) > 0) { - VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); - - /*--- Loop through all fields specified in the config ---*/ - - for (size_t iReqField = 0; iReqField < restartVolumeFields.size(); iReqField++) { + const auto it = volumeOutput_Map.find(fieldReference); + if (it != volumeOutput_Map.end()) { + VolumeOutputField &Field = it->second; - // minimum required fields for restarts - RequiredField = restartVolumeFields[iReqField]; + /*--- Loop through the minimum required fields for restarts. ---*/ - if (((RequiredField == Field.outputGroup) || (RequiredField == fieldReference)) && (Field.offset == -1)) { - Field.offsetCompact = nVolumeFieldsCompact; + for (const auto& RequiredField : restartVolumeFields) { + if ((RequiredField == Field.outputGroup || RequiredField == fieldReference) && Field.offsetCompact == -1) { + Field.offsetCompact = nVolumeFieldsCompact++; requiredVolumeFieldNames.push_back(Field.fieldName); - nVolumeFieldsCompact++; } } - } - } - - unsigned short nVolumeFields = 0; - for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) { - - const string &fieldReference = volumeOutput_List[iField_Output]; - if (volumeOutput_Map.count(fieldReference) > 0){ - VolumeOutputField &Field = volumeOutput_Map.at(fieldReference); - - /*--- Loop through all fields specified in the config ---*/ + /*--- Loop through all fields specified in the config. ---*/ for (size_t iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++) { + const auto &RequestedField = requestedVolumeFields[iReqField]; - const string &RequestedField = requestedVolumeFields[iReqField]; - - if (((RequestedField == Field.outputGroup) || (RequestedField == fieldReference)) && (Field.offset == -1)) { - - Field.offset = nVolumeFields; + if ((RequestedField == Field.outputGroup || RequestedField == fieldReference) && Field.offset == -1) { + Field.offset = nVolumeFields++; volumeFieldNames.push_back(Field.fieldName); - nVolumeFields++; FoundField[iReqField] = true; } } From ae84d15a6650cf05b4971dd8ebb2af9dc74ee7af Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Wed, 1 Jan 2025 17:34:55 -0800 Subject: [PATCH 070/129] time average fix --- SU2_CFD/src/output/COutput.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index e66c1752ea9..edae19efa44 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -1712,7 +1712,6 @@ void COutput::SetVolumeOutputValue(const string& name, unsigned long iPoint, su2 SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION); } } else { - /*--- Use the offset caches for the access. ---*/ const short Offset = fieldIndexCache[cachePosition]; const short OffsetCompact = fieldIndexCacheCompact[cachePosition++]; @@ -1740,6 +1739,9 @@ su2double COutput::GetVolumeOutputValue(const string& name, unsigned long iPoint if (it != volumeOutput_Map.end()) { const short Offset = it->second.offset; fieldGetIndexCache.push_back(Offset); + /*--- This function is used for time-averaged fields and we know + * those are not part of the compact restart fields. ---*/ + fieldIndexCacheCompact.push_back(-1); if (Offset != -1) { return volumeDataSorter->GetUnsortedData(iPoint, Offset); } From 13b08f559cdab16c14713e211e7efffaadc27a42 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Wed, 1 Jan 2025 18:54:05 -0800 Subject: [PATCH 071/129] fix... --- SU2_CFD/src/output/COutput.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index edae19efa44..016b5d35ec0 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -380,6 +380,7 @@ void COutput::LoadData(CGeometry *geometry, CConfig *config, CSolver** solver_co /*--- Partition and sort the volume output data -- */ volumeDataSorter->SortOutputData(); + if (volumeDataSorterCompact != nullptr) volumeDataSorterCompact->SortOutputData(); } @@ -1739,9 +1740,6 @@ su2double COutput::GetVolumeOutputValue(const string& name, unsigned long iPoint if (it != volumeOutput_Map.end()) { const short Offset = it->second.offset; fieldGetIndexCache.push_back(Offset); - /*--- This function is used for time-averaged fields and we know - * those are not part of the compact restart fields. ---*/ - fieldIndexCacheCompact.push_back(-1); if (Offset != -1) { return volumeDataSorter->GetUnsortedData(iPoint, Offset); } @@ -1776,6 +1774,9 @@ void COutput::SetAvgVolumeOutputValue(const string& name, unsigned long iPoint, if (it != volumeOutput_Map.end()) { const short Offset = it->second.offset; fieldIndexCache.push_back(Offset); + /*--- This function is used for time-averaged fields and we know + * those are not part of the compact restart fields. ---*/ + fieldIndexCacheCompact.push_back(-1); if (Offset != -1) { const su2double old_value = volumeDataSorter->GetUnsortedData(iPoint, Offset); const su2double new_value = value * scaling + old_value * (1.0 - scaling); From 77a5b14d70e5e668d924bfc0358d71d26addeb98 Mon Sep 17 00:00:00 2001 From: Nijso Date: Fri, 10 Jan 2025 21:46:30 +0100 Subject: [PATCH 072/129] fix (#2415) --- SU2_PY/FSI_tools/FSIInterface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_PY/FSI_tools/FSIInterface.py b/SU2_PY/FSI_tools/FSIInterface.py index 61148d805c7..267e6660aaf 100644 --- a/SU2_PY/FSI_tools/FSIInterface.py +++ b/SU2_PY/FSI_tools/FSIInterface.py @@ -307,7 +307,7 @@ def connect(self, FSI_config, FluidSolver, SolidSolver): print("Fluid solver is initialized on process {}".format(myid)) self.haveFluidSolver = True allMovingMarkersTags = FluidSolver.GetDeformableMarkerTags() - allMarkersID = FluidSolver.GetMarkerTags() + allMarkersID = FluidSolver.GetMarkerIndices() if not allMovingMarkersTags: raise Exception("No interface for FSI was defined.") else: From 140dec2d90344ed7566d7e32e1bd6b639e0e7023 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Mon, 13 Jan 2025 14:37:10 +0100 Subject: [PATCH 073/129] - Added Non-dimensionalization to translation velocity --- SU2_CFD/src/solvers/CMeshSolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/solvers/CMeshSolver.cpp b/SU2_CFD/src/solvers/CMeshSolver.cpp index 0335e1759d0..b3f0043847d 100644 --- a/SU2_CFD/src/solvers/CMeshSolver.cpp +++ b/SU2_CFD/src/solvers/CMeshSolver.cpp @@ -1450,7 +1450,7 @@ void CMeshSolver::Surface_Translating(CGeometry *geometry, CConfig *config, unsi } for (iDim = 0; iDim < 3; iDim++) { - xDot[iDim] = config->GetMarkerTranslationRate(jMarker, iDim); + xDot[iDim] = config->GetMarkerTranslationRate(jMarker, iDim)/config->GetVelocity_Ref(); Center[iDim] = config->GetMarkerMotion_Origin(jMarker, iDim); } From 72d8f3053dae5d0b2ae897d76811b4432456782d Mon Sep 17 00:00:00 2001 From: rois1995 Date: Mon, 13 Jan 2025 15:05:47 +0100 Subject: [PATCH 074/129] - fixed unsteady names --- SU2_CFD/src/output/COutput.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 016b5d35ec0..3733f40ed8e 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -389,6 +389,9 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form /*--- File writer that will later be used to write the file to disk. Created below in the "switch" ---*/ CFileWriter *fileWriter = nullptr; + /*--- Set current time iter even if history file is not written ---*/ + curTimeIter = config->GetTimeIter(); + /*--- If it is still present, strip the extension (suffix) from the filename ---*/ const auto lastindex = fileName.find_last_of('.'); fileName = fileName.substr(0, lastindex); @@ -476,7 +479,7 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form extension = CSU2MeshFileWriter::fileExt; if (fileName.empty()) - fileName = volumeFilename; + fileName = config->GetFilename(volumeFilename, "", curTimeIter); if (!config->GetWrt_Volume_Overwrite()) filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter); From 62b87961f56f1f5cc631ff1d1168d1fb61333682 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 15 Jan 2025 22:45:58 +0100 Subject: [PATCH 075/129] regression --- .github/workflows/regression.yml | 2 +- TestCases/tutorials.py | 52 ++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 2502204b64c..a869184925d 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -300,7 +300,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2-asan:240320-1536 with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--asan" + args: -b ${{github.ref}} -t design_pipe -c tutorial_bend_Design -s ${{matrix.testscript}} -a "--asan" - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2-asan:240320-1536 with: diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index e819ff246c1..f5b42acaa9b 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -73,6 +73,7 @@ def main(): cht_CR.multizone = True test_list.append(cht_CR) + ### Incompressible Flow # 2D pin case massflow periodic with heatflux BC and prescribed extracted outlet heat @@ -91,6 +92,34 @@ def main(): sp_pinArray_2d_dp_hf_tp.test_vals = [-4.640621, 1.436697, -0.707302, 208.023676] test_list.append(sp_pinArray_2d_dp_hf_tp) + # 90 degree pipe bend with wall functions from the experiments of Sudo et al. + sudo_tutorial = TestCase('sudo_bend') + sudo_tutorial.cfg_dir = "../Tutorials/incompressible_flow/Inc_Turbulent_Bend_Wallfunctions" + sudo_tutorial.cfg_file = "sudo.cfg" + sudo_tutorial.test_iter = 10 + sudo_tutorial.test_vals = [-14.579462, -13.203791, -13.601782, -12.616876, -14.005299, -10.817605, 15.000000, -2.296083] + sudo_tutorial.command = TestCase.Command("mpirun -n 2", "SU2_CFD") + test_list.append(sudo_tutorial) + + # design-primal: 90 degree pipe bend with wall functions from the experiments of Sudo et al. + sudo_design_primal = TestCase('sudo_bend_design_primal') + sudo_design_primal.cfg_dir = "../Tutorials/incompressible_flow/Inc_Turbulent_Bend_Wallfunctions" + sudo_design_primal.cfg_file = "sudo_primal.cfg" + sudo_design_primal.test_iter = 10 + sudo_design_primal.test_vals = [-14.579462, -13.203791, -13.601782, -12.616876, -14.005299, -10.817605, 15.000000, -2.296083] + sudo_design_primal.command = TestCase.Command("mpirun -n 2", "SU2_CFD") + test_list.append(sudo_design_primal) + + # design-adjoint: 90 degree pipe bend with wall functions from the experiments of Sudo et al. + sudo_design_adjoint = TestCase('sudo_bend_design_adjoint') + sudo_design_adjoint.cfg_dir = "../Tutorials/incompressible_flow/Inc_Turbulent_Bend_Wallfunctions" + sudo_design_adjoint.cfg_file = "sudo_adjoint.cfg" + sudo_design_adjoint.test_iter = 10 + sudo_design_adjoint.test_vals = [-14.579462, -13.203791, -13.601782, -12.616876, -14.005299, -10.817605, 15.000000, -2.296083] + sudo_design_adjoint.command = TestCase.Command("mpirun -n 2", "SU2_CFD_AD") + test_list.append(sudo_design_adjoint) + + ### Species Transport # 3 species (2 eq) primitive venturi mixing @@ -116,18 +145,20 @@ def main(): kenics_mixer_tutorial.cfg_dir = "../Tutorials/incompressible_flow/Inc_Species_Transport_Composition_Dependent_Model" kenics_mixer_tutorial.cfg_file = "kenics_mixer_tutorial.cfg" kenics_mixer_tutorial.test_iter = 10 - kenics_mixer_tutorial.test_vals = [-7.489796, -6.823473, -6.838032, -5.157793, -7.911512, -3.166212, -7.447901, 5.000000, -1.862212, 4.000000, -5.131048, 3.000000, -6.380193, 0.025472, 0.000000, 0.025472, 0.000000, 64.105000, 8.479200, 48.099000, 7.526700] + kenics_mixer_tutorial.test_vals = [-7.490002, -6.823162, -6.837602, -5.156401, -7.928720, -3.089782, -7.447883, 5.000000, -1.863052, 4.000000, -5.174773, 3.000000, -6.382946, 0.025471, 0.000000, 0.025471, 0.000000, 64.126000, 8.479400, 48.120000, 7.526800] kenics_mixer_tutorial.command = TestCase.Command("mpirun -n 2", "SU2_CFD") test_list.append(kenics_mixer_tutorial) - # 90 degree pipe bend with wall functions from the experiments of Sudo et al. - sudo_tutorial = TestCase('sudo_bend') - sudo_tutorial.cfg_dir = "../Tutorials/incompressible_flow/Inc_Turbulent_Bend_Wallfunctions" - sudo_tutorial.cfg_file = "sudo.cfg" - sudo_tutorial.test_iter = 10 - sudo_tutorial.test_vals = [-14.579462, -13.203791, -13.601782, -12.616876, -14.005299, -10.817605, 15.000000, -2.296083] - sudo_tutorial.command = TestCase.Command("mpirun -n 2", "SU2_CFD") - test_list.append(sudo_tutorial) + # 3 species (2 eq) primitive venturi mixing + DAspecies3_primitiveVenturi = TestCase('DAspecies3_primitiveVenturi') + DAspecies3_primitiveVenturi.cfg_dir = "../Tutorials/incompressible_flow/Inc_Species_Transport" + DAspecies3_primitiveVenturi.cfg_file = "DAspecies3_primitiveVenturi.cfg" + DAspecies3_primitiveVenturi.test_iter = 50 + DAspecies3_primitiveVenturi.test_vals = [-7.584508, -7.211527, -6.740742, -6.896386, -11.472089, -10.865347, -10.096770] + DAspecies3_primitiveVenturi.test_vals_aarch64 = [-7.865411, -7.548131, -7.347978, -7.217536, -11.822422, -10.968444, -10.193225] + DAspecies3_primitiveVenturi.command = TestCase.Command("mpirun -n 2", "SU2_CFD_AD") + test_list.append(DAspecies3_primitiveVenturi) + ### Incompressible Combustion @@ -139,6 +170,7 @@ def main(): premixed_hydrogen.test_vals = [-9.809794, -10.369804, -11.044267, -4.332945, -11.883789] test_list.append(premixed_hydrogen) + ### Compressible Flow # Inviscid Bump @@ -254,7 +286,7 @@ def main(): tutorial_nicfd_nozzle.cfg_dir = "../Tutorials/compressible_flow/NICFD_nozzle" tutorial_nicfd_nozzle.cfg_file = "NICFD_nozzle.cfg" tutorial_nicfd_nozzle.test_iter = 20 - tutorial_nicfd_nozzle.test_vals = [-2.056675, -2.124123, 3.687027, 0.000000, 0.000000] + tutorial_nicfd_nozzle.test_vals = [-2.056675, -2.124123, 3.687857, 0.000000, 0.000000] tutorial_nicfd_nozzle.no_restart = True test_list.append(tutorial_nicfd_nozzle) From b70c3fe2593c087fadb31dfc7c17dc5fb79e8bb5 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 16 Jan 2025 23:23:08 +0100 Subject: [PATCH 076/129] regression --- TestCases/tutorials.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index f5b42acaa9b..63ba071851a 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -73,7 +73,6 @@ def main(): cht_CR.multizone = True test_list.append(cht_CR) - ### Incompressible Flow # 2D pin case massflow periodic with heatflux BC and prescribed extracted outlet heat @@ -103,7 +102,7 @@ def main(): # design-primal: 90 degree pipe bend with wall functions from the experiments of Sudo et al. sudo_design_primal = TestCase('sudo_bend_design_primal') - sudo_design_primal.cfg_dir = "../Tutorials/incompressible_flow/Inc_Turbulent_Bend_Wallfunctions" + sudo_design_primal.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" sudo_design_primal.cfg_file = "sudo_primal.cfg" sudo_design_primal.test_iter = 10 sudo_design_primal.test_vals = [-14.579462, -13.203791, -13.601782, -12.616876, -14.005299, -10.817605, 15.000000, -2.296083] @@ -112,7 +111,7 @@ def main(): # design-adjoint: 90 degree pipe bend with wall functions from the experiments of Sudo et al. sudo_design_adjoint = TestCase('sudo_bend_design_adjoint') - sudo_design_adjoint.cfg_dir = "../Tutorials/incompressible_flow/Inc_Turbulent_Bend_Wallfunctions" + sudo_design_adjoint.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" sudo_design_adjoint.cfg_file = "sudo_adjoint.cfg" sudo_design_adjoint.test_iter = 10 sudo_design_adjoint.test_vals = [-14.579462, -13.203791, -13.601782, -12.616876, -14.005299, -10.817605, 15.000000, -2.296083] @@ -145,20 +144,10 @@ def main(): kenics_mixer_tutorial.cfg_dir = "../Tutorials/incompressible_flow/Inc_Species_Transport_Composition_Dependent_Model" kenics_mixer_tutorial.cfg_file = "kenics_mixer_tutorial.cfg" kenics_mixer_tutorial.test_iter = 10 - kenics_mixer_tutorial.test_vals = [-7.490002, -6.823162, -6.837602, -5.156401, -7.928720, -3.089782, -7.447883, 5.000000, -1.863052, 4.000000, -5.174773, 3.000000, -6.382946, 0.025471, 0.000000, 0.025471, 0.000000, 64.126000, 8.479400, 48.120000, 7.526800] + kenics_mixer_tutorial.test_vals = [kenics_mixer_tutorial.test_vals = [-7.489796, -6.823473, -6.838032, -5.157793, -7.911512, -3.166212, -7.447901, 5.000000, -1.862212, 4.000000, -5.131048, 3.000000, -6.380193, 0.025472, 0.000000, 0.025472, 0.000000, 64.105000, 8.479200, 48.099000, 7.526700] kenics_mixer_tutorial.command = TestCase.Command("mpirun -n 2", "SU2_CFD") test_list.append(kenics_mixer_tutorial) - # 3 species (2 eq) primitive venturi mixing - DAspecies3_primitiveVenturi = TestCase('DAspecies3_primitiveVenturi') - DAspecies3_primitiveVenturi.cfg_dir = "../Tutorials/incompressible_flow/Inc_Species_Transport" - DAspecies3_primitiveVenturi.cfg_file = "DAspecies3_primitiveVenturi.cfg" - DAspecies3_primitiveVenturi.test_iter = 50 - DAspecies3_primitiveVenturi.test_vals = [-7.584508, -7.211527, -6.740742, -6.896386, -11.472089, -10.865347, -10.096770] - DAspecies3_primitiveVenturi.test_vals_aarch64 = [-7.865411, -7.548131, -7.347978, -7.217536, -11.822422, -10.968444, -10.193225] - DAspecies3_primitiveVenturi.command = TestCase.Command("mpirun -n 2", "SU2_CFD_AD") - test_list.append(DAspecies3_primitiveVenturi) - ### Incompressible Combustion @@ -286,7 +275,7 @@ def main(): tutorial_nicfd_nozzle.cfg_dir = "../Tutorials/compressible_flow/NICFD_nozzle" tutorial_nicfd_nozzle.cfg_file = "NICFD_nozzle.cfg" tutorial_nicfd_nozzle.test_iter = 20 - tutorial_nicfd_nozzle.test_vals = [-2.056675, -2.124123, 3.687857, 0.000000, 0.000000] + tutorial_nicfd_nozzle.test_vals = [-2.056675, -2.124123, 3.687027, 0.000000, 0.000000] tutorial_nicfd_nozzle.no_restart = True test_list.append(tutorial_nicfd_nozzle) From fafba321aff2a756afe240e07067c150c96b8c3a Mon Sep 17 00:00:00 2001 From: bigfooted Date: Thu, 16 Jan 2025 23:53:04 +0100 Subject: [PATCH 077/129] regression --- TestCases/tutorials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 63ba071851a..5cae096f0b7 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -144,7 +144,7 @@ def main(): kenics_mixer_tutorial.cfg_dir = "../Tutorials/incompressible_flow/Inc_Species_Transport_Composition_Dependent_Model" kenics_mixer_tutorial.cfg_file = "kenics_mixer_tutorial.cfg" kenics_mixer_tutorial.test_iter = 10 - kenics_mixer_tutorial.test_vals = [kenics_mixer_tutorial.test_vals = [-7.489796, -6.823473, -6.838032, -5.157793, -7.911512, -3.166212, -7.447901, 5.000000, -1.862212, 4.000000, -5.131048, 3.000000, -6.380193, 0.025472, 0.000000, 0.025472, 0.000000, 64.105000, 8.479200, 48.099000, 7.526700] + kenics_mixer_tutorial.test_vals = [-7.489796, -6.823473, -6.838032, -5.157793, -7.911512, -3.166212, -7.447901, 5.000000, -1.862212, 4.000000, -5.131048, 3.000000, -6.380193, 0.025472, 0.000000, 0.025472, 0.000000, 64.105000, 8.479200, 48.099000, 7.526700] kenics_mixer_tutorial.command = TestCase.Command("mpirun -n 2", "SU2_CFD") test_list.append(kenics_mixer_tutorial) From e58cb56a8e826943ace8cd8bf31bf49799f1125b Mon Sep 17 00:00:00 2001 From: vikram Date: Thu, 16 Jan 2025 23:33:14 +0000 Subject: [PATCH 078/129] CTurbSASolver.cpp changed as mentioned --- SU2_CFD/src/solvers/CTurbSASolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/solvers/CTurbSASolver.cpp b/SU2_CFD/src/solvers/CTurbSASolver.cpp index 6b465e802fd..08eb5ccc83d 100644 --- a/SU2_CFD/src/solvers/CTurbSASolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSASolver.cpp @@ -500,7 +500,7 @@ void CTurbSASolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_conta Res_Wall = coeff*RoughWallBC*Area; LinSysRes.SubtractBlock(iPoint, &Res_Wall); - su2double Jacobian_i = (laminar_viscosity*Area)/(0.03*Roughness_Height*sigma); + su2double Jacobian_i = Jacobian_i = (laminar_viscosity /density *Area)/(0.03*Roughness_Height*sigma); Jacobian_i += 2.0*RoughWallBC*Area/sigma; if (implicit) Jacobian.AddVal2Diag(iPoint, -Jacobian_i); } From c675d737a79f798f0f13f6167c4034393cdf3508 Mon Sep 17 00:00:00 2001 From: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:30:07 -0800 Subject: [PATCH 079/129] Update SU2_CFD/src/solvers/CTurbSASolver.cpp --- SU2_CFD/src/solvers/CTurbSASolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/solvers/CTurbSASolver.cpp b/SU2_CFD/src/solvers/CTurbSASolver.cpp index 08eb5ccc83d..7d9999d965f 100644 --- a/SU2_CFD/src/solvers/CTurbSASolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSASolver.cpp @@ -500,7 +500,7 @@ void CTurbSASolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_conta Res_Wall = coeff*RoughWallBC*Area; LinSysRes.SubtractBlock(iPoint, &Res_Wall); - su2double Jacobian_i = Jacobian_i = (laminar_viscosity /density *Area)/(0.03*Roughness_Height*sigma); + su2double Jacobian_i = (laminar_viscosity /density *Area)/(0.03*Roughness_Height*sigma); Jacobian_i += 2.0*RoughWallBC*Area/sigma; if (implicit) Jacobian.AddVal2Diag(iPoint, -Jacobian_i); } From e9fe4e8a10df30f638980c8d006be27480ac8b05 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 17 Jan 2025 08:24:58 +0100 Subject: [PATCH 080/129] regression --- .github/workflows/regression.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index a869184925d..528dba96bf9 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -209,7 +209,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2:240320-1536 with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} + args: -b ${{github.ref}} -t design_pipe -c tutorial_bend_Design -s ${{matrix.testscript}} - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2:240320-1536 with: @@ -300,7 +300,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2-asan:240320-1536 with: # -t -c - args: -b ${{github.ref}} -t design_pipe -c tutorial_bend_Design -s ${{matrix.testscript}} -a "--asan" + args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--asan" - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2-asan:240320-1536 with: From 89d73a4a47130f673d2d3b1cfe9eebbb31e25df9 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 17 Jan 2025 09:37:32 +0100 Subject: [PATCH 081/129] regression --- .github/workflows/regression.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 528dba96bf9..e3340aba167 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -209,7 +209,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2:240320-1536 with: # -t -c - args: -b ${{github.ref}} -t design_pipe -c tutorial_bend_Design -s ${{matrix.testscript}} + args: -b ${{github.ref}} -t design_pipe -c develop -s ${{matrix.testscript}} - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2:240320-1536 with: From b88ed078f337a31e769c82266701157547c9fb75 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 17 Jan 2025 10:08:43 +0100 Subject: [PATCH 082/129] - Added output function to set curTimeIter --- SU2_CFD/include/output/COutput.hpp | 6 ++++++ SU2_CFD/src/iteration/CFluidIteration.cpp | 2 ++ SU2_CFD/src/output/COutput.cpp | 5 ----- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 14b0bbec9b6..8300f1a568d 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -418,6 +418,12 @@ class COutput { */ void SetMultizoneHistoryOutput(COutput** output, CConfig **config, CConfig *driver_config, unsigned long TimeIter, unsigned long OuterIter); + + /*! + * \brief Sets the current time iteration + * \param[in] timeIter - the current time iteration + */ + inline void SetCurTimeIter(unsigned long val_curTimeIter) {curTimeIter = val_curTimeIter;} /*! * \brief Sets the volume output filename diff --git a/SU2_CFD/src/iteration/CFluidIteration.cpp b/SU2_CFD/src/iteration/CFluidIteration.cpp index 4ca6c45a172..77a058c39df 100644 --- a/SU2_CFD/src/iteration/CFluidIteration.cpp +++ b/SU2_CFD/src/iteration/CFluidIteration.cpp @@ -376,6 +376,8 @@ void CFluidIteration::Solve(COutput* output, CIntegration**** integration, CGeom /*--- Boolean to determine if we are running a static or dynamic case ---*/ bool steady = !config[val_iZone]->GetTime_Domain(); + if (!steady) output->SetCurTimeIter(config[val_iZone]->GetTimeIter()); + unsigned long Inner_Iter, nInner_Iter = config[val_iZone]->GetnInner_Iter(); bool StopCalc = false; diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 3733f40ed8e..36c743cebe3 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -207,7 +207,6 @@ void COutput::SetHistoryOutput(CGeometry *geometry, unsigned long OuterIter, unsigned long InnerIter) { - curTimeIter = TimeIter; curAbsTimeIter = max(TimeIter, config->GetStartWindowIteration()) - config->GetStartWindowIteration(); curOuterIter = OuterIter; curInnerIter = InnerIter; @@ -273,7 +272,6 @@ void COutput::SetHistoryOutput(CGeometry ****geometry, CSolver *****solver, CCon void COutput::SetMultizoneHistoryOutput(COutput **output, CConfig **config, CConfig *driver_config, unsigned long TimeIter, unsigned long OuterIter){ - curTimeIter = TimeIter; curAbsTimeIter = max(TimeIter, driver_config->GetStartWindowIteration()) - driver_config->GetStartWindowIteration(); curOuterIter = OuterIter; @@ -389,9 +387,6 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form /*--- File writer that will later be used to write the file to disk. Created below in the "switch" ---*/ CFileWriter *fileWriter = nullptr; - /*--- Set current time iter even if history file is not written ---*/ - curTimeIter = config->GetTimeIter(); - /*--- If it is still present, strip the extension (suffix) from the filename ---*/ const auto lastindex = fileName.find_last_of('.'); fileName = fileName.substr(0, lastindex); From b49e352043e355502bd0f9286bed99112c0b00c8 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 17 Jan 2025 10:30:54 +0100 Subject: [PATCH 083/129] regression --- TestCases/tutorials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 5cae096f0b7..86f5d5c50b8 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -105,7 +105,7 @@ def main(): sudo_design_primal.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" sudo_design_primal.cfg_file = "sudo_primal.cfg" sudo_design_primal.test_iter = 10 - sudo_design_primal.test_vals = [-14.579462, -13.203791, -13.601782, -12.616876, -14.005299, -10.817605, 15.000000, -2.296083] + sudo_design_primal.test_vals = [-7.971711, -8.161161, -7.869243, -4.884869, 5.000000, -0.666692, 5.000000, -2.567875] sudo_design_primal.command = TestCase.Command("mpirun -n 2", "SU2_CFD") test_list.append(sudo_design_primal) From 6e0d7a1465e63f36ee9f1a139ede9abfe0feb543 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Tue, 21 Jan 2025 18:00:02 +0100 Subject: [PATCH 084/129] - Fixed multizone history output --- SU2_CFD/src/drivers/CMultizoneDriver.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SU2_CFD/src/drivers/CMultizoneDriver.cpp b/SU2_CFD/src/drivers/CMultizoneDriver.cpp index d5e2fbbafbb..4a726812e7b 100644 --- a/SU2_CFD/src/drivers/CMultizoneDriver.cpp +++ b/SU2_CFD/src/drivers/CMultizoneDriver.cpp @@ -397,6 +397,10 @@ void CMultizoneDriver::Corrector(unsigned short val_iZone) { bool CMultizoneDriver::OuterConvergence(unsigned long OuterIter) { + // Set the current time iter for the multizone problem + bool unsteady = config_container[ZONE_0]->GetTime_Domain(); + if (unsteady) driver_output->SetCurTimeIter(config_container[ZONE_0]->GetTimeIter()); + /*--- Update the residual for the all the zones. ---*/ for (iZone = 0; iZone < nZone; iZone++) { From 181af084f5734e89cb3998b2011dc64c7dbb1727 Mon Sep 17 00:00:00 2001 From: Nijso Date: Wed, 22 Jan 2025 23:01:52 +0100 Subject: [PATCH 085/129] Remove unused option SMOOTH_GEOMETRY (#2427) * remove implicit smoothing remains --- Common/include/CConfig.hpp | 7 -- Common/include/geometry/CGeometry.hpp | 8 --- Common/include/geometry/CPhysicalGeometry.hpp | 8 --- Common/include/geometry/dual_grid/CPoint.hpp | 25 +------- Common/src/CConfig.cpp | 5 -- Common/src/geometry/CPhysicalGeometry.cpp | 64 ------------------- Common/src/geometry/dual_grid/CPoint.cpp | 8 --- 7 files changed, 2 insertions(+), 123 deletions(-) diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index 0afaff13ddc..58918bfdc2c 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -108,7 +108,6 @@ class CConfig { su2double Opt_RelaxFactor; /*!< \brief Scale factor for the line search. */ su2double Opt_LineSearch_Bound; /*!< \brief Bounds for the line search. */ su2double StartTime; - unsigned short SmoothNumGrid; /*!< \brief Smooth the numerical grid. */ bool ContinuousAdjoint, /*!< \brief Flag to know if the code is solving an adjoint problem. */ Viscous, /*!< \brief Flag to know if the code is solving a viscous problem. */ EquivArea, /*!< \brief Flag to know if the code is going to compute and plot the equivalent area. */ @@ -6338,12 +6337,6 @@ class CConfig { */ bool GetAxisymmetric(void) const { return Axisymmetric; } - /*! - * \brief Get information about there is a smoothing of the grid coordinates. - * \return TRUE if there is smoothing of the grid coordinates; otherwise FALSE. - */ - unsigned short GetSmoothNumGrid(void) const { return SmoothNumGrid; } - /*! * \brief Subtract one to the index of the finest grid (full multigrid strategy). * \return Change the index of the finest grid. diff --git a/Common/include/geometry/CGeometry.hpp b/Common/include/geometry/CGeometry.hpp index 738618ba2cd..dd79546f56b 100644 --- a/Common/include/geometry/CGeometry.hpp +++ b/Common/include/geometry/CGeometry.hpp @@ -913,14 +913,6 @@ class CGeometry { */ inline virtual void SetMultiGridWallTemperature(const CGeometry* fine_grid, unsigned short val_marker) {} - /*! - * \brief A virtual member. - * \param[in] val_nSmooth - Number of smoothing iterations. - * \param[in] val_smooth_coeff - Relaxation factor. - * \param[in] config - Definition of the particular problem. - */ - inline virtual void SetCoord_Smoothing(unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig* config) {} - /*! * \brief A virtual member. * \param[in] fine_grid - Geometrical definition of the child grid (for multigrid). diff --git a/Common/include/geometry/CPhysicalGeometry.hpp b/Common/include/geometry/CPhysicalGeometry.hpp index 8214e4ea7f0..5671ceae247 100644 --- a/Common/include/geometry/CPhysicalGeometry.hpp +++ b/Common/include/geometry/CPhysicalGeometry.hpp @@ -545,14 +545,6 @@ class CPhysicalGeometry final : public CGeometry { void DetermineTimeLevelElements(CConfig* config, const vector& localFaces, map& mapExternalElemIDToTimeLevel); - /*! - * \brief Do an implicit smoothing of the grid coordinates. - * \param[in] val_nSmooth - Number of smoothing iterations. - * \param[in] val_smooth_coeff - Relaxation factor. - * \param[in] config - Definition of the particular problem. - */ - void SetCoord_Smoothing(unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig* config) override; - /*! * \brief Compute 3 grid quality metrics: orthogonality angle, dual cell aspect ratio, and dual cell volume ratio. * \param[in] config - Definition of the particular problem. diff --git a/Common/include/geometry/dual_grid/CPoint.hpp b/Common/include/geometry/dual_grid/CPoint.hpp index 17d540a2a7b..e497df35307 100644 --- a/Common/include/geometry/dual_grid/CPoint.hpp +++ b/Common/include/geometry/dual_grid/CPoint.hpp @@ -771,14 +771,14 @@ class CPoint { } /*! - * \brief Get the value of the old coordinates for implicit smoothing. + * \brief Get the value of the old coordinates. * \param[in] iPoint - Index of the point. * \return Old coordinates at a point. */ inline su2double* GetCoord_Old(unsigned long iPoint) { return Coord_Old[iPoint]; } /*! - * \brief Set the value of the vector Coord_Old for implicit smoothing. + * \brief Set the value of the vector Coord_Old. * \param[in] iPoint - Index of the point. * \param[in] coord_old - Value of the coordinates. */ @@ -791,27 +791,6 @@ class CPoint { */ void SetCoord_Old(); - /*! - * \brief Get the value of the summed coordinates for implicit smoothing. - * \param[in] iPoint - Index of the point. - * \return Sum of coordinates at a point. - */ - inline su2double* GetCoord_Sum(unsigned long iPoint) { return Coord_Sum[iPoint]; } - - /*! - * \brief Add the value of the coordinates to the Coord_Sum vector for implicit smoothing. - * \param[in] iPoint - Index of the point. - * \param[in] coord_sum - Value of the coordinates to add. - */ - inline void AddCoord_Sum(unsigned long iPoint, const su2double* coord_sum) { - for (unsigned long iDim = 0; iDim < nDim; iDim++) Coord_Sum(iPoint, iDim) += coord_sum[iDim]; - } - - /*! - * \brief Initialize the vector Coord_Sum. - */ - void SetCoord_SumZero(); - /*! * \brief Get the value of the grid velocity at the point. * \param[in] iPoint - Index of the point. diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 1ec938832e2..cc5bd3faca6 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -2264,9 +2264,6 @@ void CConfig::SetConfig_Options() { /* DESCRIPTION: Value to move motion origins (1 or 0) */ addUShortListOption("MOVE_MOTION_ORIGIN", nMoveMotion_Origin, MoveMotion_Origin); - /* DESCRIPTION: Before each computation, implicitly smooth the nodal coordinates */ - addUnsignedShortOption("SMOOTH_GEOMETRY", SmoothNumGrid, 0); - /*!\par CONFIG_CATEGORY: Aeroelastic Simulation (Typical Section Model) \ingroup Config*/ /*--- Options related to aeroelastic simulations using the Typical Section Model) ---*/ /* DESCRIPTION: The flutter speed index (modifies the freestream condition) */ @@ -6877,8 +6874,6 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { cout << endl <<"--------------- Space Numerical Integration ( Zone " << iZone << " ) ------------------" << endl; - if (SmoothNumGrid) cout << "There are some smoothing iterations on the grid coordinates." << endl; - if ((Kind_Solver == MAIN_SOLVER::EULER) || (Kind_Solver == MAIN_SOLVER::NAVIER_STOKES) || (Kind_Solver == MAIN_SOLVER::RANS) || (Kind_Solver == MAIN_SOLVER::INC_EULER) || (Kind_Solver == MAIN_SOLVER::INC_NAVIER_STOKES) || (Kind_Solver == MAIN_SOLVER::INC_RANS) || (Kind_Solver == MAIN_SOLVER::NEMO_EULER) || (Kind_Solver == MAIN_SOLVER::NEMO_NAVIER_STOKES) || diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index 6e34e715be5..6bbbaa38e3d 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -7417,70 +7417,6 @@ void CPhysicalGeometry::VisualizeControlVolume(const CConfig* config) const { } } -void CPhysicalGeometry::SetCoord_Smoothing(unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig* config) { - unsigned short iSmooth, nneigh, iMarker; - su2double *Coord_Old, *Coord_Sum, *Coord, *Coord_i, *Coord_j, Position_Plane = 0.0; - unsigned long iEdge, iPoint, jPoint, iVertex; - su2double eps = 1E-6; - bool NearField = false; - - Coord = new su2double[nDim]; - - nodes->SetCoord_Old(); - - /*--- Jacobi iterations ---*/ - for (iSmooth = 0; iSmooth < val_nSmooth; iSmooth++) { - nodes->SetCoord_SumZero(); - - /*--- Loop over Interior edges ---*/ - for (iEdge = 0; iEdge < nEdge; iEdge++) { - iPoint = edges->GetNode(iEdge, 0); - Coord_i = nodes->GetCoord(iPoint); - - jPoint = edges->GetNode(iEdge, 1); - Coord_j = nodes->GetCoord(jPoint); - - /*--- Accumulate nearest neighbor Coord to Res_sum for each variable ---*/ - nodes->AddCoord_Sum(iPoint, Coord_j); - nodes->AddCoord_Sum(jPoint, Coord_i); - } - - /*--- Loop over all mesh points (Update Coords with averaged sum) ---*/ - for (iPoint = 0; iPoint < nPoint; iPoint++) { - nneigh = nodes->GetnPoint(iPoint); - Coord_Sum = nodes->GetCoord_Sum(iPoint); - Coord_Old = nodes->GetCoord_Old(iPoint); - - if (nDim == 2) { - Coord[0] = (Coord_Old[0] + val_smooth_coeff * Coord_Sum[0]) / (1.0 + val_smooth_coeff * su2double(nneigh)); - Coord[1] = (Coord_Old[1] + val_smooth_coeff * Coord_Sum[1]) / (1.0 + val_smooth_coeff * su2double(nneigh)); - if ((NearField) && ((Coord_Old[1] > Position_Plane - eps) && (Coord_Old[1] < Position_Plane + eps))) - Coord[1] = Coord_Old[1]; - } - - if (nDim == 3) { - Coord[0] = (Coord_Old[0] + val_smooth_coeff * Coord_Sum[0]) / (1.0 + val_smooth_coeff * su2double(nneigh)); - Coord[1] = (Coord_Old[1] + val_smooth_coeff * Coord_Sum[1]) / (1.0 + val_smooth_coeff * su2double(nneigh)); - Coord[2] = (Coord_Old[2] + val_smooth_coeff * Coord_Sum[2]) / (1.0 + val_smooth_coeff * su2double(nneigh)); - if ((NearField) && ((Coord_Old[2] > Position_Plane - eps) && (Coord_Old[2] < Position_Plane + eps))) - Coord[2] = Coord_Old[2]; - } - - nodes->SetCoord(iPoint, Coord); - } - - /*--- Copy boundary values ---*/ - for (iMarker = 0; iMarker < nMarker; iMarker++) - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { - iPoint = vertex[iMarker][iVertex]->GetNode(); - Coord_Old = nodes->GetCoord_Old(iPoint); - nodes->SetCoord(iPoint, Coord_Old); - } - } - - delete[] Coord; -} - bool CPhysicalGeometry::FindFace(unsigned long first_elem, unsigned long second_elem, unsigned short& face_first_elem, unsigned short& face_second_elem) { if (first_elem == second_elem) return false; diff --git a/Common/src/geometry/dual_grid/CPoint.cpp b/Common/src/geometry/dual_grid/CPoint.cpp index 35c45a826b4..7096dfa6443 100644 --- a/Common/src/geometry/dual_grid/CPoint.cpp +++ b/Common/src/geometry/dual_grid/CPoint.cpp @@ -94,12 +94,6 @@ void CPoint::FullAllocation(unsigned short imesh, const CConfig* config) { Vertex.resize(npoint); - /*--- For smoothing the numerical grid coordinates ---*/ - if (config->GetSmoothNumGrid()) { - Coord_Old.resize(npoint, nDim) = su2double(0.0); - Coord_Sum.resize(npoint, nDim) = su2double(0.0); - } - /*--- Storage of grid velocities for dynamic meshes. ---*/ if (config->GetDynamic_Grid()) { @@ -190,5 +184,3 @@ void CPoint::SetCoord_Old() { assert(Coord_Old.size() == Coord.size()); parallelCopy(Coord.size(), Coord.data(), Coord_Old.data()); } - -void CPoint::SetCoord_SumZero() { parallelSet(Coord_Sum.size(), 0.0, Coord_Sum.data()); } From f5d0c8258d7f7c4f45c690a505effb5640c0aa0c Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 23 Jan 2025 16:00:21 +0100 Subject: [PATCH 086/129] - Simplified implementation --- SU2_CFD/src/drivers/CMultizoneDriver.cpp | 4 ++-- SU2_CFD/src/iteration/CFluidIteration.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/SU2_CFD/src/drivers/CMultizoneDriver.cpp b/SU2_CFD/src/drivers/CMultizoneDriver.cpp index 4a726812e7b..91885f0c731 100644 --- a/SU2_CFD/src/drivers/CMultizoneDriver.cpp +++ b/SU2_CFD/src/drivers/CMultizoneDriver.cpp @@ -398,13 +398,13 @@ void CMultizoneDriver::Corrector(unsigned short val_iZone) { bool CMultizoneDriver::OuterConvergence(unsigned long OuterIter) { // Set the current time iter for the multizone problem - bool unsteady = config_container[ZONE_0]->GetTime_Domain(); - if (unsteady) driver_output->SetCurTimeIter(config_container[ZONE_0]->GetTimeIter()); /*--- Update the residual for the all the zones. ---*/ for (iZone = 0; iZone < nZone; iZone++) { + output_container[iZone]->SetCurTimeIter(config_container[iZone]->GetTimeIter()); + /*--- Account for all the solvers in this zone. ---*/ auto solvers = solver_container[iZone][INST_0][MESH_0]; diff --git a/SU2_CFD/src/iteration/CFluidIteration.cpp b/SU2_CFD/src/iteration/CFluidIteration.cpp index 77a058c39df..84c70c2b64e 100644 --- a/SU2_CFD/src/iteration/CFluidIteration.cpp +++ b/SU2_CFD/src/iteration/CFluidIteration.cpp @@ -375,8 +375,7 @@ void CFluidIteration::Solve(COutput* output, CIntegration**** integration, CGeom unsigned short val_iInst) { /*--- Boolean to determine if we are running a static or dynamic case ---*/ bool steady = !config[val_iZone]->GetTime_Domain(); - - if (!steady) output->SetCurTimeIter(config[val_iZone]->GetTimeIter()); + output->SetCurTimeIter(config[val_iZone]->GetTimeIter()); unsigned long Inner_Iter, nInner_Iter = config[val_iZone]->GetnInner_Iter(); bool StopCalc = false; From 2c3e3c75bbc9fbe655bdb44c88cbcc2f656f0e94 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 23 Jan 2025 17:42:38 +0100 Subject: [PATCH 087/129] - Revert to previous commit --- SU2_CFD/src/drivers/CMultizoneDriver.cpp | 2 -- SU2_CFD/src/iteration/CFluidIteration.cpp | 1 - SU2_CFD/src/output/COutput.cpp | 7 ++++++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/SU2_CFD/src/drivers/CMultizoneDriver.cpp b/SU2_CFD/src/drivers/CMultizoneDriver.cpp index 91885f0c731..8c6e3cd2194 100644 --- a/SU2_CFD/src/drivers/CMultizoneDriver.cpp +++ b/SU2_CFD/src/drivers/CMultizoneDriver.cpp @@ -403,8 +403,6 @@ bool CMultizoneDriver::OuterConvergence(unsigned long OuterIter) { for (iZone = 0; iZone < nZone; iZone++) { - output_container[iZone]->SetCurTimeIter(config_container[iZone]->GetTimeIter()); - /*--- Account for all the solvers in this zone. ---*/ auto solvers = solver_container[iZone][INST_0][MESH_0]; diff --git a/SU2_CFD/src/iteration/CFluidIteration.cpp b/SU2_CFD/src/iteration/CFluidIteration.cpp index 84c70c2b64e..4ca6c45a172 100644 --- a/SU2_CFD/src/iteration/CFluidIteration.cpp +++ b/SU2_CFD/src/iteration/CFluidIteration.cpp @@ -375,7 +375,6 @@ void CFluidIteration::Solve(COutput* output, CIntegration**** integration, CGeom unsigned short val_iInst) { /*--- Boolean to determine if we are running a static or dynamic case ---*/ bool steady = !config[val_iZone]->GetTime_Domain(); - output->SetCurTimeIter(config[val_iZone]->GetTimeIter()); unsigned long Inner_Iter, nInner_Iter = config[val_iZone]->GetnInner_Iter(); bool StopCalc = false; diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 36c743cebe3..58f01d7f742 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -206,7 +206,8 @@ void COutput::SetHistoryOutput(CGeometry *geometry, unsigned long TimeIter, unsigned long OuterIter, unsigned long InnerIter) { - + + curTimeIter = TimeIter; curAbsTimeIter = max(TimeIter, config->GetStartWindowIteration()) - config->GetStartWindowIteration(); curOuterIter = OuterIter; curInnerIter = InnerIter; @@ -272,6 +273,7 @@ void COutput::SetHistoryOutput(CGeometry ****geometry, CSolver *****solver, CCon void COutput::SetMultizoneHistoryOutput(COutput **output, CConfig **config, CConfig *driver_config, unsigned long TimeIter, unsigned long OuterIter){ + curTimeIter = TimeIter; curAbsTimeIter = max(TimeIter, driver_config->GetStartWindowIteration()) - driver_config->GetStartWindowIteration(); curOuterIter = OuterIter; @@ -387,6 +389,9 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form /*--- File writer that will later be used to write the file to disk. Created below in the "switch" ---*/ CFileWriter *fileWriter = nullptr; + /*--- Set current time iter even if history file is not written ---*/ + curTimeIter = config->GetTimeIter(); + /*--- If it is still present, strip the extension (suffix) from the filename ---*/ const auto lastindex = fileName.find_last_of('.'); fileName = fileName.substr(0, lastindex); From 8fc042cf82e74f2685e4b6e277d0c359646300fe Mon Sep 17 00:00:00 2001 From: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> Date: Thu, 23 Jan 2025 10:47:13 -0800 Subject: [PATCH 088/129] Apply suggestions from code review --- SU2_CFD/include/output/COutput.hpp | 6 ------ SU2_CFD/src/drivers/CMultizoneDriver.cpp | 2 -- SU2_CFD/src/output/COutput.cpp | 1 - 3 files changed, 9 deletions(-) diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 8300f1a568d..14b0bbec9b6 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -418,12 +418,6 @@ class COutput { */ void SetMultizoneHistoryOutput(COutput** output, CConfig **config, CConfig *driver_config, unsigned long TimeIter, unsigned long OuterIter); - - /*! - * \brief Sets the current time iteration - * \param[in] timeIter - the current time iteration - */ - inline void SetCurTimeIter(unsigned long val_curTimeIter) {curTimeIter = val_curTimeIter;} /*! * \brief Sets the volume output filename diff --git a/SU2_CFD/src/drivers/CMultizoneDriver.cpp b/SU2_CFD/src/drivers/CMultizoneDriver.cpp index 8c6e3cd2194..d5e2fbbafbb 100644 --- a/SU2_CFD/src/drivers/CMultizoneDriver.cpp +++ b/SU2_CFD/src/drivers/CMultizoneDriver.cpp @@ -397,8 +397,6 @@ void CMultizoneDriver::Corrector(unsigned short val_iZone) { bool CMultizoneDriver::OuterConvergence(unsigned long OuterIter) { - // Set the current time iter for the multizone problem - /*--- Update the residual for the all the zones. ---*/ for (iZone = 0; iZone < nZone; iZone++) { diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index 58f01d7f742..631a4ba6bde 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -206,7 +206,6 @@ void COutput::SetHistoryOutput(CGeometry *geometry, unsigned long TimeIter, unsigned long OuterIter, unsigned long InnerIter) { - curTimeIter = TimeIter; curAbsTimeIter = max(TimeIter, config->GetStartWindowIteration()) - config->GetStartWindowIteration(); curOuterIter = OuterIter; From 1a30b5821b75e9d1cc6c81a7a0ba66c42327207b Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Fri, 24 Jan 2025 16:22:21 -0800 Subject: [PATCH 089/129] add submodule --- .gitmodules | 3 +++ externals/FADO | 1 + 2 files changed, 4 insertions(+) create mode 160000 externals/FADO diff --git a/.gitmodules b/.gitmodules index 2c655cb36da..4c6d8a819f8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -27,3 +27,6 @@ [submodule "subprojects/MLPCpp"] path = subprojects/MLPCpp url = https://github.com/EvertBunschoten/MLPCpp.git +[submodule "externals/FADO"] + path = externals/FADO + url = https://github.com/pcarruscag/FADO.git diff --git a/externals/FADO b/externals/FADO new file mode 160000 index 00000000000..ee0eb0ba08e --- /dev/null +++ b/externals/FADO @@ -0,0 +1 @@ +Subproject commit ee0eb0ba08e04c83051d805ee64de6d97d9fda38 From bd72165069e39834a2ee77abc34cb70831a2d4d9 Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Fri, 24 Jan 2025 16:39:13 -0800 Subject: [PATCH 090/129] install --- SU2_PY/meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SU2_PY/meson.build b/SU2_PY/meson.build index 85ae325f3f0..5c00ac9b1ad 100644 --- a/SU2_PY/meson.build +++ b/SU2_PY/meson.build @@ -70,3 +70,5 @@ install_data(['FSI_tools/__init__.py', install_data(['SU2_Nastran/__init__.py', 'SU2_Nastran/pysu2_nastran.py'], install_dir: join_paths(get_option('bindir'), 'SU2_Nastran')) + +install_subdir(['../externals/FADO'], install_dir: join_paths(get_option('bindir'), 'FADO')) From 9697a85c98e67bd13a596ff3fa00489bcd48edbe Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Fri, 24 Jan 2025 17:37:08 -0800 Subject: [PATCH 091/129] fixes for importing easily --- SU2_PY/meson.build | 2 +- TestCases/serial_regression.py | 4 ++++ externals/FADO | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/SU2_PY/meson.build b/SU2_PY/meson.build index 5c00ac9b1ad..ced81290346 100644 --- a/SU2_PY/meson.build +++ b/SU2_PY/meson.build @@ -71,4 +71,4 @@ install_data(['SU2_Nastran/__init__.py', 'SU2_Nastran/pysu2_nastran.py'], install_dir: join_paths(get_option('bindir'), 'SU2_Nastran')) -install_subdir(['../externals/FADO'], install_dir: join_paths(get_option('bindir'), 'FADO')) +install_subdir(['../externals/FADO'], install_dir: get_option('bindir')) diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index b4b9cd473a9..7f8baec7e9a 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -30,6 +30,10 @@ from TestCase import TestCase from TestCase import parse_args +import FADO +FADO.printDocumentation() + + def main(): '''This program runs SU2 and ensures that the output matches specified values. This will be used to do checks when code is pushed to github diff --git a/externals/FADO b/externals/FADO index ee0eb0ba08e..de318644e81 160000 --- a/externals/FADO +++ b/externals/FADO @@ -1 +1 @@ -Subproject commit ee0eb0ba08e04c83051d805ee64de6d97d9fda38 +Subproject commit de318644e81037cfd20af3e12c51bf14dcdf77ba From 4d9a0d9aab2f4e86d1f651f30a4645d5a46f7fcb Mon Sep 17 00:00:00 2001 From: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> Date: Fri, 24 Jan 2025 19:40:31 -0800 Subject: [PATCH 092/129] Update TestCases/serial_regression.py --- TestCases/serial_regression.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 7f8baec7e9a..b4b9cd473a9 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -30,10 +30,6 @@ from TestCase import TestCase from TestCase import parse_args -import FADO -FADO.printDocumentation() - - def main(): '''This program runs SU2 and ensures that the output matches specified values. This will be used to do checks when code is pushed to github From b1c3a15e89a7ae6fb7ed39795576a6b0bd2dd93a Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Fri, 24 Jan 2025 19:45:26 -0800 Subject: [PATCH 093/129] update authors --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index 511ebcf4b33..48b2140480a 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -136,6 +136,7 @@ Thomas D. Economon Tim Albring TobiKattmann Trent Lukaczyk +Vikram Bharadwaj Vinzenz Götz VivaanKhatri Wally Maier From 9cfe08d9c061e6e39caab9dc3a591deefa60737d Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 25 Jan 2025 16:25:18 -0800 Subject: [PATCH 094/129] add FADO to init script --- externals/FADO | 2 +- meson_scripts/init.py | 9 +++++++++ preconfigure.py | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/externals/FADO b/externals/FADO index de318644e81..ce7ee018e4e 160000 --- a/externals/FADO +++ b/externals/FADO @@ -1 +1 @@ -Subproject commit de318644e81037cfd20af3e12c51bf14dcdf77ba +Subproject commit ce7ee018e4e699af5028d69baa1939fea290e18a diff --git a/meson_scripts/init.py b/meson_scripts/init.py index e3df3e023ba..56114ebad35 100755 --- a/meson_scripts/init.py +++ b/meson_scripts/init.py @@ -48,6 +48,7 @@ def init_submodules( own_mpp=True, own_cool=True, own_mel=True, + own_fado=True, own_mlpcpp=True, ): @@ -71,6 +72,8 @@ def init_submodules( github_repo_coolprop = "https://github.com/CoolProp/CoolProp" sha_version_mel = "46205ab019e5224559091375a6d71aabae6bc5b9" github_repo_mel = "https://github.com/pcarruscag/MEL" + sha_version_fado = "ce7ee018e4e699af5028d69baa1939fea290e18a" + github_repo_fado = "https://github.com/pcarruscag/FADO" sha_version_mlpcpp = "6865a58b22f21a92977839d9c93eae9522402f55" github_repo_mlpcpp = "https://github.com/EvertBunschoten/MLPCpp" @@ -82,6 +85,7 @@ def init_submodules( mpp_name = "Mutationpp" coolprop_name = "CoolProp" mel_name = "MEL" + fado_name = "FADO" mlpcpp_name = "MLPCpp" base_path = cur_dir + os.path.sep + "externals" + os.path.sep @@ -91,6 +95,7 @@ def init_submodules( alt_name_meson = base_path + "meson" alt_name_ninja = base_path + "ninja" alt_name_mel = base_path + "mel" + alt_name_mel = base_path + "fado" alt_name_mpp = cur_dir + os.path.sep + "subprojects" + os.path.sep + "Mutationpp" alt_name_coolprop = cur_dir + os.path.sep + "subprojects" + os.path.sep + "CoolProp" alt_name_mlpcpp = cur_dir + os.path.sep + "subprojects" + os.path.sep + "MLPCpp" @@ -123,6 +128,8 @@ def init_submodules( submodule_status(alt_name_coolprop, sha_version_coolprop) if own_mel: submodule_status(alt_name_mel, sha_version_mel) + if own_fado: + submodule_status(alt_name_fado, sha_version_fado) if own_mlpcpp: submodule_status(alt_name_mlpcpp, sha_version_mlpcpp) # Otherwise download the zip file from git @@ -157,6 +164,8 @@ def init_submodules( ) if own_mel: download_module(mel_name, alt_name_mel, github_repo_mel, sha_version_mel) + if own_fado: + download_module(fado_name, alt_name_fado, github_repo_fado, sha_version_fado) if own_mlpcpp: download_module( mlpcpp_name, alt_name_mlpcpp, github_repo_mlpcpp, sha_version_mlpcpp diff --git a/preconfigure.py b/preconfigure.py index 51cb0599e6e..5dfe8acd8a9 100755 --- a/preconfigure.py +++ b/preconfigure.py @@ -81,6 +81,7 @@ def run( own_mpp=True, own_cool=True, own_mel=True, + own_fado=True, own_mlpcpp=True, ): @@ -94,6 +95,7 @@ def run( own_mpp=own_mpp, own_cool=own_cool, own_mel=own_mel, + own_fado=own_fado, own_mlpcpp=own_mlpcpp, ) @@ -137,6 +139,9 @@ def run( parser.add_argument( "--no-mel", help="do not download own copy of MEL", action="store_false" ) + parser.add_argument( + "--no-fado", help="do not download own copy of FADO", action="store_false" + ) parser.add_argument( "--no-mlpcpp", help="do not download copy of MLpCpp", @@ -152,5 +157,6 @@ def run( own_mpp=args.no_mpp, own_cool=args.no_coolprop, own_mel=args.no_mel, + own_fado=args.no_fado, own_mlpcpp=args.no_mlpcpp, ) From 423e3a33caf014daed21bd32c1b53e85ef0aed8d Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 25 Jan 2025 16:55:35 -0800 Subject: [PATCH 095/129] fix --- meson_scripts/init.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/meson_scripts/init.py b/meson_scripts/init.py index 56114ebad35..109c0232271 100755 --- a/meson_scripts/init.py +++ b/meson_scripts/init.py @@ -95,7 +95,7 @@ def init_submodules( alt_name_meson = base_path + "meson" alt_name_ninja = base_path + "ninja" alt_name_mel = base_path + "mel" - alt_name_mel = base_path + "fado" + alt_name_mel = base_path + "FADO" alt_name_mpp = cur_dir + os.path.sep + "subprojects" + os.path.sep + "Mutationpp" alt_name_coolprop = cur_dir + os.path.sep + "subprojects" + os.path.sep + "CoolProp" alt_name_mlpcpp = cur_dir + os.path.sep + "subprojects" + os.path.sep + "MLPCpp" @@ -165,7 +165,9 @@ def init_submodules( if own_mel: download_module(mel_name, alt_name_mel, github_repo_mel, sha_version_mel) if own_fado: - download_module(fado_name, alt_name_fado, github_repo_fado, sha_version_fado) + download_module( + fado_name, alt_name_fado, github_repo_fado, sha_version_fado + ) if own_mlpcpp: download_module( mlpcpp_name, alt_name_mlpcpp, github_repo_mlpcpp, sha_version_mlpcpp From 4a0b4cea87678a87cc861389dfc2f4f5f395569a Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 25 Jan 2025 17:00:34 -0800 Subject: [PATCH 096/129] fix --- meson_scripts/init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson_scripts/init.py b/meson_scripts/init.py index 109c0232271..67a2e41a2ec 100755 --- a/meson_scripts/init.py +++ b/meson_scripts/init.py @@ -95,7 +95,7 @@ def init_submodules( alt_name_meson = base_path + "meson" alt_name_ninja = base_path + "ninja" alt_name_mel = base_path + "mel" - alt_name_mel = base_path + "FADO" + alt_name_fado = base_path + "FADO" alt_name_mpp = cur_dir + os.path.sep + "subprojects" + os.path.sep + "Mutationpp" alt_name_coolprop = cur_dir + os.path.sep + "subprojects" + os.path.sep + "CoolProp" alt_name_mlpcpp = cur_dir + os.path.sep + "subprojects" + os.path.sep + "MLPCpp" From 7d46701caf3724f741f22c78d6fcb92e24279b14 Mon Sep 17 00:00:00 2001 From: Nijso Date: Sun, 26 Jan 2025 13:16:01 +0100 Subject: [PATCH 097/129] Update TestCases/tutorials.py Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- TestCases/tutorials.py | 1 - 1 file changed, 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 86f5d5c50b8..58a9be5639a 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -159,7 +159,6 @@ def main(): premixed_hydrogen.test_vals = [-9.809794, -10.369804, -11.044267, -4.332945, -11.883789] test_list.append(premixed_hydrogen) - ### Compressible Flow # Inviscid Bump From 68f5ac584d0c4f65699b799a9390298a049880da Mon Sep 17 00:00:00 2001 From: Nijso Date: Sun, 26 Jan 2025 13:16:09 +0100 Subject: [PATCH 098/129] Update TestCases/tutorials.py Co-authored-by: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> --- TestCases/tutorials.py | 1 - 1 file changed, 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 58a9be5639a..60e0f878f82 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -118,7 +118,6 @@ def main(): sudo_design_adjoint.command = TestCase.Command("mpirun -n 2", "SU2_CFD_AD") test_list.append(sudo_design_adjoint) - ### Species Transport # 3 species (2 eq) primitive venturi mixing From b418cc0832070d87ab8b1ab72588dea10f1e6a09 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sun, 26 Jan 2025 15:40:41 +0100 Subject: [PATCH 099/129] fado regression --- TestCases/tutorials.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 60e0f878f82..ac726c8942a 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -118,6 +118,7 @@ def main(): sudo_design_adjoint.command = TestCase.Command("mpirun -n 2", "SU2_CFD_AD") test_list.append(sudo_design_adjoint) + ### Species Transport # 3 species (2 eq) primitive venturi mixing @@ -343,6 +344,22 @@ def main(): pass_list = [ test.run_test() for test in test_list ] + + # design-FADO: 90 degree pipe bend optimization + sudo_design_fado = TestCase('sudo_bend_design_fado') + sudo_design_fado.command = TestCase.Command("python", "optimization.py") + sudo_design_fado.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" + sudo_design_fado.cfg_file = "sudo.cfg" + sudo_design_fado.multizone = False + sudo_design_fado.test_iter = 10 + sudo_design_fado.timeout = 1600 + sudo_design_fado.reference_file = "optim.csv.ref" + sudo_design_fado.test_file = "optim.csv" + sudo_design_fado.comp_threshold = 1e-6 + sudo_design_fado.tol_file_percent = 0.1 + pass_list.append(sudo_design_fado.run_filediff()) + test_list.append(sudo_design_fado) + # Tests summary print('==================================================================') print('Summary of the parallel tests') From c5d3ae04467f221535e2b909ed5127aa9b29c7c4 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sun, 26 Jan 2025 22:25:06 +0100 Subject: [PATCH 100/129] modify for regression test --- TestCases/tutorials.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index ac726c8942a..be759101871 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -105,7 +105,7 @@ def main(): sudo_design_primal.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" sudo_design_primal.cfg_file = "sudo_primal.cfg" sudo_design_primal.test_iter = 10 - sudo_design_primal.test_vals = [-7.971711, -8.161161, -7.869243, -4.884869, 5.000000, -0.666692, 5.000000, -2.567875] + sudo_design_primal.test_vals = [-13.474698, -12.487574, -12.441102, -11.418111, -12.552674, -9.712569, 89.034000] sudo_design_primal.command = TestCase.Command("mpirun -n 2", "SU2_CFD") test_list.append(sudo_design_primal) @@ -114,7 +114,7 @@ def main(): sudo_design_adjoint.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" sudo_design_adjoint.cfg_file = "sudo_adjoint.cfg" sudo_design_adjoint.test_iter = 10 - sudo_design_adjoint.test_vals = [-14.579462, -13.203791, -13.601782, -12.616876, -14.005299, -10.817605, 15.000000, -2.296083] + sudo_design_adjoint.test_vals = [-4.133194, -3.691046, -2.581693, -3.476472, -3.837900, -6.900137] sudo_design_adjoint.command = TestCase.Command("mpirun -n 2", "SU2_CFD_AD") test_list.append(sudo_design_adjoint) From 1e70d446aec5607c1d8426f6239288c363d6bd95 Mon Sep 17 00:00:00 2001 From: vdweide Date: Mon, 27 Jan 2025 18:58:37 +0100 Subject: [PATCH 101/129] Do not make a distinction in CPhysicalGeometry anymore between FVM and FEM for reading the grid --- Common/include/geometry/CPhysicalGeometry.hpp | 4 +- Common/src/geometry/CPhysicalGeometry.cpp | 47 ++++++------------- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/Common/include/geometry/CPhysicalGeometry.hpp b/Common/include/geometry/CPhysicalGeometry.hpp index 5671ceae247..1363c46cc8c 100644 --- a/Common/include/geometry/CPhysicalGeometry.hpp +++ b/Common/include/geometry/CPhysicalGeometry.hpp @@ -285,8 +285,8 @@ class CPhysicalGeometry final : public CGeometry { * \param[in] val_iZone - Domain to be read from the grid file. * \param[in] val_nZone - Total number of domains in the grid file. */ - void Read_Mesh_FVM(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, - unsigned short val_nZone); + void Read_Mesh(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, + unsigned short val_nZone); /*! * \brief Reads for the FEM solver the geometry of the grid and adjust the boundary diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index 6bbbaa38e3d..6bddb08e383 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -72,38 +72,18 @@ CPhysicalGeometry::CPhysicalGeometry(CConfig* config, unsigned short val_iZone, string val_mesh_filename = config->GetMesh_FileName(); unsigned short val_format = config->GetMesh_FileFormat(); - /*--- Determine whether or not a FEM discretization is used ---*/ + /*--- Check for a valid mesh format ---*/ - const bool fem_solver = config->GetFEMSolver(); - - /*--- Initialize counters for local/global points & elements ---*/ - - if (fem_solver) { - switch (val_format) { - case SU2: - Read_SU2_Format_Parallel_FEM(config, val_mesh_filename, val_iZone, val_nZone); - break; - - case CGNS_GRID: - Read_CGNS_Format_Parallel_FEM(config, val_mesh_filename, val_iZone, val_nZone); - break; - - default: - SU2_MPI::Error("Unrecognized mesh format specified for the FEM solver!", CURRENT_FUNCTION); - break; - } - } else { - switch (val_format) { - case SU2: - case CGNS_GRID: - case RECTANGLE: - case BOX: - Read_Mesh_FVM(config, val_mesh_filename, val_iZone, val_nZone); - break; - default: - SU2_MPI::Error("Unrecognized mesh format specified!", CURRENT_FUNCTION); - break; - } + switch (val_format) { + case SU2: + case CGNS_GRID: + case RECTANGLE: + case BOX: + Read_Mesh(config, val_mesh_filename, val_iZone, val_nZone); + break; + default: + SU2_MPI::Error("Unrecognized mesh format specified!", CURRENT_FUNCTION); + break; } /*--- After reading the mesh, assert that the dimension is equal to 2 or 3. ---*/ @@ -3433,8 +3413,8 @@ void CPhysicalGeometry::SetBoundaries(CConfig* config) { delete[] nElem_Bound_Copy; } -void CPhysicalGeometry::Read_Mesh_FVM(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, - unsigned short val_nZone) { +void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, + unsigned short val_nZone) { /*--- Initialize counters for local/global points & elements ---*/ Global_nPoint = 0; @@ -3463,6 +3443,7 @@ void CPhysicalGeometry::Read_Mesh_FVM(CConfig* config, const string& val_mesh_fi /*--- Create a mesh reader to read a CGNS grid into linear partitions. ---*/ unsigned short val_format = config->GetMesh_FileFormat(); + const bool fem_solver = config->GetFEMSolver(); CMeshReaderFVM* MeshFVM = nullptr; switch (val_format) { From e4e670b38a748c127670fa0a0f72aa7daffb2e15 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Mon, 27 Jan 2025 22:21:02 +0100 Subject: [PATCH 102/129] change fado regression to exec --- TestCases/tutorials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index be759101871..2d7aee33d8e 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -347,7 +347,7 @@ def main(): # design-FADO: 90 degree pipe bend optimization sudo_design_fado = TestCase('sudo_bend_design_fado') - sudo_design_fado.command = TestCase.Command("python", "optimization.py") + sudo_design_fado.command = TestCase.Command(exec = "python", param = "optimization.py") sudo_design_fado.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" sudo_design_fado.cfg_file = "sudo.cfg" sudo_design_fado.multizone = False From d69757e1bf6f8aa465cd997c6a111e48dedb8b89 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Tue, 28 Jan 2025 19:14:37 +0100 Subject: [PATCH 103/129] fado regression --- TestCases/tutorials.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 2d7aee33d8e..4d49f58826e 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -345,6 +345,21 @@ def main(): pass_list = [ test.run_test() for test in test_list ] + # design-FADO: 90 degree pipe bend optimization + test1 = TestCase('test1') + test1.command = TestCase.Command(exec = "python", param = "optimization1.py") + test1.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" + test1.cfg_file = "sudo.cfg" + test1.multizone = False + test1.test_iter = 10 + test1.timeout = 1600 + test1.reference_file = "optim.csv.ref" + test1.test_file = "optim.csv" + test1.comp_threshold = 1e-6 + test1.tol_file_percent = 0.1 + pass_list.append(test1.run_filediff()) + test_list.append(test1) + # design-FADO: 90 degree pipe bend optimization sudo_design_fado = TestCase('sudo_bend_design_fado') sudo_design_fado.command = TestCase.Command(exec = "python", param = "optimization.py") @@ -352,7 +367,7 @@ def main(): sudo_design_fado.cfg_file = "sudo.cfg" sudo_design_fado.multizone = False sudo_design_fado.test_iter = 10 - sudo_design_fado.timeout = 1600 + sudo_design_fado.timeout = 3200 sudo_design_fado.reference_file = "optim.csv.ref" sudo_design_fado.test_file = "optim.csv" sudo_design_fado.comp_threshold = 1e-6 From 329492d52bf3ec0a68f6d10e6422c4d0c3073ebd Mon Sep 17 00:00:00 2001 From: bigfooted Date: Tue, 28 Jan 2025 20:01:10 +0100 Subject: [PATCH 104/129] remove test --- TestCases/tutorials.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 4d49f58826e..6979f86e7c1 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -345,21 +345,6 @@ def main(): pass_list = [ test.run_test() for test in test_list ] - # design-FADO: 90 degree pipe bend optimization - test1 = TestCase('test1') - test1.command = TestCase.Command(exec = "python", param = "optimization1.py") - test1.cfg_dir = "../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions" - test1.cfg_file = "sudo.cfg" - test1.multizone = False - test1.test_iter = 10 - test1.timeout = 1600 - test1.reference_file = "optim.csv.ref" - test1.test_file = "optim.csv" - test1.comp_threshold = 1e-6 - test1.tol_file_percent = 0.1 - pass_list.append(test1.run_filediff()) - test_list.append(test1) - # design-FADO: 90 degree pipe bend optimization sudo_design_fado = TestCase('sudo_bend_design_fado') sudo_design_fado.command = TestCase.Command(exec = "python", param = "optimization.py") From d5fc0b05dc592501192da76e61fdf91db564b635 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Tue, 28 Jan 2025 21:04:18 +0100 Subject: [PATCH 105/129] change diff output --- TestCases/TestCase.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/TestCases/TestCase.py b/TestCases/TestCase.py index 320c913ebd2..17b0f965468 100644 --- a/TestCases/TestCase.py +++ b/TestCases/TestCase.py @@ -361,7 +361,14 @@ def run_filediff(self, with_tsan=False, with_asan=False): # Assert that both files have the same number of lines if len(fromlines) != len(tolines): - diff = ["ERROR: Number of lines in " + fromfile + " and " + tofile + " differ: " + len(fromlines) + " vs " + len(tolines) + "."] + stringerr = "ERROR: Number of lines in " + str(fromfile) + " and " + str(tofile) + " differ: " + str(len(fromlines)) + " vs " + str(len(tolines)) + "." + diff = [stringerr] + print("generated file = ") + for i_line in range(0, len(tolines)): + print(i_line) + for i_line in range(0, len(fromlines)): + print(i_line) + passed = False # Loop through all lines From 63d194a0a3ebee980661aa380f91362bb060d221 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Tue, 28 Jan 2025 22:59:33 +0100 Subject: [PATCH 106/129] change diff output --- TestCases/TestCase.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TestCases/TestCase.py b/TestCases/TestCase.py index 17b0f965468..91b08199f5e 100644 --- a/TestCases/TestCase.py +++ b/TestCases/TestCase.py @@ -364,9 +364,9 @@ def run_filediff(self, with_tsan=False, with_asan=False): stringerr = "ERROR: Number of lines in " + str(fromfile) + " and " + str(tofile) + " differ: " + str(len(fromlines)) + " vs " + str(len(tolines)) + "." diff = [stringerr] print("generated file = ") - for i_line in range(0, len(tolines)): + for i_line in tolines: print(i_line) - for i_line in range(0, len(fromlines)): + for i_line in fromlines: print(i_line) passed = False From 984f45a01e9403ce1904f51f8fe0880465570d45 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Wed, 29 Jan 2025 00:19:39 +0100 Subject: [PATCH 107/129] small change --- TestCases/tutorials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 6979f86e7c1..2d7aee33d8e 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -352,7 +352,7 @@ def main(): sudo_design_fado.cfg_file = "sudo.cfg" sudo_design_fado.multizone = False sudo_design_fado.test_iter = 10 - sudo_design_fado.timeout = 3200 + sudo_design_fado.timeout = 1600 sudo_design_fado.reference_file = "optim.csv.ref" sudo_design_fado.test_file = "optim.csv" sudo_design_fado.comp_threshold = 1e-6 From cfcb6e59a78c2500e47605e882fec14e994c2f81 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 31 Jan 2025 22:46:37 +0100 Subject: [PATCH 108/129] move reference file --- TestCases/tutorials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 2d7aee33d8e..6488a2027a3 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -353,7 +353,7 @@ def main(): sudo_design_fado.multizone = False sudo_design_fado.test_iter = 10 sudo_design_fado.timeout = 1600 - sudo_design_fado.reference_file = "optim.csv.ref" + sudo_design_fado.reference_file = "../../../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref" sudo_design_fado.test_file = "optim.csv" sudo_design_fado.comp_threshold = 1e-6 sudo_design_fado.tol_file_percent = 0.1 From 78598eaf25d0cd5b9d9e42b320e83406b7f0d043 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Fri, 31 Jan 2025 23:21:30 +0100 Subject: [PATCH 109/129] move reference file --- TestCases/tutorials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 6488a2027a3..f4a151bdaad 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -353,7 +353,7 @@ def main(): sudo_design_fado.multizone = False sudo_design_fado.test_iter = 10 sudo_design_fado.timeout = 1600 - sudo_design_fado.reference_file = "../../../Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref" + sudo_design_fado.reference_file = "../../../TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref" sudo_design_fado.test_file = "optim.csv" sudo_design_fado.comp_threshold = 1e-6 sudo_design_fado.tol_file_percent = 0.1 From a20f50c931546cc153fd8231b48b44c6ba7de49e Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sat, 1 Feb 2025 00:26:09 +0100 Subject: [PATCH 110/129] move reference file --- TestCases/tutorials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index f4a151bdaad..3d25da56e40 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -353,7 +353,7 @@ def main(): sudo_design_fado.multizone = False sudo_design_fado.test_iter = 10 sudo_design_fado.timeout = 1600 - sudo_design_fado.reference_file = "../../../TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref" + sudo_design_fado.reference_file = "../../../tests/TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref" sudo_design_fado.test_file = "optim.csv" sudo_design_fado.comp_threshold = 1e-6 sudo_design_fado.tol_file_percent = 0.1 From 6672b9bfdcd1945704e658f4e111b4bd658fb09c Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sat, 1 Feb 2025 00:51:17 +0100 Subject: [PATCH 111/129] copy tutorials folder using docker --- TestCases/tutorials.py | 2 +- docker/test/runTests.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 3d25da56e40..2d7aee33d8e 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -353,7 +353,7 @@ def main(): sudo_design_fado.multizone = False sudo_design_fado.test_iter = 10 sudo_design_fado.timeout = 1600 - sudo_design_fado.reference_file = "../../../tests/TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref" + sudo_design_fado.reference_file = "optim.csv.ref" sudo_design_fado.test_file = "optim.csv" sudo_design_fado.comp_threshold = 1e-6 sudo_design_fado.tol_file_percent = 0.1 diff --git a/docker/test/runTests.sh b/docker/test/runTests.sh index 9cb55113c99..b79853d49bf 100755 --- a/docker/test/runTests.sh +++ b/docker/test/runTests.sh @@ -102,6 +102,7 @@ else fi fi cp -R ./Tutorials/ tests/. +cp -r src/SU2/TestCases/Tutorials tests/. # Set the environment variables export SU2_RUN=$PWD/install/bin From 9a408d04345e4348e49cf78b1ca38227ff0e6928 Mon Sep 17 00:00:00 2001 From: vdweide Date: Sat, 1 Feb 2025 09:21:26 +0100 Subject: [PATCH 112/129] Modifications to CPhysicalGeometry such that also for FEM the mesh reader classes will be used --- Common/include/geometry/CPhysicalGeometry.hpp | 8 ++-- .../geometry/meshreader/CBoxMeshReaderFVM.hpp | 4 +- .../meshreader/CCGNSMeshReaderFVM.hpp | 4 +- ...CMeshReaderFVM.hpp => CMeshReaderBase.hpp} | 18 ++++----- .../meshreader/CRectangularMeshReaderFVM.hpp | 4 +- .../meshreader/CSU2ASCIIMeshReaderFVM.hpp | 4 +- Common/src/geometry/CPhysicalGeometry.cpp | 40 +++++++++---------- .../geometry/meshreader/CBoxMeshReaderFVM.cpp | 2 +- .../meshreader/CCGNSMeshReaderFVM.cpp | 2 +- ...CMeshReaderFVM.cpp => CMeshReaderBase.cpp} | 6 +-- .../meshreader/CRectangularMeshReaderFVM.cpp | 2 +- .../meshreader/CSU2ASCIIMeshReaderFVM.cpp | 2 +- Common/src/geometry/meshreader/meson.build | 2 +- 13 files changed, 49 insertions(+), 49 deletions(-) rename Common/include/geometry/meshreader/{CMeshReaderFVM.hpp => CMeshReaderBase.hpp} (92%) rename Common/src/geometry/meshreader/{CMeshReaderFVM.cpp => CMeshReaderBase.cpp} (84%) diff --git a/Common/include/geometry/CPhysicalGeometry.hpp b/Common/include/geometry/CPhysicalGeometry.hpp index 1363c46cc8c..a474dcbddd6 100644 --- a/Common/include/geometry/CPhysicalGeometry.hpp +++ b/Common/include/geometry/CPhysicalGeometry.hpp @@ -28,7 +28,7 @@ #pragma once #include "CGeometry.hpp" -#include "meshreader/CMeshReaderFVM.hpp" +#include "meshreader/CMeshReaderBase.hpp" #include "../containers/C2DContainer.hpp" /*! @@ -315,21 +315,21 @@ class CPhysicalGeometry final : public CGeometry { * \param[in] config - definition of the particular problem. * \param[in] mesh - mesh reader object containing the current zone data. */ - void LoadLinearlyPartitionedPoints(CConfig* config, CMeshReaderFVM* mesh); + void LoadLinearlyPartitionedPoints(CConfig* config, CMeshReaderBase* mesh); /*! * \brief Loads the interior volume elements from the mesh reader object into the primal element data structures. * \param[in] config - definition of the particular problem. * \param[in] mesh - mesh reader object containing the current zone data. */ - void LoadLinearlyPartitionedVolumeElements(CConfig* config, CMeshReaderFVM* mesh); + void LoadLinearlyPartitionedVolumeElements(CConfig* config, CMeshReaderBase* mesh); /*! * \brief Loads the boundary elements (markers) from the mesh reader object into the primal element data structures. * \param[in] config - definition of the particular problem. * \param[in] mesh - mesh reader object containing the current zone data. */ - void LoadUnpartitionedSurfaceElements(CConfig* config, CMeshReaderFVM* mesh); + void LoadUnpartitionedSurfaceElements(CConfig* config, CMeshReaderBase* mesh); /*! * \brief Prepares the grid point adjacency based on a linearly partitioned mesh object needed by ParMETIS for graph diff --git a/Common/include/geometry/meshreader/CBoxMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CBoxMeshReaderFVM.hpp index 4c97369ec35..74956a61bba 100644 --- a/Common/include/geometry/meshreader/CBoxMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CBoxMeshReaderFVM.hpp @@ -28,14 +28,14 @@ #pragma once -#include "CMeshReaderFVM.hpp" +#include "CMeshReaderBase.hpp" /*! * \class CBoxMeshReaderFVM * \brief Reads a 3D box grid into linear partitions for the finite volume solver (FVM). * \author: T. Economon */ -class CBoxMeshReaderFVM : public CMeshReaderFVM { +class CBoxMeshReaderFVM : public CMeshReaderBase { private: unsigned long nNode; /*!< \brief Number of grid nodes in the x-direction. */ unsigned long mNode; /*!< \brief Number of grid nodes in the y-direction. */ diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp index 6199cb540d5..399e1046922 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp @@ -32,14 +32,14 @@ #include "cgnslib.h" #endif -#include "CMeshReaderFVM.hpp" +#include "CMeshReaderBase.hpp" /*! * \class CCGNSMeshReaderFVM * \brief Reads a CGNS zone into linear partitions for the finite volume solver (FVM). * \author: T. Economon */ -class CCGNSMeshReaderFVM : public CMeshReaderFVM { +class CCGNSMeshReaderFVM : public CMeshReaderBase { private: #ifdef HAVE_CGNS int cgnsFileID; /*!< \brief CGNS file identifier. */ diff --git a/Common/include/geometry/meshreader/CMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CMeshReaderBase.hpp similarity index 92% rename from Common/include/geometry/meshreader/CMeshReaderFVM.hpp rename to Common/include/geometry/meshreader/CMeshReaderBase.hpp index 7980acf39fd..6b81a4a16f8 100644 --- a/Common/include/geometry/meshreader/CMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CMeshReaderBase.hpp @@ -1,8 +1,8 @@ /*! - * \file CMeshReaderFVM.hpp - * \brief Header file for the class CMeshReaderFVM. - * The implementations are in the CMeshReaderFVM.cpp file. + * \file CMeshReaderBase.hpp + * \brief Header file for the class CMeshReaderBase. + * The implementations are in the CMeshReaderBase.cpp file. * \author T. Economon * \version 8.1.0 "Harrier" * @@ -35,11 +35,11 @@ #include "../../CConfig.hpp" /*! - * \class CMeshReaderFVM - * \brief Base class for the mesh zone readers of the finite volume solver (FVM). + * \class CMeshReaderBase + * \brief Base class for the mesh zone readers. * \author T. Economon */ -class CMeshReaderFVM { +class CMeshReaderBase { protected: const int rank; /*!< \brief MPI Rank. */ const int size; /*!< \brief MPI Size. */ @@ -69,14 +69,14 @@ class CMeshReaderFVM { public: /*! - * \brief Constructor of the CMeshReaderFVM class. + * \brief Constructor of the CMeshReaderBase class. * \param[in] val_config - config object for the current zone. * \param[in] val_iZone - Current zone index. * \param[in] val_nZone - Total number of zones. */ - CMeshReaderFVM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + CMeshReaderBase(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); - virtual ~CMeshReaderFVM() = default; + virtual ~CMeshReaderBase() = default; /*! * \brief Get the physical dimension of the problem (2 or 3). diff --git a/Common/include/geometry/meshreader/CRectangularMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CRectangularMeshReaderFVM.hpp index 54f393b88d8..acdc94b8a43 100644 --- a/Common/include/geometry/meshreader/CRectangularMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CRectangularMeshReaderFVM.hpp @@ -28,14 +28,14 @@ #pragma once -#include "CMeshReaderFVM.hpp" +#include "CMeshReaderBase.hpp" /*! * \class CRectangularMeshReaderFVM * \brief Reads a 2D rectangular grid into linear partitions for the finite volume solver (FVM). * \author: T. Economon */ -class CRectangularMeshReaderFVM : public CMeshReaderFVM { +class CRectangularMeshReaderFVM : public CMeshReaderBase { private: unsigned long nNode; /*!< \brief Number of grid nodes in the x-direction. */ unsigned long mNode; /*!< \brief Number of grid nodes in the y-direction. */ diff --git a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp index 1be0177b435..0222063fb56 100644 --- a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp @@ -30,14 +30,14 @@ #include -#include "CMeshReaderFVM.hpp" +#include "CMeshReaderBase.hpp" /*! * \class CSU2ASCIIMeshReaderFVM * \brief Reads a native SU2 ASCII grid into linear partitions for the finite volume solver (FVM). * \author T. Economon */ -class CSU2ASCIIMeshReaderFVM : public CMeshReaderFVM { +class CSU2ASCIIMeshReaderFVM : public CMeshReaderBase { private: enum class FileSection { POINTS, ELEMENTS, MARKERS }; /*!< \brief Different sections of the file. */ std::array SectionOrder{}; /*!< \brief Order of the sections in the file. */ diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index 6bddb08e383..ee2c5992c04 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -3445,19 +3445,19 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena unsigned short val_format = config->GetMesh_FileFormat(); const bool fem_solver = config->GetFEMSolver(); - CMeshReaderFVM* MeshFVM = nullptr; + CMeshReaderBase* Mesh = nullptr; switch (val_format) { case SU2: - MeshFVM = new CSU2ASCIIMeshReaderFVM(config, val_iZone, val_nZone); + Mesh = new CSU2ASCIIMeshReaderFVM(config, val_iZone, val_nZone); break; case CGNS_GRID: - MeshFVM = new CCGNSMeshReaderFVM(config, val_iZone, val_nZone); + Mesh = new CCGNSMeshReaderFVM(config, val_iZone, val_nZone); break; case RECTANGLE: - MeshFVM = new CRectangularMeshReaderFVM(config, val_iZone, val_nZone); + Mesh = new CRectangularMeshReaderFVM(config, val_iZone, val_nZone); break; case BOX: - MeshFVM = new CBoxMeshReaderFVM(config, val_iZone, val_nZone); + Mesh = new CBoxMeshReaderFVM(config, val_iZone, val_nZone); break; default: SU2_MPI::Error("Unrecognized mesh format specified!", CURRENT_FUNCTION); @@ -3466,7 +3466,7 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena /*--- Store the dimension of the problem ---*/ - nDim = MeshFVM->GetDimension(); + nDim = Mesh->GetDimension(); if (rank == MASTER_NODE) { if (nDim == 2) cout << "Two dimensional problem." << endl; if (nDim == 3) cout << "Three dimensional problem." << endl; @@ -3474,10 +3474,10 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena /*--- Store the local and global number of nodes for this rank. ---*/ - nPoint = MeshFVM->GetNumberOfLocalPoints(); - nPointDomain = MeshFVM->GetNumberOfLocalPoints(); - Global_nPoint = MeshFVM->GetNumberOfGlobalPoints(); - Global_nPointDomain = MeshFVM->GetNumberOfGlobalPoints(); + nPoint = Mesh->GetNumberOfLocalPoints(); + nPointDomain = Mesh->GetNumberOfLocalPoints(); + Global_nPoint = Mesh->GetNumberOfGlobalPoints(); + Global_nPointDomain = Mesh->GetNumberOfGlobalPoints(); if ((rank == MASTER_NODE) && (size > SINGLE_NODE)) { cout << Global_nPoint << " grid points before partitioning." << endl; @@ -3487,9 +3487,9 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena /*--- Store the local and global number of interior elements. ---*/ - nElem = MeshFVM->GetNumberOfLocalElements(); - Global_nElem = MeshFVM->GetNumberOfGlobalElements(); - Global_nElemDomain = MeshFVM->GetNumberOfGlobalElements(); + nElem = Mesh->GetNumberOfLocalElements(); + Global_nElem = Mesh->GetNumberOfGlobalElements(); + Global_nElemDomain = Mesh->GetNumberOfGlobalElements(); if ((rank == MASTER_NODE) && (size > SINGLE_NODE)) { cout << Global_nElem << " volume elements before partitioning." << endl; @@ -3500,9 +3500,9 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena /*--- Load the grid points, volume elements, and surface elements from the mesh object into the proper SU2 data structures. ---*/ - LoadLinearlyPartitionedPoints(config, MeshFVM); - LoadLinearlyPartitionedVolumeElements(config, MeshFVM); - LoadUnpartitionedSurfaceElements(config, MeshFVM); + LoadLinearlyPartitionedPoints(config, Mesh); + LoadLinearlyPartitionedVolumeElements(config, Mesh); + LoadUnpartitionedSurfaceElements(config, Mesh); /*--- Prepare the nodal adjacency structures for ParMETIS. ---*/ @@ -3511,10 +3511,10 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena /*--- Now that we have loaded all information from the mesh, delete the mesh reader object. ---*/ - delete MeshFVM; + delete Mesh; } -void CPhysicalGeometry::LoadLinearlyPartitionedPoints(CConfig* config, CMeshReaderFVM* mesh) { +void CPhysicalGeometry::LoadLinearlyPartitionedPoints(CConfig* config, CMeshReaderBase* mesh) { /*--- Get the linearly partitioned coordinates from the mesh object. ---*/ const auto& gridCoords = mesh->GetLocalPointCoordinates(); @@ -3537,7 +3537,7 @@ void CPhysicalGeometry::LoadLinearlyPartitionedPoints(CConfig* config, CMeshRead } } -void CPhysicalGeometry::LoadLinearlyPartitionedVolumeElements(CConfig* config, CMeshReaderFVM* mesh) { +void CPhysicalGeometry::LoadLinearlyPartitionedVolumeElements(CConfig* config, CMeshReaderBase* mesh) { /*--- Reset the global to local element mapping. ---*/ Global_to_Local_Elem.clear(); @@ -3624,7 +3624,7 @@ void CPhysicalGeometry::LoadLinearlyPartitionedVolumeElements(CConfig* config, C reduce(nelem_pyramid, Global_nelem_pyramid); } -void CPhysicalGeometry::LoadUnpartitionedSurfaceElements(CConfig* config, CMeshReaderFVM* mesh) { +void CPhysicalGeometry::LoadUnpartitionedSurfaceElements(CConfig* config, CMeshReaderBase* mesh) { /*--- The master node takes care of loading all markers and surface elements from the file. This information is later put into linear partitions to make its redistribution easier diff --git a/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp index e4ee811eaec..8330f1ea6fe 100644 --- a/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp @@ -30,7 +30,7 @@ #include "../../../include/geometry/meshreader/CBoxMeshReaderFVM.hpp" CBoxMeshReaderFVM::CBoxMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) - : CMeshReaderFVM(val_config, val_iZone, val_nZone) { + : CMeshReaderBase(val_config, val_iZone, val_nZone) { /* The box mesh is always 3D. */ dimension = 3; diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp index cdd06c285d6..1cd2bafd4ed 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp @@ -30,7 +30,7 @@ #include "../../../include/geometry/meshreader/CCGNSMeshReaderFVM.hpp" CCGNSMeshReaderFVM::CCGNSMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) - : CMeshReaderFVM(val_config, val_iZone, val_nZone) { + : CMeshReaderBase(val_config, val_iZone, val_nZone) { #ifdef HAVE_CGNS OpenCGNSFile(config->GetMesh_FileName()); diff --git a/Common/src/geometry/meshreader/CMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CMeshReaderBase.cpp similarity index 84% rename from Common/src/geometry/meshreader/CMeshReaderFVM.cpp rename to Common/src/geometry/meshreader/CMeshReaderBase.cpp index 17069bf7b25..47ef0081e22 100644 --- a/Common/src/geometry/meshreader/CMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CMeshReaderBase.cpp @@ -1,5 +1,5 @@ /*! - * \file CMeshReaderFVM.cpp + * \file CMeshReaderBase.cpp * \brief Helper class that provides the counts for each rank in a linear * partitioning given the global count as input. * \author T. Economon @@ -26,7 +26,7 @@ * License along with SU2. If not, see . */ -#include "../../../include/geometry/meshreader/CMeshReaderFVM.hpp" +#include "../../../include/geometry/meshreader/CMeshReaderBase.hpp" -CMeshReaderFVM::CMeshReaderFVM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) +CMeshReaderBase::CMeshReaderBase(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) : rank(SU2_MPI::GetRank()), size(SU2_MPI::GetSize()), config(val_config) {} diff --git a/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp index 5b89744bf2a..971fe37fbbd 100644 --- a/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp @@ -31,7 +31,7 @@ CRectangularMeshReaderFVM::CRectangularMeshReaderFVM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) - : CMeshReaderFVM(val_config, val_iZone, val_nZone) { + : CMeshReaderBase(val_config, val_iZone, val_nZone) { /* The rectangular mesh is always 2D. */ dimension = 2; diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp index e0ebfcc5acb..00307a90d94 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp @@ -30,7 +30,7 @@ #include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp" CSU2ASCIIMeshReaderFVM::CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) - : CMeshReaderFVM(val_config, val_iZone, val_nZone), + : CMeshReaderBase(val_config, val_iZone, val_nZone), myZone(val_iZone), nZones(val_nZone), meshFilename(config->GetMesh_FileName()) { diff --git a/Common/src/geometry/meshreader/meson.build b/Common/src/geometry/meshreader/meson.build index 3f1e12595de..fb44650ad56 100644 --- a/Common/src/geometry/meshreader/meson.build +++ b/Common/src/geometry/meshreader/meson.build @@ -1,5 +1,5 @@ common_src += files(['CBoxMeshReaderFVM.cpp', 'CCGNSMeshReaderFVM.cpp', - 'CMeshReaderFVM.cpp', + 'CMeshReaderBase.cpp', 'CRectangularMeshReaderFVM.cpp', 'CSU2ASCIIMeshReaderFVM.cpp']) From 83cc22eeea58533d52a563322c0292fa3681708d Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sat, 1 Feb 2025 10:12:51 +0100 Subject: [PATCH 113/129] copy tutorials folder using docker --- docker/test/runTests.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker/test/runTests.sh b/docker/test/runTests.sh index b79853d49bf..c6beeb08f85 100755 --- a/docker/test/runTests.sh +++ b/docker/test/runTests.sh @@ -101,8 +101,10 @@ else exit 1 fi fi +echo "Copying Tutorials folder to tests folder." cp -R ./Tutorials/ tests/. -cp -r src/SU2/TestCases/Tutorials tests/. +echo "Copying TestCases/Tutorials folder to tests/Tutorials folder" +cp -R src/SU2/TestCases/Tutorials/* tests/Tutorials/. # Set the environment variables export SU2_RUN=$PWD/install/bin From 8bc3462fd98700736b46c16e7d399c7fbf30ef5b Mon Sep 17 00:00:00 2001 From: vdweide Date: Sat, 1 Feb 2025 12:37:01 +0100 Subject: [PATCH 114/129] Split the CGNS finite volume reader in a common base class and a class that is specific to the reading of the CGNS grid for the finite volume solver --- .../meshreader/CCGNSMeshReaderBase.hpp | 108 +++++ .../meshreader/CCGNSMeshReaderFVM.hpp | 59 +-- .../meshreader/CCGNSMeshReaderBase.cpp | 410 ++++++++++++++++++ .../meshreader/CCGNSMeshReaderFVM.cpp | 362 +--------------- Common/src/geometry/meshreader/meson.build | 1 + 5 files changed, 522 insertions(+), 418 deletions(-) create mode 100644 Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp create mode 100644 Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp new file mode 100644 index 00000000000..ef12386e12c --- /dev/null +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp @@ -0,0 +1,108 @@ +/*! + * \file CCGNSMeshReaderBase.hpp + * \brief Header file for the class CCGNSMeshReaderBase. + * The implementations are in the CCGNSMeshReaderBase.cpp file. + * \author T. Economon + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#ifdef HAVE_CGNS +#include "cgnslib.h" +#endif + +#include "CMeshReaderBase.hpp" + +/*! + * \class CCGNSMeshReaderBase + * \brief Base class for the reading of a CGNS zone. + * \author: T. Economon + */ +class CCGNSMeshReaderBase : public CMeshReaderBase { + protected: +#ifdef HAVE_CGNS + int cgnsFileID; /*!< \brief CGNS file identifier. */ + const int cgnsBase = 1; /*!< \brief CGNS database index (the CGNS reader currently assumes a single database). */ + const int cgnsZone = 1; /*!< \brief CGNS zone index (and 1 zone in that database). */ + + int nSections; /*!< \brief Total number of sections in the CGNS file. */ + + vector isInterior; /*!< \brief Vector of booleans to store whether each section in the CGNS file is an interior + or boundary section. */ + vector + nElems; /*!< \brief Vector containing the local number of elements found within each CGNS section. */ + vector elemOffset; /*!< \brief Global ID offset for each interior section (i.e., the total number of + global elements that came before it). */ + vector > connElems; /*!< \brief Vector containing the local element connectivity found within each + 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). */ + + /*! + * \brief Open the CGNS file and checks for errors. + * \param[in] val_filename - string name of the CGNS file to be read. + */ + void OpenCGNSFile(const string& val_filename); + + /*! + * \brief Reads all CGNS database metadata and checks for errors. + */ + void ReadCGNSDatabaseMetadata(); + + /*! + * \brief Reads all CGNS zone metadata and checks for errors. + */ + void ReadCGNSZoneMetadata(); + + /*! + * \brief Reads the grid points from a CGNS zone into linear partitions across all ranks. + */ + void ReadCGNSPointCoordinates(); + + /*! + * \brief Reads the metadata for each CGNS section in a zone and collect information, including the size and whether + * it is an interior or boundary section. + */ + void ReadCGNSSectionMetadata(); + + /*! + * \brief Get the VTK type and string name for a CGNS element type. + * \param[in] val_elem_type - CGNS element type. + * \param[out] val_vtk_type - VTK type identifier index. + * \returns String containing the name of the element type. + */ + string GetCGNSElementType(ElementType_t val_elem_type, int& val_vtk_type); +#endif + + public: + /*! + * \brief Constructor of the CCGNSMeshReaderBase class. + */ + CCGNSMeshReaderBase(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CCGNSMeshReaderBase class. + */ + virtual ~CCGNSMeshReaderBase(void) override; +}; diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp index 399e1046922..4edb6cbf27c 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp @@ -28,64 +28,16 @@ #pragma once -#ifdef HAVE_CGNS -#include "cgnslib.h" -#endif - -#include "CMeshReaderBase.hpp" +#include "CCGNSMeshReaderBase.hpp" /*! * \class CCGNSMeshReaderFVM * \brief Reads a CGNS zone into linear partitions for the finite volume solver (FVM). * \author: T. Economon */ -class CCGNSMeshReaderFVM : public CMeshReaderBase { +class CCGNSMeshReaderFVM : public CCGNSMeshReaderBase { private: #ifdef HAVE_CGNS - int cgnsFileID; /*!< \brief CGNS file identifier. */ - const int cgnsBase = 1; /*!< \brief CGNS database index (the CGNS reader currently assumes a single database). */ - const int cgnsZone = 1; /*!< \brief CGNS zone index (and 1 zone in that database). */ - - int nSections; /*!< \brief Total number of sections in the CGNS file. */ - - vector isInterior; /*!< \brief Vector of booleans to store whether each section in the CGNS file is an interior - or boundary section. */ - vector - nElems; /*!< \brief Vector containing the local number of elements found within each CGNS section. */ - vector elemOffset; /*!< \brief Global ID offset for each interior section (i.e., the total number of - global elements that came before it). */ - vector > connElems; /*!< \brief Vector containing the local element connectivity found within each - 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). */ - - /*! - * \brief Open the CGNS file and checks for errors. - * \param[in] val_filename - string name of the CGNS file to be read. - */ - void OpenCGNSFile(const string& val_filename); - - /*! - * \brief Reads all CGNS database metadata and checks for errors. - */ - void ReadCGNSDatabaseMetadata(); - - /*! - * \brief Reads all CGNS zone metadata and checks for errors. - */ - void ReadCGNSZoneMetadata(); - - /*! - * \brief Reads the grid points from a CGNS zone into linear partitions across all ranks. - */ - void ReadCGNSPointCoordinates(); - - /*! - * \brief Reads the metadata for each CGNS section in a zone and collect information, including the size and whether - * it is an interior or boundary section. - */ - void ReadCGNSSectionMetadata(); - /*! * \brief Reads the interior volume elements from one section of a CGNS zone into linear partitions across all ranks. * \param[in] val_section - CGNS section index. @@ -108,13 +60,6 @@ class CCGNSMeshReaderFVM : public CMeshReaderBase { */ void ReformatCGNSSurfaceConnectivity(); - /*! - * \brief Get the VTK type and string name for a CGNS element type. - * \param[in] val_elem_type - CGNS element type. - * \param[out] val_vtk_type - VTK type identifier index. - * \returns String containing the name of the element type. - */ - string GetCGNSElementType(ElementType_t val_elem_type, int& val_vtk_type); #endif /*! diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp new file mode 100644 index 00000000000..8a0f4e2bdb6 --- /dev/null +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp @@ -0,0 +1,410 @@ +/*! + * \file CCGNSMeshReaderBase.cpp + * \brief Helper class for the reading of a CGNS grid file. + * linear partitions across all ranks. + * \author T. Economon + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/toolboxes/CLinearPartitioner.hpp" +#include "../../../include/geometry/meshreader/CCGNSMeshReaderBase.hpp" + +CCGNSMeshReaderBase::CCGNSMeshReaderBase(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) + : CMeshReaderBase(val_config, val_iZone, val_nZone) { +#ifdef HAVE_CGNS + /*--- Leave the option to do something in the future here. ---*/ +#else + SU2_MPI::Error(string(" SU2 built without CGNS support. \n") + string(" To use CGNS, build SU2 accordingly."), + CURRENT_FUNCTION); +#endif +} + +CCGNSMeshReaderBase::~CCGNSMeshReaderBase() = default; + +#ifdef HAVE_CGNS +void CCGNSMeshReaderBase::OpenCGNSFile(const string& val_filename) { + /*--- Check whether the supplied file is truly a CGNS file. ---*/ + + int file_type; + float file_version; + if (cg_is_cgns(val_filename.c_str(), &file_type) != CG_OK) { + SU2_MPI::Error(val_filename + string(" was not found or is not a properly formatted") + + string(" CGNS file.\nNote that SU2 expects unstructured") + + string(" CGNS files in ADF data format."), + CURRENT_FUNCTION); + } + + /*--- Open the CGNS file for reading. The value of cgnsFileID returned + is the specific index number for this file and will be + repeatedly used in the function calls. ---*/ + + if (cg_open(val_filename.c_str(), CG_MODE_READ, &cgnsFileID)) cg_error_exit(); + if (rank == MASTER_NODE) { + cout << "Reading the CGNS file: "; + cout << val_filename.c_str() << "." << endl; + } + if (cg_version(cgnsFileID, &file_version)) cg_error_exit(); + if (rank == MASTER_NODE) { + if (file_version < 4.0) { + cout + << "WARNING: The CGNS file version (" << file_version + << ") is old and may cause high memory usage issues, consider updating the file with the cgnsupdate tool.\n"; + } + } +} + +void CCGNSMeshReaderBase::ReadCGNSDatabaseMetadata() { + /*--- Get the number of databases. This is the highest node + in the CGNS heirarchy. ---*/ + + int nbases; + if (cg_nbases(cgnsFileID, &nbases)) cg_error_exit(); + if (rank == MASTER_NODE) cout << "CGNS file contains " << nbases << " database(s)." << endl; + + /*--- Check if there is more than one database. Throw an + error if there is because this reader can currently + only handle one database. ---*/ + + if (nbases > 1) { + SU2_MPI::Error("CGNS reader currently can only handle 1 database.", CURRENT_FUNCTION); + } + + /*--- Read the database. Note that the CGNS indexing starts at 1. ---*/ + + int cell_dim, phys_dim; + char basename[CGNS_STRING_SIZE]; + if (cg_base_read(cgnsFileID, cgnsBase, basename, &cell_dim, &phys_dim)) cg_error_exit(); + if (rank == MASTER_NODE) { + cout << "Database " << cgnsBase << ", " << basename << ": "; + cout << " cell dimension of " << cell_dim << ", physical "; + cout << "dimension of " << phys_dim << "." << endl; + } + + /*--- Set the number of dimensions baed on cell_dim. ---*/ + + dimension = (unsigned short)cell_dim; +} + +void CCGNSMeshReaderBase::ReadCGNSZoneMetadata() { + /*--- First, check all sections to find the element types and to + classify them as either surface or volume elements. We will also + perform some error checks here to avoid partitioning issues. ---*/ + + /*--- Get the number of zones for this base. ---*/ + + int nzones; + if (cg_nzones(cgnsFileID, cgnsBase, &nzones)) cg_error_exit(); + if (rank == MASTER_NODE) { + cout << nzones << " total zone(s)." << endl; + } + + /*--- Check if there is more than one zone. Until we enable it, we + will require a single zone CGNS file. Multizone problems can still + be run with CGNS by using separate CGNS files for each zone. ---*/ + + if (nzones > 1) { + SU2_MPI::Error(string("CGNS reader currently expects only 1 zone per CGNS file.") + + string("Multizone problems can be run with separate CGNS files for each zone."), + CURRENT_FUNCTION); + } + + /*--- Read the basic information for this zone, including + the name and the number of vertices, cells, and + boundary cells which are stored in the cgsize variable. ---*/ + + vector cgsize(3); + ZoneType_t zonetype; + char zonename[CGNS_STRING_SIZE]; + if (cg_zone_read(cgnsFileID, cgnsBase, cgnsZone, zonename, cgsize.data())) cg_error_exit(); + + /*--- Rename the zone size information for clarity. + NOTE: The number of cells here may be only the number of + interior elements or it may be the total. This needs to + be counted explicitly later. ---*/ + + numberOfGlobalPoints = cgsize[0]; + int nElemCGNS = cgsize[1]; + + /*--- Get some additional information about the current zone. ---*/ + + if (cg_zone_type(cgnsFileID, cgnsBase, cgnsZone, &zonetype)) cg_error_exit(); + + /*--- Check for an unstructured mesh. Throw an error if not found. ---*/ + + if (zonetype != Unstructured) + SU2_MPI::Error("Structured CGNS zone found while unstructured expected.", CURRENT_FUNCTION); + + /*--- Print current zone info to the console. ---*/ + + if (rank == MASTER_NODE) { + cout << "Zone " << cgnsZone << ", " << zonename << ": "; + cout << numberOfGlobalPoints << " total vertices, "; + cout << nElemCGNS << " total elements." << endl; + } + + /*--- Retrieve the number of grids in this zone. For now, we know + this is one, but to be more general, this will need to check and + allow for a loop over all grids. ---*/ + + int ngrids; + if (cg_ngrids(cgnsFileID, cgnsBase, cgnsZone, &ngrids)) cg_error_exit(); + if (ngrids > 1) { + SU2_MPI::Error("CGNS reader currently handles only 1 grid per zone.", CURRENT_FUNCTION); + } +} + +void CCGNSMeshReaderBase::ReadCGNSPointCoordinates() { + /*--- Compute the number of points that will be on each processor. + This is a linear partitioning with the addition of a simple load + balancing for any remainder points. ---*/ + + CLinearPartitioner pointPartitioner(numberOfGlobalPoints, 0); + + /*--- Store the local number of nodes for this rank. ---*/ + + numberOfLocalPoints = pointPartitioner.GetSizeOnRank(rank); + + /*--- Create buffer to hold the grid coordinates for our rank. ---*/ + + localPointCoordinates.resize(dimension); + for (int k = 0; k < dimension; k++) localPointCoordinates[k].resize(numberOfLocalPoints, 0.0); + + /*--- Set the value of range_max to the total number of nodes in + the unstructured mesh. Also allocate memory for the temporary array + that will hold the grid coordinates as they are extracted. Note the + +1 for CGNS convention. ---*/ + + cgsize_t range_min = (cgsize_t)pointPartitioner.GetFirstIndexOnRank(rank) + 1; + auto range_max = (cgsize_t)pointPartitioner.GetLastIndexOnRank(rank); + + /*--- Loop over each set of coordinates. ---*/ + + for (int k = 0; k < dimension; k++) { + /*--- Read the coordinate info. This will retrieve the + data type (either RealSingle or RealDouble) as + well as the coordname which will specify the + type of data that it is based in the SIDS convention. + This might be "CoordinateX," for instance. ---*/ + + char coordname[CGNS_STRING_SIZE]; + DataType_t datatype; + if (cg_coord_info(cgnsFileID, cgnsBase, cgnsZone, k + 1, &datatype, coordname)) cg_error_exit(); + if (rank == MASTER_NODE) { + cout << "Loading " << coordname; + if (size > SINGLE_NODE) { + cout << " values into linear partitions." << endl; + } else { + cout << " values." << endl; + } + } + + /*--- Check the coordinate name to decide the index for storage. ---*/ + + unsigned short indC = 0; + if (string(coordname) == "CoordinateX") + indC = 0; + else if (string(coordname) == "CoordinateY") + indC = 1; + else if (string(coordname) == "CoordinateZ") + indC = 2; + else + SU2_MPI::Error(string("Unknown coordinate name, ") + coordname + string(", in the CGNS file."), CURRENT_FUNCTION); + + /*--- Now read our rank's chunk of coordinates from the file. + Ask for datatype RealDouble and let CGNS library do the translation + when RealSingle is found. ---*/ + + if (cg_coord_read(cgnsFileID, cgnsBase, cgnsZone, coordname, RealDouble, &range_min, &range_max, + localPointCoordinates[indC].data())) + cg_error_exit(); + } +} + +void CCGNSMeshReaderBase::ReadCGNSSectionMetadata() { + /*--- Begin section for retrieving the connectivity info. ---*/ + + if ((rank == MASTER_NODE) && (size > SINGLE_NODE)) cout << "Distributing connectivity across all ranks." << endl; + + /*--- First check the number of sections. ---*/ + + if (cg_nsections(cgnsFileID, cgnsBase, cgnsZone, &nSections)) cg_error_exit(); + if (rank == MASTER_NODE) { + cout << "Number of connectivity sections is "; + cout << nSections << "." << endl; + } + + /*--- Prepare several data structures to hold the various + pieces of information describing each section. ---*/ + + isInterior.resize(nSections); + nElems.resize(nSections, 0); + elemOffset.resize(nSections + 1, 0); + elemOffset[0] = 0; + connElems.resize(nSections); + sectionNames.resize(nSections, vector(CGNS_STRING_SIZE)); + numberOfGlobalElements = 0; + + for (int s = 0; s < nSections; s++) { + /*--- Read the connectivity details for this section. ---*/ + + int nbndry, parent_flag, vtk_type; + cgsize_t startE, endE, sizeNeeded; + ElementType_t elemType; + if (cg_section_read(cgnsFileID, cgnsBase, cgnsZone, s + 1, sectionNames[s].data(), &elemType, &startE, &endE, + &nbndry, &parent_flag)) + cg_error_exit(); + + /*--- Compute the total element count in this section (global). ---*/ + + unsigned long element_count = (endE - startE + 1); + + /* Get the details for the CGNS element type in this section. */ + + string elem_name = GetCGNSElementType(elemType, vtk_type); + + /* We assume that each section contains interior elements by default. + If we find 1D elements in a 2D problem or 2D elements in a 3D + problem, then we know the section must contain boundary elements. + We assume that each section is composed of either entirely interior + or entirely boundary elements. */ + + isInterior[s] = true; + + if (elemType == MIXED) { + /* For a mixed section, we check the type of the first element + so that we can correctly label this section as an interior or + boundary element section. Here, we also assume that a section + can not hold both interior and boundary elements. First, get + the size required to read a single element from the section. */ + + if (cg_ElementPartialSize(cgnsFileID, cgnsBase, cgnsZone, s + 1, startE, startE, &sizeNeeded) != CG_OK) + cg_error_exit(); + + /* A couple of auxiliary vectors for mixed element sections. */ + + vector connElemCGNS(sizeNeeded); + vector connOffsetCGNS(2, 0); + + /* Retrieve the connectivity information for the first element. */ + + if (cg_poly_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, s + 1, startE, startE, connElemCGNS.data(), + connOffsetCGNS.data(), nullptr) != CG_OK) + cg_error_exit(); + + /* The element type is in the first position of the connectivity + information that we retrieved from the CGNS file. */ + + elemType = ElementType_t(connElemCGNS[0]); + } + + /* Check for 1D elements in 2D problems, or for 2D elements in + 3D problems. If found, mark the section as a boundary section. */ + + if ((dimension == 2) && (elemType == BAR_2 || elemType == BAR_3)) isInterior[s] = false; + if ((dimension == 3) && (elemType == TRI_3 || elemType == QUAD_4)) isInterior[s] = false; + + /*--- Increment the global element offset for each section + based on whether or not this is a surface or volume section. + We also keep a running count of the total elements globally. ---*/ + + elemOffset[s + 1] = elemOffset[s]; + if (!isInterior[s]) + elemOffset[s + 1] += element_count; + else + numberOfGlobalElements += element_count; + + /*--- Print some information to the console. ---*/ + + if (rank == MASTER_NODE) { + cout << "Section " << string(sectionNames[s].data()); + cout << " contains " << element_count << " elements"; + cout << " of type " << elem_name << "." << endl; + } + } +} + +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. */ + + string elem_name; + switch (val_elem_type) { + case NODE: + elem_name = "Vertex"; + val_vtk_type = 1; + SU2_MPI::Error("Vertex elements detected. Please remove.", CURRENT_FUNCTION); + break; + case BAR_2: case BAR_3: case BAR_4: case BAR_5: + elem_name = "Line"; + val_vtk_type = 3; + if (dimension == 3) + SU2_MPI::Error("Line elements detected in a 3D mesh. Please remove.", + CURRENT_FUNCTION); + break; + case TRI_3: case TRI_6: case TRI_9: case TRI_10: + case TRI_12: case TRI_15: + elem_name = "Triangle"; + val_vtk_type = 5; + break; + case QUAD_4: case QUAD_8: case QUAD_9: case QUAD_12: + case QUAD_16: case QUAD_P4_16: case QUAD_25: + elem_name = "Quadrilateral"; + val_vtk_type = 9; + break; + case TETRA_4: case TETRA_10: case TETRA_16: case TETRA_20: + case TETRA_22: case TETRA_34: case TETRA_35: + elem_name = "Tetrahedron"; + val_vtk_type = 10; + break; + case HEXA_8: case HEXA_20: case HEXA_27: case HEXA_32: + case HEXA_56: case HEXA_64: case HEXA_44: case HEXA_98: + case HEXA_125: + elem_name = "Hexahedron"; + val_vtk_type = 12; + break; + case PENTA_6: case PENTA_15: case PENTA_18: case PENTA_24: + case PENTA_38: case PENTA_40: case PENTA_33: case PENTA_66: + case PENTA_75: + elem_name = "Prism"; + val_vtk_type = 13; + break; + case PYRA_5: case PYRA_14: case PYRA_13: case PYRA_21: + case PYRA_29: case PYRA_30: case PYRA_P4_29: case PYRA_50: + case PYRA_55: + elem_name = "Pyramid"; + val_vtk_type = 14; + break; + case MIXED: + elem_name = "Mixed"; + val_vtk_type = -1; + break; + default: + char buf[100]; + SPRINTF(buf, "Unsupported or unknown CGNS element type: (type %d)\n", val_elem_type); + SU2_MPI::Error(string(buf), CURRENT_FUNCTION); + break; + } + + return elem_name; +} +#endif \ No newline at end of file diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp index 1cd2bafd4ed..147f5de0323 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp @@ -30,7 +30,7 @@ #include "../../../include/geometry/meshreader/CCGNSMeshReaderFVM.hpp" CCGNSMeshReaderFVM::CCGNSMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) - : CMeshReaderBase(val_config, val_iZone, val_nZone) { + : CCGNSMeshReaderBase(val_config, val_iZone, val_nZone) { #ifdef HAVE_CGNS OpenCGNSFile(config->GetMesh_FileName()); @@ -74,307 +74,6 @@ CCGNSMeshReaderFVM::CCGNSMeshReaderFVM(CConfig* val_config, unsigned short val_i CCGNSMeshReaderFVM::~CCGNSMeshReaderFVM() = default; #ifdef HAVE_CGNS -void CCGNSMeshReaderFVM::OpenCGNSFile(const string& val_filename) { - /*--- Check whether the supplied file is truly a CGNS file. ---*/ - - int file_type; - float file_version; - if (cg_is_cgns(val_filename.c_str(), &file_type) != CG_OK) { - SU2_MPI::Error(val_filename + string(" was not found or is not a properly formatted") + - string(" CGNS file.\nNote that SU2 expects unstructured") + - string(" CGNS files in ADF data format."), - CURRENT_FUNCTION); - } - - /*--- Open the CGNS file for reading. The value of cgnsFileID returned - is the specific index number for this file and will be - repeatedly used in the function calls. ---*/ - - if (cg_open(val_filename.c_str(), CG_MODE_READ, &cgnsFileID)) cg_error_exit(); - if (rank == MASTER_NODE) { - cout << "Reading the CGNS file: "; - cout << val_filename.c_str() << "." << endl; - } - if (cg_version(cgnsFileID, &file_version)) cg_error_exit(); - if (rank == MASTER_NODE) { - if (file_version < 4.0) { - cout - << "WARNING: The CGNS file version (" << file_version - << ") is old and may cause high memory usage issues, consider updating the file with the cgnsupdate tool.\n"; - } - } -} - -void CCGNSMeshReaderFVM::ReadCGNSDatabaseMetadata() { - /*--- Get the number of databases. This is the highest node - in the CGNS heirarchy. ---*/ - - int nbases; - if (cg_nbases(cgnsFileID, &nbases)) cg_error_exit(); - if (rank == MASTER_NODE) cout << "CGNS file contains " << nbases << " database(s)." << endl; - - /*--- Check if there is more than one database. Throw an - error if there is because this reader can currently - only handle one database. ---*/ - - if (nbases > 1) { - SU2_MPI::Error("CGNS reader currently can only handle 1 database.", CURRENT_FUNCTION); - } - - /*--- Read the database. Note that the CGNS indexing starts at 1. ---*/ - - int cell_dim, phys_dim; - char basename[CGNS_STRING_SIZE]; - if (cg_base_read(cgnsFileID, cgnsBase, basename, &cell_dim, &phys_dim)) cg_error_exit(); - if (rank == MASTER_NODE) { - cout << "Database " << cgnsBase << ", " << basename << ": "; - cout << " cell dimension of " << cell_dim << ", physical "; - cout << "dimension of " << phys_dim << "." << endl; - } - - /*--- Set the number of dimensions baed on cell_dim. ---*/ - - dimension = (unsigned short)cell_dim; -} - -void CCGNSMeshReaderFVM::ReadCGNSZoneMetadata() { - /*--- First, check all sections to find the element types and to - classify them as either surface or volume elements. We will also - perform some error checks here to avoid partitioning issues. ---*/ - - /*--- Get the number of zones for this base. ---*/ - - int nzones; - if (cg_nzones(cgnsFileID, cgnsBase, &nzones)) cg_error_exit(); - if (rank == MASTER_NODE) { - cout << nzones << " total zone(s)." << endl; - } - - /*--- Check if there is more than one zone. Until we enable it, we - will require a single zone CGNS file. Multizone problems can still - be run with CGNS by using separate CGNS files for each zone. ---*/ - - if (nzones > 1) { - SU2_MPI::Error(string("CGNS reader currently expects only 1 zone per CGNS file.") + - string("Multizone problems can be run with separate CGNS files for each zone."), - CURRENT_FUNCTION); - } - - /*--- Read the basic information for this zone, including - the name and the number of vertices, cells, and - boundary cells which are stored in the cgsize variable. ---*/ - - vector cgsize(3); - ZoneType_t zonetype; - char zonename[CGNS_STRING_SIZE]; - if (cg_zone_read(cgnsFileID, cgnsBase, cgnsZone, zonename, cgsize.data())) cg_error_exit(); - - /*--- Rename the zone size information for clarity. - NOTE: The number of cells here may be only the number of - interior elements or it may be the total. This needs to - be counted explicitly later. ---*/ - - numberOfGlobalPoints = cgsize[0]; - int nElemCGNS = cgsize[1]; - - /*--- Get some additional information about the current zone. ---*/ - - if (cg_zone_type(cgnsFileID, cgnsBase, cgnsZone, &zonetype)) cg_error_exit(); - - /*--- Check for an unstructured mesh. Throw an error if not found. ---*/ - - if (zonetype != Unstructured) - SU2_MPI::Error("Structured CGNS zone found while unstructured expected.", CURRENT_FUNCTION); - - /*--- Print current zone info to the console. ---*/ - - if (rank == MASTER_NODE) { - cout << "Zone " << cgnsZone << ", " << zonename << ": "; - cout << numberOfGlobalPoints << " total vertices, "; - cout << nElemCGNS << " total elements." << endl; - } - - /*--- Retrieve the number of grids in this zone. For now, we know - this is one, but to be more general, this will need to check and - allow for a loop over all grids. ---*/ - - int ngrids; - if (cg_ngrids(cgnsFileID, cgnsBase, cgnsZone, &ngrids)) cg_error_exit(); - if (ngrids > 1) { - SU2_MPI::Error("CGNS reader currently handles only 1 grid per zone.", CURRENT_FUNCTION); - } -} - -void CCGNSMeshReaderFVM::ReadCGNSPointCoordinates() { - /*--- Compute the number of points that will be on each processor. - This is a linear partitioning with the addition of a simple load - balancing for any remainder points. ---*/ - - CLinearPartitioner pointPartitioner(numberOfGlobalPoints, 0); - - /*--- Store the local number of nodes for this rank. ---*/ - - numberOfLocalPoints = pointPartitioner.GetSizeOnRank(rank); - - /*--- Create buffer to hold the grid coordinates for our rank. ---*/ - - localPointCoordinates.resize(dimension); - for (int k = 0; k < dimension; k++) localPointCoordinates[k].resize(numberOfLocalPoints, 0.0); - - /*--- Set the value of range_max to the total number of nodes in - the unstructured mesh. Also allocate memory for the temporary array - that will hold the grid coordinates as they are extracted. Note the - +1 for CGNS convention. ---*/ - - cgsize_t range_min = (cgsize_t)pointPartitioner.GetFirstIndexOnRank(rank) + 1; - auto range_max = (cgsize_t)pointPartitioner.GetLastIndexOnRank(rank); - - /*--- Loop over each set of coordinates. ---*/ - - for (int k = 0; k < dimension; k++) { - /*--- Read the coordinate info. This will retrieve the - data type (either RealSingle or RealDouble) as - well as the coordname which will specify the - type of data that it is based in the SIDS convention. - This might be "CoordinateX," for instance. ---*/ - - char coordname[CGNS_STRING_SIZE]; - DataType_t datatype; - if (cg_coord_info(cgnsFileID, cgnsBase, cgnsZone, k + 1, &datatype, coordname)) cg_error_exit(); - if (rank == MASTER_NODE) { - cout << "Loading " << coordname; - if (size > SINGLE_NODE) { - cout << " values into linear partitions." << endl; - } else { - cout << " values." << endl; - } - } - - /*--- Check the coordinate name to decide the index for storage. ---*/ - - unsigned short indC = 0; - if (string(coordname) == "CoordinateX") - indC = 0; - else if (string(coordname) == "CoordinateY") - indC = 1; - else if (string(coordname) == "CoordinateZ") - indC = 2; - else - SU2_MPI::Error(string("Unknown coordinate name, ") + coordname + string(", in the CGNS file."), CURRENT_FUNCTION); - - /*--- Now read our rank's chunk of coordinates from the file. - Ask for datatype RealDouble and let CGNS library do the translation - when RealSingle is found. ---*/ - - if (cg_coord_read(cgnsFileID, cgnsBase, cgnsZone, coordname, RealDouble, &range_min, &range_max, - localPointCoordinates[indC].data())) - cg_error_exit(); - } -} - -void CCGNSMeshReaderFVM::ReadCGNSSectionMetadata() { - /*--- Begin section for retrieving the connectivity info. ---*/ - - if ((rank == MASTER_NODE) && (size > SINGLE_NODE)) cout << "Distributing connectivity across all ranks." << endl; - - /*--- First check the number of sections. ---*/ - - if (cg_nsections(cgnsFileID, cgnsBase, cgnsZone, &nSections)) cg_error_exit(); - if (rank == MASTER_NODE) { - cout << "Number of connectivity sections is "; - cout << nSections << "." << endl; - } - - /*--- Prepare several data structures to hold the various - pieces of information describing each section. ---*/ - - isInterior.resize(nSections); - nElems.resize(nSections, 0); - elemOffset.resize(nSections + 1, 0); - elemOffset[0] = 0; - connElems.resize(nSections); - sectionNames.resize(nSections, vector(CGNS_STRING_SIZE)); - numberOfGlobalElements = 0; - - for (int s = 0; s < nSections; s++) { - /*--- Read the connectivity details for this section. ---*/ - - int nbndry, parent_flag, vtk_type; - cgsize_t startE, endE, sizeNeeded; - ElementType_t elemType; - if (cg_section_read(cgnsFileID, cgnsBase, cgnsZone, s + 1, sectionNames[s].data(), &elemType, &startE, &endE, - &nbndry, &parent_flag)) - cg_error_exit(); - - /*--- Compute the total element count in this section (global). ---*/ - - unsigned long element_count = (endE - startE + 1); - - /* Get the details for the CGNS element type in this section. */ - - string elem_name = GetCGNSElementType(elemType, vtk_type); - - /* We assume that each section contains interior elements by default. - If we find 1D elements in a 2D problem or 2D elements in a 3D - problem, then we know the section must contain boundary elements. - We assume that each section is composed of either entirely interior - or entirely boundary elements. */ - - isInterior[s] = true; - - if (elemType == MIXED) { - /* For a mixed section, we check the type of the first element - so that we can correctly label this section as an interior or - boundary element section. Here, we also assume that a section - can not hold both interior and boundary elements. First, get - the size required to read a single element from the section. */ - - if (cg_ElementPartialSize(cgnsFileID, cgnsBase, cgnsZone, s + 1, startE, startE, &sizeNeeded) != CG_OK) - cg_error_exit(); - - /* A couple of auxiliary vectors for mixed element sections. */ - - vector connElemCGNS(sizeNeeded); - vector connOffsetCGNS(2, 0); - - /* Retrieve the connectivity information for the first element. */ - - if (cg_poly_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, s + 1, startE, startE, connElemCGNS.data(), - connOffsetCGNS.data(), nullptr) != CG_OK) - cg_error_exit(); - - /* The element type is in the first position of the connectivity - information that we retrieved from the CGNS file. */ - - elemType = ElementType_t(connElemCGNS[0]); - } - - /* Check for 1D elements in 2D problems, or for 2D elements in - 3D problems. If found, mark the section as a boundary section. */ - - if ((dimension == 2) && (elemType == BAR_2 || elemType == BAR_3)) isInterior[s] = false; - if ((dimension == 3) && (elemType == TRI_3 || elemType == QUAD_4)) isInterior[s] = false; - - /*--- Increment the global element offset for each section - based on whether or not this is a surface or volume section. - We also keep a running count of the total elements globally. ---*/ - - elemOffset[s + 1] = elemOffset[s]; - if (!isInterior[s]) - elemOffset[s + 1] += element_count; - else - numberOfGlobalElements += element_count; - - /*--- Print some information to the console. ---*/ - - if (rank == MASTER_NODE) { - cout << "Section " << string(sectionNames[s].data()); - cout << " contains " << element_count << " elements"; - cout << " of type " << elem_name << "." << endl; - } - } -} - void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { /*--- In this routine, each rank will read a chunk of the element connectivity for a single specified section of the CGNS mesh file. @@ -951,65 +650,6 @@ void CCGNSMeshReaderFVM::ReformatCGNSSurfaceConnectivity() { } } } - -string CCGNSMeshReaderFVM::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. */ - - string elem_name; - switch (val_elem_type) { - case NODE: - elem_name = "Vertex"; - val_vtk_type = 1; - SU2_MPI::Error("Vertex elements detected. Please remove.", CURRENT_FUNCTION); - break; - case BAR_2: - elem_name = "Line"; - val_vtk_type = 3; - if (dimension == 3) SU2_MPI::Error("Line elements detected in a 3D mesh. Please remove.", CURRENT_FUNCTION); - break; - case BAR_3: - elem_name = "Line"; - val_vtk_type = 3; - if (dimension == 3) SU2_MPI::Error("Line elements detected in a 3D mesh. Please remove.", CURRENT_FUNCTION); - break; - case TRI_3: - elem_name = "Triangle"; - val_vtk_type = 5; - break; - case QUAD_4: - elem_name = "Quadrilateral"; - val_vtk_type = 9; - break; - case TETRA_4: - elem_name = "Tetrahedron"; - val_vtk_type = 10; - break; - case HEXA_8: - elem_name = "Hexahedron"; - val_vtk_type = 12; - break; - case PENTA_6: - elem_name = "Prism"; - val_vtk_type = 13; - break; - case PYRA_5: - elem_name = "Pyramid"; - val_vtk_type = 14; - break; - case MIXED: - elem_name = "Mixed"; - val_vtk_type = -1; - break; - default: - char buf[100]; - SPRINTF(buf, "Unsupported or unknown CGNS element type: (type %d)\n", val_elem_type); - SU2_MPI::Error(string(buf), CURRENT_FUNCTION); - break; - } - - return elem_name; -} #endif void CCGNSMeshReaderFVM::InitiateCommsAll(void* bufSend, const int* nElemSend, SU2_MPI::Request* sendReq, void* bufRecv, diff --git a/Common/src/geometry/meshreader/meson.build b/Common/src/geometry/meshreader/meson.build index fb44650ad56..f2ade5b4473 100644 --- a/Common/src/geometry/meshreader/meson.build +++ b/Common/src/geometry/meshreader/meson.build @@ -1,4 +1,5 @@ common_src += files(['CBoxMeshReaderFVM.cpp', + 'CCGNSMeshReaderBase.cpp', 'CCGNSMeshReaderFVM.cpp', 'CMeshReaderBase.cpp', 'CRectangularMeshReaderFVM.cpp', From 1108a49f1a2646bbd5f6da875639a3e38d22fa72 Mon Sep 17 00:00:00 2001 From: vdweide Date: Sat, 1 Feb 2025 18:12:56 +0100 Subject: [PATCH 115/129] Split the SU2 ASCII finite volume reader in a common base class and a class that is specific to the reading of the SU2 ASCII grid for the finite volume solver --- .../meshreader/CSU2ASCIIMeshReaderBase.hpp | 116 ++++ .../meshreader/CSU2ASCIIMeshReaderFVM.hpp | 68 +-- .../meshreader/CSU2ASCIIMeshReaderBase.cpp | 519 ++++++++++++++++++ .../meshreader/CSU2ASCIIMeshReaderFVM.cpp | 487 +--------------- Common/src/geometry/meshreader/meson.build | 1 + 5 files changed, 639 insertions(+), 552 deletions(-) create mode 100644 Common/include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp create mode 100644 Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp diff --git a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp new file mode 100644 index 00000000000..891141cf9ad --- /dev/null +++ b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp @@ -0,0 +1,116 @@ +/*! + * \file CSU2ASCIIMeshReaderBase.hpp + * \brief Header file for the class CSU2ASCIIMeshReaderBase. + * The implementations are in the CSU2ASCIIMeshReaderBase.cpp file. + * \author T. Economon + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include + +#include "CMeshReaderBase.hpp" + +/*! + * \class CSU2ASCIIMeshReaderBase + * \brief Base class for the reading of a native SU2 ASCII grid. + * \author T. Economon + */ +class CSU2ASCIIMeshReaderBase : public CMeshReaderBase { + protected: + enum class FileSection { POINTS, ELEMENTS, MARKERS }; /*!< \brief Different sections of the file. */ + std::array SectionOrder{}; /*!< \brief Order of the sections in the file. */ + + const unsigned short myZone; /*!< \brief Current SU2 zone index. */ + const unsigned short nZones; /*!< \brief Total number of zones in the SU2 file. */ + + const string meshFilename; /*!< \brief Name of the SU2 ASCII mesh file being read. */ + ifstream mesh_file; /*!< \brief File object for the SU2 ASCII mesh file. */ + + bool actuator_disk; /*!< \brief Boolean for whether we have an actuator disk to split. */ + + unsigned long ActDiskNewPoints = + 0; /*!< \brief Total number of new grid points to add due to actuator disk splitting. */ + + su2double Xloc = 0.0; /*!< \brief X-coordinate of the CG of the actuator disk surface. */ + su2double Yloc = 0.0; /*!< \brief X-coordinate of the CG of the actuator disk surface. */ + su2double Zloc = 0.0; /*!< \brief X-coordinate of the CG of the actuator disk surface. */ + + vector ActDisk_Bool; /*!< \brief Flag to identify the grid points on the actuator disk. */ + + vector ActDiskPoint_Back; /*!< \brief Vector containing the global index for the new grid points added + to the back of the actuator disk. */ + vector VolumePoint_Inv; /*!< \brief Vector containing the inverse mapping from the global index to the + added point index for the actuator disk. */ + + vector CoordXActDisk; /*!< \brief X-coordinates of the new grid points added by splitting the actuator disk + (size = ActDiskNewPoints). */ + vector CoordYActDisk; /*!< \brief Y-coordinates of the new grid points added by splitting the actuator disk + (size = ActDiskNewPoints). */ + vector CoordZActDisk; /*!< \brief Z-coordinates of the new grid points added by splitting the actuator disk + (size = ActDiskNewPoints). */ + + vector CoordXVolumePoint; /*!< \brief X-coordinates of the volume elements touching the actuator disk. */ + vector CoordYVolumePoint; /*!< \brief Y-coordinates of the volume elements touching the actuator disk. */ + vector CoordZVolumePoint; /*!< \brief Z-coordinates of the volume elements touching the actuator disk. */ + + /*! + * \brief Reads all SU2 ASCII mesh metadata and checks for errors. + * \param[in] single_pass - Try to read the contents together with the metadata if the order allows (points before + * elements). \param[in,out] config - Problem configuration where some metadata is updated (e.g. AoA). \returns True + * if single_pass was successful. + */ + bool ReadMetadata(const bool single_pass, CConfig* config); + + /*! + * \brief Reads the grid points from an SU2 zone into linear partitions across all ranks. + */ + void ReadPointCoordinates(const bool single_pass = false); + + /*! + * \brief Reads the interior volume elements from one section of an SU2 zone into linear partitions across all ranks. + */ + void ReadVolumeElementConnectivity(const bool single_pass = false); + + /*! + * \brief Reads the surface (boundary) elements from the SU2 zone. + */ + void ReadSurfaceElementConnectivity(const bool single_pass = false); + + /*! + * \brief Helper function to find the current zone in an SU2 ASCII mesh object. + */ + void FastForwardToMyZone(); + + public: + /*! + * \brief Constructor of the CSU2ASCIIMeshReaderBase class. + */ + CSU2ASCIIMeshReaderBase(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CSU2ASCIIMeshReaderBase class. + */ + virtual ~CSU2ASCIIMeshReaderBase(void) override; +}; diff --git a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp index 0222063fb56..10fada303d2 100644 --- a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp @@ -30,84 +30,20 @@ #include -#include "CMeshReaderBase.hpp" +#include "CSU2ASCIIMeshReaderBase.hpp" /*! * \class CSU2ASCIIMeshReaderFVM * \brief Reads a native SU2 ASCII grid into linear partitions for the finite volume solver (FVM). * \author T. Economon */ -class CSU2ASCIIMeshReaderFVM : public CMeshReaderBase { +class CSU2ASCIIMeshReaderFVM : public CSU2ASCIIMeshReaderBase { private: - enum class FileSection { POINTS, ELEMENTS, MARKERS }; /*!< \brief Different sections of the file. */ - std::array SectionOrder{}; /*!< \brief Order of the sections in the file. */ - - const unsigned short myZone; /*!< \brief Current SU2 zone index. */ - const unsigned short nZones; /*!< \brief Total number of zones in the SU2 file. */ - - const string meshFilename; /*!< \brief Name of the SU2 ASCII mesh file being read. */ - ifstream mesh_file; /*!< \brief File object for the SU2 ASCII mesh file. */ - - bool actuator_disk; /*!< \brief Boolean for whether we have an actuator disk to split. */ - - unsigned long ActDiskNewPoints = - 0; /*!< \brief Total number of new grid points to add due to actuator disk splitting. */ - - su2double Xloc = 0.0; /*!< \brief X-coordinate of the CG of the actuator disk surface. */ - su2double Yloc = 0.0; /*!< \brief X-coordinate of the CG of the actuator disk surface. */ - su2double Zloc = 0.0; /*!< \brief X-coordinate of the CG of the actuator disk surface. */ - - vector ActDisk_Bool; /*!< \brief Flag to identify the grid points on the actuator disk. */ - - vector ActDiskPoint_Back; /*!< \brief Vector containing the global index for the new grid points added - to the back of the actuator disk. */ - vector VolumePoint_Inv; /*!< \brief Vector containing the inverse mapping from the global index to the - added point index for the actuator disk. */ - - vector CoordXActDisk; /*!< \brief X-coordinates of the new grid points added by splitting the actuator disk - (size = ActDiskNewPoints). */ - vector CoordYActDisk; /*!< \brief Y-coordinates of the new grid points added by splitting the actuator disk - (size = ActDiskNewPoints). */ - vector CoordZActDisk; /*!< \brief Z-coordinates of the new grid points added by splitting the actuator disk - (size = ActDiskNewPoints). */ - - vector CoordXVolumePoint; /*!< \brief X-coordinates of the volume elements touching the actuator disk. */ - vector CoordYVolumePoint; /*!< \brief Y-coordinates of the volume elements touching the actuator disk. */ - vector CoordZVolumePoint; /*!< \brief Z-coordinates of the volume elements touching the actuator disk. */ - - /*! - * \brief Reads all SU2 ASCII mesh metadata and checks for errors. - * \param[in] single_pass - Try to read the contents together with the metadata if the order allows (points before - * elements). \param[in,out] config - Problem configuration where some metadata is updated (e.g. AoA). \returns True - * if single_pass was successful. - */ - bool ReadMetadata(const bool single_pass, CConfig* config); - /*! * \brief Splits a single surface actuator disk boundary into two separate markers (repeated points). */ void SplitActuatorDiskSurface(); - /*! - * \brief Reads the grid points from an SU2 zone into linear partitions across all ranks. - */ - void ReadPointCoordinates(const bool single_pass = false); - - /*! - * \brief Reads the interior volume elements from one section of an SU2 zone into linear partitions across all ranks. - */ - void ReadVolumeElementConnectivity(const bool single_pass = false); - - /*! - * \brief Reads the surface (boundary) elements from the SU2 zone. - */ - void ReadSurfaceElementConnectivity(const bool single_pass = false); - - /*! - * \brief Helper function to find the current zone in an SU2 ASCII mesh object. - */ - void FastForwardToMyZone(); - public: /*! * \brief Constructor of the CSU2ASCIIMeshReaderFVM class. diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp new file mode 100644 index 00000000000..845221356cb --- /dev/null +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp @@ -0,0 +1,519 @@ +/*! + * \file CSU2ASCIIMeshReaderBase.cpp + * \brief Helper class for the reading of a native SU2 ASCII grid file. + * \author T. Economon + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/toolboxes/CLinearPartitioner.hpp" +#include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp" + +CSU2ASCIIMeshReaderBase::CSU2ASCIIMeshReaderBase(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) + : CMeshReaderBase(val_config, val_iZone, val_nZone), + myZone(val_iZone), + nZones(val_nZone), + meshFilename(config->GetMesh_FileName()) { +} + +CSU2ASCIIMeshReaderBase::~CSU2ASCIIMeshReaderBase(void) = default; + +bool CSU2ASCIIMeshReaderBase::ReadMetadata(const bool single_pass, CConfig* config) { + const bool harmonic_balance = config->GetTime_Marching() == TIME_MARCHING::HARMONIC_BALANCE; + const bool multizone_file = config->GetMultizone_Mesh(); + + /*--- Open grid file ---*/ + + mesh_file.open(meshFilename); + if (mesh_file.fail()) { + SU2_MPI::Error( + "Error opening SU2 ASCII grid.\n" + "Check that the file exists.", + CURRENT_FUNCTION); + } + + /*--- If more than one, find the curent zone in the mesh file. ---*/ + + string text_line; + if ((nZones > 1 && multizone_file) || harmonic_balance) { + if (harmonic_balance) { + if (rank == MASTER_NODE) cout << "Reading time instance " << config->GetiInst() + 1 << "." << endl; + } else { + bool foundZone = false; + while (getline(mesh_file, text_line)) { + /*--- Search for the current domain ---*/ + if (text_line.find("IZONE=", 0) != string::npos) { + text_line.erase(0, 6); + unsigned short jZone = atoi(text_line.c_str()); + if (jZone == myZone + 1) { + if (rank == MASTER_NODE) cout << "Reading zone " << myZone << " from native SU2 ASCII mesh." << endl; + foundZone = true; + break; + } + } + } + if (!foundZone) { + SU2_MPI::Error( + "Could not find the IZONE= keyword or the zone contents.\n" + "Check the SU2 ASCII file format.", + CURRENT_FUNCTION); + } + } + } + + /*--- Read the metadata: problem dimension, offsets for angle + of attack and angle of sideslip, global points, global elements, + and number of markers. Perform error checks as we go. ---*/ + + bool foundNDIME = false, foundNPOIN = false; + bool foundNELEM = false, foundNMARK = false; + + int current_section_idx = 0; + bool single_pass_active = false; + + while (getline(mesh_file, text_line)) { + /*--- Read the dimension of the problem ---*/ + + if (!foundNDIME && text_line.find("NDIME=", 0) != string::npos) { + text_line.erase(0, 6); + dimension = atoi(text_line.c_str()); + foundNDIME = true; + continue; + } + + /*--- The AoA and AoS offset values are optional. ---*/ + + if (text_line.find("AOA_OFFSET=", 0) != string::npos) { + text_line.erase(0, 11); + su2double AoA_Offset = atof(text_line.c_str()); + + /*--- The offset is in deg ---*/ + const su2double AoA_Current = config->GetAoA() + AoA_Offset; + config->SetAoA_Offset(AoA_Offset); + config->SetAoA(AoA_Current); + + if (AoA_Offset != 0.0) { + if (!config->GetDiscard_InFiles()) { + cout << "WARNING: AoA in the config file (" << config->GetAoA() << " deg.) +\n"; + cout << " AoA offset in mesh file (" << AoA_Offset << " deg.) = " << AoA_Current << " deg." << endl; + } else { + cout << "WARNING: Discarding the AoA offset in the mesh file." << endl; + } + } + continue; + } + + if (text_line.find("AOS_OFFSET=", 0) != string::npos) { + text_line.erase(0, 11); + su2double AoS_Offset = atof(text_line.c_str()); + + /*--- The offset is in deg ---*/ + const su2double AoS_Current = config->GetAoS() + AoS_Offset; + config->SetAoS_Offset(AoS_Offset); + config->SetAoS(AoS_Current); + + if (AoS_Offset != 0.0) { + if (!config->GetDiscard_InFiles()) { + cout << "WARNING: AoS in the config file (" << config->GetAoS() << " deg.) +\n"; + cout << " AoS offset in mesh file (" << AoS_Offset << " deg.) = " << AoS_Current << " deg." << endl; + } else { + cout << "WARNING: Discarding the AoS offset in the mesh file." << endl; + } + } + continue; + } + + if (!foundNPOIN && text_line.find("NPOIN=", 0) != string::npos) { + text_line.erase(0, 6); + numberOfGlobalPoints = atoi(text_line.c_str()); + + /* If the points were found first, read them, otherwise just consume the lines. */ + if (single_pass && foundNDIME && current_section_idx == 0) { + single_pass_active = true; + ReadPointCoordinates(true); + } else { + for (auto iPoint = 0ul; iPoint < numberOfGlobalPoints; iPoint++) getline(mesh_file, text_line); + } + SectionOrder[current_section_idx++] = FileSection::POINTS; + foundNPOIN = true; + continue; + } + + if (!foundNELEM && text_line.find("NELEM=", 0) != string::npos) { + text_line.erase(0, 6); + numberOfGlobalElements = atoi(text_line.c_str()); + + if (single_pass_active) { + ReadVolumeElementConnectivity(true); + } else { + for (auto iElem = 0ul; iElem < numberOfGlobalElements; iElem++) getline(mesh_file, text_line); + } + SectionOrder[current_section_idx++] = FileSection::ELEMENTS; + foundNELEM = true; + continue; + } + + if (!foundNMARK && text_line.find("NMARK=", 0) != string::npos) { + text_line.erase(0, 6); + numberOfMarkers = atoi(text_line.c_str()); + + if (current_section_idx != 2) { + SU2_MPI::Error("Markers must be listed after points and elements in the SU2 mesh file.", CURRENT_FUNCTION); + } + + if (single_pass_active) ReadSurfaceElementConnectivity(true); + + SectionOrder[current_section_idx++] = FileSection::MARKERS; + foundNMARK = true; + continue; + } + + /* Stop before we reach the next zone then check for errors below. */ + if (text_line.find("IZONE=", 0) != string::npos) { + break; + } + } + + mesh_file.close(); + + /* Throw an error if any of the keywords was not found. */ + if (!foundNDIME) { + SU2_MPI::Error( + "Could not find the keyword \"NDIME=\".\n" + "Check the SU2 ASCII file format.", + CURRENT_FUNCTION); + } + if (!foundNPOIN) { + SU2_MPI::Error( + "Could not find the keyword \"NPOIN=\".\n" + "Check the SU2 ASCII file format.", + CURRENT_FUNCTION); + } + if (!foundNELEM) { + SU2_MPI::Error( + "Could not find the keyword \"NELEM=\".\n" + "Check the SU2 ASCII file format.", + CURRENT_FUNCTION); + } + if (!foundNMARK) { + SU2_MPI::Error( + "Could not find the keyword \"NMARK=\".\n" + "Check the SU2 ASCII file format.", + CURRENT_FUNCTION); + } + + return single_pass_active; +} + +void CSU2ASCIIMeshReaderBase::ReadPointCoordinates(const bool single_pass) { + /* Get a partitioner to help with linear partitioning. */ + CLinearPartitioner pointPartitioner(numberOfGlobalPoints, 0); + + /* Determine number of local points */ + numberOfLocalPoints = pointPartitioner.GetSizeOnRank(rank); + + /* Prepare our data structure for the point coordinates. */ + localPointCoordinates.resize(dimension); + for (int k = 0; k < dimension; k++) localPointCoordinates[k].reserve(numberOfLocalPoints); + + /*--- Read the point coordinates into our data structure. ---*/ + + while (true) { + string text_line; + if (!single_pass) { + getline(mesh_file, text_line); + if (text_line.find("NPOIN=", 0) == string::npos) continue; + } + + for (unsigned long GlobalIndex = 0; GlobalIndex < numberOfGlobalPoints; ++GlobalIndex) { + if (!actuator_disk) { + getline(mesh_file, text_line); + } else { + if (GlobalIndex < numberOfGlobalPoints - ActDiskNewPoints) { + getline(mesh_file, text_line); + } else { + /* This is a new actuator disk point, so we must construct a + string with the new point's coordinates. */ + ostringstream strsX, strsY, strsZ; + unsigned long BackActDisk_Index = GlobalIndex; + unsigned long LocalIndex = BackActDisk_Index - (numberOfGlobalPoints - ActDiskNewPoints); + strsX.precision(20); + strsY.precision(20); + strsZ.precision(20); + su2double CoordX = CoordXActDisk[LocalIndex]; + strsX << scientific << CoordX; + su2double CoordY = CoordYActDisk[LocalIndex]; + strsY << scientific << CoordY; + su2double CoordZ = CoordZActDisk[LocalIndex]; + strsZ << scientific << CoordZ; + text_line = strsX.str() + "\t" + strsY.str() + "\t" + strsZ.str(); + } + } + + /*--- We only read information for this node if it is owned by this + rank based upon our initial linear partitioning. ---*/ + + passivedouble Coords[3] = {0.0, 0.0, 0.0}; + if (pointPartitioner.IndexBelongsToRank(GlobalIndex, rank)) { + istringstream point_line(text_line); + + /* Store the coordinates more clearly. */ + point_line >> Coords[0]; + point_line >> Coords[1]; + if (dimension == 3) { + point_line >> Coords[2]; + } + + /* Load into the coordinate class data structure. */ + for (unsigned short iDim = 0; iDim < dimension; iDim++) { + localPointCoordinates[iDim].push_back(Coords[iDim]); + } + } + } + break; + } +} + +void CSU2ASCIIMeshReaderBase::ReadVolumeElementConnectivity(const bool single_pass) { + /* Get a partitioner to help with linear partitioning. */ + CLinearPartitioner pointPartitioner(numberOfGlobalPoints, 0); + + /* Loop over our analytically defined of elements and store only those + that contain a node within our linear partition of points. */ + numberOfLocalElements = 0; + array connectivity{}; + + while (true) { + string text_line; + if (!single_pass) { + if (!getline(mesh_file, text_line)) break; + if (text_line.find("NELEM=", 0) == string::npos) continue; + } + + /*--- Loop over all the volumetric elements and store any element that + contains at least one of an owned node for this rank (i.e., there will + be element redundancy, since multiple ranks will store the same elems + on the boundaries of the initial linear partitioning. ---*/ + + numberOfLocalElements = 0; + + for (unsigned long GlobalIndex = 0; GlobalIndex < numberOfGlobalElements; ++GlobalIndex) { + getline(mesh_file, text_line); + istringstream elem_line(text_line); + + /*--- Decide whether this rank needs each element. ---*/ + + unsigned short VTK_Type; + elem_line >> VTK_Type; + + const auto nPointsElem = nPointsOfElementType(VTK_Type); + + for (unsigned short i = 0; i < nPointsElem; i++) { + elem_line >> connectivity[i]; + } + + if (actuator_disk) { + for (unsigned short i = 0; i < nPointsElem; i++) { + if (ActDisk_Bool[connectivity[i]]) { + su2double Xcg = 0.0; + unsigned long Counter = 0; + for (unsigned short j = 0; j < nPointsElem; j++) { + if (connectivity[j] < numberOfGlobalPoints - ActDiskNewPoints) { + Xcg += CoordXVolumePoint[VolumePoint_Inv[connectivity[j]]]; + Counter++; + } + } + Xcg = Xcg / su2double(Counter); + + if (Counter != 0 && Xcg > Xloc) { + connectivity[i] = ActDiskPoint_Back[connectivity[i]]; + } + } + } + } + + /* Check whether any of the points reside in our linear partition. */ + bool isOwned = false; + for (unsigned short i = 0; i < nPointsElem; i++) { + if (pointPartitioner.IndexBelongsToRank(connectivity[i], rank)) { + isOwned = true; + break; + } + } + + /* If element is owned, we need to store it locally. */ + if (isOwned) { + localVolumeElementConnectivity.push_back(GlobalIndex); + localVolumeElementConnectivity.push_back(VTK_Type); + /// TODO: Use a compressed format. + for (unsigned short i = 0; i < N_POINTS_HEXAHEDRON; i++) { + localVolumeElementConnectivity.push_back(connectivity[i]); + } + numberOfLocalElements++; + } + } + break; + } +} + +void CSU2ASCIIMeshReaderBase::ReadSurfaceElementConnectivity(const bool single_pass) { + /* We already read in the number of markers with the metadata. */ + surfaceElementConnectivity.resize(numberOfMarkers); + markerNames.resize(numberOfMarkers); + + array connectivity{}; + + /*--- In this routine, the boundary info is read by all ranks, + however, the surface connectivity is still handled by the + master node (and eventually distributed by the master as well). ---*/ + + while (true) { + string text_line; + if (!single_pass) { + if (!getline(mesh_file, text_line)) break; + if (text_line.find("NMARK=", 0) == string::npos) continue; + } + + for (unsigned short iMarker = 0; iMarker < numberOfMarkers; ++iMarker) { + getline(mesh_file, text_line); + text_line.erase(0, 11); + string::size_type position; + + for (unsigned short iChar = 0; iChar < 20; iChar++) { + position = text_line.find(' ', 0); + if (position != string::npos) text_line.erase(position, 1); + position = text_line.find('\r', 0); + if (position != string::npos) text_line.erase(position, 1); + position = text_line.find('\n', 0); + if (position != string::npos) text_line.erase(position, 1); + } + markerNames[iMarker] = text_line; + + bool duplicate = false; + if ((actuator_disk) && (markerNames[iMarker] == config->GetMarker_ActDiskInlet_TagBound(0))) { + duplicate = true; + markerNames[iMarker + 1] = config->GetMarker_ActDiskOutlet_TagBound(0); + } + + /*--- Physical boundaries definition ---*/ + + if (markerNames[iMarker] == "SEND_RECEIVE") { + /*--- Throw an error if we find deprecated references to SEND_RECEIVE + boundaries in the mesh. ---*/ + SU2_MPI::Error( + "Mesh file contains deprecated SEND_RECEIVE marker!\n" + "Please remove any SEND_RECEIVE markers from the SU2 ASCII mesh.", + CURRENT_FUNCTION); + } + + getline(mesh_file, text_line); + text_line.erase(0, 13); + unsigned long nElem_Bound = atoi(text_line.c_str()); + + /*--- Allocate space for elements ---*/ + + for (unsigned long iElem_Bound = 0; iElem_Bound < nElem_Bound; iElem_Bound++) { + getline(mesh_file, text_line); + istringstream bound_line(text_line); + + unsigned short VTK_Type; + bound_line >> VTK_Type; + + const auto nPointsElem = nPointsOfElementType(VTK_Type); + + if (dimension == 3 && VTK_Type == LINE) { + SU2_MPI::Error( + "Line boundary conditions are not possible for 3D calculations.\n" + "Please check the SU2 ASCII mesh file.", + CURRENT_FUNCTION); + } + + for (unsigned short i = 0; i < nPointsElem; i++) { + bound_line >> connectivity[i]; + } + + surfaceElementConnectivity[iMarker].push_back(0); + surfaceElementConnectivity[iMarker].push_back(VTK_Type); + for (unsigned short i = 0; i < N_POINTS_HEXAHEDRON; i++) { + surfaceElementConnectivity[iMarker].push_back(connectivity[i]); + } + + if (duplicate) { + for (unsigned short i = 0; i < nPointsElem; i++) { + if (ActDisk_Bool[connectivity[i]]) { + connectivity[i] = ActDiskPoint_Back[connectivity[i]]; + } + } + surfaceElementConnectivity[iMarker + 1].push_back(0); + surfaceElementConnectivity[iMarker + 1].push_back(VTK_Type); + for (unsigned short i = 0; i < N_POINTS_HEXAHEDRON; i++) { + surfaceElementConnectivity[iMarker + 1].push_back(connectivity[i]); + } + } + } + /*--- Increment the counter an extra time if we stored a duplicate. ---*/ + iMarker += duplicate; + } + break; + } + + if (rank != MASTER_NODE) return; + + /*--- Final error check for deprecated periodic BC format. ---*/ + + string text_line; + while (getline(mesh_file, text_line)) { + /*--- Find any periodic transformation information. ---*/ + + if (text_line.find("NPERIODIC=", 0) != string::npos) { + /*--- Read and store the number of transformations. ---*/ + text_line.erase(0, 10); + unsigned short nPeriodic = atoi(text_line.c_str()); + if (nPeriodic - 1 != 0) { + SU2_MPI::Error( + "Mesh file contains deprecated periodic format!\n\n" + "For SU2 v7.0.0 and later, preprocessing of periodic grids by SU2_MSH\n" + "is no longer necessary. Please use the original mesh file (prior to SU2_MSH)\n" + "with the same MARKER_PERIODIC definition in the configuration file.", + CURRENT_FUNCTION); + } + } + + /*--- Stop before we reach the next zone. ---*/ + if (text_line.find("IZONE=", 0) != string::npos) break; + } +} + +void CSU2ASCIIMeshReaderBase::FastForwardToMyZone() { + /*--- If more than one, fast-forward to my zone in the mesh file. ---*/ + + if (nZones == 1 || !config->GetMultizone_Mesh()) return; + + string text_line; + while (getline(mesh_file, text_line)) { + /*--- Search for the current domain ---*/ + if (text_line.find("IZONE=", 0) == string::npos) continue; + text_line.erase(0, 6); + unsigned short jZone = atoi(text_line.c_str()); + if (jZone == myZone + 1) break; + } +} diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp index 00307a90d94..96a30abb5e0 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp @@ -26,14 +26,10 @@ * License along with SU2. If not, see . */ -#include "../../../include/toolboxes/CLinearPartitioner.hpp" #include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp" CSU2ASCIIMeshReaderFVM::CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) - : CMeshReaderBase(val_config, val_iZone, val_nZone), - myZone(val_iZone), - nZones(val_nZone), - meshFilename(config->GetMesh_FileName()) { + : CSU2ASCIIMeshReaderBase(val_config, val_iZone, val_nZone) { actuator_disk = (((config->GetnMarker_ActDiskInlet() != 0) || (config->GetnMarker_ActDiskOutlet() != 0)) && ((config->GetKind_SU2() == SU2_COMPONENT::SU2_CFD) || ((config->GetKind_SU2() == SU2_COMPONENT::SU2_DEF) && (config->GetActDisk_SU2_DEF())))); @@ -75,193 +71,6 @@ CSU2ASCIIMeshReaderFVM::CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned sho mesh_file.close(); } -bool CSU2ASCIIMeshReaderFVM::ReadMetadata(const bool single_pass, CConfig* config) { - const bool harmonic_balance = config->GetTime_Marching() == TIME_MARCHING::HARMONIC_BALANCE; - const bool multizone_file = config->GetMultizone_Mesh(); - - /*--- Open grid file ---*/ - - mesh_file.open(meshFilename); - if (mesh_file.fail()) { - SU2_MPI::Error( - "Error opening SU2 ASCII grid.\n" - "Check that the file exists.", - CURRENT_FUNCTION); - } - - /*--- If more than one, find the curent zone in the mesh file. ---*/ - - string text_line; - if ((nZones > 1 && multizone_file) || harmonic_balance) { - if (harmonic_balance) { - if (rank == MASTER_NODE) cout << "Reading time instance " << config->GetiInst() + 1 << "." << endl; - } else { - bool foundZone = false; - while (getline(mesh_file, text_line)) { - /*--- Search for the current domain ---*/ - if (text_line.find("IZONE=", 0) != string::npos) { - text_line.erase(0, 6); - unsigned short jZone = atoi(text_line.c_str()); - if (jZone == myZone + 1) { - if (rank == MASTER_NODE) cout << "Reading zone " << myZone << " from native SU2 ASCII mesh." << endl; - foundZone = true; - break; - } - } - } - if (!foundZone) { - SU2_MPI::Error( - "Could not find the IZONE= keyword or the zone contents.\n" - "Check the SU2 ASCII file format.", - CURRENT_FUNCTION); - } - } - } - - /*--- Read the metadata: problem dimension, offsets for angle - of attack and angle of sideslip, global points, global elements, - and number of markers. Perform error checks as we go. ---*/ - - bool foundNDIME = false, foundNPOIN = false; - bool foundNELEM = false, foundNMARK = false; - - int current_section_idx = 0; - bool single_pass_active = false; - - while (getline(mesh_file, text_line)) { - /*--- Read the dimension of the problem ---*/ - - if (!foundNDIME && text_line.find("NDIME=", 0) != string::npos) { - text_line.erase(0, 6); - dimension = atoi(text_line.c_str()); - foundNDIME = true; - continue; - } - - /*--- The AoA and AoS offset values are optional. ---*/ - - if (text_line.find("AOA_OFFSET=", 0) != string::npos) { - text_line.erase(0, 11); - su2double AoA_Offset = atof(text_line.c_str()); - - /*--- The offset is in deg ---*/ - const su2double AoA_Current = config->GetAoA() + AoA_Offset; - config->SetAoA_Offset(AoA_Offset); - config->SetAoA(AoA_Current); - - if (AoA_Offset != 0.0) { - if (!config->GetDiscard_InFiles()) { - cout << "WARNING: AoA in the config file (" << config->GetAoA() << " deg.) +\n"; - cout << " AoA offset in mesh file (" << AoA_Offset << " deg.) = " << AoA_Current << " deg." << endl; - } else { - cout << "WARNING: Discarding the AoA offset in the mesh file." << endl; - } - } - continue; - } - - if (text_line.find("AOS_OFFSET=", 0) != string::npos) { - text_line.erase(0, 11); - su2double AoS_Offset = atof(text_line.c_str()); - - /*--- The offset is in deg ---*/ - const su2double AoS_Current = config->GetAoS() + AoS_Offset; - config->SetAoS_Offset(AoS_Offset); - config->SetAoS(AoS_Current); - - if (AoS_Offset != 0.0) { - if (!config->GetDiscard_InFiles()) { - cout << "WARNING: AoS in the config file (" << config->GetAoS() << " deg.) +\n"; - cout << " AoS offset in mesh file (" << AoS_Offset << " deg.) = " << AoS_Current << " deg." << endl; - } else { - cout << "WARNING: Discarding the AoS offset in the mesh file." << endl; - } - } - continue; - } - - if (!foundNPOIN && text_line.find("NPOIN=", 0) != string::npos) { - text_line.erase(0, 6); - numberOfGlobalPoints = atoi(text_line.c_str()); - - /* If the points were found first, read them, otherwise just consume the lines. */ - if (single_pass && foundNDIME && current_section_idx == 0) { - single_pass_active = true; - ReadPointCoordinates(true); - } else { - for (auto iPoint = 0ul; iPoint < numberOfGlobalPoints; iPoint++) getline(mesh_file, text_line); - } - SectionOrder[current_section_idx++] = FileSection::POINTS; - foundNPOIN = true; - continue; - } - - if (!foundNELEM && text_line.find("NELEM=", 0) != string::npos) { - text_line.erase(0, 6); - numberOfGlobalElements = atoi(text_line.c_str()); - - if (single_pass_active) { - ReadVolumeElementConnectivity(true); - } else { - for (auto iElem = 0ul; iElem < numberOfGlobalElements; iElem++) getline(mesh_file, text_line); - } - SectionOrder[current_section_idx++] = FileSection::ELEMENTS; - foundNELEM = true; - continue; - } - - if (!foundNMARK && text_line.find("NMARK=", 0) != string::npos) { - text_line.erase(0, 6); - numberOfMarkers = atoi(text_line.c_str()); - - if (current_section_idx != 2) { - SU2_MPI::Error("Markers must be listed after points and elements in the SU2 mesh file.", CURRENT_FUNCTION); - } - - if (single_pass_active) ReadSurfaceElementConnectivity(true); - - SectionOrder[current_section_idx++] = FileSection::MARKERS; - foundNMARK = true; - continue; - } - - /* Stop before we reach the next zone then check for errors below. */ - if (text_line.find("IZONE=", 0) != string::npos) { - break; - } - } - - mesh_file.close(); - - /* Throw an error if any of the keywords was not found. */ - if (!foundNDIME) { - SU2_MPI::Error( - "Could not find the keyword \"NDIME=\".\n" - "Check the SU2 ASCII file format.", - CURRENT_FUNCTION); - } - if (!foundNPOIN) { - SU2_MPI::Error( - "Could not find the keyword \"NPOIN=\".\n" - "Check the SU2 ASCII file format.", - CURRENT_FUNCTION); - } - if (!foundNELEM) { - SU2_MPI::Error( - "Could not find the keyword \"NELEM=\".\n" - "Check the SU2 ASCII file format.", - CURRENT_FUNCTION); - } - if (!foundNMARK) { - SU2_MPI::Error( - "Could not find the keyword \"NMARK=\".\n" - "Check the SU2 ASCII file format.", - CURRENT_FUNCTION); - } - - return single_pass_active; -} - void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { /*--- Actuator disk preprocesing ---*/ @@ -783,297 +592,3 @@ void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { mesh_file.close(); } - -void CSU2ASCIIMeshReaderFVM::ReadPointCoordinates(const bool single_pass) { - /* Get a partitioner to help with linear partitioning. */ - CLinearPartitioner pointPartitioner(numberOfGlobalPoints, 0); - - /* Determine number of local points */ - numberOfLocalPoints = pointPartitioner.GetSizeOnRank(rank); - - /* Prepare our data structure for the point coordinates. */ - localPointCoordinates.resize(dimension); - for (int k = 0; k < dimension; k++) localPointCoordinates[k].reserve(numberOfLocalPoints); - - /*--- Read the point coordinates into our data structure. ---*/ - - while (true) { - string text_line; - if (!single_pass) { - getline(mesh_file, text_line); - if (text_line.find("NPOIN=", 0) == string::npos) continue; - } - - for (unsigned long GlobalIndex = 0; GlobalIndex < numberOfGlobalPoints; ++GlobalIndex) { - if (!actuator_disk) { - getline(mesh_file, text_line); - } else { - if (GlobalIndex < numberOfGlobalPoints - ActDiskNewPoints) { - getline(mesh_file, text_line); - } else { - /* This is a new actuator disk point, so we must construct a - string with the new point's coordinates. */ - ostringstream strsX, strsY, strsZ; - unsigned long BackActDisk_Index = GlobalIndex; - unsigned long LocalIndex = BackActDisk_Index - (numberOfGlobalPoints - ActDiskNewPoints); - strsX.precision(20); - strsY.precision(20); - strsZ.precision(20); - su2double CoordX = CoordXActDisk[LocalIndex]; - strsX << scientific << CoordX; - su2double CoordY = CoordYActDisk[LocalIndex]; - strsY << scientific << CoordY; - su2double CoordZ = CoordZActDisk[LocalIndex]; - strsZ << scientific << CoordZ; - text_line = strsX.str() + "\t" + strsY.str() + "\t" + strsZ.str(); - } - } - - /*--- We only read information for this node if it is owned by this - rank based upon our initial linear partitioning. ---*/ - - passivedouble Coords[3] = {0.0, 0.0, 0.0}; - if (pointPartitioner.IndexBelongsToRank(GlobalIndex, rank)) { - istringstream point_line(text_line); - - /* Store the coordinates more clearly. */ - point_line >> Coords[0]; - point_line >> Coords[1]; - if (dimension == 3) { - point_line >> Coords[2]; - } - - /* Load into the coordinate class data structure. */ - for (unsigned short iDim = 0; iDim < dimension; iDim++) { - localPointCoordinates[iDim].push_back(Coords[iDim]); - } - } - } - break; - } -} - -void CSU2ASCIIMeshReaderFVM::ReadVolumeElementConnectivity(const bool single_pass) { - /* Get a partitioner to help with linear partitioning. */ - CLinearPartitioner pointPartitioner(numberOfGlobalPoints, 0); - - /* Loop over our analytically defined of elements and store only those - that contain a node within our linear partition of points. */ - numberOfLocalElements = 0; - array connectivity{}; - - while (true) { - string text_line; - if (!single_pass) { - if (!getline(mesh_file, text_line)) break; - if (text_line.find("NELEM=", 0) == string::npos) continue; - } - - /*--- Loop over all the volumetric elements and store any element that - contains at least one of an owned node for this rank (i.e., there will - be element redundancy, since multiple ranks will store the same elems - on the boundaries of the initial linear partitioning. ---*/ - - numberOfLocalElements = 0; - - for (unsigned long GlobalIndex = 0; GlobalIndex < numberOfGlobalElements; ++GlobalIndex) { - getline(mesh_file, text_line); - istringstream elem_line(text_line); - - /*--- Decide whether this rank needs each element. ---*/ - - unsigned short VTK_Type; - elem_line >> VTK_Type; - - const auto nPointsElem = nPointsOfElementType(VTK_Type); - - for (unsigned short i = 0; i < nPointsElem; i++) { - elem_line >> connectivity[i]; - } - - if (actuator_disk) { - for (unsigned short i = 0; i < nPointsElem; i++) { - if (ActDisk_Bool[connectivity[i]]) { - su2double Xcg = 0.0; - unsigned long Counter = 0; - for (unsigned short j = 0; j < nPointsElem; j++) { - if (connectivity[j] < numberOfGlobalPoints - ActDiskNewPoints) { - Xcg += CoordXVolumePoint[VolumePoint_Inv[connectivity[j]]]; - Counter++; - } - } - Xcg = Xcg / su2double(Counter); - - if (Counter != 0 && Xcg > Xloc) { - connectivity[i] = ActDiskPoint_Back[connectivity[i]]; - } - } - } - } - - /* Check whether any of the points reside in our linear partition. */ - bool isOwned = false; - for (unsigned short i = 0; i < nPointsElem; i++) { - if (pointPartitioner.IndexBelongsToRank(connectivity[i], rank)) { - isOwned = true; - break; - } - } - - /* If element is owned, we need to store it locally. */ - if (isOwned) { - localVolumeElementConnectivity.push_back(GlobalIndex); - localVolumeElementConnectivity.push_back(VTK_Type); - /// TODO: Use a compressed format. - for (unsigned short i = 0; i < N_POINTS_HEXAHEDRON; i++) { - localVolumeElementConnectivity.push_back(connectivity[i]); - } - numberOfLocalElements++; - } - } - break; - } -} - -void CSU2ASCIIMeshReaderFVM::ReadSurfaceElementConnectivity(const bool single_pass) { - /* We already read in the number of markers with the metadata. */ - surfaceElementConnectivity.resize(numberOfMarkers); - markerNames.resize(numberOfMarkers); - - array connectivity{}; - - /*--- In this routine, the boundary info is read by all ranks, - however, the surface connectivity is still handled by the - master node (and eventually distributed by the master as well). ---*/ - - while (true) { - string text_line; - if (!single_pass) { - if (!getline(mesh_file, text_line)) break; - if (text_line.find("NMARK=", 0) == string::npos) continue; - } - - for (unsigned short iMarker = 0; iMarker < numberOfMarkers; ++iMarker) { - getline(mesh_file, text_line); - text_line.erase(0, 11); - string::size_type position; - - for (unsigned short iChar = 0; iChar < 20; iChar++) { - position = text_line.find(' ', 0); - if (position != string::npos) text_line.erase(position, 1); - position = text_line.find('\r', 0); - if (position != string::npos) text_line.erase(position, 1); - position = text_line.find('\n', 0); - if (position != string::npos) text_line.erase(position, 1); - } - markerNames[iMarker] = text_line; - - bool duplicate = false; - if ((actuator_disk) && (markerNames[iMarker] == config->GetMarker_ActDiskInlet_TagBound(0))) { - duplicate = true; - markerNames[iMarker + 1] = config->GetMarker_ActDiskOutlet_TagBound(0); - } - - /*--- Physical boundaries definition ---*/ - - if (markerNames[iMarker] == "SEND_RECEIVE") { - /*--- Throw an error if we find deprecated references to SEND_RECEIVE - boundaries in the mesh. ---*/ - SU2_MPI::Error( - "Mesh file contains deprecated SEND_RECEIVE marker!\n" - "Please remove any SEND_RECEIVE markers from the SU2 ASCII mesh.", - CURRENT_FUNCTION); - } - - getline(mesh_file, text_line); - text_line.erase(0, 13); - unsigned long nElem_Bound = atoi(text_line.c_str()); - - /*--- Allocate space for elements ---*/ - - for (unsigned long iElem_Bound = 0; iElem_Bound < nElem_Bound; iElem_Bound++) { - getline(mesh_file, text_line); - istringstream bound_line(text_line); - - unsigned short VTK_Type; - bound_line >> VTK_Type; - - const auto nPointsElem = nPointsOfElementType(VTK_Type); - - if (dimension == 3 && VTK_Type == LINE) { - SU2_MPI::Error( - "Line boundary conditions are not possible for 3D calculations.\n" - "Please check the SU2 ASCII mesh file.", - CURRENT_FUNCTION); - } - - for (unsigned short i = 0; i < nPointsElem; i++) { - bound_line >> connectivity[i]; - } - - surfaceElementConnectivity[iMarker].push_back(0); - surfaceElementConnectivity[iMarker].push_back(VTK_Type); - for (unsigned short i = 0; i < N_POINTS_HEXAHEDRON; i++) { - surfaceElementConnectivity[iMarker].push_back(connectivity[i]); - } - - if (duplicate) { - for (unsigned short i = 0; i < nPointsElem; i++) { - if (ActDisk_Bool[connectivity[i]]) { - connectivity[i] = ActDiskPoint_Back[connectivity[i]]; - } - } - surfaceElementConnectivity[iMarker + 1].push_back(0); - surfaceElementConnectivity[iMarker + 1].push_back(VTK_Type); - for (unsigned short i = 0; i < N_POINTS_HEXAHEDRON; i++) { - surfaceElementConnectivity[iMarker + 1].push_back(connectivity[i]); - } - } - } - /*--- Increment the counter an extra time if we stored a duplicate. ---*/ - iMarker += duplicate; - } - break; - } - - if (rank != MASTER_NODE) return; - - /*--- Final error check for deprecated periodic BC format. ---*/ - - string text_line; - while (getline(mesh_file, text_line)) { - /*--- Find any periodic transformation information. ---*/ - - if (text_line.find("NPERIODIC=", 0) != string::npos) { - /*--- Read and store the number of transformations. ---*/ - text_line.erase(0, 10); - unsigned short nPeriodic = atoi(text_line.c_str()); - if (nPeriodic - 1 != 0) { - SU2_MPI::Error( - "Mesh file contains deprecated periodic format!\n\n" - "For SU2 v7.0.0 and later, preprocessing of periodic grids by SU2_MSH\n" - "is no longer necessary. Please use the original mesh file (prior to SU2_MSH)\n" - "with the same MARKER_PERIODIC definition in the configuration file.", - CURRENT_FUNCTION); - } - } - - /*--- Stop before we reach the next zone. ---*/ - if (text_line.find("IZONE=", 0) != string::npos) break; - } -} - -void CSU2ASCIIMeshReaderFVM::FastForwardToMyZone() { - /*--- If more than one, fast-forward to my zone in the mesh file. ---*/ - - if (nZones == 1 || !config->GetMultizone_Mesh()) return; - - string text_line; - while (getline(mesh_file, text_line)) { - /*--- Search for the current domain ---*/ - if (text_line.find("IZONE=", 0) == string::npos) continue; - text_line.erase(0, 6); - unsigned short jZone = atoi(text_line.c_str()); - if (jZone == myZone + 1) break; - } -} diff --git a/Common/src/geometry/meshreader/meson.build b/Common/src/geometry/meshreader/meson.build index f2ade5b4473..789dc1edf84 100644 --- a/Common/src/geometry/meshreader/meson.build +++ b/Common/src/geometry/meshreader/meson.build @@ -3,4 +3,5 @@ common_src += files(['CBoxMeshReaderFVM.cpp', 'CCGNSMeshReaderFVM.cpp', 'CMeshReaderBase.cpp', 'CRectangularMeshReaderFVM.cpp', + 'CSU2ASCIIMeshReaderBase.cpp', 'CSU2ASCIIMeshReaderFVM.cpp']) From 4944325d4a756abf73b13769b5f022cd5fa19b55 Mon Sep 17 00:00:00 2001 From: bigfooted Date: Sat, 1 Feb 2025 20:13:42 +0100 Subject: [PATCH 116/129] move reference file --- .../design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref diff --git a/TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref b/TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref new file mode 100644 index 00000000000..2f0fb6fc297 --- /dev/null +++ b/TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref @@ -0,0 +1,2 @@ +ITER, avg_dp +1, 89.03358290403737 From 9888bc5a6b002ae7e1a9f468ae0a70fd5b0360c2 Mon Sep 17 00:00:00 2001 From: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> Date: Sat, 1 Feb 2025 14:10:12 -0800 Subject: [PATCH 117/129] Apply suggestions from code review --- TestCases/tutorials.py | 2 +- docker/test/runTests.sh | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/TestCases/tutorials.py b/TestCases/tutorials.py index 2d7aee33d8e..f4a151bdaad 100644 --- a/TestCases/tutorials.py +++ b/TestCases/tutorials.py @@ -353,7 +353,7 @@ def main(): sudo_design_fado.multizone = False sudo_design_fado.test_iter = 10 sudo_design_fado.timeout = 1600 - sudo_design_fado.reference_file = "optim.csv.ref" + sudo_design_fado.reference_file = "../../../TestCases/Tutorials/design/Inc_Turbulent_Bend_Wallfunctions/optim.csv.ref" sudo_design_fado.test_file = "optim.csv" sudo_design_fado.comp_threshold = 1e-6 sudo_design_fado.tol_file_percent = 0.1 diff --git a/docker/test/runTests.sh b/docker/test/runTests.sh index c6beeb08f85..9cb55113c99 100755 --- a/docker/test/runTests.sh +++ b/docker/test/runTests.sh @@ -101,10 +101,7 @@ else exit 1 fi fi -echo "Copying Tutorials folder to tests folder." cp -R ./Tutorials/ tests/. -echo "Copying TestCases/Tutorials folder to tests/Tutorials folder" -cp -R src/SU2/TestCases/Tutorials/* tests/Tutorials/. # Set the environment variables export SU2_RUN=$PWD/install/bin From cff3b3850a160b9ebdf21d497df02790025af630 Mon Sep 17 00:00:00 2001 From: Pedro Gomes <38071223+pcarruscag@users.noreply.github.com> Date: Sat, 1 Feb 2025 15:12:18 -0800 Subject: [PATCH 118/129] Update .github/workflows/regression.yml --- .github/workflows/regression.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index e3340aba167..2502204b64c 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -209,7 +209,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2:240320-1536 with: # -t -c - args: -b ${{github.ref}} -t design_pipe -c develop -s ${{matrix.testscript}} + args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2:240320-1536 with: From 844d5316f5bb848d9e17eae955ecb870c0b7ed16 Mon Sep 17 00:00:00 2001 From: vdweide Date: Mon, 3 Feb 2025 10:05:28 +0100 Subject: [PATCH 119/129] The reading of CGNS files for the FEM solver done via the meshreader classes --- Common/include/fem/fem_cgns_elements.hpp | 198 --- Common/include/fem/fem_geometry_structure.hpp | 3 - Common/include/geometry/CPhysicalGeometry.hpp | 11 - .../geometry/meshreader/CCGNSElementType.hpp | 425 +++++ .../meshreader/CCGNSMeshReaderFEM.hpp | 100 ++ .../meshreader/CCGNSMeshReaderFVM.hpp | 4 +- .../geometry/meshreader/CMeshReaderBase.hpp | 40 +- Common/src/fem/fem_cgns_elements.cpp | 1578 ----------------- .../src/fem/geometry_structure_fem_part.cpp | 1064 ----------- Common/src/fem/meson.build | 3 +- Common/src/geometry/CPhysicalGeometry.cpp | 4 +- .../geometry/meshreader/CCGNSElementType.cpp | 840 +++++++++ .../meshreader/CCGNSMeshReaderFEM.cpp | 550 ++++++ .../geometry/meshreader/CMeshReaderBase.cpp | 70 + Common/src/geometry/meshreader/meson.build | 2 + 15 files changed, 2032 insertions(+), 2860 deletions(-) delete mode 100644 Common/include/fem/fem_cgns_elements.hpp create mode 100644 Common/include/geometry/meshreader/CCGNSElementType.hpp create mode 100644 Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp delete mode 100644 Common/src/fem/fem_cgns_elements.cpp create mode 100644 Common/src/geometry/meshreader/CCGNSElementType.cpp create mode 100644 Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp diff --git a/Common/include/fem/fem_cgns_elements.hpp b/Common/include/fem/fem_cgns_elements.hpp deleted file mode 100644 index f3debaeb0ea..00000000000 --- a/Common/include/fem/fem_cgns_elements.hpp +++ /dev/null @@ -1,198 +0,0 @@ -/*! - * \file fem_cgns_elements.hpp - * \brief Headers of the classes and functions for reading CGNS files - * with high order elements. - * The functions are in the cgns_elements.cpp file. - * \author E. van der Weide - * \version 8.1.0 "Harrier" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#pragma once - -#include "../parallelization/mpi_structure.hpp" - -#ifdef HAVE_CGNS -#include "cgnslib.h" -#endif - -#include "../geometry/primal_grid/CPrimalGridFEM.hpp" - -/* Forward declaration of CBoundaryFace to avoid problems. */ -class CBoundaryFace; - -#ifdef HAVE_CGNS -#if CGNS_VERSION >= 3300 - -/*! - * \class CCGNSElementType - * \brief Class which stores the CGNS element type info for a connectivity section. - */ - -class CCGNSElementType { - public: - int connID; /*!< \brief CGNS connectivity ID of this connectivity. */ - ElementType_t elemType; /*!< \brief Element type according to the CGNS convention, - possibly MIXED. */ - cgsize_t indBeg; /*!< \brief Index of the first element in the CGNS connectivity. */ - cgsize_t indEnd; /*!< \brief Index of the last element in the CGNS connectivity. */ - cgsize_t nElem; /*!< \brief Number of elements present for this element type. */ - - std::string connName; /*!< \brief Name of this connectivity. */ - - bool volumeConn; /*!< \brief Whether or not this is a volume connectivity. */ - bool surfaceConn; /*!< \brief Whether or not this is a surface connectivity. */ - - /* Standard constructor, nothing to be done. */ - CCGNSElementType() {} - - /* Destructor, nothing to be done. */ - ~CCGNSElementType() {} - - /*--- Member function, which determines the meta data for this element type. ---*/ - void DetermineMetaData(const unsigned short nDim, const int fn, const int iBase, const int iZone, const int iConn); - - /*--- Member function, which reads the required boundary connectivity range. ---*/ - void ReadBoundaryConnectivityRange(const int fn, const int iBase, const int iZone, const unsigned long offsetRank, - const unsigned long nBoundElemRank, const unsigned long startingBoundElemIDRank, - unsigned long& locBoundElemCount, std::vector& boundElems); - - /*--- Member function, which reads the required connectivity range. ---*/ - void ReadConnectivityRange(const int fn, const int iBase, const int iZone, const unsigned long offsetRank, - const unsigned long nElemRank, const unsigned long startingElemIDRank, CPrimalGrid**& elem, - unsigned long& locElemCount, unsigned long& nDOFsLoc); - - private: - /*--- Member function, which creates the required data for the given - element type. ---*/ - void CreateDataElementType(const ElementType_t typeElem, unsigned short& VTK_Type, unsigned short& nPoly, - unsigned short& nDOFs, std::vector& SU2ToCGNS); - - /*--- Member function, which determines the element dimension, i.e. the - number of parametric coordinates. ---*/ - unsigned short DetermineElementDimension(const int fn, const int iBase, const int iZone); - - /*--- Member function, which determines the element dimension when the - connectivity is mixed. ---*/ - unsigned short DetermineElementDimensionMixed(const int fn, const int iBase, const int iZone); - - /*--- Member function, which determines the corresponding index of the - given element in the stored types. If not present, a new index - is created. ---*/ - unsigned short IndexInStoredTypes(const ElementType_t typeElem, std::vector& CGNS_Type, - std::vector& VTK_Type, std::vector& nPoly, - std::vector& nDOFs, - std::vector >& SU2ToCGNS); - - /*--- Functions to create the conversion data from CGNS format to SU2 format - for all the supported CGNS elements. ---*/ - void CreateDataNODE(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataBAR_2(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataBAR_3(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataBAR_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataBAR_5(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataTRI_3(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataTRI_6(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataTRI_10(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataTRI_15(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataQUAD_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataQUAD_9(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataQUAD_16(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataQUAD_25(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataTETRA_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataTETRA_10(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataTETRA_20(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataTETRA_35(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataPYRA_5(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataPYRA_14(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataPYRA_30(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataPYRA_55(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataPENTA_6(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataPENTA_18(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataPENTA_40(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataPENTA_75(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataHEXA_8(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataHEXA_27(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataHEXA_64(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); - - void CreateDataHEXA_125(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - std::vector& SU2ToCGNS); -}; -#endif -#endif - -using namespace std; diff --git a/Common/include/fem/fem_geometry_structure.hpp b/Common/include/fem/fem_geometry_structure.hpp index 4d3e9cc367d..ab4cc457f40 100644 --- a/Common/include/fem/fem_geometry_structure.hpp +++ b/Common/include/fem/fem_geometry_structure.hpp @@ -30,9 +30,6 @@ #include "../geometry/CGeometry.hpp" #include "fem_standard_element.hpp" -#ifdef HAVE_CGNS -#include "fem_cgns_elements.hpp" -#endif #include "../wall_model.hpp" #include "../linear_algebra/blas_structure.hpp" diff --git a/Common/include/geometry/CPhysicalGeometry.hpp b/Common/include/geometry/CPhysicalGeometry.hpp index a474dcbddd6..b20b2991566 100644 --- a/Common/include/geometry/CPhysicalGeometry.hpp +++ b/Common/include/geometry/CPhysicalGeometry.hpp @@ -299,17 +299,6 @@ class CPhysicalGeometry final : public CGeometry { void Read_SU2_Format_Parallel_FEM(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, unsigned short val_nZone); - /*! - * \brief Reads for the FEM solver the geometry of the grid and adjust the boundary - * conditions with the configuration file in parallel (for parmetis). - * \param[in] config - Definition of the particular problem. - * \param[in] val_mesh_filename - Name of the file with the grid information. - * \param[in] val_iZone - Domain to be read from the grid file. - * \param[in] val_nZone - Total number of domains in the grid file. - */ - void Read_CGNS_Format_Parallel_FEM(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, - unsigned short val_nZone); - /*! * \brief Routine to load the CGNS grid points from a single zone into the proper SU2 data structures. * \param[in] config - definition of the particular problem. diff --git a/Common/include/geometry/meshreader/CCGNSElementType.hpp b/Common/include/geometry/meshreader/CCGNSElementType.hpp new file mode 100644 index 00000000000..e081347be1b --- /dev/null +++ b/Common/include/geometry/meshreader/CCGNSElementType.hpp @@ -0,0 +1,425 @@ +/*! + * \file CCGNSElementType.hpp + * \brief Header file for the class CCGNSElementType. + * The implementations are in the CCGNSElementType.cpp file. + * \author E. van der Weide + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include + +#ifdef HAVE_CGNS +#include "cgnslib.h" +#endif + +#ifdef HAVE_CGNS + +using namespace std; + +/*! + * \class CCGNSElementType + * \brief Class used to convert the CGNS format to SU2 format for high order elements. +* \author: E. van der Weide + */ +class CCGNSElementType { +private: + + vector CGNSTypeStored; /*!< \brief CGNS element types for which the data is stored. */ + vector VTKTypeStored; /*!< \brief VTK type of the element. */ + vector nPolyStored; /*!< \brief Polynomial degree of the element. */ + vector nDOFsStored; /*!< \brief Number of DOFs of the element. */ + vector > SU2ToCGNSStored; /*!< \brief Double vector, which stores the conversion + from SU2 to CGNS for the type in local numbering. */ +public: + + /*--- Standard constructor, nothing to be done. ---*/ + CCGNSElementType() = default; + + /*--- Destructor, nothing to be done. ---*/ + ~CCGNSElementType() = default; + + /*! + * \brief Converts the connectivity information from CGNS to SU2 format. + * \param[in] val_elemType - CGNS elements type to be converted. + * \param[in] val_globalID - Global ID of this element. + * \param[in] connCGNS - Array with the connectivity of the element in CGNS format. + * \param[out] connSU2 - Vector with the connectivity and meta data in SU2 format. + */ + void CGNSToSU2(const ElementType_t val_elemType, + const unsigned long val_globalID, + const cgsize_t *connCGNS, + std::vector &connSU2); + +private: + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a node. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataNODE(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Bar2 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataBAR_2(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Bar3 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataBAR_3(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Bar4 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataBAR_4(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Bar5 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataBAR_5(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Tri3 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataTRI_3(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Tri6 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataTRI_6(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Tri10 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataTRI_10(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Tri15 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataTRI_15(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Quad4 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataQUAD_4(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Quad9 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataQUAD_9(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Quad16 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataQUAD_16(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Quad25 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataQUAD_25(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Tetra4 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataTETRA_4(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Tetra10 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataTETRA_10(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Tetra20 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataTETRA_20(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Tetra35 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataTETRA_35(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Pyra5 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataPYRA_5(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Pyra14 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataPYRA_14(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Pyra30 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataPYRA_30(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Pyra55 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataPYRA_55(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Penta6 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataPENTA_6(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Penta18 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataPENTA_18(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Penta40 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataPENTA_40(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Penta75 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataPENTA_75(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Hexa8 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataHEXA_8(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Hexa27 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataHEXA_27(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Hexa64 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataHEXA_64(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); + + /*! + * \brief Converts the connectivity from CGNS to SU2 for a Hexa125 element. + * \param[out] VTK_Type - Corresponding VTK type + * \param[out] nPoly - Polynomial degree + * \param[out] nDOFs - Number of DOFs of the element. + * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. + */ + void CreateDataHEXA_125(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS); +}; +#endif diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp new file mode 100644 index 00000000000..dfd8aa7c680 --- /dev/null +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp @@ -0,0 +1,100 @@ +/*! + * \file CCGNSMeshReaderFEM.hpp + * \brief Header file for the class CCGNSMeshReaderFEM. + * The implementations are in the CCGNSMeshReaderFEM.cpp file. + * \author T. Economon + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include "CCGNSMeshReaderBase.hpp" + +/*! + * \class CCGNSMeshReaderFEM + * \brief Reads a CGNS zone into linear partitions for the finite element solver (FEM). + * \author: T. Economon + */ +class CCGNSMeshReaderFEM final : public CCGNSMeshReaderBase { + private: + + /*! + * \brief Communicates the grid points to the MPI rank where they are needed. + */ + void CommPointCoordinates(); + +#ifdef HAVE_CGNS + + /*! + * \brief Reads the connectivity range from a CGNS section and convert it to the internal format. + * \param[in] val_section - CGNS section index. + * \param[in] val_firstIndex - Global index of the first element to be stored on this rank. + * \param[in] val_lastIndex - Global index of the last element (not included) to be stored on this rank. + * \param[inout] elemCount - Counter, which keeps track how many global elements are stored. + * \param[inout] localElemCount - Counter, which keeps track how many local elements are stored. + * \param[inout] localConn - Vector where the connectivity must be stored. + */ + void ReadCGNSConnectivityRangeSection(const int val_section, + const unsigned long val_firstIndex, + const unsigned long val_lastIndex, + unsigned long &elemCount, + unsigned long &localElemCount, + vector &localConn); + +/*! + * \brief Reads the interior volume elements from one section of a CGNS zone into linear partitions across all ranks. + */ + void ReadCGNSVolumeElementConnectivity(); + + /*! + * \brief Reads the surface (boundary) elements from one section of a CGNS zone into linear partitions across all ranks. + */ + void ReadCGNSSurfaceElementConnectivity(); + + /*! + * \brief Reads the connectivity from a CGNS surface section and select the relevant faces. + * \param[in] val_section - CGNS section index. + * \param[in] localFaces - The faces of the locally stored volume elements. + * \param[out] nSurfElem - Number of local surface elements stored for this surface section. + * \param[out] surfConn - Vector to store the connectivity of the surface elements to be stored. + */ + void ReadCGNSSurfaceSection(const int val_section, + const vector &localFaces, + unsigned long &nSurfElem, + vector &surfConn); +#endif + + public: + + /*! + * \brief Constructor of the CCGNSMeshReaderFEM class. + */ + CCGNSMeshReaderFEM(CConfig *val_config, + unsigned short val_iZone, + unsigned short val_nZone); + + /*! + * \brief Destructor of the CCGNSMeshReaderFEM class. + */ + ~CCGNSMeshReaderFEM(void); +}; diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp index 4edb6cbf27c..8e7770c973a 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp @@ -35,7 +35,7 @@ * \brief Reads a CGNS zone into linear partitions for the finite volume solver (FVM). * \author: T. Economon */ -class CCGNSMeshReaderFVM : public CCGNSMeshReaderBase { +class CCGNSMeshReaderFVM final : public CCGNSMeshReaderBase { private: #ifdef HAVE_CGNS /*! @@ -96,5 +96,5 @@ class CCGNSMeshReaderFVM : public CCGNSMeshReaderBase { /*! * \brief Destructor of the CCGNSMeshReaderFVM class. */ - ~CCGNSMeshReaderFVM(void) override; + ~CCGNSMeshReaderFVM(void); }; diff --git a/Common/include/geometry/meshreader/CMeshReaderBase.hpp b/Common/include/geometry/meshreader/CMeshReaderBase.hpp index 6b81a4a16f8..da3f72c48cc 100644 --- a/Common/include/geometry/meshreader/CMeshReaderBase.hpp +++ b/Common/include/geometry/meshreader/CMeshReaderBase.hpp @@ -31,6 +31,8 @@ #include +#include "../primal_grid/CPrimalGridFEM.hpp" +#include "../../fem/geometry_structure_fem_part.hpp" #include "../../parallelization/mpi_structure.hpp" #include "../../CConfig.hpp" @@ -54,6 +56,7 @@ class CMeshReaderBase { vector > localPointCoordinates; /*!< \brief Vector holding the coordinates from the mesh file for the local grid points. First index is dimension, second is point index. */ + vector globalPointIDs; /*!< \brief Vector holding the global IDs of the local grid points. */ unsigned long numberOfLocalElements = 0; /*!< \brief Number of local elements within the linear partition on this rank. */ @@ -63,9 +66,28 @@ class CMeshReaderBase { unsigned long numberOfMarkers = 0; /*!< \brief Total number of markers contained within the mesh file. */ vector markerNames; /*!< \brief String names for all markers in the mesh file. */ + vector numberOfLocalSurfaceElements; /*!< \brief Vector containing the number of local surface elements. */ vector > surfaceElementConnectivity; /*!< \brief Vector containing the surface element connectivity from the mesh file on a - per-marker basis. Only the master node reads and stores this connectivity. */ + per-marker basis. For FVM, only the master node reads and stores this connectivity. */ + + /*! + * \brief Function, which determines the faces of the local volume elements. + * \param[out] localFaces - The faces of the locally stored volume elements. + */ + void DetermineFacesVolumeElements(vector &localFaces); + + /*! + * \brief Get all the corner points of all the faces of the given element. It must + * \param[in] elemInfo - Array, which contains the info of the given element. + * \param[out] nFaces - Number of faces of the element. + * \param[out] nPointsPerFace - Number of corner points for each of the faces. + * \param[out] faceConn - Global IDs of the corner points of the faces. + */ + void GetCornerPointsAllFaces(const unsigned long *elemInfo, + unsigned short &numFaces, + unsigned short nPointsPerFace[], + unsigned long faceConn[6][4]); public: /*! @@ -84,6 +106,14 @@ class CMeshReaderBase { */ inline unsigned short GetDimension() const { return dimension; } + /*! + * \brief Get the global IDs of the local points. + * \returns Reference to the vector containing the global points IDs. + */ + inline const vector &GetGlobalPointIDs() const { + return globalPointIDs; + } + /*! * \brief Get the local point coordinates (linearly partitioned). * \returns Local point coordinates (linear partitioned). @@ -99,6 +129,14 @@ class CMeshReaderBase { return surfaceElementConnectivity[val_iMarker]; } + /*! + * \brief Get the number surface elements for all markers. + * \returns Reference to the vector containing the number of surface elements for all markers. + */ + inline const vector &GetNumberOfSurfaceElementsAllMarkers() const { + return numberOfLocalSurfaceElements; + } + /*! * \brief Get the number surface elements for the specified marker. * \param[in] val_iMarker - current marker index. diff --git a/Common/src/fem/fem_cgns_elements.cpp b/Common/src/fem/fem_cgns_elements.cpp deleted file mode 100644 index e4df7f0393b..00000000000 --- a/Common/src/fem/fem_cgns_elements.cpp +++ /dev/null @@ -1,1578 +0,0 @@ -/*! - * \file fem_cgns_elements.cpp - * \brief CGNS element definitions and conversions to the SU2 standard. - * \author E. van der Weide - * \version 8.1.0 "Harrier" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#ifdef HAVE_CGNS -#include "../../include/fem/fem_cgns_elements.hpp" -#include "../../include/fem/geometry_structure_fem_part.hpp" -#include "../../include/parallelization/mpi_structure.hpp" - -#include -#include -#include - -using namespace std; - -#if CGNS_VERSION >= 3300 - -void CCGNSElementType::DetermineMetaData(const unsigned short nDim, const int fn, const int iBase, const int iZone, - const int iConn) { - /* Store the connectivity ID. */ - connID = iConn; - - /* Read the element type and range from the CGNS file. */ - char cgnsname[CGNS_STRING_SIZE]; - int nBndry, parentFlag; - if (cg_section_read(fn, iBase, iZone, iConn, cgnsname, &elemType, &indBeg, &indEnd, &nBndry, &parentFlag) != CG_OK) - cg_error_exit(); - - /* Store the name of this connectivity. */ - connName = cgnsname; - - /* Determine the number of elements present in this connectivity section. */ - nElem = indEnd - indBeg + 1; - - /* Determine the dimension of this element type, i.e. the number of - parametric coordinates and conclude whether or not this is a volume or - surface connectivity. Note that it is possible that it is neither of these, - e.g. line elements for 3D. This information is not needed for the DG - flow solver and is therefore ignored. */ - const unsigned short nDimElem = DetermineElementDimension(fn, iBase, iZone); - volumeConn = (nDimElem == nDim); - surfaceConn = (nDimElem == nDim - 1); -} - -void CCGNSElementType::ReadBoundaryConnectivityRange(const int fn, const int iBase, const int iZone, - const unsigned long offsetRank, const unsigned long nBoundElemRank, - const unsigned long startingBoundElemIDRank, - unsigned long& locBoundElemCount, - vector& boundElems) { - /* Determine the index range to be read for this rank. */ - const cgsize_t iBeg = indBeg + offsetRank; - const cgsize_t iEnd = iBeg + nBoundElemRank - 1; - - /* Determine the size of the vector needed to read the connectivity - data from the CGNS file. */ - cgsize_t sizeNeeded; - if (cg_ElementPartialSize(fn, iBase, iZone, connID, iBeg, iEnd, &sizeNeeded) != CG_OK) cg_error_exit(); - - /* Allocate the memory for the connectivity and read the data. */ - vector connCGNSVec(sizeNeeded); - if (elemType == MIXED) { - vector connCGNSOffsetVec(iEnd - iBeg + 2); - if (cg_poly_elements_partial_read(fn, iBase, iZone, connID, iBeg, iEnd, connCGNSVec.data(), - connCGNSOffsetVec.data(), nullptr) != CG_OK) - cg_error_exit(); - } else { - if (cg_elements_partial_read(fn, iBase, iZone, connID, iBeg, iEnd, connCGNSVec.data(), nullptr) != CG_OK) - cg_error_exit(); - } - - /* Define the variables needed to convert the connectivities from CGNS to - SU2 format. Note that the vectors are needed to support a connectivity - section with mixed element types. */ - vector CGNS_Type; - vector VTK_Type; - vector nPoly; - vector nDOFs; - - vector > SU2ToCGNS; - - /* Definition of variables used in the loop below. */ - cgsize_t* connCGNS = connCGNSVec.data(); - ElementType_t typeElem = elemType; - vector connSU2; - - /* Loop over the elements just read. */ - for (unsigned long i = 0; i < nBoundElemRank; ++i, ++locBoundElemCount) { - /* Determine the element type for this element if this is a mixed - connectivity and set the pointer to the actual connectivity data. */ - if (elemType == MIXED) { - typeElem = (ElementType_t)connCGNS[0]; - ++connCGNS; - } - - /* Determine the index in the stored vectors (CGNS_Type, VTK_Type, etc), - which corresponds to this element. If the type is not stored yet, - a new entry in these vectors will be created. */ - const unsigned short ind = IndexInStoredTypes(typeElem, CGNS_Type, VTK_Type, nPoly, nDOFs, SU2ToCGNS); - - /* Resize the connSU2 vector to the appropriate size. */ - connSU2.resize(nDOFs[ind]); - - /* Create the connectivity used in SU2 by carrying out the renumbering. - Note that in CGNS the numbering starts at 1, while in SU2 it starts - at 0. This explains the addition of -1. */ - for (unsigned short j = 0; j < nDOFs[ind]; ++j) connSU2[j] = connCGNS[SU2ToCGNS[ind][j]] - 1; - - /* Set the pointer for connCGNS for the data of the next element. */ - connCGNS += nDOFs[ind]; - - /* Determine the global boundary element ID of this element. */ - const unsigned long globBoundElemID = startingBoundElemIDRank + locBoundElemCount; - - /* Create an object of CBoundaryFace and store it in boundElems. - Note that the corresponding domain element is not known yet and - is therefore set to ULONG_MAX. */ - CBoundaryFace thisBoundFace; - thisBoundFace.VTK_Type = VTK_Type[ind]; - thisBoundFace.nPolyGrid = nPoly[ind]; - thisBoundFace.nDOFsGrid = nDOFs[ind]; - thisBoundFace.globalBoundElemID = globBoundElemID; - thisBoundFace.domainElementID = ULONG_MAX; - thisBoundFace.Nodes = connSU2; - - boundElems.push_back(thisBoundFace); - } -} - -void CCGNSElementType::ReadConnectivityRange(const int fn, const int iBase, const int iZone, - const unsigned long offsetRank, const unsigned long nElemRank, - const unsigned long startingElemIDRank, CPrimalGrid**& elem, - unsigned long& locElemCount, unsigned long& nDOFsLoc) { - /* Determine the index range to be read for this rank. */ - const cgsize_t iBeg = indBeg + offsetRank; - const cgsize_t iEnd = iBeg + nElemRank - 1; - - /* Determine the size of the vector needed to read the connectivity - data from the CGNS file. */ - cgsize_t sizeNeeded; - if (cg_ElementPartialSize(fn, iBase, iZone, connID, iBeg, iEnd, &sizeNeeded) != CG_OK) cg_error_exit(); - - /* Allocate the memory for the connectivity and read the data. */ - vector connCGNSVec(sizeNeeded); - if (elemType == MIXED) { - vector connCGNSOffsetVec(iEnd - iBeg + 2); - if (cg_poly_elements_partial_read(fn, iBase, iZone, connID, iBeg, iEnd, connCGNSVec.data(), - connCGNSOffsetVec.data(), nullptr) != CG_OK) - cg_error_exit(); - - } else { - if (cg_elements_partial_read(fn, iBase, iZone, connID, iBeg, iEnd, connCGNSVec.data(), nullptr) != CG_OK) - cg_error_exit(); - } - - /* Define the variables needed to convert the connectivities from CGNS to - SU2 format. Note that the vectors are needed to support a connectivity - section with mixed element types. */ - vector CGNS_Type; - vector VTK_Type; - vector nPoly; - vector nDOFs; - - vector > SU2ToCGNS; - - /* Definition of variables used in the loop below. */ - cgsize_t* connCGNS = connCGNSVec.data(); - ElementType_t typeElem = elemType; - vector connSU2; - - /* Loop over the elements just read. */ - for (unsigned long i = 0; i < nElemRank; ++i, ++locElemCount) { - /* Determine the element type for this element if this is a mixed - connectivity and set the pointer to the actual connectivity data. */ - if (elemType == MIXED) { - typeElem = (ElementType_t)connCGNS[0]; - ++connCGNS; - } - - /* Determine the index in the stored vectors (CGNS_Type, VTK_Type, etc), - which corresponds to this element. If the type is not stored yet, - a new entry in these vectors will be created. */ - const unsigned short ind = IndexInStoredTypes(typeElem, CGNS_Type, VTK_Type, nPoly, nDOFs, SU2ToCGNS); - - /* Resize the connSU2 vector to the appropriate size. */ - connSU2.resize(nDOFs[ind]); - - /* Create the connectivity used in SU2 by carrying out the renumbering. - Note that in CGNS the numbering starts at 1, while in SU2 it starts - at 0. This explains the addition of -1. */ - for (unsigned short j = 0; j < nDOFs[ind]; ++j) connSU2[j] = connCGNS[SU2ToCGNS[ind][j]] - 1; - - /* Set the pointer for connCGNS for the data of the next element. */ - connCGNS += nDOFs[ind]; - - /* Determine the global element ID of this element. */ - const unsigned long globElemID = startingElemIDRank + locElemCount; - - /* Create a new FEM primal grid element, which stores the required - information. Note that the second to last argument contains the local - offset of the DOFs. This will be corrected to the global offset - afterwards in CPhysicalGeometry::Read_CGNS_Format_Parallel_FEM. - Also note that in CGNS it is not possible (at least at the moment) - to specify a different polynomial degree for the grid and solution. */ - elem[locElemCount] = new CPrimalGridFEM(globElemID, VTK_Type[ind], nPoly[ind], nPoly[ind], nDOFs[ind], nDOFs[ind], - nDOFsLoc, connSU2.data()); - - /* Update the counter nDOFsLoc. */ - nDOFsLoc += nDOFs[ind]; - } -} - -unsigned short CCGNSElementType::DetermineElementDimension(const int fn, const int iBase, const int iZone) { - /*--- Determine the element type and return the appropriate element - dimension, i.e. the number of parametric coordinates needed to - describe the element. ---*/ - switch (elemType) { - case NODE: - return 0; - - case BAR_2: - case BAR_3: - case BAR_4: - case BAR_5: - return 1; - - case TRI_3: - case TRI_6: - case TRI_9: - case TRI_10: - case TRI_12: - case TRI_15: - case QUAD_4: - case QUAD_8: - case QUAD_9: - case QUAD_12: - case QUAD_16: - case QUAD_P4_16: - case QUAD_25: - return 2; - - case TETRA_4: - case TETRA_10: - case TETRA_16: - case TETRA_20: - case TETRA_22: - case TETRA_34: - case TETRA_35: - case PYRA_5: - case PYRA_14: - case PYRA_13: - case PYRA_21: - case PYRA_29: - case PYRA_30: - case PYRA_P4_29: - case PYRA_50: - case PYRA_55: - case PENTA_6: - case PENTA_15: - case PENTA_18: - case PENTA_24: - case PENTA_38: - case PENTA_40: - case PENTA_33: - case PENTA_66: - case PENTA_75: - case HEXA_8: - case HEXA_20: - case HEXA_27: - case HEXA_32: - case HEXA_56: - case HEXA_64: - case HEXA_44: - case HEXA_98: - case HEXA_125: - return 3; - - case MIXED: - return DetermineElementDimensionMixed(fn, iBase, iZone); - - default: - ostringstream message; - message << "Unsupported CGNS element type, " << elemType << ", encountered."; - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } - - /* Just return a value to avoid a compiler warning. The program should - never reach this position. */ - return 0; -} - -unsigned short CCGNSElementType::DetermineElementDimensionMixed(const int fn, const int iBase, const int iZone) { - /* Determine the required size of the vector to read the - data of the first element of this connectivity. */ - cgsize_t sizeNeeded; - if (cg_ElementPartialSize(fn, iBase, iZone, connID, indBeg, indBeg, &sizeNeeded) != CG_OK) cg_error_exit(); - - /* Read the data of the first element in this section. */ - vector buf(sizeNeeded); - vector buf_offset(2, 0); - if (cg_poly_elements_partial_read(fn, iBase, iZone, connID, indBeg, indBeg, buf.data(), buf_offset.data(), nullptr) != - CG_OK) - cg_error_exit(); - - /* The first entry of buf contains the element type. Copy this value - temporarily into the member variable elemType and determine the - element dimension of this element. */ - elemType = (ElementType_t)buf[0]; - - unsigned short nDimElem = DetermineElementDimension(fn, iBase, iZone); - - /* Reset the element type to MIXED and return the element dimension. */ - elemType = MIXED; - return nDimElem; -} - -unsigned short CCGNSElementType::IndexInStoredTypes(const ElementType_t typeElem, vector& CGNS_Type, - vector& VTK_Type, vector& nPoly, - vector& nDOFs, - vector >& SU2ToCGNS) { - /* Loop over the available types and check if the current type is present. - If so, break the loop, such that the correct index is stored. */ - unsigned short ind; - for (ind = 0; ind < CGNS_Type.size(); ++ind) - if (typeElem == CGNS_Type[ind]) break; - - /* If the current element type is not present yet, the data for this - type must be created. */ - if (ind == CGNS_Type.size()) { - unsigned short VTKElem, nPolyElem, nDOFsElem; - vector SU2ToCGNSElem; - CreateDataElementType(typeElem, VTKElem, nPolyElem, nDOFsElem, SU2ToCGNSElem); - - CGNS_Type.push_back(typeElem); - VTK_Type.push_back(VTKElem); - nPoly.push_back(nPolyElem); - nDOFs.push_back(nDOFsElem); - SU2ToCGNS.push_back(SU2ToCGNSElem); - } - - /* Return the index. */ - return ind; -} - -void CCGNSElementType::CreateDataElementType(const ElementType_t typeElem, unsigned short& VTK_Type, - unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /*--- Determine the element type and call the corresponding function - to determine the actual data. ---*/ - switch (typeElem) { - case NODE: - CreateDataNODE(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case BAR_2: - CreateDataBAR_2(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case BAR_3: - CreateDataBAR_3(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case BAR_4: - CreateDataBAR_4(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case BAR_5: - CreateDataBAR_5(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case TRI_3: - CreateDataTRI_3(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case TRI_6: - CreateDataTRI_6(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case TRI_10: - CreateDataTRI_10(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case TRI_15: - CreateDataTRI_15(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case QUAD_4: - CreateDataQUAD_4(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case QUAD_9: - CreateDataQUAD_9(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case QUAD_16: - CreateDataQUAD_16(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case QUAD_25: - CreateDataQUAD_25(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case TETRA_4: - CreateDataTETRA_4(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case TETRA_10: - CreateDataTETRA_10(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case TETRA_20: - CreateDataTETRA_20(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case TETRA_35: - CreateDataTETRA_35(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case PYRA_5: - CreateDataPYRA_5(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case PYRA_14: - CreateDataPYRA_14(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case PYRA_30: - CreateDataPYRA_30(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case PYRA_55: - CreateDataPYRA_55(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case PENTA_6: - CreateDataPENTA_6(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case PENTA_18: - CreateDataPENTA_18(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case PENTA_40: - CreateDataPENTA_40(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case PENTA_75: - CreateDataPENTA_75(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case HEXA_8: - CreateDataHEXA_8(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case HEXA_27: - CreateDataHEXA_27(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case HEXA_64: - CreateDataHEXA_64(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - case HEXA_125: - CreateDataHEXA_125(VTK_Type, nPoly, nDOFs, SU2ToCGNS); - break; - - default: - /* Print an error message that this element type is not supported and exit. */ - ostringstream message; - message << "CGNS element type " << typeElem << " not supported."; - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } -} - -/*------------------------------------------------------------------------*/ -/*--- Below this line there are only the conversion routines between ---*/ -/*--- CGNS and SU2 format for the specific elements. ---*/ -/*------------------------------------------------------------------------*/ - -void CCGNSElementType::CreateDataNODE(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* Set the required data for a NODE. */ - VTK_Type = VERTEX; - nPoly = 0; - nDOFs = 1; - SU2ToCGNS.push_back(0); -} - -void CCGNSElementType::CreateDataBAR_2(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The BAR_2 element is a linear element. The numbering of the nodes is - the same for CGNS and SU2. */ - VTK_Type = LINE; - nPoly = 1; - nDOFs = 2; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 1; -} - -void CCGNSElementType::CreateDataBAR_3(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The BAR_3 element is a quadratic element. SU2 numbers to nodes with - increasing parametric value, while in CGNS the internal node is - numbered last. */ - VTK_Type = LINE; - nPoly = 2; - nDOFs = 3; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 2; - SU2ToCGNS[2] = 1; -} - -void CCGNSElementType::CreateDataBAR_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The BAR_4 element is a cubic element. SU2 numbers to nodes with - increasing parametric value, while in CGNS the internal nodes are - numbered last. */ - VTK_Type = LINE; - nPoly = 3; - nDOFs = 4; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 2; - SU2ToCGNS[2] = 3; - SU2ToCGNS[3] = 1; -} - -void CCGNSElementType::CreateDataBAR_5(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The BAR_5 element is a quartic element. SU2 numbers to nodes with - increasing parametric value, while in CGNS the internal nodes are - numbered last. */ - VTK_Type = LINE; - nPoly = 4; - nDOFs = 5; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 2; - SU2ToCGNS[2] = 3; - SU2ToCGNS[3] = 4; - SU2ToCGNS[4] = 1; -} - -void CCGNSElementType::CreateDataTRI_3(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The TRI_3 element is a linear triangle. The node numbering is the same - in SU2 and CGNS. */ - VTK_Type = TRIANGLE; - nPoly = 1; - nDOFs = 3; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 1; - SU2ToCGNS[2] = 2; -} - -void CCGNSElementType::CreateDataTRI_6(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The TRI_6 element is a quadratic triangle. In CGNS the nodes are numbered - as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes (not present for TRI_6). - In SU2 the node numbering takes place along increasing i- and j-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the other edge. */ - VTK_Type = TRIANGLE; - nPoly = 2; - nDOFs = 6; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 3; - SU2ToCGNS[2] = 1; - SU2ToCGNS[3] = 5; - SU2ToCGNS[4] = 4; - SU2ToCGNS[5] = 2; -} - -void CCGNSElementType::CreateDataTRI_10(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The TRI_10 element is a cubic triangle. In CGNS the nodes are numbered - as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - In SU2 the node numbering takes place along increasing i- and j-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the other edge. */ - VTK_Type = TRIANGLE; - nPoly = 3; - nDOFs = 10; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 3; - SU2ToCGNS[2] = 4; - SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 8; - SU2ToCGNS[5] = 9; - SU2ToCGNS[6] = 5; - SU2ToCGNS[7] = 7; - SU2ToCGNS[8] = 6; - SU2ToCGNS[9] = 2; -} - -void CCGNSElementType::CreateDataTRI_15(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The TRI_15 element is a quartic triangle. In CGNS the nodes are numbered - as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - In SU2 the node numbering takes place along increasing i- and j-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the other edge. - Also note that in the CGNS standard the face nodes are not placed at - the location for uniform spacing. This effect is currently ignored, - i.e. it is assumed that the spacing in parameter space is uniform. */ - VTK_Type = TRIANGLE; - nPoly = 4; - nDOFs = 15; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 3; - SU2ToCGNS[2] = 4; - SU2ToCGNS[3] = 5; - SU2ToCGNS[4] = 1; - SU2ToCGNS[5] = 11; - SU2ToCGNS[6] = 12; - SU2ToCGNS[7] = 13; - SU2ToCGNS[8] = 6; - SU2ToCGNS[9] = 10; - SU2ToCGNS[10] = 14; - SU2ToCGNS[11] = 7; - SU2ToCGNS[12] = 9; - SU2ToCGNS[13] = 8; - SU2ToCGNS[14] = 2; -} - -void CCGNSElementType::CreateDataQUAD_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The QUAD_4 element is a linear quadrilateral. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes (not present for QUAD_4). - - Third the face nodes (not present for QUAD_4). - In SU2 the node numbering takes place along increasing i- and j-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the other edge. */ - VTK_Type = QUADRILATERAL; - nPoly = 1; - nDOFs = 4; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 1; - SU2ToCGNS[2] = 3; - SU2ToCGNS[3] = 2; -} - -void CCGNSElementType::CreateDataQUAD_9(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The QUAD_9 element is a quadratic quadrilateral. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - In SU2 the node numbering takes place along increasing i- and j-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the other edge. */ - VTK_Type = QUADRILATERAL; - nPoly = 2; - nDOFs = 9; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 4; - SU2ToCGNS[2] = 1; - SU2ToCGNS[3] = 7; - SU2ToCGNS[4] = 8; - SU2ToCGNS[5] = 5; - SU2ToCGNS[6] = 3; - SU2ToCGNS[7] = 6; - SU2ToCGNS[8] = 2; -} - -void CCGNSElementType::CreateDataQUAD_16(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The QUAD_16 element is a cubic quadrilateral. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - In SU2 the node numbering takes place along increasing i- and j-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the other edge. */ - VTK_Type = QUADRILATERAL; - nPoly = 3; - nDOFs = 16; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 4; - SU2ToCGNS[2] = 5; - SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 11; - SU2ToCGNS[5] = 12; - SU2ToCGNS[6] = 13; - SU2ToCGNS[7] = 6; - SU2ToCGNS[8] = 10; - SU2ToCGNS[9] = 15; - SU2ToCGNS[10] = 14; - SU2ToCGNS[11] = 7; - SU2ToCGNS[12] = 3; - SU2ToCGNS[13] = 9; - SU2ToCGNS[14] = 8; - SU2ToCGNS[15] = 2; -} - -void CCGNSElementType::CreateDataQUAD_25(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The QUAD_25 element is a quartic quadrilateral. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - In SU2 the node numbering takes place along increasing i- and j-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the other edge. */ - VTK_Type = QUADRILATERAL; - nPoly = 4; - nDOFs = 25; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 4; - SU2ToCGNS[2] = 5; - SU2ToCGNS[3] = 6; - SU2ToCGNS[4] = 1; - SU2ToCGNS[5] = 15; - SU2ToCGNS[6] = 16; - SU2ToCGNS[7] = 17; - SU2ToCGNS[8] = 18; - SU2ToCGNS[9] = 7; - SU2ToCGNS[10] = 14; - SU2ToCGNS[11] = 23; - SU2ToCGNS[12] = 24; - SU2ToCGNS[13] = 19; - SU2ToCGNS[14] = 8; - SU2ToCGNS[15] = 13; - SU2ToCGNS[16] = 22; - SU2ToCGNS[17] = 21; - SU2ToCGNS[18] = 20; - SU2ToCGNS[19] = 9; - SU2ToCGNS[20] = 3; - SU2ToCGNS[21] = 12; - SU2ToCGNS[22] = 11; - SU2ToCGNS[23] = 10; - SU2ToCGNS[24] = 2; -} - -void CCGNSElementType::CreateDataTETRA_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The TETRA_4 element is a linear tetrahedron. The node numbering is - the same in SU2 and CGNS. */ - VTK_Type = TETRAHEDRON; - nPoly = 1; - nDOFs = 4; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 1; - SU2ToCGNS[2] = 2; - SU2ToCGNS[3] = 3; -} - -void CCGNSElementType::CreateDataTETRA_10(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The TETRA_10 element is a quadratic tetrahedron. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes (not present in TETRA_10). - - Fourth the volume nodes (not present in TETRA_10). - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = TETRAHEDRON; - nPoly = 2; - nDOFs = 10; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 4; - SU2ToCGNS[2] = 1; - SU2ToCGNS[3] = 6; - SU2ToCGNS[4] = 5; - SU2ToCGNS[5] = 2; - SU2ToCGNS[6] = 7; - SU2ToCGNS[7] = 8; - SU2ToCGNS[8] = 9; - SU2ToCGNS[9] = 3; -} - -void CCGNSElementType::CreateDataTETRA_20(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The TETRA_20 element is a cubic tetrahedron. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes (not present in TETRA_20). - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = TETRAHEDRON; - nPoly = 3; - nDOFs = 20; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 4; - SU2ToCGNS[2] = 5; - SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 9; - SU2ToCGNS[5] = 16; - SU2ToCGNS[6] = 6; - SU2ToCGNS[7] = 8; - SU2ToCGNS[8] = 7; - SU2ToCGNS[9] = 2; - SU2ToCGNS[10] = 10; - SU2ToCGNS[11] = 17; - SU2ToCGNS[12] = 12; - SU2ToCGNS[13] = 19; - SU2ToCGNS[14] = 18; - SU2ToCGNS[15] = 14; - SU2ToCGNS[16] = 11; - SU2ToCGNS[17] = 13; - SU2ToCGNS[18] = 15; - SU2ToCGNS[19] = 3; -} - -void CCGNSElementType::CreateDataTETRA_35(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The TETRA_35 element is a quartic tetrahedron. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes. - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. Also note that in the CGNS standard the face and volume - nodes are not placed at the location for uniform spacing. This effect is - currently ignored, i.e. it is assumed that the spacing in parameter space - is uniform. */ - VTK_Type = TETRAHEDRON; - nPoly = 4; - nDOFs = 35; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 4; - SU2ToCGNS[2] = 5; - SU2ToCGNS[3] = 6; - SU2ToCGNS[4] = 1; - SU2ToCGNS[5] = 12; - SU2ToCGNS[6] = 22; - SU2ToCGNS[7] = 23; - SU2ToCGNS[8] = 7; - SU2ToCGNS[9] = 11; - SU2ToCGNS[10] = 24; - SU2ToCGNS[11] = 8; - SU2ToCGNS[12] = 10; - SU2ToCGNS[13] = 9; - SU2ToCGNS[14] = 2; - SU2ToCGNS[15] = 13; - SU2ToCGNS[16] = 25; - SU2ToCGNS[17] = 26; - SU2ToCGNS[18] = 16; - SU2ToCGNS[19] = 32; - SU2ToCGNS[20] = 34; - SU2ToCGNS[21] = 28; - SU2ToCGNS[22] = 31; - SU2ToCGNS[23] = 29; - SU2ToCGNS[24] = 19; - SU2ToCGNS[25] = 14; - SU2ToCGNS[26] = 27; - SU2ToCGNS[27] = 17; - SU2ToCGNS[28] = 33; - SU2ToCGNS[29] = 30; - SU2ToCGNS[30] = 20; - SU2ToCGNS[31] = 15; - SU2ToCGNS[32] = 18; - SU2ToCGNS[33] = 21; - SU2ToCGNS[34] = 3; -} - -void CCGNSElementType::CreateDataPYRA_5(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The PYRA_5 element is a linear pyramid. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes (not present in PYRA_5). - - Third the face nodes (not present in PYRA_5). - - Fourth the volume nodes (not present in PYRA_5). - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = PYRAMID; - nPoly = 1; - nDOFs = 5; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 1; - SU2ToCGNS[2] = 3; - SU2ToCGNS[3] = 2; - SU2ToCGNS[4] = 4; -} - -void CCGNSElementType::CreateDataPYRA_14(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The PYRA_14 element is a quadratic pyramid. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes (not present in PYRA_14). - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = PYRAMID; - nPoly = 2; - nDOFs = 14; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 5; - SU2ToCGNS[2] = 1; - SU2ToCGNS[3] = 8; - SU2ToCGNS[4] = 13; - SU2ToCGNS[5] = 6; - SU2ToCGNS[6] = 3; - SU2ToCGNS[7] = 7; - SU2ToCGNS[8] = 2; - SU2ToCGNS[9] = 9; - SU2ToCGNS[10] = 10; - SU2ToCGNS[11] = 12; - SU2ToCGNS[12] = 11; - SU2ToCGNS[13] = 4; -} - -void CCGNSElementType::CreateDataPYRA_30(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The PYRA_30 element is a cubic pyramid. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes. - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = PYRAMID; - nPoly = 3; - nDOFs = 30; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 5; - SU2ToCGNS[2] = 6; - SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 12; - SU2ToCGNS[5] = 21; - SU2ToCGNS[6] = 22; - SU2ToCGNS[7] = 7; - SU2ToCGNS[8] = 11; - SU2ToCGNS[9] = 24; - SU2ToCGNS[10] = 23; - SU2ToCGNS[11] = 8; - SU2ToCGNS[12] = 3; - SU2ToCGNS[13] = 20; - SU2ToCGNS[14] = 9; - SU2ToCGNS[15] = 3; - SU2ToCGNS[16] = 13; - SU2ToCGNS[17] = 25; - SU2ToCGNS[18] = 15; - SU2ToCGNS[19] = 28; - SU2ToCGNS[20] = 29; - SU2ToCGNS[21] = 26; - SU2ToCGNS[22] = 19; - SU2ToCGNS[23] = 27; - SU2ToCGNS[24] = 17; - SU2ToCGNS[25] = 14; - SU2ToCGNS[26] = 16; - SU2ToCGNS[27] = 20; - SU2ToCGNS[28] = 18; - SU2ToCGNS[29] = 4; -} - -void CCGNSElementType::CreateDataPYRA_55(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The PYRA_55 element is a quartic pyramid. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes. - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. Also note that in the CGNS standard the triangular face - and volume nodes are not placed at the location for uniform spacing. This - effect is currently ignored, i.e. it is assumed that the spacing in - parameter space is uniform.*/ - VTK_Type = PYRAMID; - nPoly = 4; - nDOFs = 55; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 5; - SU2ToCGNS[2] = 6; - SU2ToCGNS[3] = 7; - SU2ToCGNS[4] = 1; - SU2ToCGNS[5] = 16; - SU2ToCGNS[6] = 29; - SU2ToCGNS[7] = 30; - SU2ToCGNS[8] = 31; - SU2ToCGNS[9] = 8; - SU2ToCGNS[10] = 15; - SU2ToCGNS[11] = 36; - SU2ToCGNS[12] = 37; - SU2ToCGNS[13] = 32; - SU2ToCGNS[14] = 9; - SU2ToCGNS[15] = 14; - SU2ToCGNS[16] = 35; - SU2ToCGNS[17] = 34; - SU2ToCGNS[18] = 33; - SU2ToCGNS[19] = 10; - SU2ToCGNS[20] = 3; - SU2ToCGNS[21] = 13; - SU2ToCGNS[22] = 12; - SU2ToCGNS[23] = 11; - SU2ToCGNS[24] = 2; - SU2ToCGNS[25] = 17; - SU2ToCGNS[26] = 38; - SU2ToCGNS[27] = 39; - SU2ToCGNS[28] = 20; - SU2ToCGNS[29] = 48; - SU2ToCGNS[30] = 50; - SU2ToCGNS[31] = 51; - SU2ToCGNS[32] = 41; - SU2ToCGNS[33] = 47; - SU2ToCGNS[34] = 53; - SU2ToCGNS[35] = 52; - SU2ToCGNS[36] = 42; - SU2ToCGNS[37] = 26; - SU2ToCGNS[38] = 45; - SU2ToCGNS[39] = 44; - SU2ToCGNS[40] = 23; - SU2ToCGNS[41] = 18; - SU2ToCGNS[42] = 40; - SU2ToCGNS[43] = 21; - SU2ToCGNS[44] = 49; - SU2ToCGNS[45] = 54; - SU2ToCGNS[46] = 43; - SU2ToCGNS[47] = 27; - SU2ToCGNS[48] = 46; - SU2ToCGNS[49] = 24; - SU2ToCGNS[50] = 19; - SU2ToCGNS[51] = 22; - SU2ToCGNS[52] = 28; - SU2ToCGNS[53] = 25; - SU2ToCGNS[54] = 4; -} - -void CCGNSElementType::CreateDataPENTA_6(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The PENTA_6 element is a linear prism. The node numbering is - the same in SU2 and CGNS. */ - VTK_Type = PRISM; - nPoly = 1; - nDOFs = 6; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 1; - SU2ToCGNS[2] = 2; - SU2ToCGNS[3] = 3; - SU2ToCGNS[4] = 4; - SU2ToCGNS[5] = 5; -} - -void CCGNSElementType::CreateDataPENTA_18(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The PENTA_18 element is a quadratic prism. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes (not present in PENTA_18). - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = PRISM; - nPoly = 2; - nDOFs = 18; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 6; - SU2ToCGNS[2] = 1; - SU2ToCGNS[3] = 8; - SU2ToCGNS[4] = 7; - SU2ToCGNS[5] = 2; - SU2ToCGNS[6] = 9; - SU2ToCGNS[7] = 15; - SU2ToCGNS[8] = 10; - SU2ToCGNS[9] = 17; - SU2ToCGNS[10] = 16; - SU2ToCGNS[11] = 11; - SU2ToCGNS[12] = 3; - SU2ToCGNS[13] = 12; - SU2ToCGNS[14] = 4; - SU2ToCGNS[15] = 14; - SU2ToCGNS[16] = 13; - SU2ToCGNS[17] = 5; -} - -void CCGNSElementType::CreateDataPENTA_40(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The PENTA_40 element is a cubic prism. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes. - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = PRISM; - nPoly = 3; - nDOFs = 40; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 6; - SU2ToCGNS[2] = 7; - SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 11; - SU2ToCGNS[5] = 24; - SU2ToCGNS[6] = 8; - SU2ToCGNS[7] = 10; - SU2ToCGNS[8] = 9; - SU2ToCGNS[9] = 2; - SU2ToCGNS[10] = 12; - SU2ToCGNS[11] = 25; - SU2ToCGNS[12] = 26; - SU2ToCGNS[13] = 14; - SU2ToCGNS[14] = 34; - SU2ToCGNS[15] = 38; - SU2ToCGNS[16] = 29; - SU2ToCGNS[17] = 33; - SU2ToCGNS[18] = 30; - SU2ToCGNS[19] = 16; - SU2ToCGNS[20] = 13; - SU2ToCGNS[21] = 28; - SU2ToCGNS[22] = 27; - SU2ToCGNS[23] = 15; - SU2ToCGNS[24] = 35; - SU2ToCGNS[25] = 39; - SU2ToCGNS[26] = 32; - SU2ToCGNS[27] = 36; - SU2ToCGNS[28] = 31; - SU2ToCGNS[29] = 17; - SU2ToCGNS[30] = 3; - SU2ToCGNS[31] = 18; - SU2ToCGNS[32] = 19; - SU2ToCGNS[33] = 4; - SU2ToCGNS[34] = 23; - SU2ToCGNS[35] = 37; - SU2ToCGNS[36] = 20; - SU2ToCGNS[37] = 22; - SU2ToCGNS[38] = 21; - SU2ToCGNS[39] = 5; -} - -void CCGNSElementType::CreateDataPENTA_75(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The PENTA_75 element is a quartic prism. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes. - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. Also note that in the CGNS standard the triangular face - and volume nodes are not placed at the location for uniform spacing. This - effect is currently ignored, i.e. it is assumed that the spacing in - parameter space is uniform. */ - VTK_Type = PRISM; - nPoly = 4; - nDOFs = 75; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 6; - SU2ToCGNS[2] = 7; - SU2ToCGNS[3] = 8; - SU2ToCGNS[4] = 1; - SU2ToCGNS[5] = 14; - SU2ToCGNS[6] = 33; - SU2ToCGNS[7] = 34; - SU2ToCGNS[8] = 9; - SU2ToCGNS[9] = 13; - SU2ToCGNS[10] = 35; - SU2ToCGNS[11] = 10; - SU2ToCGNS[12] = 12; - SU2ToCGNS[13] = 11; - SU2ToCGNS[14] = 2; - SU2ToCGNS[15] = 15; - SU2ToCGNS[16] = 36; - SU2ToCGNS[17] = 37; - SU2ToCGNS[18] = 38; - SU2ToCGNS[19] = 18; - SU2ToCGNS[20] = 56; - SU2ToCGNS[21] = 66; - SU2ToCGNS[22] = 67; - SU2ToCGNS[23] = 45; - SU2ToCGNS[24] = 55; - SU2ToCGNS[25] = 68; - SU2ToCGNS[26] = 46; - SU2ToCGNS[27] = 54; - SU2ToCGNS[28] = 47; - SU2ToCGNS[29] = 21; - SU2ToCGNS[30] = 16; - SU2ToCGNS[31] = 43; - SU2ToCGNS[32] = 44; - SU2ToCGNS[33] = 39; - SU2ToCGNS[34] = 19; - SU2ToCGNS[35] = 57; - SU2ToCGNS[36] = 69; - SU2ToCGNS[37] = 70; - SU2ToCGNS[38] = 52; - SU2ToCGNS[39] = 62; - SU2ToCGNS[40] = 71; - SU2ToCGNS[41] = 53; - SU2ToCGNS[42] = 61; - SU2ToCGNS[43] = 48; - SU2ToCGNS[44] = 22; - SU2ToCGNS[45] = 17; - SU2ToCGNS[46] = 42; - SU2ToCGNS[47] = 41; - SU2ToCGNS[48] = 40; - SU2ToCGNS[49] = 20; - SU2ToCGNS[50] = 58; - SU2ToCGNS[51] = 72; - SU2ToCGNS[52] = 73; - SU2ToCGNS[53] = 51; - SU2ToCGNS[54] = 59; - SU2ToCGNS[55] = 74; - SU2ToCGNS[56] = 50; - SU2ToCGNS[57] = 60; - SU2ToCGNS[58] = 49; - SU2ToCGNS[59] = 23; - SU2ToCGNS[60] = 3; - SU2ToCGNS[61] = 24; - SU2ToCGNS[62] = 25; - SU2ToCGNS[63] = 26; - SU2ToCGNS[64] = 4; - SU2ToCGNS[65] = 32; - SU2ToCGNS[66] = 63; - SU2ToCGNS[67] = 64; - SU2ToCGNS[68] = 27; - SU2ToCGNS[69] = 31; - SU2ToCGNS[70] = 65; - SU2ToCGNS[71] = 28; - SU2ToCGNS[72] = 30; - SU2ToCGNS[73] = 29; - SU2ToCGNS[74] = 5; -} - -void CCGNSElementType::CreateDataHEXA_8(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The HEXA_8 element is a linear hexahedron. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes (not present in HEXA_8). - - Third the face nodes (not present in HEXA_8). - - Fourth the volume nodes (not present in HEXA_8). - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = HEXAHEDRON; - nPoly = 1; - nDOFs = 8; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 1; - SU2ToCGNS[2] = 3; - SU2ToCGNS[3] = 2; - SU2ToCGNS[4] = 4; - SU2ToCGNS[5] = 5; - SU2ToCGNS[6] = 7; - SU2ToCGNS[7] = 6; -} - -void CCGNSElementType::CreateDataHEXA_27(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The HEXA_27 element is a quadratic hexahedron. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes. - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = HEXAHEDRON; - nPoly = 2; - nDOFs = 27; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 8; - SU2ToCGNS[2] = 1; - SU2ToCGNS[3] = 11; - SU2ToCGNS[4] = 20; - SU2ToCGNS[5] = 9; - SU2ToCGNS[6] = 3; - SU2ToCGNS[7] = 10; - SU2ToCGNS[8] = 2; - SU2ToCGNS[9] = 12; - SU2ToCGNS[10] = 21; - SU2ToCGNS[11] = 13; - SU2ToCGNS[12] = 24; - SU2ToCGNS[13] = 26; - SU2ToCGNS[14] = 22; - SU2ToCGNS[15] = 15; - SU2ToCGNS[16] = 23; - SU2ToCGNS[17] = 14; - SU2ToCGNS[18] = 4; - SU2ToCGNS[19] = 16; - SU2ToCGNS[20] = 5; - SU2ToCGNS[21] = 19; - SU2ToCGNS[22] = 25; - SU2ToCGNS[23] = 17; - SU2ToCGNS[24] = 7; - SU2ToCGNS[25] = 18; - SU2ToCGNS[26] = 6; -} - -void CCGNSElementType::CreateDataHEXA_64(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The HEXA_64 element is a cubic hexahedron. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes. - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = HEXAHEDRON; - nPoly = 3; - nDOFs = 64; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 8; - SU2ToCGNS[2] = 9; - SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 15; - SU2ToCGNS[5] = 32; - SU2ToCGNS[6] = 33; - SU2ToCGNS[7] = 10; - SU2ToCGNS[8] = 14; - SU2ToCGNS[9] = 35; - SU2ToCGNS[10] = 34; - SU2ToCGNS[11] = 11; - SU2ToCGNS[12] = 3; - SU2ToCGNS[13] = 13; - SU2ToCGNS[14] = 12; - SU2ToCGNS[15] = 2; - SU2ToCGNS[16] = 16; - SU2ToCGNS[17] = 36; - SU2ToCGNS[18] = 37; - SU2ToCGNS[19] = 18; - SU2ToCGNS[20] = 49; - SU2ToCGNS[21] = 56; - SU2ToCGNS[22] = 57; - SU2ToCGNS[23] = 40; - SU2ToCGNS[24] = 48; - SU2ToCGNS[25] = 59; - SU2ToCGNS[26] = 58; - SU2ToCGNS[27] = 41; - SU2ToCGNS[28] = 22; - SU2ToCGNS[29] = 45; - SU2ToCGNS[30] = 44; - SU2ToCGNS[31] = 20; - SU2ToCGNS[32] = 17; - SU2ToCGNS[33] = 39; - SU2ToCGNS[34] = 38; - SU2ToCGNS[35] = 19; - SU2ToCGNS[36] = 50; - SU2ToCGNS[37] = 60; - SU2ToCGNS[38] = 61; - SU2ToCGNS[39] = 43; - SU2ToCGNS[40] = 51; - SU2ToCGNS[41] = 63; - SU2ToCGNS[42] = 62; - SU2ToCGNS[43] = 42; - SU2ToCGNS[44] = 23; - SU2ToCGNS[45] = 46; - SU2ToCGNS[46] = 47; - SU2ToCGNS[47] = 21; - SU2ToCGNS[48] = 4; - SU2ToCGNS[49] = 24; - SU2ToCGNS[50] = 25; - SU2ToCGNS[51] = 5; - SU2ToCGNS[52] = 31; - SU2ToCGNS[53] = 52; - SU2ToCGNS[54] = 53; - SU2ToCGNS[55] = 26; - SU2ToCGNS[56] = 30; - SU2ToCGNS[57] = 55; - SU2ToCGNS[58] = 54; - SU2ToCGNS[59] = 27; - SU2ToCGNS[60] = 7; - SU2ToCGNS[61] = 29; - SU2ToCGNS[62] = 28; - SU2ToCGNS[63] = 6; -} - -void CCGNSElementType::CreateDataHEXA_125(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, - vector& SU2ToCGNS) { - /* The HEXA_125 element is a quartic hexahedron. In CGNS the nodes are - numbered as follows: - First the vertex nodes. - - Second the edge nodes. - - Third the face nodes. - - Fourth the volume nodes. - In SU2 the node numbering takes place along increasing i-, j- and k-lines, - where the i-direction is defined from node 0 to 1 and the j-direction - from node 0 along the second edge and the k-direction from node 0 along - the third edge. */ - VTK_Type = HEXAHEDRON; - nPoly = 4; - nDOFs = 125; - - SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; - SU2ToCGNS[1] = 8; - SU2ToCGNS[2] = 9; - SU2ToCGNS[3] = 10; - SU2ToCGNS[4] = 1; - SU2ToCGNS[5] = 19; - SU2ToCGNS[6] = 44; - SU2ToCGNS[7] = 45; - SU2ToCGNS[8] = 46; - SU2ToCGNS[9] = 11; - SU2ToCGNS[10] = 18; - SU2ToCGNS[11] = 51; - SU2ToCGNS[12] = 52; - SU2ToCGNS[13] = 47; - SU2ToCGNS[14] = 12; - SU2ToCGNS[15] = 17; - SU2ToCGNS[16] = 50; - SU2ToCGNS[17] = 49; - SU2ToCGNS[18] = 48; - SU2ToCGNS[19] = 13; - SU2ToCGNS[20] = 3; - SU2ToCGNS[21] = 16; - SU2ToCGNS[22] = 15; - SU2ToCGNS[23] = 14; - SU2ToCGNS[24] = 2; - SU2ToCGNS[25] = 20; - SU2ToCGNS[26] = 53; - SU2ToCGNS[27] = 54; - SU2ToCGNS[28] = 55; - SU2ToCGNS[29] = 23; - SU2ToCGNS[30] = 82; - SU2ToCGNS[31] = 98; - SU2ToCGNS[32] = 99; - SU2ToCGNS[33] = 100; - SU2ToCGNS[34] = 62; - SU2ToCGNS[35] = 81; - SU2ToCGNS[36] = 105; - SU2ToCGNS[37] = 106; - SU2ToCGNS[38] = 101; - SU2ToCGNS[39] = 63; - SU2ToCGNS[40] = 80; - SU2ToCGNS[41] = 104; - SU2ToCGNS[42] = 103; - SU2ToCGNS[43] = 102; - SU2ToCGNS[44] = 64; - SU2ToCGNS[45] = 29; - SU2ToCGNS[46] = 73; - SU2ToCGNS[47] = 72; - SU2ToCGNS[48] = 71; - SU2ToCGNS[49] = 26; - SU2ToCGNS[50] = 21; - SU2ToCGNS[51] = 60; - SU2ToCGNS[52] = 61; - SU2ToCGNS[53] = 56; - SU2ToCGNS[54] = 24; - SU2ToCGNS[55] = 83; - SU2ToCGNS[56] = 107; - SU2ToCGNS[57] = 108; - SU2ToCGNS[58] = 109; - SU2ToCGNS[59] = 69; - SU2ToCGNS[60] = 88; - SU2ToCGNS[61] = 114; - SU2ToCGNS[62] = 115; - SU2ToCGNS[63] = 110; - SU2ToCGNS[64] = 70; - SU2ToCGNS[65] = 87; - SU2ToCGNS[66] = 113; - SU2ToCGNS[67] = 112; - SU2ToCGNS[68] = 111; - SU2ToCGNS[69] = 65; - SU2ToCGNS[70] = 30; - SU2ToCGNS[71] = 74; - SU2ToCGNS[72] = 79; - SU2ToCGNS[73] = 78; - SU2ToCGNS[74] = 27; - SU2ToCGNS[75] = 22; - SU2ToCGNS[76] = 59; - SU2ToCGNS[77] = 58; - SU2ToCGNS[78] = 57; - SU2ToCGNS[79] = 25; - SU2ToCGNS[80] = 84; - SU2ToCGNS[81] = 116; - SU2ToCGNS[82] = 117; - SU2ToCGNS[83] = 118; - SU2ToCGNS[84] = 68; - SU2ToCGNS[85] = 85; - SU2ToCGNS[86] = 123; - SU2ToCGNS[87] = 124; - SU2ToCGNS[88] = 119; - SU2ToCGNS[89] = 67; - SU2ToCGNS[90] = 86; - SU2ToCGNS[91] = 122; - SU2ToCGNS[92] = 121; - SU2ToCGNS[93] = 120; - SU2ToCGNS[94] = 66; - SU2ToCGNS[95] = 31; - SU2ToCGNS[96] = 75; - SU2ToCGNS[97] = 76; - SU2ToCGNS[98] = 77; - SU2ToCGNS[99] = 28; - SU2ToCGNS[100] = 4; - SU2ToCGNS[101] = 32; - SU2ToCGNS[102] = 33; - SU2ToCGNS[103] = 34; - SU2ToCGNS[104] = 5; - SU2ToCGNS[105] = 43; - SU2ToCGNS[106] = 89; - SU2ToCGNS[107] = 90; - SU2ToCGNS[108] = 91; - SU2ToCGNS[109] = 35; - SU2ToCGNS[110] = 42; - SU2ToCGNS[111] = 96; - SU2ToCGNS[112] = 97; - SU2ToCGNS[113] = 92; - SU2ToCGNS[114] = 36; - SU2ToCGNS[115] = 41; - SU2ToCGNS[116] = 95; - SU2ToCGNS[117] = 94; - SU2ToCGNS[118] = 93; - SU2ToCGNS[119] = 37; - SU2ToCGNS[120] = 7; - SU2ToCGNS[121] = 40; - SU2ToCGNS[122] = 39; - SU2ToCGNS[123] = 38; - SU2ToCGNS[124] = 6; -} - -#endif -#endif diff --git a/Common/src/fem/geometry_structure_fem_part.cpp b/Common/src/fem/geometry_structure_fem_part.cpp index d9536a67903..0af57647bac 100644 --- a/Common/src/fem/geometry_structure_fem_part.cpp +++ b/Common/src/fem/geometry_structure_fem_part.cpp @@ -30,9 +30,6 @@ #include "../../include/geometry/primal_grid/CPrimalGridFEM.hpp" #include "../../include/geometry/primal_grid/CPrimalGridBoundFEM.hpp" -#ifdef HAVE_CGNS -#include "../../include/fem/fem_cgns_elements.hpp" -#endif #include "../../include/adt/CADTElemClass.hpp" #include "../../include/linear_algebra/blas_structure.hpp" @@ -802,1067 +799,6 @@ void CPhysicalGeometry::Read_SU2_Format_Parallel_FEM(CConfig* config, const stri mesh_file.close(); } -void CPhysicalGeometry::Read_CGNS_Format_Parallel_FEM(CConfig* config, const string& val_mesh_filename, - unsigned short val_iZone, unsigned short val_nZone) { -#ifdef HAVE_CGNS - - /*--- For proper support of the high order elements, at least version 3.3 - of CGNS must be used. Check this. ---*/ -#if CGNS_VERSION >= 3300 - - /*--- Check whether the supplied file is truly a CGNS file. ---*/ - int file_type; - if (cg_is_cgns(val_mesh_filename.c_str(), &file_type) != CG_OK) - SU2_MPI::Error(val_mesh_filename + string(" is not a CGNS file that can be read."), CURRENT_FUNCTION); - - /*--- Initialize counters for local/global points & elements ---*/ - Global_nPoint = 0; - Global_nPointDomain = 0; - Global_nElem = 0; - nelem_edge = 0; - Global_nelem_edge = 0; - nelem_triangle = 0; - Global_nelem_triangle = 0; - nelem_quad = 0; - Global_nelem_quad = 0; - nelem_tetra = 0; - Global_nelem_tetra = 0; - nelem_hexa = 0; - Global_nelem_hexa = 0; - nelem_prism = 0; - Global_nelem_prism = 0; - nelem_pyramid = 0; - Global_nelem_pyramid = 0; - - /*--------------------------------------------------------------------------*/ - /*--- Checking of the file, determine the dimensions, etc. ---*/ - /*--------------------------------------------------------------------------*/ - - /*--- Allocate memory for the linear partition of the elements of the mesh. - These arrays are the size of the number of ranks. ---*/ - beg_node = new unsigned long[size]; - end_node = new unsigned long[size]; - nPointLinear = new unsigned long[size]; - - /* Open the CGNS file for reading and check if it went OK. */ - int fn; - if (cg_open(val_mesh_filename.c_str(), CG_MODE_READ, &fn) != CG_OK) cg_error_exit(); - if (rank == MASTER_NODE) { - cout << "Reading the CGNS file: " << val_mesh_filename << "." << endl; - } - - /* Get the number of databases. This is the highest node in the CGNS heirarchy. - The current implementation assumes that there is only one database. */ - int nbases; - if (cg_nbases(fn, &nbases) != CG_OK) cg_error_exit(); - if (nbases > 1) { - ostringstream message; - message << "CGNS file contains " << nbases << " databases." << endl; - message << "CGNS reader can handle only 1 at the moment." << endl; - - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } - - /* Read the information of the base, especially the number of dimensions. */ - char cgnsname[CGNS_STRING_SIZE]; - int cellDim, physDim; - const int iBase = 1; - if (cg_base_read(fn, iBase, cgnsname, &cellDim, &physDim)) cg_error_exit(); - nDim = physDim; - - if (cellDim != physDim) { - ostringstream message; - message << "The element dimension, " << cellDim << ", differs from the physical dimension, " << physDim << "." - << endl; - message << "These should be the same for the DG-FEM solver." << endl; - - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } - - /* Write the info about the number of dimensions. */ - if (rank == MASTER_NODE) { - if (nDim == 2) cout << "Two dimensional problem." << endl; - if (nDim == 3) cout << "Three dimensional problem." << endl; - } - - /* Set the zone ID for CGNS, CGNS indices starts at 1, and check - if the requested zone ID is a valid one. */ - const int iZone = val_iZone + 1; - - int nzones; - if (cg_nzones(fn, iBase, &nzones) != CG_OK) cg_error_exit(); - if (iZone < 1 || iZone > nzones) { - ostringstream message; - message << "Zone " << iZone << " requested for reading, but there are only " << nzones - << " zones present in the CGNS file." << endl; - - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } - - /* Determine the zone type for the requested zone and check if it is - unstructured. */ - ZoneType_t zoneType; - if (cg_zone_type(fn, iBase, iZone, &zoneType) != CG_OK) cg_error_exit(); - if (zoneType != Unstructured) - SU2_MPI::Error("Structured CGNS zone found while unstructured expected.", CURRENT_FUNCTION); - - /* Determine the number of sections for the connectivities in this zone. */ - int nsections; - if (cg_nsections(fn, iBase, iZone, &nsections) != CG_OK) cg_error_exit(); - - /*--------------------------------------------------------------------------*/ - /*--- Reading and distributing the volume elements. ---*/ - /*--------------------------------------------------------------------------*/ - - /* Loop over the sections to store the meta data in CGNSElemTypes - and to determine the number of volume elements. - Note that the indices start at 1 in CGNS. */ - vector CGNSElemTypes(nsections); - - for (int iConn = 1; iConn <= nsections; ++iConn) { - CGNSElemTypes[iConn - 1].DetermineMetaData(nDim, fn, iBase, iZone, iConn); - if (CGNSElemTypes[iConn - 1].volumeConn) Global_nElem += CGNSElemTypes[iConn - 1].nElem; - } - - if ((rank == MASTER_NODE) && (size > SINGLE_NODE)) - cout << Global_nElem << " interior elements before parallel partitioning." << endl; - - /*--- Check if the number of cores used is larger than the number of - elements. Terminate if this is the case, because it does not make - sense to do this. ---*/ - unsigned long nCores = size; // Correct for the number of cores per rank. - if (nCores > Global_nElem) { - ostringstream message; - message << "The number of cores, " << nCores; - message << ", is larger than the number of elements, " << Global_nElem << "." << endl; - message << "This is not an efficient use of the resources and therefore " - << "SU2 will terminate."; - - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } - - /*--- Compute the number of elements that will be stored on each rank. - This is a linear partitioning with the addition of a simple load - balancing for any remainder elements. ---*/ - unsigned long total_elem_accounted = 0; - for (unsigned long i = 0; i < (unsigned long)size; i++) { - nPointLinear[i] = Global_nElem / size; - total_elem_accounted = total_elem_accounted + nPointLinear[i]; - } - - /*--- Get the number of remainder elements after the even division ---*/ - const unsigned long rem_elem = Global_nElem - total_elem_accounted; - for (unsigned long i = 0; i < rem_elem; i++) { - ++nPointLinear[i]; - } - - /*--- Store the local number of elements and the beginning/end index ---*/ - nElem = nPointLinear[rank]; - beg_node[0] = 0; - end_node[0] = beg_node[0] + nPointLinear[0]; - for (int i = 1; i < size; i++) { - beg_node[i] = end_node[i - 1]; - end_node[i] = beg_node[i] + nPointLinear[i]; - } - - /*--- Allocate space for elements ---*/ - elem = new CPrimalGrid*[nElem](); - - /*--- Loop over over the connectivities and read the elements to be stored on - this rank. Furthermore, determine the local amount of DOFs for the - solution (which may differ from the number of DOFS for the grid). ---*/ - unsigned long nDOFsLoc = 0, elemCount = 0, locElemCount = 0; - - for (int iConn = 0; iConn < nsections; ++iConn) { - if (CGNSElemTypes[iConn].volumeConn) { - /* Determine the global volume element range for this connectivity. */ - const unsigned long elemCountOld = elemCount; - elemCount += CGNSElemTypes[iConn].nElem; - - /* Check for overlap with the element range this rank is responsible for. */ - const unsigned long indBegOverlap = max(elemCountOld, beg_node[rank]); - const unsigned long indEndOverlap = min(elemCount, end_node[rank]); - - if (indEndOverlap > indBegOverlap) { - /* This rank must read element data from this connectivity section. - Determine the offset relative to the start of this section and the - number of elements to be read by this rank. */ - const unsigned long offsetRank = indBegOverlap - elemCountOld; - const unsigned long nElemRank = indEndOverlap - indBegOverlap; - - /* Read the connectivity range determined above. */ - CGNSElemTypes[iConn].ReadConnectivityRange(fn, iBase, iZone, offsetRank, nElemRank, beg_node[rank], elem, - locElemCount, nDOFsLoc); - } - } - } - -#ifdef HAVE_MPI - /* The global offset of the DOFs must be corrected when running in - parallel. Therefore gather the number of DOFs of all the ranks. */ - vector nDOFsPerRank(size); - SU2_MPI::Allgather(&nDOFsLoc, 1, MPI_UNSIGNED_LONG, nDOFsPerRank.data(), 1, MPI_UNSIGNED_LONG, SU2_MPI::GetComm()); - - /* Determine the offset for the DOFs on this rank. */ - unsigned long offsetRank = 0; - for (int i = 0; i < rank; ++i) offsetRank += nDOFsPerRank[i]; - - /* Loop over the local elements to correct the global offset of the DOFs. */ - for (unsigned long i = 0; i < nElem; ++i) elem[i]->AddOffsetGlobalDOFs(offsetRank); -#endif - - /*--------------------------------------------------------------------------*/ - /*--- Reading and distributing the coordinates. ---*/ - /*--------------------------------------------------------------------------*/ - - /* Determine the global number of vertices in the requested zone. - The other size information is not used. */ - cgsize_t sizes[3]; - if (cg_zone_read(fn, iBase, iZone, cgnsname, sizes) != CG_OK) cg_error_exit(); - Global_nPoint = sizes[0]; - - /*--- Determine the number of points per rank in cumulative storage format. - This is done to avoid that every rank reads all the coordinates. - The required coordinates for each rank are later obtained via - communication. ---*/ - unsigned long totalPointsAccounted = 0; - vector nPointsPerRank(size + 1); - for (int i = 1; i <= size; ++i) { - nPointsPerRank[i] = Global_nPoint / size; - totalPointsAccounted += nPointsPerRank[i]; - } - - const unsigned long nPointsRem = Global_nPoint - totalPointsAccounted; - for (unsigned long i = 1; i <= nPointsRem; ++i) ++nPointsPerRank[i]; - - nPointsPerRank[0] = 0; - for (int i = 0; i < size; ++i) nPointsPerRank[i + 1] += nPointsPerRank[i]; - - /* Determine the number of points that must be read by this rank and - allocate the memory for the coordinate buffers. */ - const cgsize_t nPointsRead = nPointsPerRank[rank + 1] - nPointsPerRank[rank]; - vector > coorBuf(nDim, vector(nPointsRead)); - - /* Loop over the number of dimensions to read the coordinates. Note that - the loop starts at 1 and ends at nDim because CGNS requires this. */ - for (unsigned short iDim = 1; iDim <= nDim; ++iDim) { - /* Determine the data type and name of the coordinate. Copy the name - of the coordinate in a string for easier comparison. */ - DataType_t datatype; - if (cg_coord_info(fn, iBase, iZone, iDim, &datatype, cgnsname) != CG_OK) cg_error_exit(); - string coorname = cgnsname; - - /* Check the name of the coordinate and determine the index in coorBuf - where to store this coordinate. Normally this should be iDim-1. */ - unsigned short indC = 0; - if (coorname == "CoordinateX") - indC = 0; - else if (coorname == "CoordinateY") - indC = 1; - else if (coorname == "CoordinateZ") - indC = 2; - else - SU2_MPI::Error(string("Unknown coordinate name, ") + coorname + string(", encountered in the CGNS file."), - CURRENT_FUNCTION); - - /* Easier storage of the range in the CGNS file. */ - cgsize_t range_min = nPointsPerRank[rank] + 1; - cgsize_t range_max = nPointsPerRank[rank + 1]; - - /*--- Read the coordinate with the required precision and copy - this data to the correct index in coorBuf. ---*/ - switch (datatype) { - case RealSingle: { - /* Single precision used. */ - vector buf(nPointsRead); - if (cg_coord_read(fn, iBase, iZone, cgnsname, datatype, &range_min, &range_max, buf.data()) != CG_OK) - cg_error_exit(); - - for (cgsize_t i = 0; i < nPointsRead; ++i) coorBuf[indC][i] = buf[i]; - break; - } - - case RealDouble: { - /* Double precision used. */ - vector buf(nPointsRead); - if (cg_coord_read(fn, iBase, iZone, cgnsname, datatype, &range_min, &range_max, buf.data()) != CG_OK) - cg_error_exit(); - - for (cgsize_t i = 0; i < nPointsRead; ++i) coorBuf[indC][i] = buf[i]; - break; - } - - default: { - ostringstream message; - message << "Datatype for coordinates must be RealSingle or RealDouble, " - << "not " << datatype << endl; - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } - } - } - - /* Make a distinction between sequential and parallel mode. */ -#ifdef HAVE_MPI - /*--- Parallel mode. Create a vector, which contains the global - node IDs of the local elements. ---*/ - vector nodeIDsElemLoc; - nodeIDsElemLoc.reserve(nDOFsLoc); - for (unsigned long i = 0; i < locElemCount; ++i) { - unsigned short nDOFsElem = elem[i]->GetnNodes(); - for (unsigned short j = 0; j < nDOFsElem; ++j) nodeIDsElemLoc.push_back(elem[i]->GetNode(j)); - } - - sort(nodeIDsElemLoc.begin(), nodeIDsElemLoc.end()); - vector::iterator lastNode; - lastNode = unique(nodeIDsElemLoc.begin(), nodeIDsElemLoc.end()); - nodeIDsElemLoc.erase(lastNode, nodeIDsElemLoc.end()); - - /*--- Allocate the memory for the coordinates to be stored on this rank. ---*/ - nPoint = nodeIDsElemLoc.size(); - nodes = new CPoint(nPoint, nDim); - - /*--- Store the global ID's of the nodes in such a way that they can - be sent to the rank that actually stores the coordinates.. ---*/ - vector > nodeBuf(size, vector(0)); - for (unsigned long i = 0; i < nodeIDsElemLoc.size(); ++i) { - const cgsize_t nodeID = nodeIDsElemLoc[i]; - vector::iterator low; - low = lower_bound(nPointsPerRank.begin(), nPointsPerRank.end(), nodeID); - cgsize_t rankNode = low - nPointsPerRank.begin(); - if (*low > nodeID) --rankNode; - - nodeBuf[rankNode].push_back(nodeIDsElemLoc[i]); - } - - /*--- Determine the total number of ranks to which this rank will send - a message and also determine the number of ranks from which this - rank will receive a message. Furthermore, determine the starting - indices where data from the different ranks should be stored in - node. ---*/ - int nRankSend = 0; - vector sendToRank(size, 0); - vector startingIndRanksInNode(size + 1); - startingIndRanksInNode[0] = 0; - - for (int i = 0; i < size; ++i) { - startingIndRanksInNode[i + 1] = startingIndRanksInNode[i] + nodeBuf[i].size(); - - if (!nodeBuf[i].empty()) { - ++nRankSend; - sendToRank[i] = 1; - } - } - - int nRankRecv; - vector sizeRecv(size, 1); - SU2_MPI::Reduce_scatter(sendToRank.data(), &nRankRecv, sizeRecv.data(), MPI_INT, MPI_SUM, SU2_MPI::GetComm()); - - /*--- Send out the messages with the global node numbers. Use nonblocking - sends to avoid deadlock. ---*/ - vector sendReqs(nRankSend); - nRankSend = 0; - for (int i = 0; i < size; ++i) { - if (!nodeBuf[i].empty()) { - SU2_MPI::Isend(nodeBuf[i].data(), nodeBuf[i].size(), MPI_UNSIGNED_LONG, i, i, SU2_MPI::GetComm(), - &sendReqs[nRankSend]); - ++nRankSend; - } - } - - /* Define the communication buffer for the coordinates and the vector - for the return communication requests. */ - vector returnReqs(nRankRecv); - vector > coorReturnBuf(nRankRecv, vector(0)); - - /*--- Loop over the number of ranks from which this rank receives global - point numbers that should be stored on this rank. ---*/ - for (int i = 0; i < nRankRecv; ++i) { - /* Block until a message arrives. Determine the source and size - of the message. */ - SU2_MPI::Status status; - SU2_MPI::Probe(MPI_ANY_SOURCE, rank, SU2_MPI::GetComm(), &status); - int source = status.MPI_SOURCE; - - int sizeMess; - SU2_MPI::Get_count(&status, MPI_UNSIGNED_LONG, &sizeMess); - - /* Allocate the memory for a buffer to receive this message and also - for the buffer to return to coordinates. */ - vector nodeRecvBuf(sizeMess); - coorReturnBuf[i].resize(nDim * sizeMess); - - /* Receive the message using a blocking receive. */ - SU2_MPI::Recv(nodeRecvBuf.data(), sizeMess, MPI_UNSIGNED_LONG, source, rank, SU2_MPI::GetComm(), &status); - - /*--- Loop over the nodes just received and fill the return communication - buffer with the coordinates of the requested nodes. ---*/ - for (int j = 0; j < sizeMess; ++j) { - const int jj = nDim * j; - const long kk = nodeRecvBuf[j] - nPointsPerRank[rank]; - if (kk < 0 || kk >= nPointsRead) - SU2_MPI::Error("Invalid point requested. This should not happen.", CURRENT_FUNCTION); - - for (unsigned short k = 0; k < nDim; ++k) coorReturnBuf[i][jj + k] = coorBuf[k][kk]; - } - - /* Send the buffer just filled back to the requesting rank. - Use a non-blocking send to avoid deadlock. */ - SU2_MPI::Isend(coorReturnBuf[i].data(), coorReturnBuf[i].size(), MPI_DOUBLE, source, source + 1, SU2_MPI::GetComm(), - &returnReqs[i]); - } - - /* Loop over the ranks from which this rank has requested coordinates. */ - for (int i = 0; i < nRankSend; ++i) { - /* Block until a message arrives. Determine the source of the message. */ - SU2_MPI::Status status; - SU2_MPI::Probe(MPI_ANY_SOURCE, rank + 1, SU2_MPI::GetComm(), &status); - int source = status.MPI_SOURCE; - - /* Allocate the memory for the coordinate receive buffer. */ - vector coorRecvBuf(nDim * nodeBuf[source].size()); - - /* Receive the message using a blocking receive. */ - SU2_MPI::Recv(coorRecvBuf.data(), coorRecvBuf.size(), MPI_DOUBLE, source, rank + 1, SU2_MPI::GetComm(), &status); - - /*--- Make a distinction between 2D and 3D to store the data of the nodes. - This data is created by taking the offset of the source rank into - account. In this way the nodes are numbered with increading - global node ID. ---*/ - for (unsigned long j = 0; j < nodeBuf[source].size(); ++j) { - const unsigned long jj = nDim * j; - const unsigned long kk = startingIndRanksInNode[source] + j; - - nodes->SetCoord(kk, &coorRecvBuf[jj]); - nodes->SetGlobalIndex(kk, nodeBuf[source][j]); - } - } - - /* Complete the non-blocking sends of both rounds. */ - SU2_MPI::Waitall(sendReqs.size(), sendReqs.data(), MPI_STATUSES_IGNORE); - SU2_MPI::Waitall(returnReqs.size(), returnReqs.data(), MPI_STATUSES_IGNORE); - - /* Wild cards have been used in the communication, - so synchronize the ranks to avoid problems. */ - SU2_MPI::Barrier(SU2_MPI::GetComm()); - -#else - /*--- Sequential mode. Create the data for the points. The global - number of points equals the local number of points. ---*/ - nPoint = Global_nPoint; - nodes = new CPoint(nPoint, nDim); - - for (unsigned long i = 0; i < nPoint; ++i) { - for (unsigned short iDim = 0; iDim < nDim; ++iDim) nodes->SetCoord(i, iDim, coorBuf[iDim][i]); - nodes->SetGlobalIndex(i, i); - } - -#endif - - /*--------------------------------------------------------------------------*/ - /*--- Determine and distribute the single faces of the elements. These ---*/ - /*--- faces are distributed over the ranks such that later the boundary ---*/ - /*--- can retrieve the info on which rank they must be stored without ---*/ - /*--- each rank having to read the entire connectivity data. ---*/ - /*--------------------------------------------------------------------------*/ - - /*--- Determine the faces of the local elements. --- */ - vector localFaces; - for (unsigned long k = 0; k < nElem; ++k) { - /*--- Get the global IDs of the corner points of all the faces of this elements. ---*/ - unsigned short nFaces; - unsigned short nPointsPerFace[6]; - unsigned long faceConn[6][4]; - - elem[k]->GetCornerPointsAllFaces(nFaces, nPointsPerFace, faceConn); - - /*--- Loop over the faces and add them to localFaces. For consistency - between sequential and parallel mode the rank is stored at the - position for the second element ID. ---*/ - for (unsigned short i = 0; i < nFaces; ++i) { - CFaceOfElement thisFace; - thisFace.nCornerPoints = nPointsPerFace[i]; - for (unsigned short j = 0; j < nPointsPerFace[i]; ++j) thisFace.cornerPoints[j] = faceConn[i][j]; - thisFace.elemID0 = k + beg_node[rank]; - thisFace.elemID1 = rank; - - thisFace.CreateUniqueNumbering(); - localFaces.push_back(thisFace); - } - } - - /*--- Sort localFaces in increasing order and remove the double entities, - such that unnecessary data is not communicated later on. ---*/ - sort(localFaces.begin(), localFaces.end()); - vector::iterator lastFace; - lastFace = unique(localFaces.begin(), localFaces.end()); - localFaces.erase(lastFace, localFaces.end()); - -#ifdef HAVE_MPI - - /*--- In parallel mode these faces must be distributed over the ranks. - A face is stored on the rank where its first node ID is located - based on nPointsPerRank. Define the communication buffers and - determine their contents. ---*/ - vector > faceBuf(size, vector(0)); - for (unsigned long i = 0; i < localFaces.size(); ++i) { - const cgsize_t nodeID = localFaces[i].cornerPoints[0]; - vector::iterator low; - low = lower_bound(nPointsPerRank.begin(), nPointsPerRank.end(), nodeID); - cgsize_t rankNode = low - nPointsPerRank.begin(); - if (*low > nodeID) --rankNode; - - faceBuf[rankNode].push_back(localFaces[i].nCornerPoints); - for (unsigned short j = 0; j < localFaces[i].nCornerPoints; ++j) - faceBuf[rankNode].push_back(localFaces[i].cornerPoints[j]); - faceBuf[rankNode].push_back(localFaces[i].elemID0); - } - - /* Delete the memory of localFaces again, because its contents will be - build from the messages that this rank will receive. */ - localFaces.clear(); - - /*--- Determine the number of messages this rank will send and receive. ---*/ - nRankSend = 0; - for (int i = 0; i < size; ++i) { - if (!faceBuf[i].empty()) { - ++nRankSend; - sendToRank[i] = 1; - } else { - sendToRank[i] = 0; - } - } - - SU2_MPI::Reduce_scatter(sendToRank.data(), &nRankRecv, sizeRecv.data(), MPI_INT, MPI_SUM, SU2_MPI::GetComm()); - - /*--- Send the messages using non-blocking sends to avoid deadlock. ---*/ - sendReqs.resize(nRankSend); - nRankSend = 0; - for (int i = 0; i < size; ++i) { - if (!faceBuf[i].empty()) { - SU2_MPI::Isend(faceBuf[i].data(), faceBuf[i].size(), MPI_UNSIGNED_LONG, i, i + 4, SU2_MPI::GetComm(), - &sendReqs[nRankSend]); - ++nRankSend; - } - } - - /* Loop over the number of ranks from which this rank will receive data. */ - for (int i = 0; i < nRankRecv; ++i) { - /* Block until a message arrives and determine the source and size - of the message. */ - SU2_MPI::Status status; - SU2_MPI::Probe(MPI_ANY_SOURCE, rank + 4, SU2_MPI::GetComm(), &status); - int source = status.MPI_SOURCE; - - int sizeMess; - SU2_MPI::Get_count(&status, MPI_UNSIGNED_LONG, &sizeMess); - - /* Allocate the memory for the receive buffer and receive the - message using a non-blocking receive. */ - vector faceRecvBuf(sizeMess); - SU2_MPI::Recv(faceRecvBuf.data(), faceRecvBuf.size(), MPI_UNSIGNED_LONG, source, rank + 4, SU2_MPI::GetComm(), - &status); - - /* Loop to extract the data from the receive buffer. */ - int ii = 0; - while (ii < sizeMess) { - /* Store the data for this face in localFaces. The rank where the - corresponding element is physically present is stored in the - second element ID. Note that it is not necessary to create a unique - numbering anymore, because this has already been done before the - communication buffer was created. */ - CFaceOfElement thisFace; - thisFace.nCornerPoints = (unsigned short)faceRecvBuf[ii++]; - for (unsigned short j = 0; j < thisFace.nCornerPoints; ++j, ++ii) thisFace.cornerPoints[j] = faceRecvBuf[ii]; - thisFace.elemID0 = faceRecvBuf[ii++]; - - thisFace.elemID1 = source; - localFaces.push_back(thisFace); - } - } - - /*--- Sort localFaces in increasing order and remove the double entities, - such that searching is a bit more efficient later on. ---*/ - sort(localFaces.begin(), localFaces.end()); - lastFace = unique(localFaces.begin(), localFaces.end()); - localFaces.erase(lastFace, localFaces.end()); - - /* Complete the non-blocking sends. Afterwards, synchronize the ranks, - because wild cards have been used. */ - SU2_MPI::Waitall(sendReqs.size(), sendReqs.data(), MPI_STATUSES_IGNORE); - SU2_MPI::Barrier(SU2_MPI::GetComm()); - -#endif - - /*--------------------------------------------------------------------------*/ - /*--- Reading and distributing the surface elements. ---*/ - /*--------------------------------------------------------------------------*/ - - /* Determine the number of families in this base and read their names. - Note that when multiple zones are present, this step is repeated for - every zone. */ - int nFamilies; - if (cg_nfamilies(fn, iBase, &nFamilies) != CG_OK) cg_error_exit(); - - vector familyNames(nFamilies); - for (int i = 1; i <= nFamilies; ++i) { - int nFamBC, nGeo; - if (cg_family_read(fn, iBase, i, cgnsname, &nFamBC, &nGeo) != CG_OK) cg_error_exit(); - familyNames[i - 1] = cgnsname; - } - - /* Determine the number of boundary conditions for this zone. */ - int nBCs; - if (cg_nbocos(fn, iBase, iZone, &nBCs) != CG_OK) cg_error_exit(); - - /* Read the names of the boundary conditions and determine their family names. - If not family name is specified for a boundary condition, the family name - is set to the name of the boundary condition. */ - vector BCNames(nBCs), BCFamilyNames(nBCs); - for (int i = 1; i <= nBCs; ++i) { - /* Read the info for this boundary condition. */ - BCType_t BCType; - PointSetType_t ptsetType; - cgsize_t npnts, NormalListSize; - int NormalIndex, nDataSet; - DataType_t NormalDataType; - if (cg_boco_info(fn, iBase, iZone, i, cgnsname, &BCType, &ptsetType, &npnts, &NormalIndex, &NormalListSize, - &NormalDataType, &nDataSet) != CG_OK) - cg_error_exit(); - BCNames[i - 1] = cgnsname; - - /* Read the possibly family name and set it. If not present, it is - equal to BCName. */ - if (cg_goto(fn, iBase, "Zone_t", iZone, "ZoneBC_t", 1, "BC_t", i, "end") != CG_OK) cg_error_exit(); - - int ierr = cg_famname_read(cgnsname); - if (ierr == CG_ERROR) - cg_error_exit(); - else if (ierr == CG_OK) - BCFamilyNames[i - 1] = cgnsname; - else - BCFamilyNames[i - 1] = BCNames[i - 1]; - } - - /*--- Determine the number of different surface connectivities. It is - possible to specify a family name for a surface connectivity. If that - family name is the same for multiple surface connectivities, these - connectivities are merged together for the boundary condition - treatment in the DG-FEM solver. ---*/ - vector surfaceNames; - vector > surfaceConnIDs; - - for (int i = 0; i < nsections; ++i) { - if (CGNSElemTypes[i].surfaceConn) { - /*--- Determine the surface name to use for this connectivity. - This name is determined as follows (in terms of importance). - 1) Family name specified for this connectivity. - 2) Family name of the corresponding boundary condition, - if present. - 3) Name of the connectivity. ---*/ - string thisSurfaceName; - const int connID = CGNSElemTypes[i].connID; - - /* First try to read the family name for the connectivity. */ - if (cg_goto(fn, iBase, "Zone_t", iZone, "Elements_t", connID, "end") != CG_OK) cg_error_exit(); - int ierr = cg_famname_read(cgnsname); - if (ierr == CG_ERROR) - cg_error_exit(); - else if (ierr == CG_OK) - thisSurfaceName = cgnsname; - else { - /* No family name. Check the boundary conditions. It is assumed that - the boundary conditions have the same name as the connectivities. */ - int j; - for (j = 0; j < nBCs; ++j) { - if (BCNames[j] == CGNSElemTypes[i].connName) { - thisSurfaceName = BCFamilyNames[j]; - break; - } - } - - /* If the name is not found in the boundary conditions, set the name - of this surface connectivity to the name of this connectivity. */ - if (j == nBCs) thisSurfaceName = CGNSElemTypes[i].connName; - } - - /* Loop over the previously stored surface names and check if this - surface name is already present. */ - unsigned long j; - for (j = 0; j < surfaceNames.size(); ++j) { - if (thisSurfaceName == surfaceNames[j]) { - surfaceConnIDs[j].push_back(i); - } - } - - /* If the surface name is not stored yet, create new entries in - surfaceNames and surfaceConnIDs. */ - if (j == surfaceNames.size()) { - surfaceNames.push_back(thisSurfaceName); - vector thisSurfaceConn(1, i); - surfaceConnIDs.push_back(thisSurfaceConn); - } - } - } - - /* Write a message about the number of surface markers and allocate the - memory for the data structures to store the required information. */ - nMarker = surfaceNames.size(); - if (rank == MASTER_NODE) cout << nMarker << " surface markers." << endl; - config->SetnMarker_All(nMarker); - - unsigned short nMarker_Max = config->GetnMarker_Max(); - - bound = new CPrimalGrid**[nMarker]; - nElem_Bound = new unsigned long[nMarker]; - Tag_to_Marker = new string[nMarker_Max]; - - /* Loop over the number of markers to read and distribute the connectivities. */ - for (unsigned short iMarker = 0; iMarker < nMarker; ++iMarker) { - /* Easier storage of the entries in CGNSElemTypes that contribute - to this boundary marker. */ - const int nEntries = surfaceConnIDs[iMarker].size(); - const int* entries = surfaceConnIDs[iMarker].data(); - - /* Determine the global number of elements for this boundary marker. */ - cgsize_t nElem_Bound_Global = 0; - for (int iConn = 0; iConn < nEntries; ++iConn) nElem_Bound_Global += CGNSElemTypes[entries[iConn]].nElem; - - /* Write a message about the global number of surface elements - present in this marker. */ - string Marker_Tag = surfaceNames[iMarker]; - if (rank == MASTER_NODE) - cout << nElem_Bound_Global << " boundary elements in index " << iMarker << " (Marker = " << Marker_Tag << ")." - << endl; - - /* Determine the number of surface elements per rank in cumulative storage - format. This is done to avoid that every rank reads all the elements. - This is to avoid that every rank reads all the elements. The correct - rank for storage is determined later via communication. */ - unsigned long totalBoundElemAccounted = 0; - vector nBoundElemPerRank(size + 1); - for (int i = 1; i <= size; ++i) { - nBoundElemPerRank[i] = nElem_Bound_Global / size; - totalBoundElemAccounted += nBoundElemPerRank[i]; - } - - const unsigned long nBoundElemRem = nElem_Bound_Global - totalBoundElemAccounted; - for (unsigned long i = 1; i <= nBoundElemRem; ++i) ++nBoundElemPerRank[i]; - - nBoundElemPerRank[0] = 0; - for (int i = 0; i < size; ++i) nBoundElemPerRank[i + 1] += nBoundElemPerRank[i]; - - /* Define a vector of FEM boundary elements to store the local - boundary faces to be read. */ - vector boundElems; - - /* Loop over the connectivity sections that contribute. */ - elemCount = locElemCount = 0; - for (int iConn = 0; iConn < nEntries; ++iConn) { - /* Determine the global range for this connectivity. */ - const unsigned long elemCountOld = elemCount; - elemCount += CGNSElemTypes[entries[iConn]].nElem; - - /* Check for overlap with the element range this rank is responsible for. */ - const unsigned long indBegOverlap = max(elemCountOld, nBoundElemPerRank[rank]); - const unsigned long indEndOverlap = min(elemCount, nBoundElemPerRank[rank + 1]); - - if (indEndOverlap > indBegOverlap) { - /* This rank must read boundary element data from this connectivity - section. Determine the offset relative to the start of this section - and the number of elements to be read by this rank. */ - const unsigned long offsetRank = indBegOverlap - elemCountOld; - const unsigned long nElemRank = indEndOverlap - indBegOverlap; - - /* Read the connectivity range determined above. */ - CGNSElemTypes[entries[iConn]].ReadBoundaryConnectivityRange(fn, iBase, iZone, offsetRank, nElemRank, - nBoundElemPerRank[rank], locElemCount, boundElems); - } - } - - /* Make a distinction between sequential and parallel mode. */ -#ifdef HAVE_MPI - /*--- Parallel mode. The information stored in boundElems must be - communicated to find out where it must be stored. First clear the - contents of the faceBuf, such that it can be used again to send - data to the appropiate rank. ---*/ - for (int i = 0; i < size; ++i) faceBuf[i].clear(); - - /*-- Loop over the locally read boundary elements and store its contents - in the appropiate location in faceBuf. ---*/ - for (unsigned long i = 0; i < boundElems.size(); ++i) { - /* Create an object of the class CFaceOfElement to determine the - node number that determines on which rank the corresponding face - in localFaces is stored. */ - CFaceOfElement thisFace(boundElems[i].VTK_Type, boundElems[i].nPolyGrid, boundElems[i].Nodes.data()); - thisFace.CreateUniqueNumbering(); - - /* Determine the rank to which this face must be sent to. */ - const cgsize_t nodeID = thisFace.cornerPoints[0]; - vector::iterator low; - low = lower_bound(nPointsPerRank.begin(), nPointsPerRank.end(), nodeID); - cgsize_t rankNode = low - nPointsPerRank.begin(); - if (*low > nodeID) --rankNode; - - /*--- Copy the relevant data of this boundary element into faceBuf. ---*/ - faceBuf[rankNode].push_back(boundElems[i].VTK_Type); - faceBuf[rankNode].push_back(boundElems[i].nPolyGrid); - faceBuf[rankNode].push_back(boundElems[i].nDOFsGrid); - faceBuf[rankNode].push_back(boundElems[i].globalBoundElemID); - faceBuf[rankNode].insert(faceBuf[rankNode].end(), boundElems[i].Nodes.begin(), boundElems[i].Nodes.end()); - } - - /* The contents of boundElems is copied into faceBuf, so it can - be released. */ - boundElems.clear(); - - /*--- Determine the number of messages this rank will send and receive. ---*/ - nRankSend = 0; - for (int i = 0; i < size; ++i) { - if (!faceBuf[i].empty()) { - ++nRankSend; - sendToRank[i] = 1; - } else { - sendToRank[i] = 0; - } - } - - SU2_MPI::Reduce_scatter(sendToRank.data(), &nRankRecv, sizeRecv.data(), MPI_INT, MPI_SUM, SU2_MPI::GetComm()); - - /*--- Send the messages using non-blocking sends to avoid deadlock. ---*/ - sendReqs.resize(nRankSend); - nRankSend = 0; - for (int i = 0; i < size; ++i) { - if (!faceBuf[i].empty()) { - SU2_MPI::Isend(faceBuf[i].data(), faceBuf[i].size(), MPI_UNSIGNED_LONG, i, i + 5, SU2_MPI::GetComm(), - &sendReqs[nRankSend]); - ++nRankSend; - } - } - - /* Use nodeBuf as storage for the sending of the surface element data - to the correct rank. First clear its contents. */ - for (int i = 0; i < size; ++i) nodeBuf[i].clear(); - - /*--- Loop over the number of ranks from which this rank receives - surface elements to be processed. ---*/ - for (int i = 0; i < nRankRecv; ++i) { - /* Block until a message arrives. Determine the source and size - of the message. */ - SU2_MPI::Status status; - SU2_MPI::Probe(MPI_ANY_SOURCE, rank + 5, SU2_MPI::GetComm(), &status); - int source = status.MPI_SOURCE; - - int sizeMess; - SU2_MPI::Get_count(&status, MPI_UNSIGNED_LONG, &sizeMess); - - /* Allocate the memory for the receive buffer and receive the message - using a blocking send. */ - vector boundElemRecvBuf(sizeMess); - SU2_MPI::Recv(boundElemRecvBuf.data(), sizeMess, MPI_UNSIGNED_LONG, source, rank + 5, SU2_MPI::GetComm(), - &status); - - /* Loop to extract the data from the receive buffer. */ - int ii = 0; - while (ii < sizeMess) { - /* Store the data for this boundary element. */ - const auto VTK_Type = (unsigned short)boundElemRecvBuf[ii++]; - const auto nPolyGrid = (unsigned short)boundElemRecvBuf[ii++]; - const auto nDOFsGrid = (unsigned short)boundElemRecvBuf[ii++]; - - const unsigned long globalBoundElemID = boundElemRecvBuf[ii++]; - const unsigned long* Nodes = boundElemRecvBuf.data() + ii; - ii += nDOFsGrid; - - /* Determine the corner nodes and store them in an object of - the class CFaceOfElement to carry out the search in localFaces. */ - CFaceOfElement thisFace(VTK_Type, nPolyGrid, Nodes); - - /* Check if the face is actually present. If not, print an error message - and exit. */ - thisFace.CreateUniqueNumbering(); - vector::iterator low; - low = lower_bound(localFaces.begin(), localFaces.end(), thisFace); - - bool thisFaceFound = false; - if (low != localFaces.end()) { - if (!(thisFace < *low)) thisFaceFound = true; - } - - if (!thisFaceFound) - SU2_MPI::Error("Boundary element not found in list of faces. This is a bug.", CURRENT_FUNCTION); - - /* Determine the domain element and the rank where - this boundary element should be sent to.. */ - const unsigned long domainElementID = low->elemID0; - const int rankBoundElem = (int)low->elemID1; - - /*--- Store the data for this element in the communication buffer - for rankBoundElem. ---*/ - nodeBuf[rankBoundElem].push_back(VTK_Type); - nodeBuf[rankBoundElem].push_back(nPolyGrid); - nodeBuf[rankBoundElem].push_back(nDOFsGrid); - nodeBuf[rankBoundElem].push_back(globalBoundElemID); - nodeBuf[rankBoundElem].push_back(domainElementID); - - for (unsigned short j = 0; j < nDOFsGrid; ++j) nodeBuf[rankBoundElem].push_back(Nodes[j]); - } - } - - /* Complete the non-blocking sends. */ - SU2_MPI::Waitall(sendReqs.size(), sendReqs.data(), MPI_STATUSES_IGNORE); - - /*--- Determine the number of messages this rank will send and receive. ---*/ - nRankSend = 0; - for (int i = 0; i < size; ++i) { - if (!nodeBuf[i].empty()) { - ++nRankSend; - sendToRank[i] = 1; - } else { - sendToRank[i] = 0; - } - } - - SU2_MPI::Reduce_scatter(sendToRank.data(), &nRankRecv, sizeRecv.data(), MPI_INT, MPI_SUM, SU2_MPI::GetComm()); - - /*--- Send the messages using non-blocking sends to avoid deadlock. ---*/ - sendReqs.resize(nRankSend); - nRankSend = 0; - for (int i = 0; i < size; ++i) { - if (!nodeBuf[i].empty()) { - SU2_MPI::Isend(nodeBuf[i].data(), nodeBuf[i].size(), MPI_UNSIGNED_LONG, i, i + 6, SU2_MPI::GetComm(), - &sendReqs[nRankSend]); - ++nRankSend; - } - } - - /*--- Loop over the number of ranks from which this rank receives - surface elements to be stored on this rank. ---*/ - for (int i = 0; i < nRankRecv; ++i) { - /* Block until a message arrives. Determine the source and size - of the message. */ - SU2_MPI::Status status; - SU2_MPI::Probe(MPI_ANY_SOURCE, rank + 6, SU2_MPI::GetComm(), &status); - int source = status.MPI_SOURCE; - - int sizeMess; - SU2_MPI::Get_count(&status, MPI_UNSIGNED_LONG, &sizeMess); - - /* Allocate the memory for the receive buffer and receive the message - using a blocking send. */ - vector boundElemRecvBuf(sizeMess); - SU2_MPI::Recv(boundElemRecvBuf.data(), sizeMess, MPI_UNSIGNED_LONG, source, rank + 6, SU2_MPI::GetComm(), - &status); - - /* Loop to extract the data from the receive buffer. */ - int ii = 0; - while (ii < sizeMess) { - /* Store the data for this boundary element. */ - const auto VTK_Type = (unsigned short)boundElemRecvBuf[ii++]; - const auto nPolyGrid = (unsigned short)boundElemRecvBuf[ii++]; - const auto nDOFsGrid = (unsigned short)boundElemRecvBuf[ii++]; - - const unsigned long globalBoundElemID = boundElemRecvBuf[ii++]; - const unsigned long domainElementID = boundElemRecvBuf[ii++]; - const unsigned long* Nodes = boundElemRecvBuf.data() + ii; - ii += nDOFsGrid; - - /* Create an object of CBoundaryFace and store it in boundElems. */ - CBoundaryFace thisBoundFace; - thisBoundFace.VTK_Type = VTK_Type; - thisBoundFace.nPolyGrid = nPolyGrid; - thisBoundFace.nDOFsGrid = nDOFsGrid; - thisBoundFace.globalBoundElemID = globalBoundElemID; - thisBoundFace.domainElementID = domainElementID; - - thisBoundFace.Nodes.resize(nDOFsGrid); - for (unsigned short j = 0; j < nDOFsGrid; ++j) thisBoundFace.Nodes[j] = Nodes[j]; - - boundElems.push_back(thisBoundFace); - } - } - - /* Sort boundElems in increasing order, where the less than operator - is a comparison between the globalBoundElemID's. */ - sort(boundElems.begin(), boundElems.end()); - - /* Complete the non-blocking sends and synchronize the processors, - because wild cards have been used. */ - SU2_MPI::Waitall(sendReqs.size(), sendReqs.data(), MPI_STATUSES_IGNORE); - - SU2_MPI::Barrier(SU2_MPI::GetComm()); - -#else - /*--- Sequential mode. All boundary elements read must be stored on this - rank. The only information missing is the global ID of the domain - element of the boundary elements. This is created below. ---*/ - for (unsigned long i = 0; i < boundElems.size(); ++i) { - /* Determine the corner nodes and store them in an object of - the class CFaceOfElement to carry out the search in localFaces. */ - CFaceOfElement thisFace(boundElems[i].VTK_Type, boundElems[i].nPolyGrid, boundElems[i].Nodes.data()); - - /* Check if the face is actually present. If not, print an error message - and exit. */ - thisFace.CreateUniqueNumbering(); - vector::iterator low; - low = lower_bound(localFaces.begin(), localFaces.end(), thisFace); - - bool thisFaceFound = false; - if (low != localFaces.end()) { - if (!(thisFace < *low)) thisFaceFound = true; - } - - if (!thisFaceFound) - SU2_MPI::Error("Boundary element not found in list of faces. This is a bug.", CURRENT_FUNCTION); - - /* Set the domain element. */ - boundElems[i].domainElementID = low->elemID0; - } -#endif - - /*--- Allocate space for the local boundary elements and copy the data - from boundElems into bound. ---*/ - nElem_Bound[iMarker] = boundElems.size(); - bound[iMarker] = new CPrimalGrid*[nElem_Bound[iMarker]]; - - for (unsigned long i = 0; i < nElem_Bound[iMarker]; ++i) - bound[iMarker][i] = new CPrimalGridBoundFEM(boundElems[i].globalBoundElemID, boundElems[i].domainElementID, - boundElems[i].VTK_Type, boundElems[i].nPolyGrid, - boundElems[i].nDOFsGrid, boundElems[i].Nodes); - - /*--- Update config information storing the boundary information in the right place ---*/ - Tag_to_Marker[config->GetMarker_CfgFile_TagBound(Marker_Tag)] = Marker_Tag; - config->SetMarker_All_TagBound(iMarker, Marker_Tag); - config->SetMarker_All_KindBC(iMarker, config->GetMarker_CfgFile_KindBC(Marker_Tag)); - config->SetMarker_All_Monitoring(iMarker, config->GetMarker_CfgFile_Monitoring(Marker_Tag)); - config->SetMarker_All_GeoEval(iMarker, config->GetMarker_CfgFile_GeoEval(Marker_Tag)); - config->SetMarker_All_Designing(iMarker, config->GetMarker_CfgFile_Designing(Marker_Tag)); - config->SetMarker_All_Plotting(iMarker, config->GetMarker_CfgFile_Plotting(Marker_Tag)); - config->SetMarker_All_Analyze(iMarker, config->GetMarker_CfgFile_Analyze(Marker_Tag)); - config->SetMarker_All_ZoneInterface(iMarker, config->GetMarker_CfgFile_ZoneInterface(Marker_Tag)); - config->SetMarker_All_DV(iMarker, config->GetMarker_CfgFile_DV(Marker_Tag)); - config->SetMarker_All_Moving(iMarker, config->GetMarker_CfgFile_Moving(Marker_Tag)); - config->SetMarker_All_SobolevBC(iMarker, config->GetMarker_CfgFile_SobolevBC(Marker_Tag)); - config->SetMarker_All_PerBound(iMarker, config->GetMarker_CfgFile_PerBound(Marker_Tag)); - config->SetMarker_All_SendRecv(iMarker, NONE); - } - - /* Close the CGNS file again. */ - if (cg_close(fn) != CG_OK) cg_error_exit(); - if (rank == MASTER_NODE) cout << "Successfully closed the CGNS file." << endl; - -#else /* CGNS_VERSION >= 3300 */ - - SU2_MPI::Error("CGNS version 3.3 or higher is necessary for the DG FEM solver", CURRENT_FUNCTION); - -#endif /* CGNS_VERSION >= 3300 */ - -#else /* HAVE_CGNS. */ - - SU2_MPI::Error("SU2 built without CGNS support!!\nTo use CGNS, build SU2 accordingly.", CURRENT_FUNCTION); - -#endif /* HAVE_CGNS. */ -} - void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { /*--- Initialize the color vector of the elements. ---*/ for (unsigned long i = 0; i < nElem; ++i) elem[i]->SetColor(0); diff --git a/Common/src/fem/meson.build b/Common/src/fem/meson.build index 028f179d6e4..263fccc0e84 100644 --- a/Common/src/fem/meson.build +++ b/Common/src/fem/meson.build @@ -4,5 +4,4 @@ common_src += files(['geometry_structure_fem_part.cpp', 'fem_work_estimate_metis.cpp', 'fem_standard_element.cpp', 'fem_wall_distance.cpp', - 'fem_gauss_jacobi_quadrature.cpp', - 'fem_cgns_elements.cpp']) + 'fem_gauss_jacobi_quadrature.cpp']) diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index ee2c5992c04..6f7f4a0fe98 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -33,6 +33,7 @@ #include "../../include/toolboxes/geometry_toolbox.hpp" #include "../../include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp" #include "../../include/geometry/meshreader/CCGNSMeshReaderFVM.hpp" +#include "../../include/geometry/meshreader/CCGNSMeshReaderFEM.hpp" #include "../../include/geometry/meshreader/CRectangularMeshReaderFVM.hpp" #include "../../include/geometry/meshreader/CBoxMeshReaderFVM.hpp" @@ -3451,7 +3452,8 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena Mesh = new CSU2ASCIIMeshReaderFVM(config, val_iZone, val_nZone); break; case CGNS_GRID: - Mesh = new CCGNSMeshReaderFVM(config, val_iZone, val_nZone); + if (fem_solver) Mesh = new CCGNSMeshReaderFEM(config, val_iZone, val_nZone); + else Mesh = new CCGNSMeshReaderFVM(config, val_iZone, val_nZone); break; case RECTANGLE: Mesh = new CRectangularMeshReaderFVM(config, val_iZone, val_nZone); diff --git a/Common/src/geometry/meshreader/CCGNSElementType.cpp b/Common/src/geometry/meshreader/CCGNSElementType.cpp new file mode 100644 index 00000000000..8ed50fb91df --- /dev/null +++ b/Common/src/geometry/meshreader/CCGNSElementType.cpp @@ -0,0 +1,840 @@ +/*! + * \file CCGNSElementType.cpp + * \brief Class that converts the CGNS element definitions to the SU2 standard. + * \author E. van der Weide + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#ifdef HAVE_CGNS +#include "../../../include/geometry/meshreader/CCGNSElementType.hpp" +#include "../../../include/option_structure.hpp" + +#include +#include +#include + +using namespace std; + +void CCGNSElementType::CGNSToSU2(const ElementType_t val_elemType, + const unsigned long val_globalID, + const cgsize_t *connCGNS, + std::vector &connSU2) { + + /*--- Clear the contents of connSU2. ---*/ + connSU2.clear(); + + /*--- Search in the stored elements if the current element type is present. ---*/ + unsigned long ind; + for(ind=0; ind SU2ToCGNS; + + switch( val_elemType ) { + + case NODE: CreateDataNODE (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case BAR_2: CreateDataBAR_2 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case BAR_3: CreateDataBAR_3 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case BAR_4: CreateDataBAR_4 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case BAR_5: CreateDataBAR_5 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case TRI_3: CreateDataTRI_3 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case TRI_6: CreateDataTRI_6 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case TRI_10: CreateDataTRI_10 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case TRI_15: CreateDataTRI_15 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case QUAD_4: CreateDataQUAD_4 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case QUAD_9: CreateDataQUAD_9 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case QUAD_16: CreateDataQUAD_16 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case QUAD_25: CreateDataQUAD_25 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case TETRA_4: CreateDataTETRA_4 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case TETRA_10: CreateDataTETRA_10(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case TETRA_20: CreateDataTETRA_20(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case TETRA_35: CreateDataTETRA_35(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case PYRA_5: CreateDataPYRA_5 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case PYRA_14: CreateDataPYRA_14 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case PYRA_30: CreateDataPYRA_30 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case PYRA_55: CreateDataPYRA_55 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case PENTA_6: CreateDataPENTA_6 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case PENTA_18: CreateDataPENTA_18(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case PENTA_40: CreateDataPENTA_40(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case PENTA_75: CreateDataPENTA_75(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case HEXA_8: CreateDataHEXA_8 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case HEXA_27: CreateDataHEXA_27 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case HEXA_64: CreateDataHEXA_64 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + case HEXA_125: CreateDataHEXA_125(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + + default: + ostringstream message; + message << "CGNS element type " << val_elemType << " not supported."; + SU2_MPI::Error(message.str(), CURRENT_FUNCTION); + } + + /*--- Store the data just created at the end of the corresponding vectors. ---*/ + CGNSTypeStored.push_back(val_elemType); + VTKTypeStored.push_back(VTK_Type); + nPolyStored.push_back(nPoly); + nDOFsStored.push_back(nDOFs); + SU2ToCGNSStored.push_back(SU2ToCGNS); + } + + /*--- Allocate the memory for connSU2 and store the meta data. ---*/ + connSU2.resize(nDOFsStored[ind]+5); + + connSU2[0] = VTKTypeStored[ind]; + connSU2[1] = nPolyStored[ind]; + connSU2[2] = nPolyStored[ind]; + connSU2[3] = nDOFsStored[ind]; + connSU2[4] = val_globalID; + + /*--- Loop over the DOFs and convert the connectivity from CGNS to SU2 + format. Keep in mind that CGNS start the numbering at 1 while + SU2 starts at 0. ---*/ + for(unsigned short i=0; i &SU2ToCGNS) { + + /* Set the required data for a NODE. */ + VTK_Type = VERTEX; + nPoly = 0; + nDOFs = 1; + SU2ToCGNS.push_back(0); +} + +void CCGNSElementType::CreateDataBAR_2(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The BAR_2 element is a linear element. The numbering of the nodes is + the same for CGNS and SU2. */ + VTK_Type = LINE; + nPoly = 1; + nDOFs = 2; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; +} + +void CCGNSElementType::CreateDataBAR_3(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The BAR_3 element is a quadratic element. SU2 numbers to nodes with + increasing parametric value, while in CGNS the internal node is + numbered last. */ + VTK_Type = LINE; + nPoly = 2; + nDOFs = 3; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 2; SU2ToCGNS[2] = 1; +} + +void CCGNSElementType::CreateDataBAR_4(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The BAR_4 element is a cubic element. SU2 numbers to nodes with + increasing parametric value, while in CGNS the internal nodes are + numbered last. */ + VTK_Type = LINE; + nPoly = 3; + nDOFs = 4; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 2; SU2ToCGNS[2] = 3; SU2ToCGNS[3] = 1; +} + +void CCGNSElementType::CreateDataBAR_5(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The BAR_5 element is a quartic element. SU2 numbers to nodes with + increasing parametric value, while in CGNS the internal nodes are + numbered last. */ + VTK_Type = LINE; + nPoly = 4; + nDOFs = 5; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 2; SU2ToCGNS[2] = 3; + SU2ToCGNS[3] = 4; SU2ToCGNS[4] = 1; +} + +void CCGNSElementType::CreateDataTRI_3(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The TRI_3 element is a linear triangle. The node numbering is the same + in SU2 and CGNS. */ + VTK_Type = TRIANGLE; + nPoly = 1; + nDOFs = 3; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 2; +} + +void CCGNSElementType::CreateDataTRI_6(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The TRI_6 element is a quadratic triangle. In CGNS the nodes are numbered + as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes (not present for TRI_6). + In SU2 the node numbering takes place along increasing i- and j-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the other edge. */ + VTK_Type = TRIANGLE; + nPoly = 2; + nDOFs = 6; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 3; SU2ToCGNS[2] = 1; + SU2ToCGNS[3] = 5; SU2ToCGNS[4] = 4; SU2ToCGNS[5] = 2; +} + +void CCGNSElementType::CreateDataTRI_10(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The TRI_10 element is a cubic triangle. In CGNS the nodes are numbered + as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + In SU2 the node numbering takes place along increasing i- and j-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the other edge. */ + VTK_Type = TRIANGLE; + nPoly = 3; + nDOFs = 10; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 3; SU2ToCGNS[2] = 4; SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 8; SU2ToCGNS[5] = 9; SU2ToCGNS[6] = 5; SU2ToCGNS[7] = 7; + SU2ToCGNS[8] = 6; SU2ToCGNS[9] = 2; +} + +void CCGNSElementType::CreateDataTRI_15(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The TRI_15 element is a quartic triangle. In CGNS the nodes are numbered + as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + In SU2 the node numbering takes place along increasing i- and j-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the other edge. + Also note that in the CGNS standard the face nodes are not placed at + the location for uniform spacing. This effect is currently ignored, + i.e. it is assumed that the spacing in parameter space is uniform. */ + VTK_Type = TRIANGLE; + nPoly = 4; + nDOFs = 15; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 3; SU2ToCGNS[2] = 4; SU2ToCGNS[3] = 5; + SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 11; SU2ToCGNS[6] = 12; SU2ToCGNS[7] = 13; + SU2ToCGNS[8] = 6; SU2ToCGNS[9] = 10; SU2ToCGNS[10] = 14; SU2ToCGNS[11] = 7; + SU2ToCGNS[12] = 9; SU2ToCGNS[13] = 8; SU2ToCGNS[14] = 2; +} + +void CCGNSElementType::CreateDataQUAD_4(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The QUAD_4 element is a linear quadrilateral. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes (not present for QUAD_4). + - Third the face nodes (not present for QUAD_4). + In SU2 the node numbering takes place along increasing i- and j-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the other edge. */ + VTK_Type = QUADRILATERAL; + nPoly = 1; + nDOFs = 4; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 3; SU2ToCGNS[3] = 2; +} + +void CCGNSElementType::CreateDataQUAD_9(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The QUAD_9 element is a quadratic quadrilateral. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + In SU2 the node numbering takes place along increasing i- and j-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the other edge. */ + VTK_Type = QUADRILATERAL; + nPoly = 2; + nDOFs = 9; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 7; + SU2ToCGNS[4] = 8; SU2ToCGNS[5] = 5; SU2ToCGNS[6] = 3; SU2ToCGNS[7] = 6; + SU2ToCGNS[8] = 2; +} + +void CCGNSElementType::CreateDataQUAD_16(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The QUAD_16 element is a cubic quadrilateral. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + In SU2 the node numbering takes place along increasing i- and j-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the other edge. */ + VTK_Type = QUADRILATERAL; + nPoly = 3; + nDOFs = 16; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 5; SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 11; SU2ToCGNS[5] = 12; SU2ToCGNS[6] = 13; SU2ToCGNS[7] = 6; + SU2ToCGNS[8] = 10; SU2ToCGNS[9] = 15; SU2ToCGNS[10] = 14; SU2ToCGNS[11] = 7; + SU2ToCGNS[12] = 3; SU2ToCGNS[13] = 9; SU2ToCGNS[14] = 8; SU2ToCGNS[15] = 2; +} + +void CCGNSElementType::CreateDataQUAD_25(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The QUAD_25 element is a quartic quadrilateral. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + In SU2 the node numbering takes place along increasing i- and j-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the other edge. */ + VTK_Type = QUADRILATERAL; + nPoly = 4; + nDOFs = 25; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 5; SU2ToCGNS[3] = 6; + SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 15; SU2ToCGNS[6] = 16; SU2ToCGNS[7] = 17; + SU2ToCGNS[8] = 18; SU2ToCGNS[9] = 7; SU2ToCGNS[10] = 14; SU2ToCGNS[11] = 23; + SU2ToCGNS[12] = 24; SU2ToCGNS[13] = 19; SU2ToCGNS[14] = 8; SU2ToCGNS[15] = 13; + SU2ToCGNS[16] = 22; SU2ToCGNS[17] = 21; SU2ToCGNS[18] = 20; SU2ToCGNS[19] = 9; + SU2ToCGNS[20] = 3; SU2ToCGNS[21] = 12; SU2ToCGNS[22] = 11; SU2ToCGNS[23] = 10; + SU2ToCGNS[24] = 2; +} + +void CCGNSElementType::CreateDataTETRA_4(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The TETRA_4 element is a linear tetrahedron. The node numbering is + the same in SU2 and CGNS. */ + VTK_Type = TETRAHEDRON; + nPoly = 1; + nDOFs = 4; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 2; SU2ToCGNS[3] = 3; +} + +void CCGNSElementType::CreateDataTETRA_10(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The TETRA_10 element is a quadratic tetrahedron. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes (not present in TETRA_10). + - Fourth the volume nodes (not present in TETRA_10). + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = TETRAHEDRON; + nPoly = 2; + nDOFs = 10; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 6; + SU2ToCGNS[4] = 5; SU2ToCGNS[5] = 2; SU2ToCGNS[6] = 7; SU2ToCGNS[7] = 8; + SU2ToCGNS[8] = 9; SU2ToCGNS[9] = 3; +} + +void CCGNSElementType::CreateDataTETRA_20(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The TETRA_20 element is a cubic tetrahedron. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes (not present in TETRA_20). + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = TETRAHEDRON; + nPoly = 3; + nDOFs = 20; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 5; SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 9; SU2ToCGNS[5] = 16; SU2ToCGNS[6] = 6; SU2ToCGNS[7] = 8; + SU2ToCGNS[8] = 7; SU2ToCGNS[9] = 2; SU2ToCGNS[10] = 10; SU2ToCGNS[11] = 17; + SU2ToCGNS[12] = 12; SU2ToCGNS[13] = 19; SU2ToCGNS[14] = 18; SU2ToCGNS[15] = 14; + SU2ToCGNS[16] = 11; SU2ToCGNS[17] = 13; SU2ToCGNS[18] = 15; SU2ToCGNS[19] = 3; +} + +void CCGNSElementType::CreateDataTETRA_35(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The TETRA_35 element is a quartic tetrahedron. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes. + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. Also note that in the CGNS standard the face and volume + nodes are not placed at the location for uniform spacing. This effect is + currently ignored, i.e. it is assumed that the spacing in parameter space + is uniform. */ + VTK_Type = TETRAHEDRON; + nPoly = 4; + nDOFs = 35; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 5; SU2ToCGNS[3] = 6; + SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 12; SU2ToCGNS[6] = 22; SU2ToCGNS[7] = 23; + SU2ToCGNS[8] = 7; SU2ToCGNS[9] = 11; SU2ToCGNS[10] = 24; SU2ToCGNS[11] = 8; + SU2ToCGNS[12] = 10; SU2ToCGNS[13] = 9; SU2ToCGNS[14] = 2; SU2ToCGNS[15] = 13; + SU2ToCGNS[16] = 25; SU2ToCGNS[17] = 26; SU2ToCGNS[18] = 16; SU2ToCGNS[19] = 32; + SU2ToCGNS[20] = 34; SU2ToCGNS[21] = 28; SU2ToCGNS[22] = 31; SU2ToCGNS[23] = 29; + SU2ToCGNS[24] = 19; SU2ToCGNS[25] = 14; SU2ToCGNS[26] = 27; SU2ToCGNS[27] = 17; + SU2ToCGNS[28] = 33; SU2ToCGNS[29] = 30; SU2ToCGNS[30] = 20; SU2ToCGNS[31] = 15; + SU2ToCGNS[32] = 18; SU2ToCGNS[33] = 21; SU2ToCGNS[34] = 3; +} + +void CCGNSElementType::CreateDataPYRA_5(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The PYRA_5 element is a linear pyramid. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes (not present in PYRA_5). + - Third the face nodes (not present in PYRA_5). + - Fourth the volume nodes (not present in PYRA_5). + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = PYRAMID; + nPoly = 1; + nDOFs = 5; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 3; SU2ToCGNS[3] = 2; + SU2ToCGNS[4] = 4; +} + +void CCGNSElementType::CreateDataPYRA_14(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The PYRA_14 element is a quadratic pyramid. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes (not present in PYRA_14). + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = PYRAMID; + nPoly = 2; + nDOFs = 14; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 5; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 8; + SU2ToCGNS[4] = 13; SU2ToCGNS[5] = 6; SU2ToCGNS[6] = 3; SU2ToCGNS[7] = 7; + SU2ToCGNS[8] = 2; SU2ToCGNS[9] = 9; SU2ToCGNS[10] = 10; SU2ToCGNS[11] = 12; + SU2ToCGNS[12] = 11; SU2ToCGNS[13] = 4; +} + +void CCGNSElementType::CreateDataPYRA_30(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The PYRA_30 element is a cubic pyramid. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes. + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = PYRAMID; + nPoly = 3; + nDOFs = 30; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 5; SU2ToCGNS[2] = 6; SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 12; SU2ToCGNS[5] = 21; SU2ToCGNS[6] = 22; SU2ToCGNS[7] = 7; + SU2ToCGNS[8] = 11; SU2ToCGNS[9] = 24; SU2ToCGNS[10] = 23; SU2ToCGNS[11] = 8; + SU2ToCGNS[12] = 3; SU2ToCGNS[13] = 10; SU2ToCGNS[14] = 9; SU2ToCGNS[15] = 2; + SU2ToCGNS[16] = 13; SU2ToCGNS[17] = 25; SU2ToCGNS[18] = 15; SU2ToCGNS[19] = 28; + SU2ToCGNS[20] = 29; SU2ToCGNS[21] = 26; SU2ToCGNS[22] = 19; SU2ToCGNS[23] = 27; + SU2ToCGNS[24] = 17; SU2ToCGNS[25] = 14; SU2ToCGNS[26] = 16; SU2ToCGNS[27] = 20; + SU2ToCGNS[28] = 18; SU2ToCGNS[29] = 4; +} + +void CCGNSElementType::CreateDataPYRA_55(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The PYRA_55 element is a quartic pyramid. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes. + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. Also note that in the CGNS standard the triangular face + and volume nodes are not placed at the location for uniform spacing. This + effect is currently ignored, i.e. it is assumed that the spacing in + parameter space is uniform.*/ + VTK_Type = PYRAMID; + nPoly = 4; + nDOFs = 55; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 5; SU2ToCGNS[2] = 6; SU2ToCGNS[3] = 7; + SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 16; SU2ToCGNS[6] = 29; SU2ToCGNS[7] = 30; + SU2ToCGNS[8] = 31; SU2ToCGNS[9] = 8; SU2ToCGNS[10] = 15; SU2ToCGNS[11] = 36; + SU2ToCGNS[12] = 37; SU2ToCGNS[13] = 32; SU2ToCGNS[14] = 9; SU2ToCGNS[15] = 14; + SU2ToCGNS[16] = 35; SU2ToCGNS[17] = 34; SU2ToCGNS[18] = 33; SU2ToCGNS[19] = 10; + SU2ToCGNS[20] = 3; SU2ToCGNS[21] = 13; SU2ToCGNS[22] = 12; SU2ToCGNS[23] = 11; + SU2ToCGNS[24] = 2; SU2ToCGNS[25] = 17; SU2ToCGNS[26] = 38; SU2ToCGNS[27] = 39; + SU2ToCGNS[28] = 20; SU2ToCGNS[29] = 48; SU2ToCGNS[30] = 50; SU2ToCGNS[31] = 51; + SU2ToCGNS[32] = 41; SU2ToCGNS[33] = 47; SU2ToCGNS[34] = 53; SU2ToCGNS[35] = 52; + SU2ToCGNS[36] = 42; SU2ToCGNS[37] = 26; SU2ToCGNS[38] = 45; SU2ToCGNS[39] = 44; + SU2ToCGNS[40] = 23; SU2ToCGNS[41] = 18; SU2ToCGNS[42] = 40; SU2ToCGNS[43] = 21; + SU2ToCGNS[44] = 49; SU2ToCGNS[45] = 54; SU2ToCGNS[46] = 43; SU2ToCGNS[47] = 27; + SU2ToCGNS[48] = 46; SU2ToCGNS[49] = 24; SU2ToCGNS[50] = 19; SU2ToCGNS[51] = 22; + SU2ToCGNS[52] = 28; SU2ToCGNS[53] = 25; SU2ToCGNS[54] = 4; +} + +void CCGNSElementType::CreateDataPENTA_6(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The PENTA_6 element is a linear prism. The node numbering is + the same in SU2 and CGNS. */ + VTK_Type = PRISM; + nPoly = 1; + nDOFs = 6; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 2; + SU2ToCGNS[3] = 3; SU2ToCGNS[4] = 4; SU2ToCGNS[5] = 5; +} + +void CCGNSElementType::CreateDataPENTA_18(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The PENTA_18 element is a quadratic prism. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes (not present in PENTA_18). + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = PRISM; + nPoly = 2; + nDOFs = 18; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 6; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 8; + SU2ToCGNS[4] = 7; SU2ToCGNS[5] = 2; SU2ToCGNS[6] = 9; SU2ToCGNS[7] = 15; + SU2ToCGNS[8] = 10; SU2ToCGNS[9] = 17; SU2ToCGNS[10] = 16; SU2ToCGNS[11] = 11; + SU2ToCGNS[12] = 3; SU2ToCGNS[13] = 12; SU2ToCGNS[14] = 4; SU2ToCGNS[15] = 14; + SU2ToCGNS[16] = 13; SU2ToCGNS[17] = 5; +} + +void CCGNSElementType::CreateDataPENTA_40(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The PENTA_40 element is a cubic prism. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes. + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = PRISM; + nPoly = 3; + nDOFs = 40; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 6; SU2ToCGNS[2] = 7; SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 11; SU2ToCGNS[5] = 24; SU2ToCGNS[6] = 8; SU2ToCGNS[7] = 10; + SU2ToCGNS[8] = 9; SU2ToCGNS[9] = 2; SU2ToCGNS[10] = 12; SU2ToCGNS[11] = 25; + SU2ToCGNS[12] = 26; SU2ToCGNS[13] = 14; SU2ToCGNS[14] = 34; SU2ToCGNS[15] = 38; + SU2ToCGNS[16] = 29; SU2ToCGNS[17] = 33; SU2ToCGNS[18] = 30; SU2ToCGNS[19] = 16; + SU2ToCGNS[20] = 13; SU2ToCGNS[21] = 28; SU2ToCGNS[22] = 27; SU2ToCGNS[23] = 15; + SU2ToCGNS[24] = 35; SU2ToCGNS[25] = 39; SU2ToCGNS[26] = 32; SU2ToCGNS[27] = 36; + SU2ToCGNS[28] = 31; SU2ToCGNS[29] = 17; SU2ToCGNS[30] = 3; SU2ToCGNS[31] = 18; + SU2ToCGNS[32] = 19; SU2ToCGNS[33] = 4; SU2ToCGNS[34] = 23; SU2ToCGNS[35] = 37; + SU2ToCGNS[36] = 20; SU2ToCGNS[37] = 22; SU2ToCGNS[38] = 21; SU2ToCGNS[39] = 5; +} + +void CCGNSElementType::CreateDataPENTA_75(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The PENTA_75 element is a quartic prism. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes. + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. Also note that in the CGNS standard the triangular face + and volume nodes are not placed at the location for uniform spacing. This + effect is currently ignored, i.e. it is assumed that the spacing in + parameter space is uniform. */ + VTK_Type = PRISM; + nPoly = 4; + nDOFs = 75; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 6; SU2ToCGNS[2] = 7; SU2ToCGNS[3] = 8; + SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 14; SU2ToCGNS[6] = 33; SU2ToCGNS[7] = 34; + SU2ToCGNS[8] = 9; SU2ToCGNS[9] = 13; SU2ToCGNS[10] = 35; SU2ToCGNS[11] = 10; + SU2ToCGNS[12] = 12; SU2ToCGNS[13] = 11; SU2ToCGNS[14] = 2; SU2ToCGNS[15] = 15; + SU2ToCGNS[16] = 36; SU2ToCGNS[17] = 37; SU2ToCGNS[18] = 38; SU2ToCGNS[19] = 18; + SU2ToCGNS[20] = 56; SU2ToCGNS[21] = 66; SU2ToCGNS[22] = 67; SU2ToCGNS[23] = 45; + SU2ToCGNS[24] = 55; SU2ToCGNS[25] = 68; SU2ToCGNS[26] = 46; SU2ToCGNS[27] = 54; + SU2ToCGNS[28] = 47; SU2ToCGNS[29] = 21; SU2ToCGNS[30] = 16; SU2ToCGNS[31] = 43; + SU2ToCGNS[32] = 44; SU2ToCGNS[33] = 39; SU2ToCGNS[34] = 19; SU2ToCGNS[35] = 57; + SU2ToCGNS[36] = 69; SU2ToCGNS[37] = 70; SU2ToCGNS[38] = 52; SU2ToCGNS[39] = 62; + SU2ToCGNS[40] = 71; SU2ToCGNS[41] = 53; SU2ToCGNS[42] = 61; SU2ToCGNS[43] = 48; + SU2ToCGNS[44] = 22; SU2ToCGNS[45] = 17; SU2ToCGNS[46] = 42; SU2ToCGNS[47] = 41; + SU2ToCGNS[48] = 40; SU2ToCGNS[49] = 20; SU2ToCGNS[50] = 58; SU2ToCGNS[51] = 72; + SU2ToCGNS[52] = 73; SU2ToCGNS[53] = 51; SU2ToCGNS[54] = 59; SU2ToCGNS[55] = 74; + SU2ToCGNS[56] = 50; SU2ToCGNS[57] = 60; SU2ToCGNS[58] = 49; SU2ToCGNS[59] = 23; + SU2ToCGNS[60] = 3; SU2ToCGNS[61] = 24; SU2ToCGNS[62] = 25; SU2ToCGNS[63] = 26; + SU2ToCGNS[64] = 4; SU2ToCGNS[65] = 32; SU2ToCGNS[66] = 63; SU2ToCGNS[67] = 64; + SU2ToCGNS[68] = 27; SU2ToCGNS[69] = 31; SU2ToCGNS[70] = 65; SU2ToCGNS[71] = 28; + SU2ToCGNS[72] = 30; SU2ToCGNS[73] = 29; SU2ToCGNS[74] = 5; +} + +void CCGNSElementType::CreateDataHEXA_8(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The HEXA_8 element is a linear hexahedron. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes (not present in HEXA_8). + - Third the face nodes (not present in HEXA_8). + - Fourth the volume nodes (not present in HEXA_8). + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = HEXAHEDRON; + nPoly = 1; + nDOFs = 8; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 3; SU2ToCGNS[3] = 2; + SU2ToCGNS[4] = 4; SU2ToCGNS[5] = 5; SU2ToCGNS[6] = 7; SU2ToCGNS[7] = 6; +} + +void CCGNSElementType::CreateDataHEXA_27(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The HEXA_27 element is a quadratic hexahedron. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes. + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = HEXAHEDRON; + nPoly = 2; + nDOFs = 27; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 8; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 11; + SU2ToCGNS[4] = 20; SU2ToCGNS[5] = 9; SU2ToCGNS[6] = 3; SU2ToCGNS[7] = 10; + SU2ToCGNS[8] = 2; SU2ToCGNS[9] = 12; SU2ToCGNS[10] = 21; SU2ToCGNS[11] = 13; + SU2ToCGNS[12] = 24; SU2ToCGNS[13] = 26; SU2ToCGNS[14] = 22; SU2ToCGNS[15] = 15; + SU2ToCGNS[16] = 23; SU2ToCGNS[17] = 14; SU2ToCGNS[18] = 4; SU2ToCGNS[19] = 16; + SU2ToCGNS[20] = 5; SU2ToCGNS[21] = 19; SU2ToCGNS[22] = 25; SU2ToCGNS[23] = 17; + SU2ToCGNS[24] = 7; SU2ToCGNS[25] = 18; SU2ToCGNS[26] = 6; +} + +void CCGNSElementType::CreateDataHEXA_64(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The HEXA_64 element is a cubic hexahedron. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes. + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = HEXAHEDRON; + nPoly = 3; + nDOFs = 64; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 8; SU2ToCGNS[2] = 9; SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 15; SU2ToCGNS[5] = 32; SU2ToCGNS[6] = 33; SU2ToCGNS[7] = 10; + SU2ToCGNS[8] = 14; SU2ToCGNS[9] = 35; SU2ToCGNS[10] = 34; SU2ToCGNS[11] = 11; + SU2ToCGNS[12] = 3; SU2ToCGNS[13] = 13; SU2ToCGNS[14] = 12; SU2ToCGNS[15] = 2; + SU2ToCGNS[16] = 16; SU2ToCGNS[17] = 36; SU2ToCGNS[18] = 37; SU2ToCGNS[19] = 18; + SU2ToCGNS[20] = 49; SU2ToCGNS[21] = 56; SU2ToCGNS[22] = 57; SU2ToCGNS[23] = 40; + SU2ToCGNS[24] = 48; SU2ToCGNS[25] = 59; SU2ToCGNS[26] = 58; SU2ToCGNS[27] = 41; + SU2ToCGNS[28] = 22; SU2ToCGNS[29] = 45; SU2ToCGNS[30] = 44; SU2ToCGNS[31] = 20; + SU2ToCGNS[32] = 17; SU2ToCGNS[33] = 39; SU2ToCGNS[34] = 38; SU2ToCGNS[35] = 19; + SU2ToCGNS[36] = 50; SU2ToCGNS[37] = 60; SU2ToCGNS[38] = 61; SU2ToCGNS[39] = 43; + SU2ToCGNS[40] = 51; SU2ToCGNS[41] = 63; SU2ToCGNS[42] = 62; SU2ToCGNS[43] = 42; + SU2ToCGNS[44] = 23; SU2ToCGNS[45] = 46; SU2ToCGNS[46] = 47; SU2ToCGNS[47] = 21; + SU2ToCGNS[48] = 4; SU2ToCGNS[49] = 24; SU2ToCGNS[50] = 25; SU2ToCGNS[51] = 5; + SU2ToCGNS[52] = 31; SU2ToCGNS[53] = 52; SU2ToCGNS[54] = 53; SU2ToCGNS[55] = 26; + SU2ToCGNS[56] = 30; SU2ToCGNS[57] = 55; SU2ToCGNS[58] = 54; SU2ToCGNS[59] = 27; + SU2ToCGNS[60] = 7; SU2ToCGNS[61] = 29; SU2ToCGNS[62] = 28; SU2ToCGNS[63] = 6; +} + +void CCGNSElementType::CreateDataHEXA_125(unsigned short &VTK_Type, + unsigned short &nPoly, + unsigned short &nDOFs, + vector &SU2ToCGNS) { + + /* The HEXA_125 element is a quartic hexahedron. In CGNS the nodes are + numbered as follows: - First the vertex nodes. + - Second the edge nodes. + - Third the face nodes. + - Fourth the volume nodes. + In SU2 the node numbering takes place along increasing i-, j- and k-lines, + where the i-direction is defined from node 0 to 1 and the j-direction + from node 0 along the second edge and the k-direction from node 0 along + the third edge. */ + VTK_Type = HEXAHEDRON; + nPoly = 4; + nDOFs = 125; + + SU2ToCGNS.resize(nDOFs); + SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 8; SU2ToCGNS[2] = 9; SU2ToCGNS[3] = 10; SU2ToCGNS[4] = 1; + SU2ToCGNS[5] = 19; SU2ToCGNS[6] = 44; SU2ToCGNS[7] = 45; SU2ToCGNS[8] = 46; SU2ToCGNS[9] = 11; + SU2ToCGNS[10] = 18; SU2ToCGNS[11] = 51; SU2ToCGNS[12] = 52; SU2ToCGNS[13] = 47; SU2ToCGNS[14] = 12; + SU2ToCGNS[15] = 17; SU2ToCGNS[16] = 50; SU2ToCGNS[17] = 49; SU2ToCGNS[18] = 48; SU2ToCGNS[19] = 13; + SU2ToCGNS[20] = 3; SU2ToCGNS[21] = 16; SU2ToCGNS[22] = 15; SU2ToCGNS[23] = 14; SU2ToCGNS[24] = 2; + SU2ToCGNS[25] = 20; SU2ToCGNS[26] = 53; SU2ToCGNS[27] = 54; SU2ToCGNS[28] = 55; SU2ToCGNS[29] = 23; + SU2ToCGNS[30] = 82; SU2ToCGNS[31] = 98; SU2ToCGNS[32] = 99; SU2ToCGNS[33] = 100; SU2ToCGNS[34] = 62; + SU2ToCGNS[35] = 81; SU2ToCGNS[36] = 105; SU2ToCGNS[37] = 106; SU2ToCGNS[38] = 101; SU2ToCGNS[39] = 63; + SU2ToCGNS[40] = 80; SU2ToCGNS[41] = 104; SU2ToCGNS[42] = 103; SU2ToCGNS[43] = 102; SU2ToCGNS[44] = 64; + SU2ToCGNS[45] = 29; SU2ToCGNS[46] = 73; SU2ToCGNS[47] = 72; SU2ToCGNS[48] = 71; SU2ToCGNS[49] = 26; + SU2ToCGNS[50] = 21; SU2ToCGNS[51] = 60; SU2ToCGNS[52] = 61; SU2ToCGNS[53] = 56; SU2ToCGNS[54] = 24; + SU2ToCGNS[55] = 83; SU2ToCGNS[56] = 107; SU2ToCGNS[57] = 108; SU2ToCGNS[58] = 109; SU2ToCGNS[59] = 69; + SU2ToCGNS[60] = 88; SU2ToCGNS[61] = 114; SU2ToCGNS[62] = 115; SU2ToCGNS[63] = 110; SU2ToCGNS[64] = 70; + SU2ToCGNS[65] = 87; SU2ToCGNS[66] = 113; SU2ToCGNS[67] = 112; SU2ToCGNS[68] = 111; SU2ToCGNS[69] = 65; + SU2ToCGNS[70] = 30; SU2ToCGNS[71] = 74; SU2ToCGNS[72] = 79; SU2ToCGNS[73] = 78; SU2ToCGNS[74] = 27; + SU2ToCGNS[75] = 22; SU2ToCGNS[76] = 59; SU2ToCGNS[77] = 58; SU2ToCGNS[78] = 57; SU2ToCGNS[79] = 25; + SU2ToCGNS[80] = 84; SU2ToCGNS[81] = 116; SU2ToCGNS[82] = 117; SU2ToCGNS[83] = 118; SU2ToCGNS[84] = 68; + SU2ToCGNS[85] = 85; SU2ToCGNS[86] = 123; SU2ToCGNS[87] = 124; SU2ToCGNS[88] = 119; SU2ToCGNS[89] = 67; + SU2ToCGNS[90] = 86; SU2ToCGNS[91] = 122; SU2ToCGNS[92] = 121; SU2ToCGNS[93] = 120; SU2ToCGNS[94] = 66; + SU2ToCGNS[95] = 31; SU2ToCGNS[96] = 75; SU2ToCGNS[97] = 76; SU2ToCGNS[98] = 77; SU2ToCGNS[99] = 28; + SU2ToCGNS[100] = 4; SU2ToCGNS[101] = 32; SU2ToCGNS[102] = 33; SU2ToCGNS[103] = 34; SU2ToCGNS[104] = 5; + SU2ToCGNS[105] = 43; SU2ToCGNS[106] = 89; SU2ToCGNS[107] = 90; SU2ToCGNS[108] = 91; SU2ToCGNS[109] = 35; + SU2ToCGNS[110] = 42; SU2ToCGNS[111] = 96; SU2ToCGNS[112] = 97; SU2ToCGNS[113] = 92; SU2ToCGNS[114] = 36; + SU2ToCGNS[115] = 41; SU2ToCGNS[116] = 95; SU2ToCGNS[117] = 94; SU2ToCGNS[118] = 93; SU2ToCGNS[119] = 37; + SU2ToCGNS[120] = 7; SU2ToCGNS[121] = 40; SU2ToCGNS[122] = 39; SU2ToCGNS[123] = 38; SU2ToCGNS[124] = 6; +} + +#endif diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp new file mode 100644 index 00000000000..9f527b4e6cc --- /dev/null +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp @@ -0,0 +1,550 @@ +/*! + * \file CCGNSMeshReaderFEM.cpp + * \brief Class that reads a single zone of a CGNS mesh file from disk into + * linear partitions across all ranks. + * \author T. Economon + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/toolboxes/CLinearPartitioner.hpp" +#include "../../../include/geometry/meshreader/CCGNSMeshReaderFEM.hpp" +#include "../../../include/geometry/meshreader/CCGNSElementType.hpp" + +CCGNSMeshReaderFEM::CCGNSMeshReaderFEM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) + : CCGNSMeshReaderBase(val_config, val_iZone, val_nZone) { +#ifdef HAVE_CGNS + OpenCGNSFile(config->GetMesh_FileName()); + + /*--- Read the basic information about the database and zone(s). ---*/ + ReadCGNSDatabaseMetadata(); + ReadCGNSZoneMetadata(); + + /*--- Read the volume connectivity and distribute it + linearly over the MPI ranks. ---*/ + ReadCGNSVolumeElementConnectivity(); + + /*--- Read the coordinates of the points and communicate the ones that + are needed on this MPI rank. ---*/ + ReadCGNSPointCoordinates(); + CommPointCoordinates(); + + /*--- Read the surface connectivity and store the surface elements whose + corresponding volume element is stored on this MPI rank. ---*/ + ReadCGNSSurfaceElementConnectivity(); + + /*--- We have extracted all CGNS data. Close the CGNS file. ---*/ + if (cg_close(cgnsFileID)) cg_error_exit(); + +#else + SU2_MPI::Error(string(" SU2 built without CGNS support. \n") + string(" To use CGNS, build SU2 accordingly."), + CURRENT_FUNCTION); +#endif +} + +CCGNSMeshReaderFEM::~CCGNSMeshReaderFEM() = default; + +#ifdef HAVE_CGNS +void CCGNSMeshReaderFEM::ReadCGNSConnectivityRangeSection(const int val_section, + const unsigned long val_firstIndex, + const unsigned long val_lastIndex, + unsigned long &elemCount, + unsigned long &localElemCount, + vector &localConn) { + + /*--- Read the connectivity details for this section. ---*/ + int nbndry, parent_flag; + cgsize_t startE, endE; + ElementType_t elemType; + char sectionName[CGNS_STRING_SIZE]; + + if(cg_section_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, sectionName, + &elemType, &startE, &endE, &nbndry, &parent_flag)) + cg_error_exit(); + + /*--- Determine the number of elements in this section and update + the element counters accordingly. ---*/ + const unsigned long nElemSection = (endE-startE+1); + const unsigned long elemCountOld = elemCount; + elemCount += nElemSection; + + /*--- Check for overlap with the element range this rank is responsible for. ---*/ + const unsigned long indBegOverlap = max(elemCountOld, val_firstIndex); + const unsigned long indEndOverlap = min(elemCount, val_lastIndex); + + if(indEndOverlap > indBegOverlap) { + + /*--- This rank must read element data from this connectivity section. + Determine the offset relative to the start of this section and + the number of elements to be read by this rank. ---*/ + const unsigned long offsetRank = indBegOverlap - elemCountOld; + const unsigned long nElemRank = indEndOverlap - indBegOverlap; + nElems[val_section] = nElemRank; + + /*--- Determine the index range to be read for this rank. ---*/ + const cgsize_t iBeg = startE + offsetRank; + const cgsize_t iEnd = iBeg + nElemRank -1; + + /*--- Determine the size of the vector needed to read + the connectivity data from the CGNS file. ---*/ + cgsize_t sizeNeeded; + if (cg_ElementPartialSize(cgnsFileID, cgnsBase, cgnsZone, val_section+1, + iBeg, iEnd, &sizeNeeded) != CG_OK) + cg_error_exit(); + + /*--- Allocate the memory for the connectivity and read the data. ---*/ + vector connCGNSVec(sizeNeeded); + if (elemType == MIXED) { + vector connCGNSOffsetVec(iEnd-iBeg+2); + if(cg_poly_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, + iBeg, iEnd, connCGNSVec.data(), + connCGNSOffsetVec.data(), NULL) != CG_OK) + cg_error_exit(); + + } else { + if(cg_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, + iBeg, iEnd, connCGNSVec.data(), NULL) != CG_OK) + cg_error_exit(); + } + + /*--- Define the variables needed for the conversion of the CGNS + format to the SU2 internal format. ---*/ + CCGNSElementType CGNSElem; + std::vector connSU2; + ElementType_t typeElem = elemType; + const cgsize_t *connCGNS = connCGNSVec.data(); + + /*--- Loop over the elements just read. ---*/ + for(unsigned long i=0; i SINGLE_NODE) + cout << "Loading volume elements into linear partitions." << endl; + else + cout << "Loading volume elements." << endl; + } + + /*--- Get a partitioner to help with linear partitioning. ---*/ + CLinearPartitioner elemPartitioner(numberOfGlobalElements,0); + + /*--- Determine the index of the first and last element to be stored + on this rank and the number of local elements. ---*/ + const unsigned long firstIndex = elemPartitioner.GetFirstIndexOnRank(rank); + const unsigned long lastIndex = elemPartitioner.GetLastIndexOnRank(rank); + numberOfLocalElements = elemPartitioner.GetSizeOnRank(rank); + + /*--- Loop over the section and check for a section with volume elements. ---*/ + unsigned long elemCount = 0, localElemCount = 0; + for(int s=0; s localFaces; + DetermineFacesVolumeElements(localFaces); + + /*--- Determine the number of markers. ---*/ + numberOfMarkers = 0; + for (int s = 0; s < nSections; s++) + if (!isInterior[s]) ++numberOfMarkers; + + /*--- Allocate the memory for the number of markers and local surface elements. + Also allocate the first index of surfaceElementConnectivity. ---*/ + markerNames.resize(numberOfMarkers); + numberOfLocalSurfaceElements.resize(numberOfMarkers); + surfaceElementConnectivity.resize(numberOfMarkers); + + /*--- Loop over the number of sections and check for a surface. ---*/ + int markerCount = 0; + for(int s=0; s &localFaces, + unsigned long &nSurfElem, + vector &surfConn) { + + /*--- Initialize nSurfElem to zero. ---*/ + nSurfElem = 0; + + /*--- Read the connectivity details for this section and determine the number + of elements present in this section. ---*/ + int nbndry, parent_flag; + cgsize_t startE, endE; + ElementType_t elemType; + char sectionName[CGNS_STRING_SIZE]; + + if(cg_section_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, sectionName, + &elemType, &startE, &endE, &nbndry, &parent_flag)) + cg_error_exit(); + + const unsigned long nElemSection = (endE-startE+1); + + /*--- Determine the number of chunks used for the reading of the surface + elements. This is done to avoid a memory bottleneck for extremely + big cases. For reasonably sized grids this connectivity can be + read in a single call. ---*/ + unsigned long nChunks = nElemSection/localFaces.size(); + if(nChunks*localFaces.size() != nElemSection) ++nChunks; + const unsigned long nElemChunk = nElemSection/nChunks; + + /*--- Loop over the number of chunks. ---*/ + for(unsigned long iChunk=0; iChunk connCGNSVec(sizeNeeded); + if (elemType == MIXED) { + vector connCGNSOffsetVec(iEnd-iBeg+2); + if(cg_poly_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, + iBeg, iEnd, connCGNSVec.data(), + connCGNSOffsetVec.data(), NULL) != CG_OK) + cg_error_exit(); + + } else { + if(cg_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, + iBeg, iEnd, connCGNSVec.data(), NULL) != CG_OK) + cg_error_exit(); + } + + /*--- Define the variables needed for the conversion of the CGNS + format to the SU2 internal format. ---*/ + CCGNSElementType CGNSElem; + std::vector connSU2; + ElementType_t typeElem = elemType; + const cgsize_t *connCGNS = connCGNSVec.data(); + + /*--- Loop over the elements just read. ---*/ + for(cgsize_t i=iBeg; i<=iEnd; ++i) { + + /*--- Determine the element type for this element if this is a mixed + connectivity and set the pointer to the actual connectivity data. ---*/ + if(elemType == MIXED) { + typeElem = (ElementType_t) connCGNS[0]; + ++connCGNS; + } + + /*--- Convert the CGNS connectivity to SU2 connectivity and update + the pointer for the next surface element. ---*/ + const unsigned long globalID = i-1; + CGNSElem.CGNSToSU2(typeElem, globalID, connCGNS, connSU2); + connCGNS += connSU2[3]; + + /*--- Easier storage of the VTK type, polynomial degree + and number of DOFs of the surface element. ---*/ + const unsigned short VTK_Type = (unsigned short) connSU2[0]; + const unsigned short nPolyGrid = (unsigned short) connSU2[1]; + const unsigned short nDOFsGrid = (unsigned short) connSU2[3]; + + /*--- Make a distinction between the possible element surface types and + determine the corner points in local numbering of the element. ---*/ + const unsigned short nDOFEdgeGrid = nPolyGrid + 1; + + CFaceOfElement thisFace; + thisFace.cornerPoints[0] = 0; thisFace.cornerPoints[1] = nPolyGrid; + + switch( VTK_Type ) { + case LINE: + thisFace.nCornerPoints = 2; + break; + + case TRIANGLE: + thisFace.nCornerPoints = 3; + thisFace.cornerPoints[2] = nDOFsGrid -1; + break; + + case QUADRILATERAL: + thisFace.nCornerPoints = 4; + thisFace.cornerPoints[2] = nPolyGrid*nDOFEdgeGrid; + thisFace.cornerPoints[3] = nDOFsGrid -1; + break; + + default: + ostringstream message; + message << "Unsupported FEM boundary element value, " << typeElem + << ", in surface section " << sectionName; + SU2_MPI::Error(message.str(), CURRENT_FUNCTION); + } + + /*--- Convert the local numbering of thisFace to global numbering + and create a unique numbering of corner points. ---*/ + for(unsigned short j=0; j::const_iterator low; + low = lower_bound(localFaces.begin(), localFaces.end(), thisFace); + if(low != localFaces.end()) { + if( !(thisFace < *low) ) { + + /*--- Update the number of local surface elements. ---*/ + ++nSurfElem; + + /*--- Store the meta data in the first 5 locations of connSU2. ---*/ + connSU2[0] = VTK_Type; + connSU2[1] = nPolyGrid; + connSU2[2] = nDOFsGrid; + connSU2[3] = globalID; // Global surface elem ID. + connSU2[4] = low->elemID0; // Global volume elem ID. + + /*--- Store the connectivity data in surfConn. ---*/ + surfConn.insert(surfConn.end(), connSU2.begin(), connSU2.end()); + } + } + } + } +} +#endif + +void CCGNSMeshReaderFEM::CommPointCoordinates(void) { + + /*--- Determine the linear partitioning of the points. ---*/ + CLinearPartitioner pointPartitioner(numberOfGlobalPoints,0); + + /*--- Loop over the local elements to determine the global + point IDs to be stored on this rank. --*/ + unsigned long ind = 0; + for(unsigned long i=0; i::iterator lastNode; + lastNode = unique(globalPointIDs.begin(), globalPointIDs.end()); + globalPointIDs.erase(lastNode, globalPointIDs.end()); + + /*--- Determine the number of locally stored points. ---*/ + numberOfLocalPoints = globalPointIDs.size(); + + /*--- This rest of this function only needs to done when MPI is used. ---*/ +#ifdef HAVE_MPI + + /*--- Store the global ID's of the points in such a way that they can + be sent to the rank that actually stores the coordinates.. ---*/ + vector > pointBuf(size, vector(0)); + + for(unsigned long i=0; i sendToRank(size, 0); + vector startingIndRanksInPoint(size+1); + startingIndRanksInPoint[0] = 0; + + for(int i=0; i sizeRecv(size, 1); + SU2_MPI::Reduce_scatter(sendToRank.data(), &nRankRecv, sizeRecv.data(), + MPI_INT, MPI_SUM, SU2_MPI::GetComm()); + + /*--- Send out the messages with the global point numbers. Use nonblocking + sends to avoid deadlock. ---*/ + vector sendReqs(nRankSend); + nRankSend = 0; + for(int i=0; i returnReqs(nRankRecv); + vector > coorReturnBuf(nRankRecv, vector(0)); + + /*--- Get the first index of the points as well as the number of points + currently stored on this rank. ---*/ + const unsigned long firstIndex = pointPartitioner.GetFirstIndexOnRank(rank); + const unsigned long nPointsRead = pointPartitioner.GetSizeOnRank(rank); + + /*--- Loop over the number of ranks from which this rank receives global + point numbers that should be stored on this rank. ---*/ + for(int i=0; i pointRecvBuf(sizeMess); + coorReturnBuf[i].resize(dimension*sizeMess); + + /* Receive the message using a blocking receive. */ + SU2_MPI::Recv(pointRecvBuf.data(), sizeMess, MPI_UNSIGNED_LONG, + source, rank, SU2_MPI::GetComm(), &status); + + /*--- Loop over the nodes just received and fill the return communication + buffer with the coordinates of the requested nodes. ---*/ + for(int j=0; j= static_cast(nPointsRead)) + SU2_MPI::Error("Invalid point requested. This should not happen.", CURRENT_FUNCTION); + + for(int k=0; k coorRecvBuf(dimension*pointBuf[source].size()); + + /* Receive the message using a blocking receive. */ + SU2_MPI::Recv(coorRecvBuf.data(), coorRecvBuf.size(), MPI_DOUBLE, + source, rank+1, SU2_MPI::GetComm(), &status); + + /*--- Loop over the points just received. ---*/ + for(unsigned long j=0; j &localFaces) { + + /*--- Loop over the locally stored volume elements. ---*/ + unsigned long ind = 0; + for(unsigned long k=0; k::iterator lastFace; + lastFace = unique(localFaces.begin(), localFaces.end()); + localFaces.erase(lastFace, localFaces.end()); +} + +void CMeshReaderBase::GetCornerPointsAllFaces(const unsigned long *elemInfo, + unsigned short &numFaces, + unsigned short nPointsPerFace[], + unsigned long faceConn[6][4]) { + + /*--- Retrieve the element type, polynomial degree of the grid and + number of DOFs for this element and set the pointer for the + connectivity information. ---*/ + const unsigned short VTK_Type = (const unsigned short) elemInfo[0]; + const unsigned short nPolyGrid = (const unsigned short) elemInfo[1]; + const unsigned short nDOFsGrid = (const unsigned short) elemInfo[3]; + const unsigned long *conn = elemInfo + 5; + + /*--- Call the static function GetLocalCornerPointsAllFaces of CPrimalGridFEM + to determine the local numbering of the corner points of the faces. ---*/ + CPrimalGridFEM::GetLocalCornerPointsAllFaces(VTK_Type, nPolyGrid, nDOFsGrid, + numFaces, nPointsPerFace, faceConn); + + /*--- Convert the local values of faceConn to global values. ---*/ + for(unsigned short i=0; i Date: Mon, 3 Feb 2025 11:18:22 +0100 Subject: [PATCH 120/129] The reading of SU2 ASCII files for the FEM solver done via the meshreader classes --- Common/include/geometry/CPhysicalGeometry.hpp | 11 - .../meshreader/CCGNSMeshReaderFEM.hpp | 5 - .../meshreader/CCGNSMeshReaderFVM.hpp | 5 - .../meshreader/CSU2ASCIIMeshReaderBase.hpp | 6 +- .../meshreader/CSU2ASCIIMeshReaderFEM.hpp | 64 +++ .../src/fem/geometry_structure_fem_part.cpp | 439 ------------------ Common/src/geometry/CPhysicalGeometry.cpp | 4 +- .../meshreader/CCGNSMeshReaderFEM.cpp | 4 +- .../meshreader/CCGNSMeshReaderFVM.cpp | 2 - .../meshreader/CSU2ASCIIMeshReaderFEM.cpp | 379 +++++++++++++++ Common/src/geometry/meshreader/meson.build | 1 + 11 files changed, 451 insertions(+), 469 deletions(-) create mode 100644 Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp create mode 100644 Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp diff --git a/Common/include/geometry/CPhysicalGeometry.hpp b/Common/include/geometry/CPhysicalGeometry.hpp index b20b2991566..20dba58e52e 100644 --- a/Common/include/geometry/CPhysicalGeometry.hpp +++ b/Common/include/geometry/CPhysicalGeometry.hpp @@ -288,17 +288,6 @@ class CPhysicalGeometry final : public CGeometry { void Read_Mesh(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, unsigned short val_nZone); - /*! - * \brief Reads for the FEM solver the geometry of the grid and adjust the boundary - * conditions with the configuration file in parallel (for parmetis). - * \param[in] config - Definition of the particular problem. - * \param[in] val_mesh_filename - Name of the file with the grid information. - * \param[in] val_iZone - Domain to be read from the grid file. - * \param[in] val_nZone - Total number of domains in the grid file. - */ - void Read_SU2_Format_Parallel_FEM(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, - unsigned short val_nZone); - /*! * \brief Routine to load the CGNS grid points from a single zone into the proper SU2 data structures. * \param[in] config - definition of the particular problem. diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp index dfd8aa7c680..8a23b248d89 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp @@ -92,9 +92,4 @@ class CCGNSMeshReaderFEM final : public CCGNSMeshReaderBase { CCGNSMeshReaderFEM(CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone); - - /*! - * \brief Destructor of the CCGNSMeshReaderFEM class. - */ - ~CCGNSMeshReaderFEM(void); }; diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp index 8e7770c973a..9e22b191fad 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp @@ -92,9 +92,4 @@ class CCGNSMeshReaderFVM final : public CCGNSMeshReaderBase { * \brief Constructor of the CCGNSMeshReaderFVM class. */ CCGNSMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); - - /*! - * \brief Destructor of the CCGNSMeshReaderFVM class. - */ - ~CCGNSMeshReaderFVM(void); }; diff --git a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp index 891141cf9ad..66ecbf97095 100644 --- a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp +++ b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp @@ -86,17 +86,17 @@ class CSU2ASCIIMeshReaderBase : public CMeshReaderBase { /*! * \brief Reads the grid points from an SU2 zone into linear partitions across all ranks. */ - void ReadPointCoordinates(const bool single_pass = false); + virtual void ReadPointCoordinates(const bool single_pass = false); /*! * \brief Reads the interior volume elements from one section of an SU2 zone into linear partitions across all ranks. */ - void ReadVolumeElementConnectivity(const bool single_pass = false); + virtual void ReadVolumeElementConnectivity(const bool single_pass = false); /*! * \brief Reads the surface (boundary) elements from the SU2 zone. */ - void ReadSurfaceElementConnectivity(const bool single_pass = false); + virtual void ReadSurfaceElementConnectivity(const bool single_pass = false); /*! * \brief Helper function to find the current zone in an SU2 ASCII mesh object. diff --git a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp new file mode 100644 index 00000000000..6bf11a92dec --- /dev/null +++ b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp @@ -0,0 +1,64 @@ +/*! + * \file CSU2ASCIIMeshReaderFEM.hpp + * \brief Header file for the class CSU2ASCIIMeshReaderFEM. + * The implementations are in the CSU2ASCIIMeshReaderFEM.cpp file. + * \author T. Economon, E. van der Weide + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include + +#include "CSU2ASCIIMeshReaderBase.hpp" + +/*! + * \class CSU2ASCIIMeshReaderFEM + * \brief Reads a native SU2 ASCII grid into linear partitions for the finite element solver (FEM). + * \author T. Economon, E. van der Weide + */ +class CSU2ASCIIMeshReaderFEM : public CSU2ASCIIMeshReaderBase { + private: + /*! + * \brief Reads the grid points from an SU2 zone into linear partitions across all ranks. + */ + void ReadPointCoordinates(); + + /*! + * \brief Reads the interior volume elements from one section of an SU2 zone into linear partitions across all ranks. + */ + void ReadVolumeElementConnectivity(); + + /*! + * \brief Reads the surface (boundary) elements from one section of an SU2 zone into linear partitions across all ranks. + */ + void ReadSurfaceElementConnectivity(); + + public: + /*! + * \brief Constructor of the CSU2ASCIIMeshReaderFEM class. + */ + CSU2ASCIIMeshReaderFEM(CConfig *val_config, + unsigned short val_iZone, + unsigned short val_nZone); +}; diff --git a/Common/src/fem/geometry_structure_fem_part.cpp b/Common/src/fem/geometry_structure_fem_part.cpp index 0af57647bac..c3a3547bf1d 100644 --- a/Common/src/fem/geometry_structure_fem_part.cpp +++ b/Common/src/fem/geometry_structure_fem_part.cpp @@ -360,445 +360,6 @@ void CMatchingFace::Copy(const CMatchingFace& other) { tolForMatching = other.tolForMatching; } -void CPhysicalGeometry::Read_SU2_Format_Parallel_FEM(CConfig* config, const string& val_mesh_filename, - unsigned short val_iZone, unsigned short val_nZone) { - string text_line, Marker_Tag; - ifstream mesh_file; - string::size_type position; - unsigned long nDOFsGrid_Local = 0, loc_element_count = 0; - bool domain_flag = false; - bool time_spectral = config->GetTime_Marching() == TIME_MARCHING::HARMONIC_BALANCE; - unsigned short nMarker_Max = config->GetnMarker_Max(); - nZone = val_nZone; - - /*--- Initialize counters for local/global points & elements ---*/ - Global_nPoint = 0; - Global_nPointDomain = 0; - Global_nElem = 0; - nelem_edge = 0; - Global_nelem_edge = 0; - nelem_triangle = 0; - Global_nelem_triangle = 0; - nelem_quad = 0; - Global_nelem_quad = 0; - nelem_tetra = 0; - Global_nelem_tetra = 0; - nelem_hexa = 0; - Global_nelem_hexa = 0; - nelem_prism = 0; - Global_nelem_prism = 0; - nelem_pyramid = 0; - Global_nelem_pyramid = 0; - - /*--- Allocate memory for the linear partition of the elements of the mesh. - These arrays are the size of the number of ranks. ---*/ - - beg_node = new unsigned long[size]; - end_node = new unsigned long[size]; - nPointLinear = new unsigned long[size]; - - /*--- Open grid file ---*/ - - mesh_file.open(val_mesh_filename.c_str(), ios::in); - - /*--- Check the grid ---*/ - - if (mesh_file.fail()) - SU2_MPI::Error(string("There is no mesh file (CPhysicalGeometry)!! ") + val_mesh_filename, CURRENT_FUNCTION); - - /*--- If more than one, find the zone in the mesh file ---*/ - - if (val_nZone > 1 || time_spectral) { - if (time_spectral) { - if (rank == MASTER_NODE) cout << "Reading time spectral instance " << val_iZone + 1 << ":" << endl; - } else { - while (getline(mesh_file, text_line)) { - /*--- Search for the current domain ---*/ - position = text_line.find("IZONE=", 0); - if (position != string::npos) { - text_line.erase(0, 6); - unsigned short jDomain = atoi(text_line.c_str()); - if (jDomain == val_iZone + 1) { - if (rank == MASTER_NODE) cout << "Reading zone " << val_iZone + 1 << " points:" << endl; - break; - } - } - } - } - } - - /*--- Read grid file with format SU2 ---*/ - - while (getline(mesh_file, text_line)) { - /*--- Read the dimension of the problem ---*/ - - position = text_line.find("NDIME=", 0); - if (position != string::npos) { - if (!domain_flag) { - text_line.erase(0, 6); - nDim = atoi(text_line.c_str()); - if (rank == MASTER_NODE) { - if (nDim == 2) cout << "Two dimensional problem." << endl; - if (nDim == 3) cout << "Three dimensional problem." << endl; - } - domain_flag = true; - } else { - break; - } - } - - /*--- Read the information about inner elements ---*/ - - position = text_line.find("NELEM=", 0); - if (position != string::npos) { - text_line.erase(0, 6); - stringstream stream_line(text_line); - stream_line >> Global_nElem; - - if ((rank == MASTER_NODE) && (size > SINGLE_NODE)) - cout << Global_nElem << " interior elements before parallel partitioning." << endl; - - /*--- Check if the number of cores used is larger than the number of - elements. Terminate if this is the case, because it does not make - sense to do this. ---*/ - unsigned long nCores = size; // Correct for the number of cores per rank. - if (nCores > Global_nElem) { - ostringstream message; - message << "The number of cores, " << nCores; - message << ", is larger than the number of elements, " << Global_nElem << "." << endl; - message << "This is not an efficient use of the resources and therefore " - << "SU2 will terminate."; - - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } - - /*--- Compute the number of elements that will be on each processor. - This is a linear partitioning with the addition of a simple load - balancing for any remainder elements. ---*/ - unsigned long total_elem_accounted = 0; - for (unsigned long i = 0; i < (unsigned long)size; i++) { - nPointLinear[i] = Global_nElem / size; - total_elem_accounted = total_elem_accounted + nPointLinear[i]; - } - - /*--- Get the number of remainder elements after the even division ---*/ - unsigned long rem_elem = Global_nElem - total_elem_accounted; - for (unsigned long i = 0; i < rem_elem; i++) { - ++nPointLinear[i]; - } - - /*--- Store the local number of elements and the beginning/end index ---*/ - nElem = nPointLinear[rank]; - beg_node[0] = 0; - end_node[0] = beg_node[0] + nPointLinear[0]; - for (unsigned long i = 1; i < (unsigned long)size; i++) { - beg_node[i] = end_node[i - 1]; - end_node[i] = beg_node[i] + nPointLinear[i]; - } - - /*--- Allocate space for elements ---*/ - elem = new CPrimalGrid*[nElem](); - - /*--- Loop over all the elements and store the elements to be stored on - this rank. Furthermore, determine the total amount of DOFs for - the solution (which may differ from the number of DOFS for the - grid). ---*/ - unsigned long nDOFs_tot = 0; - for (unsigned long i = 0; i < Global_nElem; i++) { - getline(mesh_file, text_line); - istringstream elem_line(text_line); - - /*--- Read the value that defines the element type, the polynomial - degree of the geometry and the polynomial degree of the - solution. Extract this info as well. ---*/ - unsigned long typeRead; - elem_line >> typeRead; - unsigned long typeReadErrorMessage = typeRead; - unsigned short nPolySol, nPolyGrid; - if (typeRead > 10000) { - nPolySol = typeRead / 10000 - 1; - typeRead = typeRead % 10000; - nPolyGrid = typeRead / 100 + 1; - } else { - nPolyGrid = typeRead / 100 + 1; - nPolySol = nPolyGrid; - } - - unsigned short VTK_Type = typeRead % 100; - - unsigned short nDOFsGrid = CFEMStandardElementBase::GetNDOFsStatic(VTK_Type, nPolyGrid, typeReadErrorMessage); - unsigned short nDOFsSol = CFEMStandardElementBase::GetNDOFsStatic(VTK_Type, nPolySol, typeReadErrorMessage); - - /*--- Allocate the memory for a new primary grid FEM element if - this element must be stored on this rank. ---*/ - if ((i >= beg_node[rank]) && (i < end_node[rank])) { - elem[loc_element_count] = - new CPrimalGridFEM(i, VTK_Type, nPolyGrid, nPolySol, nDOFsGrid, nDOFsSol, nDOFs_tot, elem_line); - nDOFsGrid_Local += nDOFsGrid; - loc_element_count++; - } - - /*--- Update the total value of the number of DOFs. ---*/ - nDOFs_tot += nDOFsSol; - } - - /*--- Break from the loop to find the element information. ---*/ - break; - } - } - - mesh_file.close(); - - /*--- Create a vector, which contains the global node IDs of the local elements. ---*/ - vector nodeIDsElemLoc; - nodeIDsElemLoc.reserve(nDOFsGrid_Local); - for (unsigned long i = 0; i < loc_element_count; i++) { - unsigned short nDOFsElem = elem[i]->GetnNodes(); - for (unsigned short j = 0; j < nDOFsElem; ++j) nodeIDsElemLoc.push_back(elem[i]->GetNode(j)); - } - - sort(nodeIDsElemLoc.begin(), nodeIDsElemLoc.end()); - vector::iterator lastNode; - lastNode = unique(nodeIDsElemLoc.begin(), nodeIDsElemLoc.end()); - nodeIDsElemLoc.erase(lastNode, nodeIDsElemLoc.end()); - - /*--- Allocate the memory for the coordinates to be stored on this rank. ---*/ - nPoint = nodeIDsElemLoc.size(); - nodes = new CPoint(nPoint, nDim); - - /*--- Open the grid file again and go to the position where - the correct zone is stored. ---*/ - mesh_file.open(val_mesh_filename.c_str(), ios::in); - - if (val_nZone > 1 && !time_spectral) { - while (getline(mesh_file, text_line)) { - position = text_line.find("IZONE=", 0); - if (position != string::npos) { - text_line.erase(0, 6); - unsigned short jDomain = atoi(text_line.c_str()); - if (jDomain == val_iZone + 1) break; - } - } - } - - /*--- While loop to read the point information. ---*/ - while (getline(mesh_file, text_line)) { - position = text_line.find("NPOIN=", 0); - if (position != string::npos) { - text_line.erase(0, 6); - stringstream stream_line(text_line); - stream_line >> Global_nPoint; - - /*--- Loop over the global number of points and store the - ones that are needed on this processor. ---*/ - unsigned long ii = 0; - for (unsigned long i = 0; i < Global_nPoint; ++i) { - getline(mesh_file, text_line); - - if (binary_search(nodeIDsElemLoc.begin(), nodeIDsElemLoc.end(), i)) { - istringstream point_line(text_line); - su2double Coord[3] = {0.0}; - point_line >> Coord[0]; - point_line >> Coord[1]; - if (nDim == 3) point_line >> Coord[2]; - nodes->SetCoord(ii, Coord); - nodes->SetGlobalIndex(ii, i); - ++ii; - } - } - - break; - } - } - - mesh_file.close(); - - /*--- Determine the faces of the local elements. --- */ - vector localFaces; - for (unsigned long k = 0; k < loc_element_count; k++) { - /*--- Get the global IDs of the corner points of all the faces of this elements. ---*/ - unsigned short nFaces; - unsigned short nPointsPerFace[6]; - unsigned long faceConn[6][4]; - - elem[k]->GetCornerPointsAllFaces(nFaces, nPointsPerFace, faceConn); - - /*--- Loop over the faces and add them to localFaces. ---*/ - for (unsigned short i = 0; i < nFaces; ++i) { - CFaceOfElement thisFace; - thisFace.nCornerPoints = nPointsPerFace[i]; - for (unsigned short j = 0; j < nPointsPerFace[i]; ++j) thisFace.cornerPoints[j] = faceConn[i][j]; - thisFace.elemID0 = k + beg_node[rank]; - - thisFace.CreateUniqueNumbering(); - localFaces.push_back(thisFace); - } - } - - /*--- Sort localFaces in increasing order and remove the double entities, - such that the binary search later on is a bit more efficient. ---*/ - sort(localFaces.begin(), localFaces.end()); - vector::iterator lastFace; - lastFace = unique(localFaces.begin(), localFaces.end()); - localFaces.erase(lastFace, localFaces.end()); - - /*--- Open the grid file again and go to the position where - the correct zone is stored. ---*/ - mesh_file.open(val_mesh_filename.c_str(), ios::in); - - if (val_nZone > 1 && !time_spectral) { - while (getline(mesh_file, text_line)) { - position = text_line.find("IZONE=", 0); - if (position != string::npos) { - text_line.erase(0, 6); - unsigned short jDomain = atoi(text_line.c_str()); - if (jDomain == val_iZone + 1) break; - } - } - } - - /*--- While loop to read the boundary information. ---*/ - while (getline(mesh_file, text_line)) { - /*--- Read number of markers ---*/ - position = text_line.find("NMARK=", 0); - if (position != string::npos) { - text_line.erase(0, 6); - istringstream stream_line(text_line); - stream_line >> nMarker; - - if (rank == MASTER_NODE) cout << nMarker << " surface markers." << endl; - config->SetnMarker_All(nMarker); - bound = new CPrimalGrid**[nMarker]; - nElem_Bound = new unsigned long[nMarker]; - Tag_to_Marker = new string[nMarker_Max]; - - for (unsigned short iMarker = 0; iMarker < nMarker; iMarker++) { - getline(mesh_file, text_line); - text_line.erase(0, 11); - text_line.erase(remove(text_line.begin(), text_line.end(), ' '), text_line.end()); - text_line.erase(remove(text_line.begin(), text_line.end(), '\r'), text_line.end()); - text_line.erase(remove(text_line.begin(), text_line.end(), '\n'), text_line.end()); - - Marker_Tag = text_line; - - /*--- Read the number of elements for this marker. ---*/ - getline(mesh_file, text_line); - text_line.erase(0, 13); - istringstream nmark_line(text_line); - unsigned long nElem_Bound_Global; - nmark_line >> nElem_Bound_Global; - if (rank == MASTER_NODE) - cout << nElem_Bound_Global << " boundary elements in index " << iMarker << " (Marker = " << Marker_Tag << ")." - << endl; - - /*--- Define a vector of FEM boundary elements to store the local boundary faces. ---*/ - vector boundElems; - - /*--- Loop over the global boundary faces. ---*/ - for (unsigned long i = 0; i < nElem_Bound_Global; ++i) { - getline(mesh_file, text_line); - istringstream bound_line(text_line); - - /*--- Determine the element type, its number of DOFs and read - its node IDs. ---*/ - unsigned long typeRead; - bound_line >> typeRead; - unsigned short nPolyGrid = typeRead / 100 + 1; - unsigned short VTK_Type = typeRead % 100; - unsigned short nDOFEdgeGrid = nPolyGrid + 1; - - unsigned short nDOFsGrid = 0; - CFaceOfElement thisFace; - thisFace.cornerPoints[0] = 0; - thisFace.cornerPoints[1] = nPolyGrid; - switch (VTK_Type) { - case LINE: - nDOFsGrid = nDOFEdgeGrid; - thisFace.nCornerPoints = 2; - break; - - case TRIANGLE: - nDOFsGrid = nDOFEdgeGrid * (nDOFEdgeGrid + 1) / 2; - thisFace.nCornerPoints = 3; - thisFace.cornerPoints[2] = nDOFsGrid - 1; - break; - - case QUADRILATERAL: - nDOFsGrid = nDOFEdgeGrid * nDOFEdgeGrid; - thisFace.nCornerPoints = 4; - thisFace.cornerPoints[2] = nPolyGrid * nDOFEdgeGrid; - thisFace.cornerPoints[3] = nDOFsGrid - 1; - break; - - default: - ostringstream message; - message << "Unknown FEM boundary element value, " << typeRead << ", in " << val_mesh_filename; - SU2_MPI::Error(message.str(), CURRENT_FUNCTION); - } - - vector nodeIDs(nDOFsGrid); - for (unsigned short j = 0; j < nDOFsGrid; ++j) bound_line >> nodeIDs[j]; - - /*--- Convert the local numbering of thisFace to global numbering - and create a unique numbering of these nodes. ---*/ - for (unsigned short j = 0; j < thisFace.nCornerPoints; ++j) - thisFace.cornerPoints[j] = nodeIDs[thisFace.cornerPoints[j]]; - thisFace.CreateUniqueNumbering(); - - /*--- Check if this boundary face must be stored on this rank. - If so, create an object of CBoundaryFace and add it - to boundElems. ---*/ - vector::iterator low; - low = lower_bound(localFaces.begin(), localFaces.end(), thisFace); - if (low != localFaces.end()) { - if (!(thisFace < *low)) { - CBoundaryFace thisBoundFace; - thisBoundFace.VTK_Type = VTK_Type; - thisBoundFace.nPolyGrid = nPolyGrid; - thisBoundFace.nDOFsGrid = nDOFsGrid; - thisBoundFace.globalBoundElemID = i; - thisBoundFace.domainElementID = low->elemID0; - thisBoundFace.Nodes = nodeIDs; - - boundElems.push_back(thisBoundFace); - } - } - } - - /*--- Allocate space for the boundary elements and store the ones - whose parent element is stored on this rank. ---*/ - nElem_Bound[iMarker] = boundElems.size(); - bound[iMarker] = new CPrimalGrid*[nElem_Bound[iMarker]]; - - for (unsigned long i = 0; i < nElem_Bound[iMarker]; ++i) - bound[iMarker][i] = new CPrimalGridBoundFEM(boundElems[i].globalBoundElemID, boundElems[i].domainElementID, - boundElems[i].VTK_Type, boundElems[i].nPolyGrid, - boundElems[i].nDOFsGrid, boundElems[i].Nodes); - - /*--- Update config information storing the boundary information in the right place ---*/ - Tag_to_Marker[config->GetMarker_CfgFile_TagBound(Marker_Tag)] = Marker_Tag; - config->SetMarker_All_TagBound(iMarker, Marker_Tag); - config->SetMarker_All_KindBC(iMarker, config->GetMarker_CfgFile_KindBC(Marker_Tag)); - config->SetMarker_All_Monitoring(iMarker, config->GetMarker_CfgFile_Monitoring(Marker_Tag)); - config->SetMarker_All_GeoEval(iMarker, config->GetMarker_CfgFile_GeoEval(Marker_Tag)); - config->SetMarker_All_Designing(iMarker, config->GetMarker_CfgFile_Designing(Marker_Tag)); - config->SetMarker_All_Plotting(iMarker, config->GetMarker_CfgFile_Plotting(Marker_Tag)); - config->SetMarker_All_Analyze(iMarker, config->GetMarker_CfgFile_Analyze(Marker_Tag)); - config->SetMarker_All_ZoneInterface(iMarker, config->GetMarker_CfgFile_ZoneInterface(Marker_Tag)); - config->SetMarker_All_DV(iMarker, config->GetMarker_CfgFile_DV(Marker_Tag)); - config->SetMarker_All_Moving(iMarker, config->GetMarker_CfgFile_Moving(Marker_Tag)); - config->SetMarker_All_SobolevBC(iMarker, config->GetMarker_CfgFile_SobolevBC(Marker_Tag)); - config->SetMarker_All_PerBound(iMarker, config->GetMarker_CfgFile_PerBound(Marker_Tag)); - config->SetMarker_All_SendRecv(iMarker, NONE); - } - - break; - } - } - - mesh_file.close(); -} - void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { /*--- Initialize the color vector of the elements. ---*/ for (unsigned long i = 0; i < nElem; ++i) elem[i]->SetColor(0); diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index 6f7f4a0fe98..b53f2ba62c6 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -31,6 +31,7 @@ #include "../../include/toolboxes/CLinearPartitioner.hpp" #include "../../include/toolboxes/C1DInterpolation.hpp" #include "../../include/toolboxes/geometry_toolbox.hpp" +#include "../../include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp" #include "../../include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp" #include "../../include/geometry/meshreader/CCGNSMeshReaderFVM.hpp" #include "../../include/geometry/meshreader/CCGNSMeshReaderFEM.hpp" @@ -3449,7 +3450,8 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena CMeshReaderBase* Mesh = nullptr; switch (val_format) { case SU2: - Mesh = new CSU2ASCIIMeshReaderFVM(config, val_iZone, val_nZone); + if (fem_solver) Mesh = new CSU2ASCIIMeshReaderFEM(config, val_iZone, val_nZone); + else Mesh = new CSU2ASCIIMeshReaderFVM(config, val_iZone, val_nZone); break; case CGNS_GRID: if (fem_solver) Mesh = new CCGNSMeshReaderFEM(config, val_iZone, val_nZone); diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp index 9f527b4e6cc..f6c48c62f05 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp @@ -61,8 +61,6 @@ CCGNSMeshReaderFEM::CCGNSMeshReaderFEM(CConfig* val_config, unsigned short val_i #endif } -CCGNSMeshReaderFEM::~CCGNSMeshReaderFEM() = default; - #ifdef HAVE_CGNS void CCGNSMeshReaderFEM::ReadCGNSConnectivityRangeSection(const int val_section, const unsigned long val_firstIndex, @@ -547,4 +545,4 @@ void CCGNSMeshReaderFEM::CommPointCoordinates(void) { SU2_MPI::Barrier(SU2_MPI::GetComm()); #endif -} \ No newline at end of file +} diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp index 147f5de0323..6e3bfb15189 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp @@ -71,8 +71,6 @@ CCGNSMeshReaderFVM::CCGNSMeshReaderFVM(CConfig* val_config, unsigned short val_i #endif } -CCGNSMeshReaderFVM::~CCGNSMeshReaderFVM() = default; - #ifdef HAVE_CGNS void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { /*--- In this routine, each rank will read a chunk of the element diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp new file mode 100644 index 00000000000..277c7a983f8 --- /dev/null +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp @@ -0,0 +1,379 @@ +/*! + * \file CSU2ASCIIMeshReaderFEM.cpp + * \brief Reads a native SU2 ASCII grid into linear partitions for the + * finite element solver (FEM). + * \author T. Economon, E. van der Weide + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/toolboxes/CLinearPartitioner.hpp" +#include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp" +#include "../../../include/fem/fem_standard_element.hpp" + +CSU2ASCIIMeshReaderFEM::CSU2ASCIIMeshReaderFEM(CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone) + : CSU2ASCIIMeshReaderBase(val_config, val_iZone, val_nZone) { + + /* Read the basic metadata and perform some basic error checks. */ + ReadMetadata(true, val_config); + + /*--- Read the volume connectivity and distribute it + linearly over the MPI ranks. ---*/ + ReadVolumeElementConnectivity(); + + /*--- Read the coordinates of the points that are needed + on this MPI rank. ---*/ + ReadPointCoordinates(); + + /*--- Read the surface connectivity and store the surface elements whose + corresponding volume element is stored on this MPI rank. ---*/ + ReadSurfaceElementConnectivity(); +} + +void CSU2ASCIIMeshReaderFEM::ReadPointCoordinates() { + + /*--- Loop over the local elements to determine the global + point IDs to be stored on this rank. --*/ + unsigned long ind = 0; + for(unsigned long i=0; i::iterator lastNode; + lastNode = unique(globalPointIDs.begin(), globalPointIDs.end()); + globalPointIDs.erase(lastNode, globalPointIDs.end()); + + /*--- Determine the number of locally stored points. ---*/ + numberOfLocalPoints = globalPointIDs.size(); + + /*--- Prepare our data structure for the point coordinates. ---*/ + localPointCoordinates.resize(dimension); + for(int k=0; k> nodeID; + localVolumeElementConnectivity.push_back(nodeID); + } + + /*--- If a linear element is used, the node numbering for non-simplices + must be adapted. The reason is that compatability with the original + SU2 format is maintained for linear elements, but for the FEM solver + the nodes of the elements are stored row-wise. ---*/ + if(nPolyGrid == 1) { + switch( VTK_Type ) { + + case QUADRILATERAL: + swap(localVolumeElementConnectivity[ind+2], + localVolumeElementConnectivity[ind+3]); + break; + + case HEXAHEDRON: + swap(localVolumeElementConnectivity[ind+2], + localVolumeElementConnectivity[ind+3]); + swap(localVolumeElementConnectivity[ind+6], + localVolumeElementConnectivity[ind+7]); + break; + + case PYRAMID: + swap(localVolumeElementConnectivity[ind+2], + localVolumeElementConnectivity[ind+3]); + break; + } + } + } + + /*--- Close the mesh file again. ---*/ + mesh_file.close(); +} + +void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { + + /*--- Determine the vector to hold the faces of the local elements. ---*/ + vector localFaces; + DetermineFacesVolumeElements(localFaces); + + /*--- We already read in the number of markers with the metadata. + Allocate the memory for the marker names, number of local surface + elements and the first index of the surface element connectivity. ---*/ + surfaceElementConnectivity.resize(numberOfMarkers); + markerNames.resize(numberOfMarkers); + numberOfLocalSurfaceElements.resize(numberOfMarkers, 0); + + /*--- Open the mesh file and jump to our zone. ---*/ + mesh_file.open(meshFilename, ios::in); + FastForwardToMyZone(); + + /*--- Find the section containing the markers. ---*/ + string text_line; + while (getline (mesh_file, text_line)) { + string::size_type position = text_line.find ("NMARK=",0); + if (position != string::npos) break; + } + + /*--- Loop over the number of boundary markers. ---*/ + for(unsigned long iMarker=0; iMarker connFace(nDOFsGrid); + for(unsigned short j=0; j> connFace[j]; + + /*--- If a linear quadrilateral is used, the node numbering must be adapted. + The reason is that compatability with the original SU2 format is + maintained for linear elements, but for the FEM solver the nodes + of the elements are stored row-wise. ---*/ + if((nPolyGrid == 1) && (VTK_Type == QUADRILATERAL)) + swap(connFace[2], connFace[3]); + + /*--- Convert the local numbering of thisFace to global numbering + and create a unique numbering of corner points. ---*/ + for(unsigned short j=0; j::iterator low; + low = lower_bound(localFaces.begin(), localFaces.end(), thisFace); + if(low != localFaces.end()) { + if( !(thisFace < *low) ) { + + /*--- Update the counter for this boundary marker and store + the meta data in surfaceElementConnectivity. ---*/ + ++numberOfLocalSurfaceElements[iMarker]; + + surfaceElementConnectivity[iMarker].push_back(VTK_Type); + surfaceElementConnectivity[iMarker].push_back(nPolyGrid); + surfaceElementConnectivity[iMarker].push_back(nDOFsGrid); + surfaceElementConnectivity[iMarker].push_back(i); // Global surface elem ID. + surfaceElementConnectivity[iMarker].push_back(low->elemID0); // Global volume elem ID. + + /*--- Copy the connectivity to surfaceElementConnectivity. ---*/ + surfaceElementConnectivity[iMarker].insert(surfaceElementConnectivity[iMarker].end(), + connFace.begin(), connFace.end()); + } + } + } + } + + /*--- Close the mesh file again. ---*/ + mesh_file.close(); +} \ No newline at end of file diff --git a/Common/src/geometry/meshreader/meson.build b/Common/src/geometry/meshreader/meson.build index cbc952d7649..6d994fb8420 100644 --- a/Common/src/geometry/meshreader/meson.build +++ b/Common/src/geometry/meshreader/meson.build @@ -6,4 +6,5 @@ common_src += files(['CBoxMeshReaderFVM.cpp', 'CMeshReaderBase.cpp', 'CRectangularMeshReaderFVM.cpp', 'CSU2ASCIIMeshReaderBase.cpp', + 'CSU2ASCIIMeshReaderFEM.cpp', 'CSU2ASCIIMeshReaderFVM.cpp']) From 00a735b55196217837140aed8cd78ae6022c5f4c Mon Sep 17 00:00:00 2001 From: vdweide Date: Mon, 3 Feb 2025 14:54:40 +0100 Subject: [PATCH 121/129] The reading of Rectangular and Box grids for the FEM solver done via the meshreader classes --- Common/include/CConfig.hpp | 7 + .../geometry/meshreader/CBoxMeshReaderFEM.hpp | 85 ++++ .../geometry/meshreader/CBoxMeshReaderFVM.hpp | 2 +- .../meshreader/CCGNSMeshReaderBase.hpp | 2 +- .../meshreader/CCGNSMeshReaderFEM.hpp | 9 +- .../meshreader/CCGNSMeshReaderFVM.hpp | 7 +- .../meshreader/CRectangularMeshReaderFEM.hpp | 79 ++++ .../meshreader/CRectangularMeshReaderFVM.hpp | 5 + .../meshreader/CSU2ASCIIMeshReaderFEM.hpp | 9 +- .../meshreader/CSU2ASCIIMeshReaderFVM.hpp | 5 + Common/src/CConfig.cpp | 3 + Common/src/geometry/CPhysicalGeometry.cpp | 8 +- .../geometry/meshreader/CBoxMeshReaderFEM.cpp | 369 ++++++++++++++++++ .../geometry/meshreader/CBoxMeshReaderFVM.cpp | 2 +- .../meshreader/CCGNSMeshReaderBase.cpp | 5 +- .../meshreader/CCGNSMeshReaderFEM.cpp | 5 +- .../meshreader/CCGNSMeshReaderFVM.cpp | 5 +- .../meshreader/CRectangularMeshReaderFEM.cpp | 271 +++++++++++++ .../meshreader/CRectangularMeshReaderFVM.cpp | 2 + .../meshreader/CSU2ASCIIMeshReaderBase.cpp | 3 +- .../meshreader/CSU2ASCIIMeshReaderFEM.cpp | 7 +- .../meshreader/CSU2ASCIIMeshReaderFVM.cpp | 5 +- Common/src/geometry/meshreader/meson.build | 4 +- 23 files changed, 878 insertions(+), 21 deletions(-) create mode 100644 Common/include/geometry/meshreader/CBoxMeshReaderFEM.hpp create mode 100644 Common/include/geometry/meshreader/CRectangularMeshReaderFEM.hpp create mode 100644 Common/src/geometry/meshreader/CBoxMeshReaderFEM.cpp create mode 100644 Common/src/geometry/meshreader/CRectangularMeshReaderFEM.cpp diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index 58918bfdc2c..d55416ed681 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -804,6 +804,7 @@ class CConfig { nRefOriginMoment_Z; /*!< \brief Number of Z-coordinate moment computation origins. */ unsigned short nMesh_Box_Size; short *Mesh_Box_Size; /*!< \brief Array containing the number of grid points in the x-, y-, and z-directions for the analytic RECTANGLE and BOX grid formats. */ + unsigned short Mesh_Box_PSolFEM; /*!< \brief FEM polynomial degree of the solution for the RECTANGLE and BOX grid formats. */ string Mesh_FileName, /*!< \brief Mesh input file. */ Mesh_Out_FileName, /*!< \brief Mesh output file. */ Solution_FileName, /*!< \brief Flow solution input file. */ @@ -9606,6 +9607,12 @@ class CConfig { */ su2double GetMeshBoxOffset(unsigned short val_iDim) const { return mesh_box_offset[val_iDim]; } + /*! + * \brief Get the polynomial degree of the FEM solution for the analytic RECTANGLE or BOX. + * \return The polynomial degree of the FEM solution. + */ + unsigned short GetMeshBoxPSolFEM(void) const { return Mesh_Box_PSolFEM; } + /*! * \brief Get the number of screen output variables requested (maximum 6) */ diff --git a/Common/include/geometry/meshreader/CBoxMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CBoxMeshReaderFEM.hpp new file mode 100644 index 00000000000..acfafef6365 --- /dev/null +++ b/Common/include/geometry/meshreader/CBoxMeshReaderFEM.hpp @@ -0,0 +1,85 @@ +/*! + * \file CBoxMeshReaderFEM.hpp + * \brief Header file for the class CBoxMeshReaderFEM. + * The implementations are in the CBoxMeshReaderFEM.cpp file. + * \author T. Economon + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include "CMeshReaderBase.hpp" + +/*! + * \class CBoxMeshReaderFEM + * \brief Reads a 3D box grid into linear partitions for the finite element solver (FEM). + * \author: T. Economon, E. van der Weide + */ +class CBoxMeshReaderFEM final: public CMeshReaderBase { + +private: + + unsigned long nNode; /*!< \brief Number of grid nodes in the x-direction. */ + unsigned long mNode; /*!< \brief Number of grid nodes in the y-direction. */ + unsigned long pNode; /*!< \brief Number of grid nodes in the z-direction. */ + + su2double Lx; /*!< \brief Length of the domain in the x-direction. */ + su2double Ly; /*!< \brief Length of the domain in the y-direction. */ + su2double Lz; /*!< \brief Length of the domain in the z-direction. */ + + su2double Ox; /*!< \brief Offset of the domain from 0.0 in the x-direction. */ + su2double Oy; /*!< \brief Offset of the domain from 0.0 in the y-direction. */ + su2double Oz; /*!< \brief Offset of the domain from 0.0 in the z-direction. */ + + unsigned short KindElem; /*!< \brief VTK identifier of the interior elements. */ + unsigned short KindBound; /*!< \brief VTK identifier of the surface elements. */ + + unsigned short nPolySol; /*!< \brief Polynomial degree of the solution. */ + + /*! + * \brief Computes and stores the grid points based on an analytic definition of a box grid. + */ + void ComputeBoxPointCoordinates(); + + /*! + * \brief Computes and stores the volume element connectivity based on an analytic definition of a box grid. + */ + void ComputeBoxVolumeConnectivity(); + + /*! + * \brief Computes and stores the surface element connectivity based on an analytic definition of a box grid. + */ + void ComputeBoxSurfaceConnectivity(); + +public: + + /*! + * \brief Constructor of the CBoxMeshReaderFEM class. + */ + CBoxMeshReaderFEM(const CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CBoxMeshReaderFEM class. + */ + ~CBoxMeshReaderFEM(void) override; +}; diff --git a/Common/include/geometry/meshreader/CBoxMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CBoxMeshReaderFVM.hpp index 74956a61bba..a557630e7c8 100644 --- a/Common/include/geometry/meshreader/CBoxMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CBoxMeshReaderFVM.hpp @@ -71,7 +71,7 @@ class CBoxMeshReaderFVM : public CMeshReaderBase { /*! * \brief Constructor of the CBoxMeshReaderFVM class. */ - CBoxMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + CBoxMeshReaderFVM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); /*! * \brief Destructor of the CBoxMeshReaderFVM class. diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp index ef12386e12c..01574423fcc 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderBase.hpp @@ -99,7 +99,7 @@ class CCGNSMeshReaderBase : public CMeshReaderBase { /*! * \brief Constructor of the CCGNSMeshReaderBase class. */ - CCGNSMeshReaderBase(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + CCGNSMeshReaderBase(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); /*! * \brief Destructor of the CCGNSMeshReaderBase class. diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp index 8a23b248d89..a07bf969f4c 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp @@ -89,7 +89,10 @@ class CCGNSMeshReaderFEM final : public CCGNSMeshReaderBase { /*! * \brief Constructor of the CCGNSMeshReaderFEM class. */ - CCGNSMeshReaderFEM(CConfig *val_config, - unsigned short val_iZone, - unsigned short val_nZone); + CCGNSMeshReaderFEM(const CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CCGNSMeshReaderFEM class. + */ + ~CCGNSMeshReaderFEM(void) override; }; diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp index 9e22b191fad..fe8612b3bbb 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFVM.hpp @@ -91,5 +91,10 @@ class CCGNSMeshReaderFVM final : public CCGNSMeshReaderBase { /*! * \brief Constructor of the CCGNSMeshReaderFVM class. */ - CCGNSMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + CCGNSMeshReaderFVM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CCGNSMeshReaderFVM class. + */ + ~CCGNSMeshReaderFVM(void) override; }; diff --git a/Common/include/geometry/meshreader/CRectangularMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CRectangularMeshReaderFEM.hpp new file mode 100644 index 00000000000..cc4745659a9 --- /dev/null +++ b/Common/include/geometry/meshreader/CRectangularMeshReaderFEM.hpp @@ -0,0 +1,79 @@ +/*! + * \file CRectangularMeshReaderFEM.hpp + * \brief Header file for the class CRectangularMeshReaderFEM. + * The implementations are in the CRectangularMeshReaderFEM.cpp file. + * \author T. Economon + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include "CMeshReaderBase.hpp" + +/*! + * \class CRectangularMeshReaderFEM + * \brief Reads a 2D rectangular grid into linear partitions for the finite element solver (FEM). + * \author: T. Economon, E. van der Weide + */ +class CRectangularMeshReaderFEM : public CMeshReaderBase { + private: + unsigned long nNode; /*!< \brief Number of grid nodes in the x-direction. */ + unsigned long mNode; /*!< \brief Number of grid nodes in the y-direction. */ + + su2double Lx; /*!< \brief Length of the domain in the x-direction. */ + su2double Ly; /*!< \brief Length of the domain in the y-direction. */ + + su2double Ox; /*!< \brief Offset of the domain from 0.0 in the x-direction. */ + su2double Oy; /*!< \brief Offset of the domain from 0.0 in the y-direction. */ + + unsigned short KindElem; /*!< \brief VTK identifier of the interior elements. */ + unsigned short KindBound; /*!< \brief VTK identifier of the surface elements. */ + + unsigned short nPolySol; /*!< \brief Polynomial degree of the solution. */ + + /*! + * \brief Computes and stores the grid points based on an analytic definition of a rectangular grid. + */ + void ComputeRectangularPointCoordinates(); + + /*! + * \brief Computes and stores the volume element connectivity based on an analytic definition of a rectangular grid. + */ + void ComputeRectangularVolumeConnectivity(); + + /*! + * \brief Computes and stores the surface element connectivity based on an analytic definition of a rectangular grid. + */ + void ComputeRectangularSurfaceConnectivity(); + + public: + /*! + * \brief Constructor of the CRectangularMeshReaderFEM class. + */ + CRectangularMeshReaderFEM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CRectangularMeshReaderFEM class. + */ + ~CRectangularMeshReaderFEM(void) override; +}; diff --git a/Common/include/geometry/meshreader/CRectangularMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CRectangularMeshReaderFVM.hpp index acdc94b8a43..30f28354d12 100644 --- a/Common/include/geometry/meshreader/CRectangularMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CRectangularMeshReaderFVM.hpp @@ -69,4 +69,9 @@ class CRectangularMeshReaderFVM : public CMeshReaderBase { * \brief Constructor of the CRectangularMeshReaderFVM class. */ CRectangularMeshReaderFVM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CRectangularMeshReaderFVM class. + */ + ~CRectangularMeshReaderFVM(void) override; }; diff --git a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp index 6bf11a92dec..3b4759a9301 100644 --- a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp +++ b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp @@ -58,7 +58,10 @@ class CSU2ASCIIMeshReaderFEM : public CSU2ASCIIMeshReaderBase { /*! * \brief Constructor of the CSU2ASCIIMeshReaderFEM class. */ - CSU2ASCIIMeshReaderFEM(CConfig *val_config, - unsigned short val_iZone, - unsigned short val_nZone); + CSU2ASCIIMeshReaderFEM(CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CSU2ASCIIMeshReaderFEM class. + */ + ~CSU2ASCIIMeshReaderFEM(void) override; }; diff --git a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp index 10fada303d2..20f88bc66bc 100644 --- a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp +++ b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp @@ -49,4 +49,9 @@ class CSU2ASCIIMeshReaderFVM : public CSU2ASCIIMeshReaderBase { * \brief Constructor of the CSU2ASCIIMeshReaderFVM class. */ CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); + + /*! + * \brief Destructor of the CSU2ASCIIMeshReaderFVM class. + */ + ~CSU2ASCIIMeshReaderFVM(void) override; }; diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index cc5bd3faca6..d54d1dc3a6c 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -2145,6 +2145,9 @@ void CConfig::SetConfig_Options() { mesh_box_offset[0] = 0.0; mesh_box_offset[1] = 0.0; mesh_box_offset[2] = 0.0; addDoubleArrayOption("MESH_BOX_OFFSET", 3, mesh_box_offset); + /* DESCRIPTION: Polynomial degree of the FEM solution for the RECTANGLE or BOX grid. (default: 1). */ + addUnsignedShortOption("MESH_BOX_POLY_SOL_FEM", Mesh_Box_PSolFEM, 1); + /* DESCRIPTION: Determine if the mesh file supports multizone. \n DEFAULT: true (temporarily) */ addBoolOption("MULTIZONE_MESH", Multizone_Mesh, true); /* DESCRIPTION: Determine if we need to allocate memory to store the multizone residual. \n DEFAULT: false (temporarily) */ diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index b53f2ba62c6..f3cd14e2bd4 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -35,7 +35,9 @@ #include "../../include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp" #include "../../include/geometry/meshreader/CCGNSMeshReaderFVM.hpp" #include "../../include/geometry/meshreader/CCGNSMeshReaderFEM.hpp" +#include "../../include/geometry/meshreader/CRectangularMeshReaderFEM.hpp" #include "../../include/geometry/meshreader/CRectangularMeshReaderFVM.hpp" +#include "../../include/geometry/meshreader/CBoxMeshReaderFEM.hpp" #include "../../include/geometry/meshreader/CBoxMeshReaderFVM.hpp" #include "../../include/geometry/primal_grid/CPrimalGrid.hpp" @@ -3458,10 +3460,12 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena else Mesh = new CCGNSMeshReaderFVM(config, val_iZone, val_nZone); break; case RECTANGLE: - Mesh = new CRectangularMeshReaderFVM(config, val_iZone, val_nZone); + if (fem_solver) Mesh = new CRectangularMeshReaderFEM(config, val_iZone, val_nZone); + else Mesh = new CRectangularMeshReaderFVM(config, val_iZone, val_nZone); break; case BOX: - Mesh = new CBoxMeshReaderFVM(config, val_iZone, val_nZone); + if (fem_solver) Mesh = new CBoxMeshReaderFEM(config, val_iZone, val_nZone); + else Mesh = new CBoxMeshReaderFVM(config, val_iZone, val_nZone); break; default: SU2_MPI::Error("Unrecognized mesh format specified!", CURRENT_FUNCTION); diff --git a/Common/src/geometry/meshreader/CBoxMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CBoxMeshReaderFEM.cpp new file mode 100644 index 00000000000..56551341517 --- /dev/null +++ b/Common/src/geometry/meshreader/CBoxMeshReaderFEM.cpp @@ -0,0 +1,369 @@ +/*! + * \file CBoxMeshReaderFEM.cpp + * \brief Reads a 3D box grid into linear partitions for the + * finite element solver (FEM). + * \author T. Economon, E. van der Weide + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/toolboxes/CLinearPartitioner.hpp" +#include "../../../include/geometry/meshreader/CBoxMeshReaderFEM.hpp" + +CBoxMeshReaderFEM::CBoxMeshReaderFEM(const CConfig *val_config, unsigned short val_iZone, + unsigned short val_nZone) + : CMeshReaderBase(val_config, val_iZone, val_nZone) { + + /* The box mesh is always 3D. */ + dimension = 3; + + /* Set the VTK type for the interior elements and the boundary elements. */ + KindElem = HEXAHEDRON; + KindBound = QUADRILATERAL; + + /* The number of grid nodes in the i, j and k directions. */ + nNode = config->GetMeshBoxSize(0); + mNode = config->GetMeshBoxSize(1); + pNode = config->GetMeshBoxSize(2); + + /* Lengths for non-square domains. */ + Lx = config->GetMeshBoxLength(0); + Ly = config->GetMeshBoxLength(1); + Lz = config->GetMeshBoxLength(2); + + /* Offsets in x, y and z directions from 0.0. */ + Ox = config->GetMeshBoxOffset(0); + Oy = config->GetMeshBoxOffset(1); + Oz = config->GetMeshBoxOffset(2); + + /* Polynomial degree of the solution. */ + nPolySol = config->GetMeshBoxPSolFEM(); + + /*--- Compute and store the interior elements, points, and surface elements + for this rank, for which simple analytic formulae can be used. ---*/ + ComputeBoxVolumeConnectivity(); + ComputeBoxPointCoordinates(); + ComputeBoxSurfaceConnectivity(); +} + +CBoxMeshReaderFEM::~CBoxMeshReaderFEM() = default; + +void CBoxMeshReaderFEM::ComputeBoxPointCoordinates() { + + /*--- Set the global count of points based on the grid dimensions. ---*/ + numberOfGlobalPoints = nNode*mNode*pNode; + + /*--- Loop over the local elements to determine the global + point IDs to be stored on this rank. --*/ + unsigned long ind = 0; + for(unsigned long i=0; i::iterator lastNode; + lastNode = unique(globalPointIDs.begin(), globalPointIDs.end()); + globalPointIDs.erase(lastNode, globalPointIDs.end()); + + /*--- Determine the number of locally stored points. ---*/ + numberOfLocalPoints = globalPointIDs.size(); + + /*--- Allocate the memory for the locally stored points. ---*/ + localPointCoordinates.resize(dimension); + for (int k = 0; k < dimension; k++) + localPointCoordinates[k].resize(numberOfLocalPoints); + + /*--- Loop over the locally stored points. ---*/ + const unsigned long nPointIJ = nNode*mNode; + for(unsigned long i=0; i(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[0].push_back(KindBound); // VTK type. + surfaceElementConnectivity[0].push_back(1); // Poly degree grid. + surfaceElementConnectivity[0].push_back(4); // Number of grid DOFs. + surfaceElementConnectivity[0].push_back(ind); // Global surface element ID. + surfaceElementConnectivity[0].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[0].push_back(kNode*mNode*nNode + jNode*nNode); + surfaceElementConnectivity[0].push_back((kNode+1)*mNode*nNode + jNode*nNode); + surfaceElementConnectivity[0].push_back(kNode*mNode*nNode + (jNode+1)*nNode); + surfaceElementConnectivity[0].push_back((kNode+1)*mNode*nNode + (jNode+1)*nNode); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[0]; + } + } + } + + /*--- Loop over all faces on the xMax (= iMax) boundary. ---*/ + markerNames[1] = "x_plus"; + + ind = 0; + for(unsigned long kNode = 0; kNode < pNode-1; ++kNode) { + for(unsigned long jNode = 0; jNode < mNode-1; ++jNode, ++ind) { + + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = kNode*nElemIJ + jNode*nElemI + nElemI-1; + if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[1].push_back(KindBound); // VTK type. + surfaceElementConnectivity[1].push_back(1); // Poly degree grid. + surfaceElementConnectivity[1].push_back(4); // Number of grid DOFs. + surfaceElementConnectivity[1].push_back(ind); // Global surface element ID. + surfaceElementConnectivity[1].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[1].push_back(kNode*mNode*nNode + jNode*nNode + (nNode-1)); + surfaceElementConnectivity[1].push_back(kNode*mNode*nNode + (jNode+1)*nNode + (nNode-1)); + surfaceElementConnectivity[1].push_back((kNode+1)*mNode*nNode + jNode*nNode + (nNode-1)); + surfaceElementConnectivity[1].push_back((kNode+1)*mNode*nNode + (jNode+1)*nNode + (nNode-1)); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[1]; + } + } + } + + /*--- Loop over all faces on the yMin (= jMin) boundary. ---*/ + markerNames[2] = "y_minus"; + + ind = 0; + for (unsigned long kNode = 0; kNode < pNode-1; ++kNode) { + for (unsigned long iNode = 0; iNode < nNode-1; ++iNode, ++ind) { + + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = kNode*nElemIJ + iNode; + if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[2].push_back(KindBound); // VTK type. + surfaceElementConnectivity[2].push_back(1); // Poly degree grid. + surfaceElementConnectivity[2].push_back(4); // Number of grid DOFs. + surfaceElementConnectivity[2].push_back(ind); // Global surface element ID. + surfaceElementConnectivity[2].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[2].push_back(kNode*mNode*nNode + iNode); + surfaceElementConnectivity[2].push_back(kNode*mNode*nNode + iNode+1); + surfaceElementConnectivity[2].push_back((kNode+1)*mNode*nNode + iNode); + surfaceElementConnectivity[2].push_back((kNode+1)*mNode*nNode + iNode+1); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[2]; + } + } + } + + /*--- Loop over all faces on the yMax (= jMax) boundary. ---*/ + markerNames[3] = "y_plus"; + + ind = 0; + for (unsigned long kNode = 0; kNode < pNode-1; ++kNode) { + for (unsigned long iNode = 0; iNode < nNode-1; ++iNode, ++ind) { + + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = kNode*nElemIJ + (mNode-2)*nElemI + iNode; + if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[3].push_back(KindBound); // VTK type. + surfaceElementConnectivity[3].push_back(1); // Poly degree grid. + surfaceElementConnectivity[3].push_back(4); // Number of grid DOFs. + surfaceElementConnectivity[3].push_back(ind); // Global surface element ID. + surfaceElementConnectivity[3].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[3].push_back(kNode*mNode*nNode + (mNode-1)*nNode + iNode); + surfaceElementConnectivity[3].push_back(kNode*mNode*nNode + (mNode-1)*nNode + iNode+1); + surfaceElementConnectivity[3].push_back((kNode+1)*mNode*nNode + (mNode-1)*nNode + iNode); + surfaceElementConnectivity[3].push_back((kNode+1)*mNode*nNode + (mNode-1)*nNode + iNode+1); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[3]; + } + } + } + + /*--- Loop over all faces on the zMin (= kMin) boundary. ---*/ + markerNames[4] = "z_minus"; + + ind = 0; + for (unsigned long jNode = 0; jNode < mNode-1; ++jNode) { + for (unsigned long iNode = 0; iNode < nNode-1; ++iNode, ++ind) { + + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = jNode*nElemI + iNode; + if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[4].push_back(KindBound); // VTK type. + surfaceElementConnectivity[4].push_back(1); // Poly degree grid. + surfaceElementConnectivity[4].push_back(4); // Number of grid DOFs. + surfaceElementConnectivity[4].push_back(ind); // Global surface element ID. + surfaceElementConnectivity[4].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[4].push_back(jNode*nNode + iNode); + surfaceElementConnectivity[4].push_back(jNode*nNode + iNode+1); + surfaceElementConnectivity[4].push_back((jNode+1)*nNode + iNode); + surfaceElementConnectivity[4].push_back((jNode+1)*nNode + iNode+1); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[4]; + } + } + } + + /*--- Loop over all faces on the zMax (= kMax) boundary. ---*/ + markerNames[5] = "z_plus"; + + ind = 0; + for (unsigned long jNode = 0; jNode < mNode-1; ++jNode) { + for (unsigned long iNode = 0; iNode < nNode-1; ++iNode, ++ind) { + + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = (pNode-2)*nElemIJ + jNode*nElemI + iNode; + if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[5].push_back(KindBound); // VTK type. + surfaceElementConnectivity[5].push_back(1); // Poly degree grid. + surfaceElementConnectivity[5].push_back(4); // Number of grid DOFs. + surfaceElementConnectivity[5].push_back(ind); // Global surface element ID. + surfaceElementConnectivity[5].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[5].push_back((pNode-1)*mNode*nNode + jNode*nNode + iNode); + surfaceElementConnectivity[5].push_back((pNode-1)*mNode*nNode + jNode*nNode + iNode+1); + surfaceElementConnectivity[5].push_back((pNode-1)*mNode*nNode + (jNode+1)*nNode + iNode); + surfaceElementConnectivity[5].push_back((pNode-1)*mNode*nNode + (jNode+1)*nNode + iNode+1); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[5]; + } + } + } +} diff --git a/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp index 8330f1ea6fe..962e32e478d 100644 --- a/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp @@ -29,7 +29,7 @@ #include "../../../include/toolboxes/CLinearPartitioner.hpp" #include "../../../include/geometry/meshreader/CBoxMeshReaderFVM.hpp" -CBoxMeshReaderFVM::CBoxMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) +CBoxMeshReaderFVM::CBoxMeshReaderFVM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) : CMeshReaderBase(val_config, val_iZone, val_nZone) { /* The box mesh is always 3D. */ dimension = 3; diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp index 8a0f4e2bdb6..379176ad6c9 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp @@ -29,7 +29,8 @@ #include "../../../include/toolboxes/CLinearPartitioner.hpp" #include "../../../include/geometry/meshreader/CCGNSMeshReaderBase.hpp" -CCGNSMeshReaderBase::CCGNSMeshReaderBase(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) +CCGNSMeshReaderBase::CCGNSMeshReaderBase(const CConfig* val_config, unsigned short val_iZone, + unsigned short val_nZone) : CMeshReaderBase(val_config, val_iZone, val_nZone) { #ifdef HAVE_CGNS /*--- Leave the option to do something in the future here. ---*/ @@ -407,4 +408,4 @@ string CCGNSMeshReaderBase::GetCGNSElementType(ElementType_t val_elem_type, int& return elem_name; } -#endif \ No newline at end of file +#endif diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp index f6c48c62f05..48c0b267cfb 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp @@ -30,7 +30,8 @@ #include "../../../include/geometry/meshreader/CCGNSMeshReaderFEM.hpp" #include "../../../include/geometry/meshreader/CCGNSElementType.hpp" -CCGNSMeshReaderFEM::CCGNSMeshReaderFEM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) +CCGNSMeshReaderFEM::CCGNSMeshReaderFEM(const CConfig* val_config, unsigned short val_iZone, + unsigned short val_nZone) : CCGNSMeshReaderBase(val_config, val_iZone, val_nZone) { #ifdef HAVE_CGNS OpenCGNSFile(config->GetMesh_FileName()); @@ -61,6 +62,8 @@ CCGNSMeshReaderFEM::CCGNSMeshReaderFEM(CConfig* val_config, unsigned short val_i #endif } +CCGNSMeshReaderFEM::~CCGNSMeshReaderFEM() = default; + #ifdef HAVE_CGNS void CCGNSMeshReaderFEM::ReadCGNSConnectivityRangeSection(const int val_section, const unsigned long val_firstIndex, diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp index 6e3bfb15189..61b6cef7020 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp @@ -29,7 +29,8 @@ #include "../../../include/toolboxes/CLinearPartitioner.hpp" #include "../../../include/geometry/meshreader/CCGNSMeshReaderFVM.hpp" -CCGNSMeshReaderFVM::CCGNSMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) +CCGNSMeshReaderFVM::CCGNSMeshReaderFVM(const CConfig* val_config, unsigned short val_iZone, + unsigned short val_nZone) : CCGNSMeshReaderBase(val_config, val_iZone, val_nZone) { #ifdef HAVE_CGNS OpenCGNSFile(config->GetMesh_FileName()); @@ -71,6 +72,8 @@ CCGNSMeshReaderFVM::CCGNSMeshReaderFVM(CConfig* val_config, unsigned short val_i #endif } +CCGNSMeshReaderFVM::~CCGNSMeshReaderFVM() = default; + #ifdef HAVE_CGNS void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { /*--- In this routine, each rank will read a chunk of the element diff --git a/Common/src/geometry/meshreader/CRectangularMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CRectangularMeshReaderFEM.cpp new file mode 100644 index 00000000000..ceda417b7d7 --- /dev/null +++ b/Common/src/geometry/meshreader/CRectangularMeshReaderFEM.cpp @@ -0,0 +1,271 @@ +/*! + * \file CRectangularMeshReaderFEM.cpp + * \brief Reads a 2D rectangular grid into linear partitions for the + * finite element solver (FEM). + * \author T. Economon, E. van der Weide + * \version 8.1.0 "Harrier" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2024, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/toolboxes/CLinearPartitioner.hpp" +#include "../../../include/geometry/meshreader/CRectangularMeshReaderFEM.hpp" + +CRectangularMeshReaderFEM::CRectangularMeshReaderFEM(const CConfig *val_config, unsigned short val_iZone, + unsigned short val_nZone) +: CMeshReaderBase(val_config, val_iZone, val_nZone) { + + /* The rectangular mesh is always 2D. */ + dimension = 2; + + /* Set the VTK type for the interior elements and the boundary elements. */ + KindElem = QUADRILATERAL; + KindBound = LINE; + + /* The number of nodes in the i and j directions. */ + nNode = config->GetMeshBoxSize(0); + mNode = config->GetMeshBoxSize(1); + + /* Lengths for non-square domains. */ + Lx = config->GetMeshBoxLength(0); + Ly = config->GetMeshBoxLength(1); + + /* Offsets in x and y directions from 0.0. */ + Ox = config->GetMeshBoxOffset(0); + Oy = config->GetMeshBoxOffset(1); + + /* Polynomial degree of the solution. */ + nPolySol = config->GetMeshBoxPSolFEM(); + + /*--- Compute and store the interior elements, points, and surface elements + for this rank, for which simple analytic formulae can be used. ---*/ + ComputeRectangularVolumeConnectivity(); + ComputeRectangularPointCoordinates(); + ComputeRectangularSurfaceConnectivity(); +} + +CRectangularMeshReaderFEM::~CRectangularMeshReaderFEM() = default; + +void CRectangularMeshReaderFEM::ComputeRectangularPointCoordinates() { + + /*--- Set the global count of points based on the grid dimensions. ---*/ + numberOfGlobalPoints = nNode*mNode; + + /*--- Loop over the local elements to determine the global + point IDs to be stored on this rank. --*/ + unsigned long ind = 0; + for(unsigned long i=0; i::iterator lastNode; + lastNode = unique(globalPointIDs.begin(), globalPointIDs.end()); + globalPointIDs.erase(lastNode, globalPointIDs.end()); + + /*--- Determine the number of locally stored points. ---*/ + numberOfLocalPoints = globalPointIDs.size(); + + /*--- Allocate the memory for the locally stored points. ---*/ + localPointCoordinates.resize(dimension); + for (int k = 0; k < dimension; k++) + localPointCoordinates[k].resize(numberOfLocalPoints); + + /*--- Loop over the locally stored points. ---*/ + for(unsigned long i=0; i(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[0].push_back(KindBound); // VTK type. + surfaceElementConnectivity[0].push_back(1); // Poly degree grid. + surfaceElementConnectivity[0].push_back(2); // Number of grid DOFs. + surfaceElementConnectivity[0].push_back(iNode); // Global surface element ID. + surfaceElementConnectivity[0].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[0].push_back(iNode); + surfaceElementConnectivity[0].push_back(iNode+1); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[0]; + } + } + + /*--- Loop over all faces on the xMax (= iMax) boundary. ---*/ + markerNames[1] = "x_plus"; + + for(unsigned long jNode = 0; jNode < mNode-1; ++jNode) { + + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = jNode*nElemI + nElemI-1; + if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[1].push_back(KindBound); // VTK type. + surfaceElementConnectivity[1].push_back(1); // Poly degree grid. + surfaceElementConnectivity[1].push_back(2); // Number of grid DOFs. + surfaceElementConnectivity[1].push_back(jNode); // Global surface element ID. + surfaceElementConnectivity[1].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[1].push_back(jNode*nNode + (nNode-1)); + surfaceElementConnectivity[1].push_back((jNode+1)*nNode + (nNode-1)); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[1]; + } + } + + /*--- Loop over all faces on the yMax (= jMax) boundary. ---*/ + markerNames[2] = "y_plus"; + + for (unsigned long iNode = 0; iNode < nNode-1; ++iNode) { + + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = (mNode-2)*nElemI + iNode; + if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[2].push_back(KindBound); // VTK type. + surfaceElementConnectivity[2].push_back(1); // Poly degree grid. + surfaceElementConnectivity[2].push_back(2); // Number of grid DOFs. + surfaceElementConnectivity[2].push_back(iNode); // Global surface element ID. + surfaceElementConnectivity[2].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[2].push_back((mNode-1)*nNode + iNode+1); + surfaceElementConnectivity[2].push_back((mNode-1)*nNode + iNode); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[2]; + } + } + + /*--- Loop over all faces on the xMin (= iMin) boundary. ---*/ + markerNames[3] = "x_minus"; + + for(unsigned long jNode = 0; jNode < mNode-1; ++jNode) { + + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = jNode*nElemI; + if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { + + /*--- The corresponding volume element is stored on this rank, + hence store the surface element as well. ---*/ + surfaceElementConnectivity[3].push_back(KindBound); // VTK type. + surfaceElementConnectivity[3].push_back(1); // Poly degree grid. + surfaceElementConnectivity[3].push_back(2); // Number of grid DOFs. + surfaceElementConnectivity[3].push_back(jNode); // Global surface element ID. + surfaceElementConnectivity[3].push_back(globalElemID); // Global volume element ID. + + surfaceElementConnectivity[3].push_back((jNode+1)*nNode); + surfaceElementConnectivity[3].push_back(jNode*nNode); + + /*--- Update the number of surface elements for this marker. ---*/ + ++numberOfLocalSurfaceElements[3]; + } + } +} diff --git a/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp index 971fe37fbbd..59d6bb74cfc 100644 --- a/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp @@ -61,6 +61,8 @@ CRectangularMeshReaderFVM::CRectangularMeshReaderFVM(const CConfig* val_config, ComputeRectangularSurfaceConnectivity(); } +CRectangularMeshReaderFVM::~CRectangularMeshReaderFVM() = default; + void CRectangularMeshReaderFVM::ComputeRectangularPointCoordinates() { /* Set the global count of points based on the grid dimensions. */ numberOfGlobalPoints = (nNode) * (mNode); diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp index 845221356cb..1802cc9233e 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp @@ -28,7 +28,8 @@ #include "../../../include/toolboxes/CLinearPartitioner.hpp" #include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderBase.hpp" -CSU2ASCIIMeshReaderBase::CSU2ASCIIMeshReaderBase(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) +CSU2ASCIIMeshReaderBase::CSU2ASCIIMeshReaderBase(CConfig* val_config, unsigned short val_iZone, + unsigned short val_nZone) : CMeshReaderBase(val_config, val_iZone, val_nZone), myZone(val_iZone), nZones(val_nZone), diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp index 277c7a983f8..ec310aa35f2 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp @@ -30,7 +30,8 @@ #include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp" #include "../../../include/fem/fem_standard_element.hpp" -CSU2ASCIIMeshReaderFEM::CSU2ASCIIMeshReaderFEM(CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone) +CSU2ASCIIMeshReaderFEM::CSU2ASCIIMeshReaderFEM(CConfig *val_config, unsigned short val_iZone, + unsigned short val_nZone) : CSU2ASCIIMeshReaderBase(val_config, val_iZone, val_nZone) { /* Read the basic metadata and perform some basic error checks. */ @@ -49,6 +50,8 @@ CSU2ASCIIMeshReaderFEM::CSU2ASCIIMeshReaderFEM(CConfig *val_config, unsigned sho ReadSurfaceElementConnectivity(); } +CSU2ASCIIMeshReaderFEM::~CSU2ASCIIMeshReaderFEM() = default; + void CSU2ASCIIMeshReaderFEM::ReadPointCoordinates() { /*--- Loop over the local elements to determine the global @@ -376,4 +379,4 @@ void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { /*--- Close the mesh file again. ---*/ mesh_file.close(); -} \ No newline at end of file +} diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp index 96a30abb5e0..71fb595e0cb 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp @@ -28,7 +28,8 @@ #include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp" -CSU2ASCIIMeshReaderFVM::CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) +CSU2ASCIIMeshReaderFVM::CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, + unsigned short val_nZone) : CSU2ASCIIMeshReaderBase(val_config, val_iZone, val_nZone) { actuator_disk = (((config->GetnMarker_ActDiskInlet() != 0) || (config->GetnMarker_ActDiskOutlet() != 0)) && ((config->GetKind_SU2() == SU2_COMPONENT::SU2_CFD) || @@ -71,6 +72,8 @@ CSU2ASCIIMeshReaderFVM::CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned sho mesh_file.close(); } +CSU2ASCIIMeshReaderFVM::~CSU2ASCIIMeshReaderFVM() = default; + void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { /*--- Actuator disk preprocesing ---*/ diff --git a/Common/src/geometry/meshreader/meson.build b/Common/src/geometry/meshreader/meson.build index 6d994fb8420..543bdfcf97a 100644 --- a/Common/src/geometry/meshreader/meson.build +++ b/Common/src/geometry/meshreader/meson.build @@ -1,9 +1,11 @@ -common_src += files(['CBoxMeshReaderFVM.cpp', +common_src += files(['CBoxMeshReaderFEM.cpp', + 'CBoxMeshReaderFVM.cpp', 'CCGNSElementType.cpp', 'CCGNSMeshReaderBase.cpp', 'CCGNSMeshReaderFEM.cpp', 'CCGNSMeshReaderFVM.cpp', 'CMeshReaderBase.cpp', + 'CRectangularMeshReaderFEM.cpp', 'CRectangularMeshReaderFVM.cpp', 'CSU2ASCIIMeshReaderBase.cpp', 'CSU2ASCIIMeshReaderFEM.cpp', From a9ce2780980bd32df80e30109f668a62399408ee Mon Sep 17 00:00:00 2001 From: vdweide Date: Mon, 3 Feb 2025 17:01:45 +0100 Subject: [PATCH 122/129] Copied the data from the mesh reader to CPhysicalGeometry for the FEM solver --- Common/include/geometry/CPhysicalGeometry.hpp | 21 ++++ .../primal_grid/CPrimalGridBoundFEM.hpp | 13 +- .../geometry/primal_grid/CPrimalGridFEM.hpp | 29 +---- .../src/fem/geometry_structure_fem_part.cpp | 119 ++++++++++++++++++ Common/src/geometry/CPhysicalGeometry.cpp | 28 +++-- .../primal_grid/CPrimalGridBoundFEM.cpp | 37 +++--- .../geometry/primal_grid/CPrimalGridFEM.cpp | 71 +++-------- 7 files changed, 197 insertions(+), 121 deletions(-) diff --git a/Common/include/geometry/CPhysicalGeometry.hpp b/Common/include/geometry/CPhysicalGeometry.hpp index 20dba58e52e..2e90f374ca7 100644 --- a/Common/include/geometry/CPhysicalGeometry.hpp +++ b/Common/include/geometry/CPhysicalGeometry.hpp @@ -295,6 +295,13 @@ class CPhysicalGeometry final : public CGeometry { */ void LoadLinearlyPartitionedPoints(CConfig* config, CMeshReaderBase* mesh); + /*! + * \brief Routine to load the grid points from a single zone into the proper SU2 data structures for the FEM solver. + * \param[in] config - definition of the particular problem. + * \param[in] mesh - mesh reader object containing the current zone data. + */ + void LoadLinearlyPartitionedPointsFEM(CConfig *config, CMeshReaderBase *mesh); + /*! * \brief Loads the interior volume elements from the mesh reader object into the primal element data structures. * \param[in] config - definition of the particular problem. @@ -302,6 +309,13 @@ class CPhysicalGeometry final : public CGeometry { */ void LoadLinearlyPartitionedVolumeElements(CConfig* config, CMeshReaderBase* mesh); + /*! + * \brief Loads the interior volume elements from the mesh reader object into the primal element data structures for the FEM solver. + * \param[in] config - definition of the particular problem. + * \param[in] mesh - mesh reader object containing the current zone data. + */ + void LoadLinearlyPartitionedVolumeElementsFEM(CConfig *config, CMeshReaderBase *mesh); + /*! * \brief Loads the boundary elements (markers) from the mesh reader object into the primal element data structures. * \param[in] config - definition of the particular problem. @@ -309,6 +323,13 @@ class CPhysicalGeometry final : public CGeometry { */ void LoadUnpartitionedSurfaceElements(CConfig* config, CMeshReaderBase* mesh); + /*! + * \brief Loads the boundary elements (markers) from the mesh reader object into the primal element data structures for the FEM solver. + * \param[in] config - definition of the particular problem. + * \param[in] mesh - mesh reader object containing the current zone data. + */ + void LoadLinearlyPartitionedSurfaceElementsFEM(CConfig *config, CMeshReaderBase *mesh); + /*! * \brief Prepares the grid point adjacency based on a linearly partitioned mesh object needed by ParMETIS for graph * partitioning in parallel. \param[in] config - Definition of the particular problem. diff --git a/Common/include/geometry/primal_grid/CPrimalGridBoundFEM.hpp b/Common/include/geometry/primal_grid/CPrimalGridBoundFEM.hpp index fd7db594f6f..3a2233246cf 100644 --- a/Common/include/geometry/primal_grid/CPrimalGridBoundFEM.hpp +++ b/Common/include/geometry/primal_grid/CPrimalGridBoundFEM.hpp @@ -51,16 +51,9 @@ class CPrimalGridBoundFEM final : public CPrimalGrid { public: /*! * \brief Constructor using data to initialize the boundary element. - * \param[in] val_elemGlobalID - Global boundary element ID of this element. - * \param[in] val_domainElementID - Global ID of the corresponding domain element. - * \param[in] val_VTK_Type - VTK type to indicate the element type - * \param[in] val_nPolyGrid - Polynomial degree to describe the geometry of the element. - * \param[in] val_nDOFsGrid - Number of DOFs used to describe the geometry of the element. - * \param[in] val_nodes - Vector, which contains the global node IDs of the element. - */ - CPrimalGridBoundFEM(unsigned long val_elemGlobalID, unsigned long val_domainElementID, unsigned short val_VTK_Type, - unsigned short val_nPolyGrid, unsigned short val_nDOFsGrid, - std::vector& val_nodes); + * \param[in] dataElem - Meta and connectivity data for this element. + */ + CPrimalGridBoundFEM(const unsigned long *dataElem); /*! * \brief Get the number of nodes that composes a face of an element. diff --git a/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp b/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp index 81c214c78ff..a0cafc9f66e 100644 --- a/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp +++ b/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp @@ -53,35 +53,12 @@ class CPrimalGridFEM final : public CPrimalGrid { is (almost) constant. */ public: - /*! - * \brief Constructor using data to initialize the element. - * \param[in] val_elemGlobalID - Global element ID of this element. - * \param[in] val_VTK_Type - VTK type to indicate the element type - * \param[in] val_nPolyGrid - Polynomial degree to describe the geometry of the element. - * \param[in] val_nPolySol - Polynomial degree to describe the solution of the element. - * \param[in] val_nDOFsGrid - Number of DOFs used to describe the geometry of the element. - * \param[in] val_nDOFsSol - Number of DOFs used to describe the solution of the element. - * \param[in] val_offDOfsSol - Global offset of the solution DOFs of the element. - * \param[in] elem_line - istringstream, which contains the grid node numbers of the element. - */ - CPrimalGridFEM(unsigned long val_elemGlobalID, unsigned short val_VTK_Type, unsigned short val_nPolyGrid, - unsigned short val_nPolySol, unsigned short val_nDOFsGrid, unsigned short val_nDOFsSol, - unsigned long val_offDOfsSol, std::istringstream& elem_line); /*! * \brief Constructor using data to initialize the element. - * \param[in] val_elemGlobalID - Global element ID of this element. - * \param[in] val_VTK_Type - VTK type to indicate the element type - * \param[in] val_nPolyGrid - Polynomial degree to describe the geometry of the element. - * \param[in] val_nPolySol - Polynomial degree to describe the solution of the element. - * \param[in] val_nDOFsGrid - Number of DOFs used to describe the geometry of the element. - * \param[in] val_nDOFsSol - Number of DOFs used to describe the solution of the element. - * \param[in] val_offDOfsSol - Global offset of the solution DOFs of the element. - * \param[in] connGrid - Array, which contains the grid node numbers of the element. - */ - CPrimalGridFEM(unsigned long val_elemGlobalID, unsigned short val_VTK_Type, unsigned short val_nPolyGrid, - unsigned short val_nPolySol, unsigned short val_nDOFsGrid, unsigned short val_nDOFsSol, - unsigned long val_offDOfsSol, const unsigned long* connGrid); + * \param[in] dataElem - Meta and connectivity data for this element. + */ + CPrimalGridFEM(const unsigned long *dataElem); /*! * \brief Get the number of nodes that composes a face of an element. diff --git a/Common/src/fem/geometry_structure_fem_part.cpp b/Common/src/fem/geometry_structure_fem_part.cpp index c3a3547bf1d..a774b7d78b0 100644 --- a/Common/src/fem/geometry_structure_fem_part.cpp +++ b/Common/src/fem/geometry_structure_fem_part.cpp @@ -360,6 +360,125 @@ void CMatchingFace::Copy(const CMatchingFace& other) { tolForMatching = other.tolForMatching; } +void CPhysicalGeometry::LoadLinearlyPartitionedPointsFEM(CConfig *config, CMeshReaderBase *mesh) { + + /*--- Get the partitioned coordinates and their global IDs from the mesh object. ---*/ + const auto &gridCoords = mesh->GetLocalPointCoordinates(); + const auto &globalPointIDs = mesh->GetGlobalPointIDs(); + + /*--- Initialize point counts and the grid node data structure. ---*/ + + nodes = new CPoint(nPoint, nDim); + + /*--- Loop over the points and set the coordinates and global index. ---*/ + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++) { + for (unsigned short iDim = 0; iDim < nDim; ++iDim) + nodes->SetCoord(iPoint, iDim, gridCoords[iDim][iPoint]); + nodes->SetGlobalIndex(iPoint, globalPointIDs[iPoint]); + } +} + +void CPhysicalGeometry::LoadLinearlyPartitionedVolumeElementsFEM(CConfig *config, + CMeshReaderBase *mesh) { + + /*--- Reset the global to local element mapping. ---*/ + Global_to_Local_Elem.clear(); + + /*--- Get the volume connectivity from the mesh object. ---*/ + const auto &dataElems = mesh->GetLocalVolumeElementConnectivity(); + + /*--- Allocate space for the interior elements in our SU2 data + structure. Note that we only instantiate our rank's local set. ---*/ + elem = new CPrimalGrid*[nElem] (); + + /*--- Loop over all of the internal, local volumetric elements. ---*/ + unsigned long ind = 0; + for (unsigned long jElem=0; jElemGetNumberOfMarkers(); + config->SetnMarker_All(nMarker); + if (rank == MASTER_NODE) + cout << nMarker << " surface markers." << endl; + + /*--- Create the data structure for boundary elements. ---*/ + bound = new CPrimalGrid**[nMarker]; + nElem_Bound = new unsigned long [nMarker]; + Tag_to_Marker = new string [config->GetnMarker_Max()]; + + /*--- Retrieve the name of the surface markers as well as + the number of surface elements for every marker. ---*/ + const auto §ionNames = mesh->GetMarkerNames(); + const auto &nSurfElemPerMarker = mesh->GetNumberOfSurfaceElementsAllMarkers(); + + /*--- Loop over all sections that we extracted from the grid file + that were identified as boundary element sections so that we can + store those elements into our SU2 data structures. ---*/ + for (int iMarker = 0; iMarker < nMarker; ++iMarker) { + + /*--- Get the string name and set the number of surface elements + for this marker. ---*/ + string Marker_Tag = sectionNames[iMarker]; + nElem_Bound[iMarker] = nSurfElemPerMarker[iMarker]; + + /*--- Allocate the memory of the pointers for the surface + elements for this marker. ---*/ + bound[iMarker] = new CPrimalGrid*[nElem_Bound[iMarker]]; + + /*--- Retrieve the boundary element data for this marker. ---*/ + const auto &dataElems = mesh->GetSurfaceElementConnectivityForMarker(iMarker); + + /*--- Loop over the number of boundary elements for this marker. ---*/ + unsigned long ind = 0; + for (unsigned long jElem=0; jElemGetMarker_CfgFile_TagBound(Marker_Tag)] = Marker_Tag; + config->SetMarker_All_TagBound(iMarker, Marker_Tag); + config->SetMarker_All_KindBC(iMarker, config->GetMarker_CfgFile_KindBC(Marker_Tag)); + config->SetMarker_All_Monitoring(iMarker, config->GetMarker_CfgFile_Monitoring(Marker_Tag)); + config->SetMarker_All_GeoEval(iMarker, config->GetMarker_CfgFile_GeoEval(Marker_Tag)); + config->SetMarker_All_Designing(iMarker, config->GetMarker_CfgFile_Designing(Marker_Tag)); + config->SetMarker_All_Plotting(iMarker, config->GetMarker_CfgFile_Plotting(Marker_Tag)); + config->SetMarker_All_Analyze(iMarker, config->GetMarker_CfgFile_Analyze(Marker_Tag)); + config->SetMarker_All_ZoneInterface(iMarker, config->GetMarker_CfgFile_ZoneInterface(Marker_Tag)); + config->SetMarker_All_DV(iMarker, config->GetMarker_CfgFile_DV(Marker_Tag)); + config->SetMarker_All_Moving(iMarker, config->GetMarker_CfgFile_Moving(Marker_Tag)); + config->SetMarker_All_Deform_Mesh(iMarker, config->GetMarker_CfgFile_Deform_Mesh(Marker_Tag)); + config->SetMarker_All_Fluid_Load(iMarker, config->GetMarker_CfgFile_Fluid_Load(Marker_Tag)); + config->SetMarker_All_PyCustom(iMarker, config->GetMarker_CfgFile_PyCustom(Marker_Tag)); + config->SetMarker_All_PerBound(iMarker, config->GetMarker_CfgFile_PerBound(Marker_Tag)); + config->SetMarker_All_SendRecv(iMarker, NONE); + config->SetMarker_All_Turbomachinery(iMarker, config->GetMarker_CfgFile_Turbomachinery(Marker_Tag)); + config->SetMarker_All_TurbomachineryFlag(iMarker, config->GetMarker_CfgFile_TurbomachineryFlag(Marker_Tag)); + config->SetMarker_All_MixingPlaneInterface(iMarker, config->GetMarker_CfgFile_MixingPlaneInterface(Marker_Tag)); + } +} + void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { /*--- Initialize the color vector of the elements. ---*/ for (unsigned long i = 0; i < nElem; ++i) elem[i]->SetColor(0); diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index f3cd14e2bd4..b97e6399df2 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -3505,16 +3505,30 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena cout << Global_nElem << " volume elements." << endl; } - /*--- Load the grid points, volume elements, and surface elements - from the mesh object into the proper SU2 data structures. ---*/ + /*--- Make a distinction between the FVM solver and FEM solver how to load + the grid data in the member variables of CPhysicalGeometry. ---*/ + if( fem_solver ) { - LoadLinearlyPartitionedPoints(config, Mesh); - LoadLinearlyPartitionedVolumeElements(config, Mesh); - LoadUnpartitionedSurfaceElements(config, Mesh); + /*--- Load the grid points, volume elements, and surface elements + from the mesh object into the proper SU2 data structures. ---*/ - /*--- Prepare the nodal adjacency structures for ParMETIS. ---*/ + LoadLinearlyPartitionedPointsFEM(config, Mesh); + LoadLinearlyPartitionedVolumeElementsFEM(config, Mesh); + LoadLinearlyPartitionedSurfaceElementsFEM(config, Mesh); + } + else { + + /*--- Load the grid points, volume elements, and surface elements + from the mesh object into the proper SU2 data structures. ---*/ + + LoadLinearlyPartitionedPoints(config, Mesh); + LoadLinearlyPartitionedVolumeElements(config, Mesh); + LoadUnpartitionedSurfaceElements(config, Mesh); - PrepareAdjacency(config); + /*--- Prepare the nodal adjacency structures for ParMETIS. ---*/ + + PrepareAdjacency(config); + } /*--- Now that we have loaded all information from the mesh, delete the mesh reader object. ---*/ diff --git a/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp b/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp index cebb3aa2ebf..562d6471cde 100644 --- a/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp +++ b/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp @@ -27,29 +27,24 @@ #include "../../../include/geometry/primal_grid/CPrimalGridBoundFEM.hpp" -CPrimalGridBoundFEM::CPrimalGridBoundFEM(unsigned long val_elemGlobalID, unsigned long val_domainElementID, - unsigned short val_VTK_Type, unsigned short val_nPolyGrid, - unsigned short val_nDOFsGrid, std::vector& val_nodes) - : CPrimalGrid(true, val_nDOFsGrid, 1) { - /*--- Store the integer data in the member variables of this object. ---*/ - VTK_Type = val_VTK_Type; - - nPolyGrid = val_nPolyGrid; - nDOFsGrid = val_nDOFsGrid; - - boundElemIDGlobal = val_elemGlobalID; - GlobalIndex_DomainElement = val_domainElementID; - - /*--- Copy face structure of the element from val_nodes. ---*/ - - for (unsigned short i = 0; i < nDOFsGrid; i++) Nodes[i] = val_nodes[i]; - - /*--- For a linear quadrilateral the two last node numbers must be swapped, - such that the element numbering is consistent with the FEM solver. ---*/ - - if (nPolyGrid == 1 && VTK_Type == QUADRILATERAL) std::swap(Nodes[2], Nodes[3]); +CPrimalGridBoundFEM::CPrimalGridBoundFEM(const unsigned long *dataElem) + :CPrimalGrid(true, dataElem[2], 1) +{ + + /*--- Store the meta data for this element. ---*/ + VTK_Type = (unsigned short) dataElem[0]; + nPolyGrid = (unsigned short) dataElem[1]; + nDOFsGrid = (unsigned short) dataElem[2]; + boundElemIDGlobal = dataElem[3]; + GlobalIndex_DomainElement = dataElem[4]; + + /*--- Allocate the memory for the global nodes of the element to define + the geometry and copy them from val_nodes. ---*/ + for(unsigned short i=0; i> Nodes[i]; - - /*--- If a linear element is used, the node numbering for non-simplices - must be adapted. The reason is that compatability with the original - SU2 format is maintained for linear elements, but for the FEM solver - the nodes of the elements are stored row-wise. ---*/ - if (nPolyGrid == 1) { - switch (VTK_Type) { - case QUADRILATERAL: - std::swap(Nodes[2], Nodes[3]); - break; - - case HEXAHEDRON: - std::swap(Nodes[2], Nodes[3]); - std::swap(Nodes[6], Nodes[7]); - break; - - case PYRAMID: - std::swap(Nodes[2], Nodes[3]); - break; - } - } -} - -CPrimalGridFEM::CPrimalGridFEM(unsigned long val_elemGlobalID, unsigned short val_VTK_Type, - unsigned short val_nPolyGrid, unsigned short val_nPolySol, unsigned short val_nDOFsGrid, - unsigned short val_nDOFsSol, unsigned long val_offDOfsSol, const unsigned long* connGrid) - : CPrimalGrid(true, val_nDOFsGrid, nFacesOfElementType(val_VTK_Type)) { - /*--- Store the integer data in the member variables of this object. ---*/ - VTK_Type = val_VTK_Type; - nFaces = nFacesOfElementType(VTK_Type); - - nPolyGrid = val_nPolyGrid; - nPolySol = val_nPolySol; - nDOFsGrid = val_nDOFsGrid; - nDOFsSol = val_nDOFsSol; - - elemIDGlobal = val_elemGlobalID; - offsetDOFsSolGlobal = val_offDOfsSol; - - /*--- Copy face structure of the element from connGrid. ---*/ - for (unsigned short i = 0; i < nDOFsGrid; i++) Nodes[i] = connGrid[i]; + for(unsigned short i=0; i Date: Tue, 4 Feb 2025 19:16:25 +0100 Subject: [PATCH 123/129] Bug fixes. It seems to be working in sequential mode --- .../geometry/primal_grid/CPrimalGridFEM.hpp | 3 +- Common/src/fem/fem_geometry_structure.cpp | 20 +- .../src/fem/geometry_structure_fem_part.cpp | 198 ++++++++++-------- .../geometry/primal_grid/CPrimalGridFEM.cpp | 7 +- 4 files changed, 127 insertions(+), 101 deletions(-) diff --git a/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp b/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp index a0cafc9f66e..5caa92e0d87 100644 --- a/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp +++ b/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp @@ -57,8 +57,9 @@ class CPrimalGridFEM final : public CPrimalGrid { /*! * \brief Constructor using data to initialize the element. * \param[in] dataElem - Meta and connectivity data for this element. + * \param[in,out] offsetDOFs - The offset of the solution DOFs for this element. */ - CPrimalGridFEM(const unsigned long *dataElem); + CPrimalGridFEM(const unsigned long *dataElem, unsigned long &offsetSolDOFs); /*! * \brief Get the number of nodes that composes a face of an element. diff --git a/Common/src/fem/fem_geometry_structure.cpp b/Common/src/fem/fem_geometry_structure.cpp index e671a2d0265..5a7db7445a9 100644 --- a/Common/src/fem/fem_geometry_structure.cpp +++ b/Common/src/fem/fem_geometry_structure.cpp @@ -25,6 +25,7 @@ * License along with SU2. If not, see . */ +#include "../../include/toolboxes/CLinearPartitioner.hpp" #include "../../include/fem/fem_geometry_structure.hpp" #include "../../include/geometry/primal_grid/CPrimalGridFEM.hpp" #include "../../include/geometry/primal_grid/CPrimalGridBoundFEM.hpp" @@ -221,6 +222,9 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /*--- Allocate the memory for blasFunctions. ---*/ blasFunctions = new CBlasStructure; + /*--- Define the linear partitioning of the elements. ---*/ + CLinearPartitioner elemPartitioner(Global_nElem, 0); + /*--- The new FEM mesh class has the same problem dimension/zone. ---*/ nDim = geometry->GetnDim(); nZone = geometry->GetnZone(); @@ -374,13 +378,14 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /* Loop over the local boundary elements in geometry for this marker. */ for (unsigned long i = 0; i < geometry->GetnElem_Bound(iMarker); ++i) { /* Determine the local ID of the corresponding domain element. */ - unsigned long elemID = geometry->bound[iMarker][i]->GetDomainElement() - geometry->beg_node[rank]; + unsigned long elemID = geometry->bound[iMarker][i]->GetDomainElement() + - elemPartitioner.GetFirstIndexOnRank(rank); /* Determine to which rank this boundary element must be sent. That is the same as its corresponding domain element. Update the corresponding index in longSendBuf. */ int ind = (int)geometry->elem[elemID]->GetColor(); - map::const_iterator MI = rankToIndCommBuf.find(ind); + const auto MI = rankToIndCommBuf.find(ind); ind = MI->second; ++longSendBuf[ind][indLongBuf[ind]]; @@ -667,8 +672,8 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { stored in cumulative storage format. */ vector nElemPerRankOr(size + 1); - for (int i = 0; i < size; ++i) nElemPerRankOr[i] = geometry->beg_node[i]; - nElemPerRankOr[size] = geometry->end_node[size - 1]; + for (int i = 0; i < size; ++i) nElemPerRankOr[i] = elemPartitioner.GetFirstIndexOnRank(i); + nElemPerRankOr[size] = Global_nElem; /* Determine to which ranks I have to send messages to find out the information of the halos stored on this rank. */ @@ -803,11 +808,10 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /* Determine the local index of the element in the original partitioning. Check if the index is valid. */ - const long localID = globalID - geometry->beg_node[rank]; - if (localID < 0 || localID >= (long)geometry->nPointLinear[rank]) { + const long localID = globalID - elemPartitioner.GetFirstIndexOnRank(rank); + if(elemPartitioner.GetRankContainingIndex(globalID) != static_cast(rank)) { ostringstream message; - message << localID << " " << geometry->nPointLinear[rank] << endl; - message << "Invalid local element ID"; + message << "Invalid local element ID: " << localID; SU2_MPI::Error(message.str(), CURRENT_FUNCTION); } diff --git a/Common/src/fem/geometry_structure_fem_part.cpp b/Common/src/fem/geometry_structure_fem_part.cpp index a774b7d78b0..8d0dc218562 100644 --- a/Common/src/fem/geometry_structure_fem_part.cpp +++ b/Common/src/fem/geometry_structure_fem_part.cpp @@ -25,6 +25,7 @@ * License along with SU2. If not, see . */ +#include "../../include/toolboxes/CLinearPartitioner.hpp" #include "../../include/geometry/CPhysicalGeometry.hpp" #include "../../include/fem/fem_standard_element.hpp" #include "../../include/geometry/primal_grid/CPrimalGridFEM.hpp" @@ -393,11 +394,12 @@ void CPhysicalGeometry::LoadLinearlyPartitionedVolumeElementsFEM(CConfig *config /*--- Loop over all of the internal, local volumetric elements. ---*/ unsigned long ind = 0; + unsigned long offsetSolDOFs = 0; for (unsigned long jElem=0; jElem nSolDOFsPerRank(size); + SU2_MPI::Allgather(&offsetSolDOFs, 1, MPI_UNSIGNED_LONG, nSolDOFsPerRank.data(), + 1, MPI_UNSIGNED_LONG, SU2_MPI::GetComm()); + + /* Determine the offset for the DOFs on this rank. */ + unsigned long offsetRank = 0; + for (int i = 0; i < rank; ++i) offsetRank += nSolDOFsPerRank[i]; + + /* Loop over the local elements to correct the global offset of the DOFs. */ + for (unsigned long jElem=0; jElemAddOffsetGlobalDOFs(offsetRank); +#endif } void CPhysicalGeometry::LoadLinearlyPartitionedSurfaceElementsFEM(CConfig *config, @@ -498,7 +516,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { CFaceOfElement thisFace; thisFace.nCornerPoints = nPointsPerFace[i]; for (unsigned short j = 0; j < nPointsPerFace[i]; ++j) thisFace.cornerPoints[j] = faceConn[i][j]; - thisFace.elemID0 = beg_node[rank] + k; + thisFace.elemID0 = elem[k]->GetGlobalElemID(); thisFace.nPolySol0 = elem[k]->GetNPolySol(); thisFace.nDOFsElem0 = elem[k]->GetNDOFsSol(); thisFace.elemType0 = elem[k]->GetVTK_Type(); @@ -857,24 +875,27 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { map mapExternalElemIDToTimeLevel; DetermineTimeLevelElements(config, localFaces, mapExternalElemIDToTimeLevel); + /*--- Define the linear partitioning of the elements. ---*/ + CLinearPartitioner elemPartitioner(Global_nElem, 0); + /*--- Determine the ownership of the internal faces, i.e. which adjacent element is responsible for computing the fluxes through the face. ---*/ for (unsigned long i = 0; i < nFacesLoc; ++i) { /* Check for a matching face. */ if (localFaces[i].elemID1 < Global_nElem) { - /* Determine the time level for both elements. Elem0 is always owned, while - elem1 is either owned or external. The data for external elements is - stored in mapExternalElemIDToTimeLevel. */ - unsigned long elemID0 = localFaces[i].elemID0 - beg_node[rank]; - unsigned short timeLevel0 = elem[elemID0]->GetTimeLevel(); + /*--- Determine the time level of Elem0, which is always owned. ---*/ + const unsigned long elemID0 = localFaces[i].elemID0 - elemPartitioner.GetFirstIndexOnRank(rank); + const unsigned short timeLevel0 = elem[elemID0]->GetTimeLevel(); + + /*--- Determine the time level of Elem1, which is either owned or + external. Hence a distinction must be made. ---*/ unsigned short timeLevel1; - if (localFaces[i].elemID1 >= beg_node[rank] && localFaces[i].elemID1 < beg_node[rank] + nElem) { - unsigned long elemID1 = localFaces[i].elemID1 - beg_node[rank]; + if(elemPartitioner.GetRankContainingIndex(localFaces[i].elemID1) == static_cast(rank)) { + const unsigned long elemID1 = localFaces[i].elemID1 - elemPartitioner.GetFirstIndexOnRank(rank); timeLevel1 = elem[elemID1]->GetTimeLevel(); } else { - map::const_iterator MI; - MI = mapExternalElemIDToTimeLevel.find(localFaces[i].elemID1); + const auto MI = mapExternalElemIDToTimeLevel.find(localFaces[i].elemID1); if (MI == mapExternalElemIDToTimeLevel.end()) SU2_MPI::Error("Entry not found in mapExternalElemIDToTimeLevel", CURRENT_FUNCTION); timeLevel1 = MI->second.short0; @@ -924,7 +945,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { CFaceOfElement thisFace; thisFace.nCornerPoints = nPointsPerFace[i]; for (unsigned short j = 0; j < nPointsPerFace[i]; ++j) thisFace.cornerPoints[j] = faceConn[i][j]; - thisFace.elemID0 = beg_node[rank] + k; + thisFace.elemID0 = k + elemPartitioner.GetFirstIndexOnRank(rank); thisFace.nPolySol0 = elem[k]->GetNPolySol(); thisFace.nDOFsElem0 = elem[k]->GetNDOFsSol(); @@ -953,12 +974,19 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { of the graph. First the faces. ---*/ vector > adjacency(nElem, vector(0)); for (unsigned long i = 0; i < nFacesLoc; ++i) { - long ii = localFaces[i].elemID0 - beg_node[rank]; - adjacency[ii].push_back(localFaces[i].elemID1); + /*--- Determine the local index of elem0, which is always stored locally, + and add elemID1 to the adjacency list. ---*/ + const unsigned long elem0 = localFaces[i].elemID0 - elemPartitioner.GetFirstIndexOnRank(rank); + adjacency[elem0].push_back(localFaces[i].elemID1); + + /*--- Check if this is not a periodic face and if the second element is + also a local element. If so, add elemID0 to the adjacency list ---*/ if (localFaces[i].periodicIndex == 0) { - ii = localFaces[i].elemID1 - beg_node[rank]; - if (ii >= 0 && ii < (long)nElem) adjacency[ii].push_back(localFaces[i].elemID0); + if(elemPartitioner.GetRankContainingIndex(localFaces[i].elemID1) == static_cast(rank)) { + const unsigned long elem1 = localFaces[i].elemID1 - elemPartitioner.GetFirstIndexOnRank(rank); + adjacency[elem1].push_back(localFaces[i].elemID0); + } } } @@ -976,7 +1004,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { are present. ParMETIS is not able to deal with self entries, hence they must be removed as well. */ for (unsigned long i = 0; i < nElem; ++i) { - const unsigned long globalElemID = i + beg_node[rank]; + const unsigned long globalElemID = i + + elemPartitioner.GetFirstIndexOnRank(rank); unsigned long nEntriesNew = adjacency[i].size(); for (unsigned long j = 0; j < adjacency[i].size(); ++j) { @@ -999,7 +1027,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { for (unsigned long l = 0; l < nElem_Bound[iMarker]; ++l) { /* Get the global and local element ID adjacent to this boundary face. */ const unsigned long globalElemID = bound[iMarker][l]->GetDomainElement(); - const unsigned long elemID = globalElemID - beg_node[rank]; + const unsigned long elemID = globalElemID - elemPartitioner.GetFirstIndexOnRank(rank); /* Get the number of donor elements for the wall function treatment and the pointer to the array which stores this info. */ @@ -1017,10 +1045,10 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { sort(adjacency[elemID].begin(), adjacency[elemID].end()); /* Check if the donor element is stored locally. */ - if (donors[i] >= beg_node[rank] && donors[i] < beg_node[rank] + nElem) { + if(elemPartitioner.GetRankContainingIndex(donors[i]) == static_cast(rank)) { /* Donor is stored locally. Add the entry to the graph and sort it afterwards. */ - const unsigned long localDonorID = donors[i] - beg_node[rank]; + const unsigned long localDonorID = donors[i] - elemPartitioner.GetFirstIndexOnRank(rank); adjacency[localDonorID].push_back(globalElemID); sort(adjacency[localDonorID].begin(), adjacency[localDonorID].end()); } else { @@ -1042,18 +1070,10 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { vector sendToRank(size, 0); for (unsigned long i = 0; i < additionalExternalEntriesGraph.size(); i += 2) { - /* Determine the rank where this external is stored. */ - const unsigned long elemID = additionalExternalEntriesGraph[i]; - int rankElem; - if (elemID >= beg_node[size - 1]) - rankElem = size - 1; - else { - const unsigned long* low; - low = lower_bound(beg_node, beg_node + size, elemID); - rankElem = low - beg_node; - if (*low > elemID) --rankElem; - } + /*--- Determine the rank where this external is stored and update + the corresponding communication buffers accordingly. ---*/ + const unsigned long rankElem = elemPartitioner.GetRankContainingIndex(additionalExternalEntriesGraph[i]); sendBufsGraphData[rankElem].push_back(additionalExternalEntriesGraph[i]); sendBufsGraphData[rankElem].push_back(additionalExternalEntriesGraph[i + 1]); @@ -1099,7 +1119,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { /* Loop over the contents of the receive buffer and update the graph accordingly. */ for (int j = 0; j < sizeMess; j += 2) { - const unsigned long elemID = recvBuf[j] - beg_node[rank]; + const unsigned long elemID = recvBuf[j] - elemPartitioner.GetFirstIndexOnRank(rank); adjacency[elemID].push_back(recvBuf[j + 1]); sort(adjacency[elemID].begin(), adjacency[elemID].end()); } @@ -1945,6 +1965,9 @@ void CPhysicalGeometry::DetermineDonorElementsWallFunctions(CConfig* config) { /*--- the local elements. ---*/ /*--------------------------------------------------------------------------*/ + /*--- Define the linear partitioning of the elements. ---*/ + CLinearPartitioner elemPartitioner(Global_nElem, 0); + /* Define the vectors, which store the boundary marker, boundary element ID and exchange coordinates for the integration points for which no donor element was found in the locally stored volume elements. */ @@ -1972,7 +1995,7 @@ void CPhysicalGeometry::DetermineDonorElementsWallFunctions(CConfig* config) { /* Easier storage of the element type, the corresponding volume element and the polynomial degree for the solution and grid. */ const unsigned short VTK_Type = bound[iMarker][l]->GetVTK_Type(); - const unsigned long elemID = bound[iMarker][l]->GetDomainElement() - beg_node[rank]; + const unsigned long elemID = bound[iMarker][l]->GetDomainElement() - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short nPolyGrid = bound[iMarker][l]->GetNPolyGrid(); const unsigned short nPolySol = elem[elemID]->GetNPolySol(); const unsigned short VTK_Elem = elem[elemID]->GetVTK_Type(); @@ -2403,6 +2426,10 @@ void CPhysicalGeometry::DetermineDonorElementsWallFunctions(CConfig* config) { void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector& localFaces, map& mapExternalElemIDToTimeLevel) { + + /*--- Define the linear partitioning of the elements. ---*/ + CLinearPartitioner elemPartitioner(Global_nElem, 0); + /*--------------------------------------------------------------------------*/ /*--- Step 1: Initialize the map mapExternalElemIDToTimeLevel. ---*/ /*--------------------------------------------------------------------------*/ @@ -2412,7 +2439,11 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector for (auto FI = localFaces.begin(); FI != localFaces.end(); ++FI) { if (FI->elemID1 < Global_nElem) { // Safeguard against non-matching faces. - if (FI->elemID1 < beg_node[rank] || FI->elemID1 >= beg_node[rank] + nElem) { + /*--- Check for external element. This is done by checking the + local elements and if it is not found, it is an external. ---*/ + const auto UMI = Global_to_Local_Elem.find(FI->elemID1); + if(UMI == Global_to_Local_Elem.end()) { + /* This element is an external element. Store it in the map mapExternalElemIDToTimeLevel if not already done so. */ map::iterator MI; @@ -2439,30 +2470,24 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector const unsigned short nDonors = bound[iMarker][l]->GetNDonorsWallFunctions(); const unsigned long* donors = bound[iMarker][l]->GetDonorsWallFunctions(); - /* Loop over the number of donors and add the externals to - mapExternalElemIDToTimeLevel, if not already present. */ - for (unsigned short i = 0; i < nDonors; ++i) { - if (donors[i] < beg_node[rank] || donors[i] >= beg_node[rank] + nElem) { - map::iterator MI; - MI = mapExternalElemIDToTimeLevel.find(donors[i]); + /*--- Loop over the number of donors for this boundary element. ---*/ + for(unsigned short i=0; i= beg_node[size - 1]) - rankDonor = size - 1; - else { - const unsigned long* low; - low = lower_bound(beg_node, beg_node + size, donors[i]); - - rankDonor = (int)(low - beg_node); - if (*low > donors[i]) --rankDonor; - } + /*--- The reverse connection may not be present either. Store the global + ID of this element in the send buffers for the additional + externals. ---*/ + const unsigned long rankDonor = elemPartitioner.GetRankContainingIndex(donors[i]); sendBufAddExternals[rankDonor].push_back(bound[iMarker][l]->GetDomainElement()); recvFromRank[rankDonor] = 1; @@ -2622,20 +2647,10 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector recvFromRank.assign(size, 0); for (MI = mapExternalElemIDToTimeLevel.begin(); MI != mapExternalElemIDToTimeLevel.end(); ++MI) { - /* Determine the rank where this external is stored. */ - const unsigned long elemID = MI->first; - int rankElem; - if (elemID >= beg_node[size - 1]) - rankElem = size - 1; - else { - const unsigned long* low; - low = lower_bound(beg_node, beg_node + size, elemID); - - rankElem = low - beg_node; - if (*low > elemID) --rankElem; - } - /* Set the corresponding index of recvFromRank to 1. */ + /*--- Determine the rank where this external is stored and set + the corresponding index of recvFromRank to 1. ---*/ + const unsigned long rankElem = elemPartitioner.GetRankContainingIndex(MI->first); recvFromRank[rankElem] = 1; } @@ -2658,18 +2673,9 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector for (MI = mapExternalElemIDToTimeLevel.begin(); MI != mapExternalElemIDToTimeLevel.end(); ++MI) { const unsigned long elemID = MI->first; - int rankElem; - if (elemID >= beg_node[size - 1]) - rankElem = size - 1; - else { - const unsigned long* low; - low = lower_bound(beg_node, beg_node + size, elemID); - - rankElem = low - beg_node; - if (*low > elemID) --rankElem; - } + const unsigned long rankElem = elemPartitioner.GetRankContainingIndex(elemID); - map::const_iterator MRI = mapRankToIndRecv.find(rankElem); + const auto MRI = mapRankToIndRecv.find(rankElem); recvElem[MRI->second].push_back(elemID); } @@ -2705,7 +2711,8 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector SU2_MPI::Recv(sendElem[i].data(), sizeMess, MPI_UNSIGNED_LONG, sendRank[i], rank, SU2_MPI::GetComm(), &status); - for (int j = 0; j < sizeMess; ++j) sendElem[i][j] -= beg_node[rank]; + for (int j = 0; j < sizeMess; ++j) + sendElem[i][j] -= elemPartitioner.GetFirstIndexOnRank(rank); } /* Complete the non-blocking sends. Synchronize the processors afterwards, @@ -2796,7 +2803,8 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector for (unsigned short iMarker = 0; iMarker < nMarker; ++iMarker) { for (unsigned long l = 0; l < nElem_Bound[iMarker]; ++l) { /* Determine the ID of the adjacent element. */ - const unsigned long elemID = bound[iMarker][l]->GetDomainElement() - beg_node[rank]; + const unsigned long elemID = bound[iMarker][l]->GetDomainElement() + - elemPartitioner.GetFirstIndexOnRank(rank); /* Get the number of donor elements for the wall function treatment and the pointer to the array which stores this info. */ @@ -2805,11 +2813,14 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector /* Loop over the number of donors and check the time levels. */ for (unsigned short i = 0; i < nDonors; ++i) { + /* Determine the status of the donor element. */ - if (donors[i] >= beg_node[rank] && donors[i] < beg_node[rank] + nElem) { + if(elemPartitioner.GetRankContainingIndex(donors[i]) == static_cast(rank)) { + /* Donor is stored locally. Determine its local ID and get the time levels of both elements. */ - const unsigned long donorID = donors[i] - beg_node[rank]; + const unsigned long donorID = donors[i] + - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short timeLevelB = elem[elemID]->GetTimeLevel(); const unsigned short timeLevelD = elem[donorID]->GetTimeLevel(); const unsigned short timeLevel = min(timeLevelB, timeLevelD); @@ -2860,15 +2871,16 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector if (FI->elemID1 < Global_nElem) { /* Local element ID of the first element. Per definition this is always a locally stored element. Also store its time level. */ - const unsigned long elemID0 = FI->elemID0 - beg_node[rank]; + const unsigned long elemID0 = FI->elemID0 + - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short timeLevel0 = elem[elemID0]->GetTimeLevel(); /* Determine the status of the second element. */ - if (FI->elemID1 >= beg_node[rank] && FI->elemID1 < beg_node[rank] + nElem) { + if(elemPartitioner.GetRankContainingIndex(FI->elemID1) == static_cast(rank)) { /* Both elements are stored locally. Determine the local element of the second element and determine the minimum time level. */ - const unsigned long elemID1 = FI->elemID1 - beg_node[rank]; + const unsigned long elemID1 = FI->elemID1 - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short timeLevel1 = elem[elemID1]->GetTimeLevel(); const unsigned short timeLevel = min(timeLevel0, timeLevel1); @@ -3016,6 +3028,10 @@ void CPhysicalGeometry::ComputeFEMGraphWeights(CConfig* config, const vector >& adjacency, const map& mapExternalElemIDToTimeLevel, vector& vwgt, vector >& adjwgt) { + + /*--- Define the linear partitioning of the elements. ---*/ + CLinearPartitioner elemPartitioner(Global_nElem, 0); + /*--- Determine the maximum time level that occurs in the grid. ---*/ unsigned short maxTimeLevel = 0; for (unsigned long i = 0; i < nElem; ++i) maxTimeLevel = max(maxTimeLevel, elem[i]->GetTimeLevel()); @@ -3077,7 +3093,7 @@ void CPhysicalGeometry::ComputeFEMGraphWeights(CConfig* config, const vectorGetVTK_Type(); - const unsigned long elemID = bound[iMarker][l]->GetDomainElement() - beg_node[rank]; + const unsigned long elemID = bound[iMarker][l]->GetDomainElement() + - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short nPolySol = elem[elemID]->GetNPolySol(); const unsigned short VTK_Type_Elem = elem[elemID]->GetVTK_Type(); const bool JacIsConstant = bound[iMarker][l]->GetJacobianConsideredConstant(); @@ -3277,17 +3294,16 @@ void CPhysicalGeometry::ComputeFEMGraphWeights(CConfig* config, const vector= beg_node[rank] && adjacency[i][j] < beg_node[rank] + nElem) { + if(elemPartitioner.GetRankContainingIndex(adjacency[i][j]) == static_cast(rank)) { /* Locally stored element. Determine its local ID and set the time level and number of solution DOFs. */ - unsigned long elemID1 = adjacency[i][j] - beg_node[rank]; + unsigned long elemID1 = adjacency[i][j] - elemPartitioner.GetFirstIndexOnRank(rank); timeLevel1 = elem[elemID1]->GetTimeLevel(); nDOFs1 = elem[elemID1]->GetNDOFsSol(); } else { /* The neighbor is an external element. Find it in mapExternalElemIDToTimeLevel and set the time level and number of solution DOFs accordingly. */ - map::const_iterator MI; - MI = mapExternalElemIDToTimeLevel.find(adjacency[i][j]); + const auto MI = mapExternalElemIDToTimeLevel.find(adjacency[i][j]); if (MI == mapExternalElemIDToTimeLevel.end()) SU2_MPI::Error("Entry not found in mapExternalElemIDToTimeLevel", CURRENT_FUNCTION); timeLevel1 = MI->second.short0; diff --git a/Common/src/geometry/primal_grid/CPrimalGridFEM.cpp b/Common/src/geometry/primal_grid/CPrimalGridFEM.cpp index c4d29007946..122127c2c92 100644 --- a/Common/src/geometry/primal_grid/CPrimalGridFEM.cpp +++ b/Common/src/geometry/primal_grid/CPrimalGridFEM.cpp @@ -28,7 +28,7 @@ #include "../../../include/geometry/primal_grid/CPrimalGridFEM.hpp" #include "../../../include/fem/fem_standard_element.hpp" -CPrimalGridFEM::CPrimalGridFEM(const unsigned long *dataElem) +CPrimalGridFEM::CPrimalGridFEM(const unsigned long *dataElem, unsigned long &offsetSolDOFs) : CPrimalGrid(true, dataElem[3], nFacesOfElementType(dataElem[0])) { /*--- Store the meta data for this element. ---*/ @@ -39,6 +39,11 @@ CPrimalGridFEM::CPrimalGridFEM(const unsigned long *dataElem) nDOFsSol = CFEMStandardElementBase::GetNDOFsStatic(VTK_Type, nPolySol); elemIDGlobal = dataElem[4]; + offsetDOFsSolGlobal = offsetSolDOFs; + offsetSolDOFs += nDOFsSol; + + nFaces = nFacesOfElementType(VTK_Type); + /*--- Allocate the memory for the global nodes of the element to define the geometry and copy the data from dataElem. ---*/ From 6b617b177eb44e4eeadc10fa018f039329e5eaff Mon Sep 17 00:00:00 2001 From: vdweide Date: Wed, 5 Feb 2025 15:46:24 +0100 Subject: [PATCH 124/129] Bug fixes to make things work in parallel --- Common/src/fem/fem_geometry_structure.cpp | 6 +++--- Common/src/fem/geometry_structure_fem_part.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Common/src/fem/fem_geometry_structure.cpp b/Common/src/fem/fem_geometry_structure.cpp index 5a7db7445a9..1f1c7495b2c 100644 --- a/Common/src/fem/fem_geometry_structure.cpp +++ b/Common/src/fem/fem_geometry_structure.cpp @@ -223,6 +223,7 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { blasFunctions = new CBlasStructure; /*--- Define the linear partitioning of the elements. ---*/ + Global_nElem = geometry->GetGlobal_nElem(); CLinearPartitioner elemPartitioner(Global_nElem, 0); /*--- The new FEM mesh class has the same problem dimension/zone. ---*/ @@ -671,9 +672,8 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /* Determine the number of elements per rank of the originally partitioned grid stored in cumulative storage format. */ vector nElemPerRankOr(size + 1); - - for (int i = 0; i < size; ++i) nElemPerRankOr[i] = elemPartitioner.GetFirstIndexOnRank(i); - nElemPerRankOr[size] = Global_nElem; + for (int i = 0; i <= size; ++i) + nElemPerRankOr[i] = elemPartitioner.GetCumulativeSizeBeforeRank(i); /* Determine to which ranks I have to send messages to find out the information of the halos stored on this rank. */ diff --git a/Common/src/fem/geometry_structure_fem_part.cpp b/Common/src/fem/geometry_structure_fem_part.cpp index 8d0dc218562..5bbf731eef8 100644 --- a/Common/src/fem/geometry_structure_fem_part.cpp +++ b/Common/src/fem/geometry_structure_fem_part.cpp @@ -1162,8 +1162,8 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { /*--- Determine the array, which stores the distribution of the graph nodes over the ranks. ---*/ vector vtxdist(size + 1); - vtxdist[0] = 0; - for (int i = 0; i < size; ++i) vtxdist[i + 1] = (idx_t)end_node[i]; + for (int i = 0; i <= size; ++i) + vtxdist[i] = static_cast(elemPartitioner.GetCumulativeSizeBeforeRank(i)); /* Create the array xadjPar, which contains the number of edges for each vertex of the graph in ParMETIS format. */ From 020f87a203f07a99ac1a32869ca874df0b4a2d7e Mon Sep 17 00:00:00 2001 From: vdweide Date: Wed, 5 Feb 2025 15:52:24 +0100 Subject: [PATCH 125/129] Result of running pre-commit --- Common/include/geometry/CPhysicalGeometry.hpp | 21 +- .../geometry/meshreader/CBoxMeshReaderFEM.hpp | 11 +- .../geometry/meshreader/CCGNSElementType.hpp | 203 +-- .../meshreader/CCGNSMeshReaderFEM.hpp | 24 +- .../geometry/meshreader/CMeshReaderBase.hpp | 20 +- .../meshreader/CSU2ASCIIMeshReaderFEM.hpp | 5 +- .../primal_grid/CPrimalGridBoundFEM.hpp | 2 +- .../geometry/primal_grid/CPrimalGridFEM.hpp | 3 +- Common/src/fem/fem_geometry_structure.cpp | 9 +- .../src/fem/geometry_structure_fem_part.cpp | 113 +- Common/src/geometry/CPhysicalGeometry.cpp | 31 +- .../geometry/meshreader/CBoxMeshReaderFEM.cpp | 215 ++- .../geometry/meshreader/CCGNSElementType.cpp | 1253 +++++++++++------ .../meshreader/CCGNSMeshReaderBase.cpp | 68 +- .../meshreader/CCGNSMeshReaderFEM.cpp | 237 ++-- .../meshreader/CCGNSMeshReaderFVM.cpp | 3 +- .../geometry/meshreader/CMeshReaderBase.cpp | 43 +- .../meshreader/CRectangularMeshReaderFEM.cpp | 120 +- .../meshreader/CSU2ASCIIMeshReaderBase.cpp | 3 +- .../meshreader/CSU2ASCIIMeshReaderFEM.cpp | 183 ++- .../meshreader/CSU2ASCIIMeshReaderFVM.cpp | 3 +- .../primal_grid/CPrimalGridBoundFEM.cpp | 17 +- .../geometry/primal_grid/CPrimalGridFEM.cpp | 18 +- 23 files changed, 1436 insertions(+), 1169 deletions(-) diff --git a/Common/include/geometry/CPhysicalGeometry.hpp b/Common/include/geometry/CPhysicalGeometry.hpp index 2e90f374ca7..e6a871bb977 100644 --- a/Common/include/geometry/CPhysicalGeometry.hpp +++ b/Common/include/geometry/CPhysicalGeometry.hpp @@ -285,8 +285,7 @@ class CPhysicalGeometry final : public CGeometry { * \param[in] val_iZone - Domain to be read from the grid file. * \param[in] val_nZone - Total number of domains in the grid file. */ - void Read_Mesh(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, - unsigned short val_nZone); + void Read_Mesh(CConfig* config, const string& val_mesh_filename, unsigned short val_iZone, unsigned short val_nZone); /*! * \brief Routine to load the CGNS grid points from a single zone into the proper SU2 data structures. @@ -300,7 +299,7 @@ class CPhysicalGeometry final : public CGeometry { * \param[in] config - definition of the particular problem. * \param[in] mesh - mesh reader object containing the current zone data. */ - void LoadLinearlyPartitionedPointsFEM(CConfig *config, CMeshReaderBase *mesh); + void LoadLinearlyPartitionedPointsFEM(CConfig* config, CMeshReaderBase* mesh); /*! * \brief Loads the interior volume elements from the mesh reader object into the primal element data structures. @@ -310,11 +309,11 @@ class CPhysicalGeometry final : public CGeometry { void LoadLinearlyPartitionedVolumeElements(CConfig* config, CMeshReaderBase* mesh); /*! - * \brief Loads the interior volume elements from the mesh reader object into the primal element data structures for the FEM solver. - * \param[in] config - definition of the particular problem. - * \param[in] mesh - mesh reader object containing the current zone data. + * \brief Loads the interior volume elements from the mesh reader object into the primal element data structures for + * the FEM solver. \param[in] config - definition of the particular problem. \param[in] mesh - mesh reader object + * containing the current zone data. */ - void LoadLinearlyPartitionedVolumeElementsFEM(CConfig *config, CMeshReaderBase *mesh); + void LoadLinearlyPartitionedVolumeElementsFEM(CConfig* config, CMeshReaderBase* mesh); /*! * \brief Loads the boundary elements (markers) from the mesh reader object into the primal element data structures. @@ -324,11 +323,11 @@ class CPhysicalGeometry final : public CGeometry { void LoadUnpartitionedSurfaceElements(CConfig* config, CMeshReaderBase* mesh); /*! - * \brief Loads the boundary elements (markers) from the mesh reader object into the primal element data structures for the FEM solver. - * \param[in] config - definition of the particular problem. - * \param[in] mesh - mesh reader object containing the current zone data. + * \brief Loads the boundary elements (markers) from the mesh reader object into the primal element data structures + * for the FEM solver. \param[in] config - definition of the particular problem. \param[in] mesh - mesh reader + * object containing the current zone data. */ - void LoadLinearlyPartitionedSurfaceElementsFEM(CConfig *config, CMeshReaderBase *mesh); + void LoadLinearlyPartitionedSurfaceElementsFEM(CConfig* config, CMeshReaderBase* mesh); /*! * \brief Prepares the grid point adjacency based on a linearly partitioned mesh object needed by ParMETIS for graph diff --git a/Common/include/geometry/meshreader/CBoxMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CBoxMeshReaderFEM.hpp index acfafef6365..f5a0e53934b 100644 --- a/Common/include/geometry/meshreader/CBoxMeshReaderFEM.hpp +++ b/Common/include/geometry/meshreader/CBoxMeshReaderFEM.hpp @@ -35,10 +35,8 @@ * \brief Reads a 3D box grid into linear partitions for the finite element solver (FEM). * \author: T. Economon, E. van der Weide */ -class CBoxMeshReaderFEM final: public CMeshReaderBase { - -private: - +class CBoxMeshReaderFEM final : public CMeshReaderBase { + private: unsigned long nNode; /*!< \brief Number of grid nodes in the x-direction. */ unsigned long mNode; /*!< \brief Number of grid nodes in the y-direction. */ unsigned long pNode; /*!< \brief Number of grid nodes in the z-direction. */ @@ -71,12 +69,11 @@ class CBoxMeshReaderFEM final: public CMeshReaderBase { */ void ComputeBoxSurfaceConnectivity(); -public: - + public: /*! * \brief Constructor of the CBoxMeshReaderFEM class. */ - CBoxMeshReaderFEM(const CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone); + CBoxMeshReaderFEM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); /*! * \brief Destructor of the CBoxMeshReaderFEM class. diff --git a/Common/include/geometry/meshreader/CCGNSElementType.hpp b/Common/include/geometry/meshreader/CCGNSElementType.hpp index e081347be1b..fbe944f0114 100644 --- a/Common/include/geometry/meshreader/CCGNSElementType.hpp +++ b/Common/include/geometry/meshreader/CCGNSElementType.hpp @@ -41,19 +41,17 @@ using namespace std; /*! * \class CCGNSElementType * \brief Class used to convert the CGNS format to SU2 format for high order elements. -* \author: E. van der Weide + * \author: E. van der Weide */ class CCGNSElementType { -private: - - vector CGNSTypeStored; /*!< \brief CGNS element types for which the data is stored. */ - vector VTKTypeStored; /*!< \brief VTK type of the element. */ - vector nPolyStored; /*!< \brief Polynomial degree of the element. */ - vector nDOFsStored; /*!< \brief Number of DOFs of the element. */ - vector > SU2ToCGNSStored; /*!< \brief Double vector, which stores the conversion + private: + vector CGNSTypeStored; /*!< \brief CGNS element types for which the data is stored. */ + vector VTKTypeStored; /*!< \brief VTK type of the element. */ + vector nPolyStored; /*!< \brief Polynomial degree of the element. */ + vector nDOFsStored; /*!< \brief Number of DOFs of the element. */ + vector > SU2ToCGNSStored; /*!< \brief Double vector, which stores the conversion from SU2 to CGNS for the type in local numbering. */ -public: - + public: /*--- Standard constructor, nothing to be done. ---*/ CCGNSElementType() = default; @@ -67,13 +65,10 @@ class CCGNSElementType { * \param[in] connCGNS - Array with the connectivity of the element in CGNS format. * \param[out] connSU2 - Vector with the connectivity and meta data in SU2 format. */ - void CGNSToSU2(const ElementType_t val_elemType, - const unsigned long val_globalID, - const cgsize_t *connCGNS, - std::vector &connSU2); - -private: + void CGNSToSU2(const ElementType_t val_elemType, const unsigned long val_globalID, const cgsize_t* connCGNS, + std::vector& connSU2); + private: /*! * \brief Converts the connectivity from CGNS to SU2 for a node. * \param[out] VTK_Type - Corresponding VTK type @@ -81,10 +76,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataNODE(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataNODE(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Bar2 element. @@ -93,10 +86,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataBAR_2(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataBAR_2(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Bar3 element. @@ -105,22 +96,18 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataBAR_3(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataBAR_3(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); - /*! + /*! * \brief Converts the connectivity from CGNS to SU2 for a Bar4 element. * \param[out] VTK_Type - Corresponding VTK type * \param[out] nPoly - Polynomial degree * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataBAR_4(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataBAR_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Bar5 element. @@ -129,10 +116,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataBAR_5(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataBAR_5(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Tri3 element. @@ -141,10 +126,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataTRI_3(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataTRI_3(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Tri6 element. @@ -153,10 +136,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataTRI_6(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataTRI_6(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Tri10 element. @@ -165,10 +146,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataTRI_10(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataTRI_10(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Tri15 element. @@ -177,10 +156,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataTRI_15(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataTRI_15(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Quad4 element. @@ -189,10 +166,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataQUAD_4(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataQUAD_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Quad9 element. @@ -201,10 +176,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataQUAD_9(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataQUAD_9(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Quad16 element. @@ -213,10 +186,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataQUAD_16(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataQUAD_16(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Quad25 element. @@ -225,10 +196,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataQUAD_25(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataQUAD_25(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Tetra4 element. @@ -237,10 +206,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataTETRA_4(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataTETRA_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Tetra10 element. @@ -249,10 +216,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataTETRA_10(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataTETRA_10(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Tetra20 element. @@ -261,10 +226,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataTETRA_20(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataTETRA_20(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Tetra35 element. @@ -273,10 +236,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataTETRA_35(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataTETRA_35(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Pyra5 element. @@ -285,10 +246,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataPYRA_5(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataPYRA_5(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Pyra14 element. @@ -297,10 +256,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataPYRA_14(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataPYRA_14(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Pyra30 element. @@ -309,10 +266,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataPYRA_30(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataPYRA_30(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Pyra55 element. @@ -321,10 +276,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataPYRA_55(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataPYRA_55(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Penta6 element. @@ -333,10 +286,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataPENTA_6(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataPENTA_6(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Penta18 element. @@ -345,10 +296,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataPENTA_18(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataPENTA_18(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Penta40 element. @@ -357,10 +306,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataPENTA_40(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataPENTA_40(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Penta75 element. @@ -369,10 +316,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataPENTA_75(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataPENTA_75(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Hexa8 element. @@ -381,10 +326,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataHEXA_8(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataHEXA_8(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Hexa27 element. @@ -393,10 +336,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataHEXA_27(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataHEXA_27(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Hexa64 element. @@ -405,10 +346,8 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataHEXA_64(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataHEXA_64(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); /*! * \brief Converts the connectivity from CGNS to SU2 for a Hexa125 element. @@ -417,9 +356,7 @@ class CCGNSElementType { * \param[out] nDOFs - Number of DOFs of the element. * \param[out] SU2ToCGNS - Vector containing the mapping from SU2 to CGNS. */ - void CreateDataHEXA_125(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS); + void CreateDataHEXA_125(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS); }; #endif diff --git a/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp index a07bf969f4c..cb7fcd404e8 100644 --- a/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp +++ b/Common/include/geometry/meshreader/CCGNSMeshReaderFEM.hpp @@ -37,7 +37,6 @@ */ class CCGNSMeshReaderFEM final : public CCGNSMeshReaderBase { private: - /*! * \brief Communicates the grid points to the MPI rank where they are needed. */ @@ -54,20 +53,18 @@ class CCGNSMeshReaderFEM final : public CCGNSMeshReaderBase { * \param[inout] localElemCount - Counter, which keeps track how many local elements are stored. * \param[inout] localConn - Vector where the connectivity must be stored. */ - void ReadCGNSConnectivityRangeSection(const int val_section, - const unsigned long val_firstIndex, - const unsigned long val_lastIndex, - unsigned long &elemCount, - unsigned long &localElemCount, - vector &localConn); + void ReadCGNSConnectivityRangeSection(const int val_section, const unsigned long val_firstIndex, + const unsigned long val_lastIndex, unsigned long& elemCount, + unsigned long& localElemCount, vector& localConn); -/*! + /*! * \brief Reads the interior volume elements from one section of a CGNS zone into linear partitions across all ranks. */ void ReadCGNSVolumeElementConnectivity(); /*! - * \brief Reads the surface (boundary) elements from one section of a CGNS zone into linear partitions across all ranks. + * \brief Reads the surface (boundary) elements from one section of a CGNS zone into linear partitions across all + * ranks. */ void ReadCGNSSurfaceElementConnectivity(); @@ -78,18 +75,15 @@ class CCGNSMeshReaderFEM final : public CCGNSMeshReaderBase { * \param[out] nSurfElem - Number of local surface elements stored for this surface section. * \param[out] surfConn - Vector to store the connectivity of the surface elements to be stored. */ - void ReadCGNSSurfaceSection(const int val_section, - const vector &localFaces, - unsigned long &nSurfElem, - vector &surfConn); + void ReadCGNSSurfaceSection(const int val_section, const vector& localFaces, unsigned long& nSurfElem, + vector& surfConn); #endif public: - /*! * \brief Constructor of the CCGNSMeshReaderFEM class. */ - CCGNSMeshReaderFEM(const CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone); + CCGNSMeshReaderFEM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); /*! * \brief Destructor of the CCGNSMeshReaderFEM class. diff --git a/Common/include/geometry/meshreader/CMeshReaderBase.hpp b/Common/include/geometry/meshreader/CMeshReaderBase.hpp index da3f72c48cc..622b48db4c8 100644 --- a/Common/include/geometry/meshreader/CMeshReaderBase.hpp +++ b/Common/include/geometry/meshreader/CMeshReaderBase.hpp @@ -66,16 +66,18 @@ class CMeshReaderBase { unsigned long numberOfMarkers = 0; /*!< \brief Total number of markers contained within the mesh file. */ vector markerNames; /*!< \brief String names for all markers in the mesh file. */ - vector numberOfLocalSurfaceElements; /*!< \brief Vector containing the number of local surface elements. */ + vector + numberOfLocalSurfaceElements; /*!< \brief Vector containing the number of local surface elements. */ vector > surfaceElementConnectivity; /*!< \brief Vector containing the surface element connectivity from the mesh file on a - per-marker basis. For FVM, only the master node reads and stores this connectivity. */ + per-marker basis. For FVM, only the master node reads and stores this connectivity. + */ /*! * \brief Function, which determines the faces of the local volume elements. * \param[out] localFaces - The faces of the locally stored volume elements. */ - void DetermineFacesVolumeElements(vector &localFaces); + void DetermineFacesVolumeElements(vector& localFaces); /*! * \brief Get all the corner points of all the faces of the given element. It must @@ -84,10 +86,8 @@ class CMeshReaderBase { * \param[out] nPointsPerFace - Number of corner points for each of the faces. * \param[out] faceConn - Global IDs of the corner points of the faces. */ - void GetCornerPointsAllFaces(const unsigned long *elemInfo, - unsigned short &numFaces, - unsigned short nPointsPerFace[], - unsigned long faceConn[6][4]); + void GetCornerPointsAllFaces(const unsigned long* elemInfo, unsigned short& numFaces, unsigned short nPointsPerFace[], + unsigned long faceConn[6][4]); public: /*! @@ -110,9 +110,7 @@ class CMeshReaderBase { * \brief Get the global IDs of the local points. * \returns Reference to the vector containing the global points IDs. */ - inline const vector &GetGlobalPointIDs() const { - return globalPointIDs; - } + inline const vector& GetGlobalPointIDs() const { return globalPointIDs; } /*! * \brief Get the local point coordinates (linearly partitioned). @@ -133,7 +131,7 @@ class CMeshReaderBase { * \brief Get the number surface elements for all markers. * \returns Reference to the vector containing the number of surface elements for all markers. */ - inline const vector &GetNumberOfSurfaceElementsAllMarkers() const { + inline const vector& GetNumberOfSurfaceElementsAllMarkers() const { return numberOfLocalSurfaceElements; } diff --git a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp index 3b4759a9301..d92cf336103 100644 --- a/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp +++ b/Common/include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp @@ -50,7 +50,8 @@ class CSU2ASCIIMeshReaderFEM : public CSU2ASCIIMeshReaderBase { void ReadVolumeElementConnectivity(); /*! - * \brief Reads the surface (boundary) elements from one section of an SU2 zone into linear partitions across all ranks. + * \brief Reads the surface (boundary) elements from one section of an SU2 zone into linear partitions across all + * ranks. */ void ReadSurfaceElementConnectivity(); @@ -58,7 +59,7 @@ class CSU2ASCIIMeshReaderFEM : public CSU2ASCIIMeshReaderBase { /*! * \brief Constructor of the CSU2ASCIIMeshReaderFEM class. */ - CSU2ASCIIMeshReaderFEM(CConfig *val_config, unsigned short val_iZone, unsigned short val_nZone); + CSU2ASCIIMeshReaderFEM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone); /*! * \brief Destructor of the CSU2ASCIIMeshReaderFEM class. diff --git a/Common/include/geometry/primal_grid/CPrimalGridBoundFEM.hpp b/Common/include/geometry/primal_grid/CPrimalGridBoundFEM.hpp index 3a2233246cf..3975d1debba 100644 --- a/Common/include/geometry/primal_grid/CPrimalGridBoundFEM.hpp +++ b/Common/include/geometry/primal_grid/CPrimalGridBoundFEM.hpp @@ -53,7 +53,7 @@ class CPrimalGridBoundFEM final : public CPrimalGrid { * \brief Constructor using data to initialize the boundary element. * \param[in] dataElem - Meta and connectivity data for this element. */ - CPrimalGridBoundFEM(const unsigned long *dataElem); + CPrimalGridBoundFEM(const unsigned long* dataElem); /*! * \brief Get the number of nodes that composes a face of an element. diff --git a/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp b/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp index 5caa92e0d87..77e1a5fc3b9 100644 --- a/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp +++ b/Common/include/geometry/primal_grid/CPrimalGridFEM.hpp @@ -53,13 +53,12 @@ class CPrimalGridFEM final : public CPrimalGrid { is (almost) constant. */ public: - /*! * \brief Constructor using data to initialize the element. * \param[in] dataElem - Meta and connectivity data for this element. * \param[in,out] offsetDOFs - The offset of the solution DOFs for this element. */ - CPrimalGridFEM(const unsigned long *dataElem, unsigned long &offsetSolDOFs); + CPrimalGridFEM(const unsigned long* dataElem, unsigned long& offsetSolDOFs); /*! * \brief Get the number of nodes that composes a face of an element. diff --git a/Common/src/fem/fem_geometry_structure.cpp b/Common/src/fem/fem_geometry_structure.cpp index 1f1c7495b2c..e5580de752e 100644 --- a/Common/src/fem/fem_geometry_structure.cpp +++ b/Common/src/fem/fem_geometry_structure.cpp @@ -379,8 +379,8 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /* Loop over the local boundary elements in geometry for this marker. */ for (unsigned long i = 0; i < geometry->GetnElem_Bound(iMarker); ++i) { /* Determine the local ID of the corresponding domain element. */ - unsigned long elemID = geometry->bound[iMarker][i]->GetDomainElement() - - elemPartitioner.GetFirstIndexOnRank(rank); + unsigned long elemID = + geometry->bound[iMarker][i]->GetDomainElement() - elemPartitioner.GetFirstIndexOnRank(rank); /* Determine to which rank this boundary element must be sent. That is the same as its corresponding domain element. @@ -672,8 +672,7 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /* Determine the number of elements per rank of the originally partitioned grid stored in cumulative storage format. */ vector nElemPerRankOr(size + 1); - for (int i = 0; i <= size; ++i) - nElemPerRankOr[i] = elemPartitioner.GetCumulativeSizeBeforeRank(i); + for (int i = 0; i <= size; ++i) nElemPerRankOr[i] = elemPartitioner.GetCumulativeSizeBeforeRank(i); /* Determine to which ranks I have to send messages to find out the information of the halos stored on this rank. */ @@ -809,7 +808,7 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /* Determine the local index of the element in the original partitioning. Check if the index is valid. */ const long localID = globalID - elemPartitioner.GetFirstIndexOnRank(rank); - if(elemPartitioner.GetRankContainingIndex(globalID) != static_cast(rank)) { + if (elemPartitioner.GetRankContainingIndex(globalID) != static_cast(rank)) { ostringstream message; message << "Invalid local element ID: " << localID; SU2_MPI::Error(message.str(), CURRENT_FUNCTION); diff --git a/Common/src/fem/geometry_structure_fem_part.cpp b/Common/src/fem/geometry_structure_fem_part.cpp index 5bbf731eef8..1babb698f7d 100644 --- a/Common/src/fem/geometry_structure_fem_part.cpp +++ b/Common/src/fem/geometry_structure_fem_part.cpp @@ -361,11 +361,10 @@ void CMatchingFace::Copy(const CMatchingFace& other) { tolForMatching = other.tolForMatching; } -void CPhysicalGeometry::LoadLinearlyPartitionedPointsFEM(CConfig *config, CMeshReaderBase *mesh) { - +void CPhysicalGeometry::LoadLinearlyPartitionedPointsFEM(CConfig* config, CMeshReaderBase* mesh) { /*--- Get the partitioned coordinates and their global IDs from the mesh object. ---*/ - const auto &gridCoords = mesh->GetLocalPointCoordinates(); - const auto &globalPointIDs = mesh->GetGlobalPointIDs(); + const auto& gridCoords = mesh->GetLocalPointCoordinates(); + const auto& globalPointIDs = mesh->GetGlobalPointIDs(); /*--- Initialize point counts and the grid node data structure. ---*/ @@ -373,32 +372,28 @@ void CPhysicalGeometry::LoadLinearlyPartitionedPointsFEM(CConfig *config, CMeshR /*--- Loop over the points and set the coordinates and global index. ---*/ for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++) { - for (unsigned short iDim = 0; iDim < nDim; ++iDim) - nodes->SetCoord(iPoint, iDim, gridCoords[iDim][iPoint]); + for (unsigned short iDim = 0; iDim < nDim; ++iDim) nodes->SetCoord(iPoint, iDim, gridCoords[iDim][iPoint]); nodes->SetGlobalIndex(iPoint, globalPointIDs[iPoint]); } } -void CPhysicalGeometry::LoadLinearlyPartitionedVolumeElementsFEM(CConfig *config, - CMeshReaderBase *mesh) { - +void CPhysicalGeometry::LoadLinearlyPartitionedVolumeElementsFEM(CConfig* config, CMeshReaderBase* mesh) { /*--- Reset the global to local element mapping. ---*/ Global_to_Local_Elem.clear(); /*--- Get the volume connectivity from the mesh object. ---*/ - const auto &dataElems = mesh->GetLocalVolumeElementConnectivity(); + const auto& dataElems = mesh->GetLocalVolumeElementConnectivity(); /*--- Allocate space for the interior elements in our SU2 data structure. Note that we only instantiate our rank's local set. ---*/ - elem = new CPrimalGrid*[nElem] (); + elem = new CPrimalGrid*[nElem](); /*--- Loop over all of the internal, local volumetric elements. ---*/ unsigned long ind = 0; unsigned long offsetSolDOFs = 0; - for (unsigned long jElem=0; jElem nSolDOFsPerRank(size); - SU2_MPI::Allgather(&offsetSolDOFs, 1, MPI_UNSIGNED_LONG, nSolDOFsPerRank.data(), - 1, MPI_UNSIGNED_LONG, SU2_MPI::GetComm()); + SU2_MPI::Allgather(&offsetSolDOFs, 1, MPI_UNSIGNED_LONG, nSolDOFsPerRank.data(), 1, MPI_UNSIGNED_LONG, + SU2_MPI::GetComm()); /* Determine the offset for the DOFs on this rank. */ unsigned long offsetRank = 0; for (int i = 0; i < rank; ++i) offsetRank += nSolDOFsPerRank[i]; /* Loop over the local elements to correct the global offset of the DOFs. */ - for (unsigned long jElem=0; jElemAddOffsetGlobalDOFs(offsetRank); + for (unsigned long jElem = 0; jElem < nElem; ++jElem) elem[jElem]->AddOffsetGlobalDOFs(offsetRank); #endif } -void CPhysicalGeometry::LoadLinearlyPartitionedSurfaceElementsFEM(CConfig *config, - CMeshReaderBase *mesh) { - +void CPhysicalGeometry::LoadLinearlyPartitionedSurfaceElementsFEM(CConfig* config, CMeshReaderBase* mesh) { /*--- Store the number of markers and print to the screen. ---*/ nMarker = mesh->GetNumberOfMarkers(); config->SetnMarker_All(nMarker); - if (rank == MASTER_NODE) - cout << nMarker << " surface markers." << endl; + if (rank == MASTER_NODE) cout << nMarker << " surface markers." << endl; /*--- Create the data structure for boundary elements. ---*/ - bound = new CPrimalGrid**[nMarker]; - nElem_Bound = new unsigned long [nMarker]; - Tag_to_Marker = new string [config->GetnMarker_Max()]; + bound = new CPrimalGrid**[nMarker]; + nElem_Bound = new unsigned long[nMarker]; + Tag_to_Marker = new string[config->GetnMarker_Max()]; /*--- Retrieve the name of the surface markers as well as the number of surface elements for every marker. ---*/ - const auto §ionNames = mesh->GetMarkerNames(); - const auto &nSurfElemPerMarker = mesh->GetNumberOfSurfaceElementsAllMarkers(); + const auto& sectionNames = mesh->GetMarkerNames(); + const auto& nSurfElemPerMarker = mesh->GetNumberOfSurfaceElementsAllMarkers(); /*--- Loop over all sections that we extracted from the grid file that were identified as boundary element sections so that we can store those elements into our SU2 data structures. ---*/ for (int iMarker = 0; iMarker < nMarker; ++iMarker) { - /*--- Get the string name and set the number of surface elements for this marker. ---*/ - string Marker_Tag = sectionNames[iMarker]; + string Marker_Tag = sectionNames[iMarker]; nElem_Bound[iMarker] = nSurfElemPerMarker[iMarker]; /*--- Allocate the memory of the pointers for the surface @@ -459,14 +449,13 @@ void CPhysicalGeometry::LoadLinearlyPartitionedSurfaceElementsFEM(CConfig *confi bound[iMarker] = new CPrimalGrid*[nElem_Bound[iMarker]]; /*--- Retrieve the boundary element data for this marker. ---*/ - const auto &dataElems = mesh->GetSurfaceElementConnectivityForMarker(iMarker); + const auto& dataElems = mesh->GetSurfaceElementConnectivityForMarker(iMarker); /*--- Loop over the number of boundary elements for this marker. ---*/ unsigned long ind = 0; - for (unsigned long jElem=0; jElemGetTimeLevel(); /*--- Determine the time level of Elem1, which is either owned or external. Hence a distinction must be made. ---*/ unsigned short timeLevel1; - if(elemPartitioner.GetRankContainingIndex(localFaces[i].elemID1) == static_cast(rank)) { + if (elemPartitioner.GetRankContainingIndex(localFaces[i].elemID1) == static_cast(rank)) { const unsigned long elemID1 = localFaces[i].elemID1 - elemPartitioner.GetFirstIndexOnRank(rank); timeLevel1 = elem[elemID1]->GetTimeLevel(); } else { @@ -974,7 +962,6 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { of the graph. First the faces. ---*/ vector > adjacency(nElem, vector(0)); for (unsigned long i = 0; i < nFacesLoc; ++i) { - /*--- Determine the local index of elem0, which is always stored locally, and add elemID1 to the adjacency list. ---*/ const unsigned long elem0 = localFaces[i].elemID0 - elemPartitioner.GetFirstIndexOnRank(rank); @@ -983,7 +970,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { /*--- Check if this is not a periodic face and if the second element is also a local element. If so, add elemID0 to the adjacency list ---*/ if (localFaces[i].periodicIndex == 0) { - if(elemPartitioner.GetRankContainingIndex(localFaces[i].elemID1) == static_cast(rank)) { + if (elemPartitioner.GetRankContainingIndex(localFaces[i].elemID1) == static_cast(rank)) { const unsigned long elem1 = localFaces[i].elemID1 - elemPartitioner.GetFirstIndexOnRank(rank); adjacency[elem1].push_back(localFaces[i].elemID0); } @@ -1004,7 +991,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { are present. ParMETIS is not able to deal with self entries, hence they must be removed as well. */ for (unsigned long i = 0; i < nElem; ++i) { - const unsigned long globalElemID = i + + elemPartitioner.GetFirstIndexOnRank(rank); + const unsigned long globalElemID = i + +elemPartitioner.GetFirstIndexOnRank(rank); unsigned long nEntriesNew = adjacency[i].size(); for (unsigned long j = 0; j < adjacency[i].size(); ++j) { @@ -1045,7 +1032,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { sort(adjacency[elemID].begin(), adjacency[elemID].end()); /* Check if the donor element is stored locally. */ - if(elemPartitioner.GetRankContainingIndex(donors[i]) == static_cast(rank)) { + if (elemPartitioner.GetRankContainingIndex(donors[i]) == static_cast(rank)) { /* Donor is stored locally. Add the entry to the graph and sort it afterwards. */ const unsigned long localDonorID = donors[i] - elemPartitioner.GetFirstIndexOnRank(rank); @@ -1070,7 +1057,6 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { vector sendToRank(size, 0); for (unsigned long i = 0; i < additionalExternalEntriesGraph.size(); i += 2) { - /*--- Determine the rank where this external is stored and update the corresponding communication buffers accordingly. ---*/ const unsigned long rankElem = elemPartitioner.GetRankContainingIndex(additionalExternalEntriesGraph[i]); @@ -1162,8 +1148,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { /*--- Determine the array, which stores the distribution of the graph nodes over the ranks. ---*/ vector vtxdist(size + 1); - for (int i = 0; i <= size; ++i) - vtxdist[i] = static_cast(elemPartitioner.GetCumulativeSizeBeforeRank(i)); + for (int i = 0; i <= size; ++i) vtxdist[i] = static_cast(elemPartitioner.GetCumulativeSizeBeforeRank(i)); /* Create the array xadjPar, which contains the number of edges for each vertex of the graph in ParMETIS format. */ @@ -1995,7 +1980,8 @@ void CPhysicalGeometry::DetermineDonorElementsWallFunctions(CConfig* config) { /* Easier storage of the element type, the corresponding volume element and the polynomial degree for the solution and grid. */ const unsigned short VTK_Type = bound[iMarker][l]->GetVTK_Type(); - const unsigned long elemID = bound[iMarker][l]->GetDomainElement() - elemPartitioner.GetFirstIndexOnRank(rank); + const unsigned long elemID = + bound[iMarker][l]->GetDomainElement() - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short nPolyGrid = bound[iMarker][l]->GetNPolyGrid(); const unsigned short nPolySol = elem[elemID]->GetNPolySol(); const unsigned short VTK_Elem = elem[elemID]->GetVTK_Type(); @@ -2426,7 +2412,6 @@ void CPhysicalGeometry::DetermineDonorElementsWallFunctions(CConfig* config) { void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector& localFaces, map& mapExternalElemIDToTimeLevel) { - /*--- Define the linear partitioning of the elements. ---*/ CLinearPartitioner elemPartitioner(Global_nElem, 0); @@ -2442,8 +2427,7 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector /*--- Check for external element. This is done by checking the local elements and if it is not found, it is an external. ---*/ const auto UMI = Global_to_Local_Elem.find(FI->elemID1); - if(UMI == Global_to_Local_Elem.end()) { - + if (UMI == Global_to_Local_Elem.end()) { /* This element is an external element. Store it in the map mapExternalElemIDToTimeLevel if not already done so. */ map::iterator MI; @@ -2471,12 +2455,10 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector const unsigned long* donors = bound[iMarker][l]->GetDonorsWallFunctions(); /*--- Loop over the number of donors for this boundary element. ---*/ - for(unsigned short i=0; ifirst); @@ -2711,8 +2692,7 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector SU2_MPI::Recv(sendElem[i].data(), sizeMess, MPI_UNSIGNED_LONG, sendRank[i], rank, SU2_MPI::GetComm(), &status); - for (int j = 0; j < sizeMess; ++j) - sendElem[i][j] -= elemPartitioner.GetFirstIndexOnRank(rank); + for (int j = 0; j < sizeMess; ++j) sendElem[i][j] -= elemPartitioner.GetFirstIndexOnRank(rank); } /* Complete the non-blocking sends. Synchronize the processors afterwards, @@ -2803,8 +2783,8 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector for (unsigned short iMarker = 0; iMarker < nMarker; ++iMarker) { for (unsigned long l = 0; l < nElem_Bound[iMarker]; ++l) { /* Determine the ID of the adjacent element. */ - const unsigned long elemID = bound[iMarker][l]->GetDomainElement() - - elemPartitioner.GetFirstIndexOnRank(rank); + const unsigned long elemID = + bound[iMarker][l]->GetDomainElement() - elemPartitioner.GetFirstIndexOnRank(rank); /* Get the number of donor elements for the wall function treatment and the pointer to the array which stores this info. */ @@ -2813,14 +2793,11 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector /* Loop over the number of donors and check the time levels. */ for (unsigned short i = 0; i < nDonors; ++i) { - /* Determine the status of the donor element. */ - if(elemPartitioner.GetRankContainingIndex(donors[i]) == static_cast(rank)) { - + if (elemPartitioner.GetRankContainingIndex(donors[i]) == static_cast(rank)) { /* Donor is stored locally. Determine its local ID and get the time levels of both elements. */ - const unsigned long donorID = donors[i] - - elemPartitioner.GetFirstIndexOnRank(rank); + const unsigned long donorID = donors[i] - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short timeLevelB = elem[elemID]->GetTimeLevel(); const unsigned short timeLevelD = elem[donorID]->GetTimeLevel(); const unsigned short timeLevel = min(timeLevelB, timeLevelD); @@ -2871,12 +2848,11 @@ void CPhysicalGeometry::DetermineTimeLevelElements(CConfig* config, const vector if (FI->elemID1 < Global_nElem) { /* Local element ID of the first element. Per definition this is always a locally stored element. Also store its time level. */ - const unsigned long elemID0 = FI->elemID0 - - elemPartitioner.GetFirstIndexOnRank(rank); + const unsigned long elemID0 = FI->elemID0 - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short timeLevel0 = elem[elemID0]->GetTimeLevel(); /* Determine the status of the second element. */ - if(elemPartitioner.GetRankContainingIndex(FI->elemID1) == static_cast(rank)) { + if (elemPartitioner.GetRankContainingIndex(FI->elemID1) == static_cast(rank)) { /* Both elements are stored locally. Determine the local element of the second element and determine the minimum time level. */ @@ -3028,7 +3004,6 @@ void CPhysicalGeometry::ComputeFEMGraphWeights(CConfig* config, const vector >& adjacency, const map& mapExternalElemIDToTimeLevel, vector& vwgt, vector >& adjwgt) { - /*--- Define the linear partitioning of the elements. ---*/ CLinearPartitioner elemPartitioner(Global_nElem, 0); @@ -3212,8 +3187,8 @@ void CPhysicalGeometry::ComputeFEMGraphWeights(CConfig* config, const vectorGetVTK_Type(); - const unsigned long elemID = bound[iMarker][l]->GetDomainElement() - - elemPartitioner.GetFirstIndexOnRank(rank); + const unsigned long elemID = + bound[iMarker][l]->GetDomainElement() - elemPartitioner.GetFirstIndexOnRank(rank); const unsigned short nPolySol = elem[elemID]->GetNPolySol(); const unsigned short VTK_Type_Elem = elem[elemID]->GetVTK_Type(); const bool JacIsConstant = bound[iMarker][l]->GetJacobianConsideredConstant(); @@ -3294,7 +3269,7 @@ void CPhysicalGeometry::ComputeFEMGraphWeights(CConfig* config, const vector(rank)) { + if (elemPartitioner.GetRankContainingIndex(adjacency[i][j]) == static_cast(rank)) { /* Locally stored element. Determine its local ID and set the time level and number of solution DOFs. */ unsigned long elemID1 = adjacency[i][j] - elemPartitioner.GetFirstIndexOnRank(rank); diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index b97e6399df2..20c2b247510 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -3452,20 +3452,28 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena CMeshReaderBase* Mesh = nullptr; switch (val_format) { case SU2: - if (fem_solver) Mesh = new CSU2ASCIIMeshReaderFEM(config, val_iZone, val_nZone); - else Mesh = new CSU2ASCIIMeshReaderFVM(config, val_iZone, val_nZone); + if (fem_solver) + Mesh = new CSU2ASCIIMeshReaderFEM(config, val_iZone, val_nZone); + else + Mesh = new CSU2ASCIIMeshReaderFVM(config, val_iZone, val_nZone); break; case CGNS_GRID: - if (fem_solver) Mesh = new CCGNSMeshReaderFEM(config, val_iZone, val_nZone); - else Mesh = new CCGNSMeshReaderFVM(config, val_iZone, val_nZone); + if (fem_solver) + Mesh = new CCGNSMeshReaderFEM(config, val_iZone, val_nZone); + else + Mesh = new CCGNSMeshReaderFVM(config, val_iZone, val_nZone); break; case RECTANGLE: - if (fem_solver) Mesh = new CRectangularMeshReaderFEM(config, val_iZone, val_nZone); - else Mesh = new CRectangularMeshReaderFVM(config, val_iZone, val_nZone); + if (fem_solver) + Mesh = new CRectangularMeshReaderFEM(config, val_iZone, val_nZone); + else + Mesh = new CRectangularMeshReaderFVM(config, val_iZone, val_nZone); break; case BOX: - if (fem_solver) Mesh = new CBoxMeshReaderFEM(config, val_iZone, val_nZone); - else Mesh = new CBoxMeshReaderFVM(config, val_iZone, val_nZone); + if (fem_solver) + Mesh = new CBoxMeshReaderFEM(config, val_iZone, val_nZone); + else + Mesh = new CBoxMeshReaderFVM(config, val_iZone, val_nZone); break; default: SU2_MPI::Error("Unrecognized mesh format specified!", CURRENT_FUNCTION); @@ -3507,17 +3515,14 @@ void CPhysicalGeometry::Read_Mesh(CConfig* config, const string& val_mesh_filena /*--- Make a distinction between the FVM solver and FEM solver how to load the grid data in the member variables of CPhysicalGeometry. ---*/ - if( fem_solver ) { - + if (fem_solver) { /*--- Load the grid points, volume elements, and surface elements from the mesh object into the proper SU2 data structures. ---*/ LoadLinearlyPartitionedPointsFEM(config, Mesh); LoadLinearlyPartitionedVolumeElementsFEM(config, Mesh); LoadLinearlyPartitionedSurfaceElementsFEM(config, Mesh); - } - else { - + } else { /*--- Load the grid points, volume elements, and surface elements from the mesh object into the proper SU2 data structures. ---*/ diff --git a/Common/src/geometry/meshreader/CBoxMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CBoxMeshReaderFEM.cpp index 56551341517..44dfde1dc7f 100644 --- a/Common/src/geometry/meshreader/CBoxMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CBoxMeshReaderFEM.cpp @@ -29,15 +29,13 @@ #include "../../../include/toolboxes/CLinearPartitioner.hpp" #include "../../../include/geometry/meshreader/CBoxMeshReaderFEM.hpp" -CBoxMeshReaderFEM::CBoxMeshReaderFEM(const CConfig *val_config, unsigned short val_iZone, - unsigned short val_nZone) +CBoxMeshReaderFEM::CBoxMeshReaderFEM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) : CMeshReaderBase(val_config, val_iZone, val_nZone) { - /* The box mesh is always 3D. */ dimension = 3; /* Set the VTK type for the interior elements and the boundary elements. */ - KindElem = HEXAHEDRON; + KindElem = HEXAHEDRON; KindBound = QUADRILATERAL; /* The number of grid nodes in the i, j and k directions. */ @@ -68,24 +66,22 @@ CBoxMeshReaderFEM::CBoxMeshReaderFEM(const CConfig *val_config, unsigned short v CBoxMeshReaderFEM::~CBoxMeshReaderFEM() = default; void CBoxMeshReaderFEM::ComputeBoxPointCoordinates() { - /*--- Set the global count of points based on the grid dimensions. ---*/ - numberOfGlobalPoints = nNode*mNode*pNode; + numberOfGlobalPoints = nNode * mNode * pNode; /*--- Loop over the local elements to determine the global point IDs to be stored on this rank. --*/ unsigned long ind = 0; - for(unsigned long i=0; i(rank)) { - + const unsigned long globalElemID = kNode * nElemIJ + jNode * nElemI; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[0].push_back(KindBound); // VTK type. @@ -201,10 +190,10 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { surfaceElementConnectivity[0].push_back(ind); // Global surface element ID. surfaceElementConnectivity[0].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[0].push_back(kNode*mNode*nNode + jNode*nNode); - surfaceElementConnectivity[0].push_back((kNode+1)*mNode*nNode + jNode*nNode); - surfaceElementConnectivity[0].push_back(kNode*mNode*nNode + (jNode+1)*nNode); - surfaceElementConnectivity[0].push_back((kNode+1)*mNode*nNode + (jNode+1)*nNode); + surfaceElementConnectivity[0].push_back(kNode * mNode * nNode + jNode * nNode); + surfaceElementConnectivity[0].push_back((kNode + 1) * mNode * nNode + jNode * nNode); + surfaceElementConnectivity[0].push_back(kNode * mNode * nNode + (jNode + 1) * nNode); + surfaceElementConnectivity[0].push_back((kNode + 1) * mNode * nNode + (jNode + 1) * nNode); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[0]; @@ -216,14 +205,12 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { markerNames[1] = "x_plus"; ind = 0; - for(unsigned long kNode = 0; kNode < pNode-1; ++kNode) { - for(unsigned long jNode = 0; jNode < mNode-1; ++jNode, ++ind) { - + for (unsigned long kNode = 0; kNode < pNode - 1; ++kNode) { + for (unsigned long jNode = 0; jNode < mNode - 1; ++jNode, ++ind) { /*--- Determine the corresponding global element ID and check if it is stored on this rank. ---*/ - const unsigned long globalElemID = kNode*nElemIJ + jNode*nElemI + nElemI-1; - if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { - + const unsigned long globalElemID = kNode * nElemIJ + jNode * nElemI + nElemI - 1; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[1].push_back(KindBound); // VTK type. @@ -232,10 +219,10 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { surfaceElementConnectivity[1].push_back(ind); // Global surface element ID. surfaceElementConnectivity[1].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[1].push_back(kNode*mNode*nNode + jNode*nNode + (nNode-1)); - surfaceElementConnectivity[1].push_back(kNode*mNode*nNode + (jNode+1)*nNode + (nNode-1)); - surfaceElementConnectivity[1].push_back((kNode+1)*mNode*nNode + jNode*nNode + (nNode-1)); - surfaceElementConnectivity[1].push_back((kNode+1)*mNode*nNode + (jNode+1)*nNode + (nNode-1)); + surfaceElementConnectivity[1].push_back(kNode * mNode * nNode + jNode * nNode + (nNode - 1)); + surfaceElementConnectivity[1].push_back(kNode * mNode * nNode + (jNode + 1) * nNode + (nNode - 1)); + surfaceElementConnectivity[1].push_back((kNode + 1) * mNode * nNode + jNode * nNode + (nNode - 1)); + surfaceElementConnectivity[1].push_back((kNode + 1) * mNode * nNode + (jNode + 1) * nNode + (nNode - 1)); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[1]; @@ -247,14 +234,12 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { markerNames[2] = "y_minus"; ind = 0; - for (unsigned long kNode = 0; kNode < pNode-1; ++kNode) { - for (unsigned long iNode = 0; iNode < nNode-1; ++iNode, ++ind) { - - /*--- Determine the corresponding global element ID and check - if it is stored on this rank. ---*/ - const unsigned long globalElemID = kNode*nElemIJ + iNode; - if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { - + for (unsigned long kNode = 0; kNode < pNode - 1; ++kNode) { + for (unsigned long iNode = 0; iNode < nNode - 1; ++iNode, ++ind) { + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = kNode * nElemIJ + iNode; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[2].push_back(KindBound); // VTK type. @@ -263,10 +248,10 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { surfaceElementConnectivity[2].push_back(ind); // Global surface element ID. surfaceElementConnectivity[2].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[2].push_back(kNode*mNode*nNode + iNode); - surfaceElementConnectivity[2].push_back(kNode*mNode*nNode + iNode+1); - surfaceElementConnectivity[2].push_back((kNode+1)*mNode*nNode + iNode); - surfaceElementConnectivity[2].push_back((kNode+1)*mNode*nNode + iNode+1); + surfaceElementConnectivity[2].push_back(kNode * mNode * nNode + iNode); + surfaceElementConnectivity[2].push_back(kNode * mNode * nNode + iNode + 1); + surfaceElementConnectivity[2].push_back((kNode + 1) * mNode * nNode + iNode); + surfaceElementConnectivity[2].push_back((kNode + 1) * mNode * nNode + iNode + 1); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[2]; @@ -278,14 +263,12 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { markerNames[3] = "y_plus"; ind = 0; - for (unsigned long kNode = 0; kNode < pNode-1; ++kNode) { - for (unsigned long iNode = 0; iNode < nNode-1; ++iNode, ++ind) { - - /*--- Determine the corresponding global element ID and check - if it is stored on this rank. ---*/ - const unsigned long globalElemID = kNode*nElemIJ + (mNode-2)*nElemI + iNode; - if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { - + for (unsigned long kNode = 0; kNode < pNode - 1; ++kNode) { + for (unsigned long iNode = 0; iNode < nNode - 1; ++iNode, ++ind) { + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = kNode * nElemIJ + (mNode - 2) * nElemI + iNode; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[3].push_back(KindBound); // VTK type. @@ -294,10 +277,10 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { surfaceElementConnectivity[3].push_back(ind); // Global surface element ID. surfaceElementConnectivity[3].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[3].push_back(kNode*mNode*nNode + (mNode-1)*nNode + iNode); - surfaceElementConnectivity[3].push_back(kNode*mNode*nNode + (mNode-1)*nNode + iNode+1); - surfaceElementConnectivity[3].push_back((kNode+1)*mNode*nNode + (mNode-1)*nNode + iNode); - surfaceElementConnectivity[3].push_back((kNode+1)*mNode*nNode + (mNode-1)*nNode + iNode+1); + surfaceElementConnectivity[3].push_back(kNode * mNode * nNode + (mNode - 1) * nNode + iNode); + surfaceElementConnectivity[3].push_back(kNode * mNode * nNode + (mNode - 1) * nNode + iNode + 1); + surfaceElementConnectivity[3].push_back((kNode + 1) * mNode * nNode + (mNode - 1) * nNode + iNode); + surfaceElementConnectivity[3].push_back((kNode + 1) * mNode * nNode + (mNode - 1) * nNode + iNode + 1); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[3]; @@ -309,14 +292,12 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { markerNames[4] = "z_minus"; ind = 0; - for (unsigned long jNode = 0; jNode < mNode-1; ++jNode) { - for (unsigned long iNode = 0; iNode < nNode-1; ++iNode, ++ind) { - - /*--- Determine the corresponding global element ID and check - if it is stored on this rank. ---*/ - const unsigned long globalElemID = jNode*nElemI + iNode; - if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { - + for (unsigned long jNode = 0; jNode < mNode - 1; ++jNode) { + for (unsigned long iNode = 0; iNode < nNode - 1; ++iNode, ++ind) { + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = jNode * nElemI + iNode; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[4].push_back(KindBound); // VTK type. @@ -325,10 +306,10 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { surfaceElementConnectivity[4].push_back(ind); // Global surface element ID. surfaceElementConnectivity[4].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[4].push_back(jNode*nNode + iNode); - surfaceElementConnectivity[4].push_back(jNode*nNode + iNode+1); - surfaceElementConnectivity[4].push_back((jNode+1)*nNode + iNode); - surfaceElementConnectivity[4].push_back((jNode+1)*nNode + iNode+1); + surfaceElementConnectivity[4].push_back(jNode * nNode + iNode); + surfaceElementConnectivity[4].push_back(jNode * nNode + iNode + 1); + surfaceElementConnectivity[4].push_back((jNode + 1) * nNode + iNode); + surfaceElementConnectivity[4].push_back((jNode + 1) * nNode + iNode + 1); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[4]; @@ -340,14 +321,12 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { markerNames[5] = "z_plus"; ind = 0; - for (unsigned long jNode = 0; jNode < mNode-1; ++jNode) { - for (unsigned long iNode = 0; iNode < nNode-1; ++iNode, ++ind) { - - /*--- Determine the corresponding global element ID and check - if it is stored on this rank. ---*/ - const unsigned long globalElemID = (pNode-2)*nElemIJ + jNode*nElemI + iNode; - if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { - + for (unsigned long jNode = 0; jNode < mNode - 1; ++jNode) { + for (unsigned long iNode = 0; iNode < nNode - 1; ++iNode, ++ind) { + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = (pNode - 2) * nElemIJ + jNode * nElemI + iNode; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[5].push_back(KindBound); // VTK type. @@ -356,10 +335,10 @@ void CBoxMeshReaderFEM::ComputeBoxSurfaceConnectivity() { surfaceElementConnectivity[5].push_back(ind); // Global surface element ID. surfaceElementConnectivity[5].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[5].push_back((pNode-1)*mNode*nNode + jNode*nNode + iNode); - surfaceElementConnectivity[5].push_back((pNode-1)*mNode*nNode + jNode*nNode + iNode+1); - surfaceElementConnectivity[5].push_back((pNode-1)*mNode*nNode + (jNode+1)*nNode + iNode); - surfaceElementConnectivity[5].push_back((pNode-1)*mNode*nNode + (jNode+1)*nNode + iNode+1); + surfaceElementConnectivity[5].push_back((pNode - 1) * mNode * nNode + jNode * nNode + iNode); + surfaceElementConnectivity[5].push_back((pNode - 1) * mNode * nNode + jNode * nNode + iNode + 1); + surfaceElementConnectivity[5].push_back((pNode - 1) * mNode * nNode + (jNode + 1) * nNode + iNode); + surfaceElementConnectivity[5].push_back((pNode - 1) * mNode * nNode + (jNode + 1) * nNode + iNode + 1); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[5]; diff --git a/Common/src/geometry/meshreader/CCGNSElementType.cpp b/Common/src/geometry/meshreader/CCGNSElementType.cpp index 8ed50fb91df..53a549c8c78 100644 --- a/Common/src/geometry/meshreader/CCGNSElementType.cpp +++ b/Common/src/geometry/meshreader/CCGNSElementType.cpp @@ -35,58 +35,111 @@ using namespace std; -void CCGNSElementType::CGNSToSU2(const ElementType_t val_elemType, - const unsigned long val_globalID, - const cgsize_t *connCGNS, - std::vector &connSU2) { - +void CCGNSElementType::CGNSToSU2(const ElementType_t val_elemType, const unsigned long val_globalID, + const cgsize_t* connCGNS, std::vector& connSU2) { /*--- Clear the contents of connSU2. ---*/ connSU2.clear(); /*--- Search in the stored elements if the current element type is present. ---*/ unsigned long ind; - for(ind=0; ind SU2ToCGNS; - switch( val_elemType ) { - - case NODE: CreateDataNODE (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case BAR_2: CreateDataBAR_2 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case BAR_3: CreateDataBAR_3 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case BAR_4: CreateDataBAR_4 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case BAR_5: CreateDataBAR_5 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case TRI_3: CreateDataTRI_3 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case TRI_6: CreateDataTRI_6 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case TRI_10: CreateDataTRI_10 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case TRI_15: CreateDataTRI_15 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case QUAD_4: CreateDataQUAD_4 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case QUAD_9: CreateDataQUAD_9 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case QUAD_16: CreateDataQUAD_16 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case QUAD_25: CreateDataQUAD_25 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case TETRA_4: CreateDataTETRA_4 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case TETRA_10: CreateDataTETRA_10(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case TETRA_20: CreateDataTETRA_20(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case TETRA_35: CreateDataTETRA_35(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case PYRA_5: CreateDataPYRA_5 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case PYRA_14: CreateDataPYRA_14 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case PYRA_30: CreateDataPYRA_30 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case PYRA_55: CreateDataPYRA_55 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case PENTA_6: CreateDataPENTA_6 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case PENTA_18: CreateDataPENTA_18(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case PENTA_40: CreateDataPENTA_40(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case PENTA_75: CreateDataPENTA_75(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case HEXA_8: CreateDataHEXA_8 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case HEXA_27: CreateDataHEXA_27 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case HEXA_64: CreateDataHEXA_64 (VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; - case HEXA_125: CreateDataHEXA_125(VTK_Type, nPoly, nDOFs, SU2ToCGNS); break; + switch (val_elemType) { + case NODE: + CreateDataNODE(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case BAR_2: + CreateDataBAR_2(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case BAR_3: + CreateDataBAR_3(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case BAR_4: + CreateDataBAR_4(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case BAR_5: + CreateDataBAR_5(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case TRI_3: + CreateDataTRI_3(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case TRI_6: + CreateDataTRI_6(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case TRI_10: + CreateDataTRI_10(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case TRI_15: + CreateDataTRI_15(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case QUAD_4: + CreateDataQUAD_4(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case QUAD_9: + CreateDataQUAD_9(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case QUAD_16: + CreateDataQUAD_16(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case QUAD_25: + CreateDataQUAD_25(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case TETRA_4: + CreateDataTETRA_4(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case TETRA_10: + CreateDataTETRA_10(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case TETRA_20: + CreateDataTETRA_20(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case TETRA_35: + CreateDataTETRA_35(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case PYRA_5: + CreateDataPYRA_5(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case PYRA_14: + CreateDataPYRA_14(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case PYRA_30: + CreateDataPYRA_30(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case PYRA_55: + CreateDataPYRA_55(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case PENTA_6: + CreateDataPENTA_6(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case PENTA_18: + CreateDataPENTA_18(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case PENTA_40: + CreateDataPENTA_40(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case PENTA_75: + CreateDataPENTA_75(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case HEXA_8: + CreateDataHEXA_8(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case HEXA_27: + CreateDataHEXA_27(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case HEXA_64: + CreateDataHEXA_64(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; + case HEXA_125: + CreateDataHEXA_125(VTK_Type, nPoly, nDOFs, SU2ToCGNS); + break; default: ostringstream message; @@ -103,7 +156,7 @@ void CCGNSElementType::CGNSToSU2(const ElementType_t val_elemType, } /*--- Allocate the memory for connSU2 and store the meta data. ---*/ - connSU2.resize(nDOFsStored[ind]+5); + connSU2.resize(nDOFsStored[ind] + 5); connSU2[0] = VTKTypeStored[ind]; connSU2[1] = nPolyStored[ind]; @@ -114,8 +167,7 @@ void CCGNSElementType::CGNSToSU2(const ElementType_t val_elemType, /*--- Loop over the DOFs and convert the connectivity from CGNS to SU2 format. Keep in mind that CGNS start the numbering at 1 while SU2 starts at 0. ---*/ - for(unsigned short i=0; i &SU2ToCGNS) { - +void CCGNSElementType::CreateDataNODE(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* Set the required data for a NODE. */ VTK_Type = VERTEX; - nPoly = 0; - nDOFs = 1; + nPoly = 0; + nDOFs = 1; SU2ToCGNS.push_back(0); } -void CCGNSElementType::CreateDataBAR_2(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataBAR_2(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The BAR_2 element is a linear element. The numbering of the nodes is the same for CGNS and SU2. */ VTK_Type = LINE; - nPoly = 1; - nDOFs = 2; + nPoly = 1; + nDOFs = 2; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 1; } -void CCGNSElementType::CreateDataBAR_3(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataBAR_3(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The BAR_3 element is a quadratic element. SU2 numbers to nodes with increasing parametric value, while in CGNS the internal node is numbered last. */ VTK_Type = LINE; - nPoly = 2; - nDOFs = 3; + nPoly = 2; + nDOFs = 3; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 2; SU2ToCGNS[2] = 1; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 2; + SU2ToCGNS[2] = 1; } -void CCGNSElementType::CreateDataBAR_4(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataBAR_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The BAR_4 element is a cubic element. SU2 numbers to nodes with increasing parametric value, while in CGNS the internal nodes are numbered last. */ VTK_Type = LINE; - nPoly = 3; - nDOFs = 4; + nPoly = 3; + nDOFs = 4; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 2; SU2ToCGNS[2] = 3; SU2ToCGNS[3] = 1; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 2; + SU2ToCGNS[2] = 3; + SU2ToCGNS[3] = 1; } -void CCGNSElementType::CreateDataBAR_5(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataBAR_5(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The BAR_5 element is a quartic element. SU2 numbers to nodes with increasing parametric value, while in CGNS the internal nodes are numbered last. */ VTK_Type = LINE; - nPoly = 4; - nDOFs = 5; + nPoly = 4; + nDOFs = 5; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 2; SU2ToCGNS[2] = 3; - SU2ToCGNS[3] = 4; SU2ToCGNS[4] = 1; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 2; + SU2ToCGNS[2] = 3; + SU2ToCGNS[3] = 4; + SU2ToCGNS[4] = 1; } -void CCGNSElementType::CreateDataTRI_3(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataTRI_3(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The TRI_3 element is a linear triangle. The node numbering is the same in SU2 and CGNS. */ VTK_Type = TRIANGLE; - nPoly = 1; - nDOFs = 3; + nPoly = 1; + nDOFs = 3; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 2; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 1; + SU2ToCGNS[2] = 2; } -void CCGNSElementType::CreateDataTRI_6(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataTRI_6(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The TRI_6 element is a quadratic triangle. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -227,19 +269,20 @@ void CCGNSElementType::CreateDataTRI_6(unsigned short &VTK_Type, where the i-direction is defined from node 0 to 1 and the j-direction from node 0 along the other edge. */ VTK_Type = TRIANGLE; - nPoly = 2; - nDOFs = 6; + nPoly = 2; + nDOFs = 6; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 3; SU2ToCGNS[2] = 1; - SU2ToCGNS[3] = 5; SU2ToCGNS[4] = 4; SU2ToCGNS[5] = 2; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 3; + SU2ToCGNS[2] = 1; + SU2ToCGNS[3] = 5; + SU2ToCGNS[4] = 4; + SU2ToCGNS[5] = 2; } -void CCGNSElementType::CreateDataTRI_10(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataTRI_10(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The TRI_10 element is a cubic triangle. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -248,20 +291,24 @@ void CCGNSElementType::CreateDataTRI_10(unsigned short &VTK_Type, where the i-direction is defined from node 0 to 1 and the j-direction from node 0 along the other edge. */ VTK_Type = TRIANGLE; - nPoly = 3; - nDOFs = 10; + nPoly = 3; + nDOFs = 10; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 3; SU2ToCGNS[2] = 4; SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 8; SU2ToCGNS[5] = 9; SU2ToCGNS[6] = 5; SU2ToCGNS[7] = 7; - SU2ToCGNS[8] = 6; SU2ToCGNS[9] = 2; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 3; + SU2ToCGNS[2] = 4; + SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 8; + SU2ToCGNS[5] = 9; + SU2ToCGNS[6] = 5; + SU2ToCGNS[7] = 7; + SU2ToCGNS[8] = 6; + SU2ToCGNS[9] = 2; } -void CCGNSElementType::CreateDataTRI_15(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataTRI_15(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The TRI_15 element is a quartic triangle. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -273,21 +320,29 @@ void CCGNSElementType::CreateDataTRI_15(unsigned short &VTK_Type, the location for uniform spacing. This effect is currently ignored, i.e. it is assumed that the spacing in parameter space is uniform. */ VTK_Type = TRIANGLE; - nPoly = 4; - nDOFs = 15; + nPoly = 4; + nDOFs = 15; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 3; SU2ToCGNS[2] = 4; SU2ToCGNS[3] = 5; - SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 11; SU2ToCGNS[6] = 12; SU2ToCGNS[7] = 13; - SU2ToCGNS[8] = 6; SU2ToCGNS[9] = 10; SU2ToCGNS[10] = 14; SU2ToCGNS[11] = 7; - SU2ToCGNS[12] = 9; SU2ToCGNS[13] = 8; SU2ToCGNS[14] = 2; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 3; + SU2ToCGNS[2] = 4; + SU2ToCGNS[3] = 5; + SU2ToCGNS[4] = 1; + SU2ToCGNS[5] = 11; + SU2ToCGNS[6] = 12; + SU2ToCGNS[7] = 13; + SU2ToCGNS[8] = 6; + SU2ToCGNS[9] = 10; + SU2ToCGNS[10] = 14; + SU2ToCGNS[11] = 7; + SU2ToCGNS[12] = 9; + SU2ToCGNS[13] = 8; + SU2ToCGNS[14] = 2; } -void CCGNSElementType::CreateDataQUAD_4(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataQUAD_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The QUAD_4 element is a linear quadrilateral. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes (not present for QUAD_4). @@ -296,18 +351,18 @@ void CCGNSElementType::CreateDataQUAD_4(unsigned short &VTK_Type, where the i-direction is defined from node 0 to 1 and the j-direction from node 0 along the other edge. */ VTK_Type = QUADRILATERAL; - nPoly = 1; - nDOFs = 4; + nPoly = 1; + nDOFs = 4; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 3; SU2ToCGNS[3] = 2; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 1; + SU2ToCGNS[2] = 3; + SU2ToCGNS[3] = 2; } -void CCGNSElementType::CreateDataQUAD_9(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataQUAD_9(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The QUAD_9 element is a quadratic quadrilateral. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -316,20 +371,23 @@ void CCGNSElementType::CreateDataQUAD_9(unsigned short &VTK_Type, where the i-direction is defined from node 0 to 1 and the j-direction from node 0 along the other edge. */ VTK_Type = QUADRILATERAL; - nPoly = 2; - nDOFs = 9; + nPoly = 2; + nDOFs = 9; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 7; - SU2ToCGNS[4] = 8; SU2ToCGNS[5] = 5; SU2ToCGNS[6] = 3; SU2ToCGNS[7] = 6; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 4; + SU2ToCGNS[2] = 1; + SU2ToCGNS[3] = 7; + SU2ToCGNS[4] = 8; + SU2ToCGNS[5] = 5; + SU2ToCGNS[6] = 3; + SU2ToCGNS[7] = 6; SU2ToCGNS[8] = 2; } -void CCGNSElementType::CreateDataQUAD_16(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataQUAD_16(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The QUAD_16 element is a cubic quadrilateral. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -338,21 +396,30 @@ void CCGNSElementType::CreateDataQUAD_16(unsigned short &VTK_Type, where the i-direction is defined from node 0 to 1 and the j-direction from node 0 along the other edge. */ VTK_Type = QUADRILATERAL; - nPoly = 3; - nDOFs = 16; + nPoly = 3; + nDOFs = 16; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 5; SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 11; SU2ToCGNS[5] = 12; SU2ToCGNS[6] = 13; SU2ToCGNS[7] = 6; - SU2ToCGNS[8] = 10; SU2ToCGNS[9] = 15; SU2ToCGNS[10] = 14; SU2ToCGNS[11] = 7; - SU2ToCGNS[12] = 3; SU2ToCGNS[13] = 9; SU2ToCGNS[14] = 8; SU2ToCGNS[15] = 2; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 4; + SU2ToCGNS[2] = 5; + SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 11; + SU2ToCGNS[5] = 12; + SU2ToCGNS[6] = 13; + SU2ToCGNS[7] = 6; + SU2ToCGNS[8] = 10; + SU2ToCGNS[9] = 15; + SU2ToCGNS[10] = 14; + SU2ToCGNS[11] = 7; + SU2ToCGNS[12] = 3; + SU2ToCGNS[13] = 9; + SU2ToCGNS[14] = 8; + SU2ToCGNS[15] = 2; } -void CCGNSElementType::CreateDataQUAD_25(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataQUAD_25(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The QUAD_25 element is a quartic quadrilateral. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -361,39 +428,54 @@ void CCGNSElementType::CreateDataQUAD_25(unsigned short &VTK_Type, where the i-direction is defined from node 0 to 1 and the j-direction from node 0 along the other edge. */ VTK_Type = QUADRILATERAL; - nPoly = 4; - nDOFs = 25; + nPoly = 4; + nDOFs = 25; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 5; SU2ToCGNS[3] = 6; - SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 15; SU2ToCGNS[6] = 16; SU2ToCGNS[7] = 17; - SU2ToCGNS[8] = 18; SU2ToCGNS[9] = 7; SU2ToCGNS[10] = 14; SU2ToCGNS[11] = 23; - SU2ToCGNS[12] = 24; SU2ToCGNS[13] = 19; SU2ToCGNS[14] = 8; SU2ToCGNS[15] = 13; - SU2ToCGNS[16] = 22; SU2ToCGNS[17] = 21; SU2ToCGNS[18] = 20; SU2ToCGNS[19] = 9; - SU2ToCGNS[20] = 3; SU2ToCGNS[21] = 12; SU2ToCGNS[22] = 11; SU2ToCGNS[23] = 10; - SU2ToCGNS[24] = 2; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 4; + SU2ToCGNS[2] = 5; + SU2ToCGNS[3] = 6; + SU2ToCGNS[4] = 1; + SU2ToCGNS[5] = 15; + SU2ToCGNS[6] = 16; + SU2ToCGNS[7] = 17; + SU2ToCGNS[8] = 18; + SU2ToCGNS[9] = 7; + SU2ToCGNS[10] = 14; + SU2ToCGNS[11] = 23; + SU2ToCGNS[12] = 24; + SU2ToCGNS[13] = 19; + SU2ToCGNS[14] = 8; + SU2ToCGNS[15] = 13; + SU2ToCGNS[16] = 22; + SU2ToCGNS[17] = 21; + SU2ToCGNS[18] = 20; + SU2ToCGNS[19] = 9; + SU2ToCGNS[20] = 3; + SU2ToCGNS[21] = 12; + SU2ToCGNS[22] = 11; + SU2ToCGNS[23] = 10; + SU2ToCGNS[24] = 2; } -void CCGNSElementType::CreateDataTETRA_4(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataTETRA_4(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The TETRA_4 element is a linear tetrahedron. The node numbering is the same in SU2 and CGNS. */ VTK_Type = TETRAHEDRON; - nPoly = 1; - nDOFs = 4; + nPoly = 1; + nDOFs = 4; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 2; SU2ToCGNS[3] = 3; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 1; + SU2ToCGNS[2] = 2; + SU2ToCGNS[3] = 3; } -void CCGNSElementType::CreateDataTETRA_10(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataTETRA_10(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The TETRA_10 element is a quadratic tetrahedron. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -404,20 +486,24 @@ void CCGNSElementType::CreateDataTETRA_10(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = TETRAHEDRON; - nPoly = 2; - nDOFs = 10; + nPoly = 2; + nDOFs = 10; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 6; - SU2ToCGNS[4] = 5; SU2ToCGNS[5] = 2; SU2ToCGNS[6] = 7; SU2ToCGNS[7] = 8; - SU2ToCGNS[8] = 9; SU2ToCGNS[9] = 3; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 4; + SU2ToCGNS[2] = 1; + SU2ToCGNS[3] = 6; + SU2ToCGNS[4] = 5; + SU2ToCGNS[5] = 2; + SU2ToCGNS[6] = 7; + SU2ToCGNS[7] = 8; + SU2ToCGNS[8] = 9; + SU2ToCGNS[9] = 3; } -void CCGNSElementType::CreateDataTETRA_20(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataTETRA_20(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The TETRA_20 element is a cubic tetrahedron. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -428,22 +514,34 @@ void CCGNSElementType::CreateDataTETRA_20(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = TETRAHEDRON; - nPoly = 3; - nDOFs = 20; + nPoly = 3; + nDOFs = 20; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 5; SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 9; SU2ToCGNS[5] = 16; SU2ToCGNS[6] = 6; SU2ToCGNS[7] = 8; - SU2ToCGNS[8] = 7; SU2ToCGNS[9] = 2; SU2ToCGNS[10] = 10; SU2ToCGNS[11] = 17; - SU2ToCGNS[12] = 12; SU2ToCGNS[13] = 19; SU2ToCGNS[14] = 18; SU2ToCGNS[15] = 14; - SU2ToCGNS[16] = 11; SU2ToCGNS[17] = 13; SU2ToCGNS[18] = 15; SU2ToCGNS[19] = 3; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 4; + SU2ToCGNS[2] = 5; + SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 9; + SU2ToCGNS[5] = 16; + SU2ToCGNS[6] = 6; + SU2ToCGNS[7] = 8; + SU2ToCGNS[8] = 7; + SU2ToCGNS[9] = 2; + SU2ToCGNS[10] = 10; + SU2ToCGNS[11] = 17; + SU2ToCGNS[12] = 12; + SU2ToCGNS[13] = 19; + SU2ToCGNS[14] = 18; + SU2ToCGNS[15] = 14; + SU2ToCGNS[16] = 11; + SU2ToCGNS[17] = 13; + SU2ToCGNS[18] = 15; + SU2ToCGNS[19] = 3; } -void CCGNSElementType::CreateDataTETRA_35(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataTETRA_35(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The TETRA_35 element is a quartic tetrahedron. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -457,26 +555,49 @@ void CCGNSElementType::CreateDataTETRA_35(unsigned short &VTK_Type, currently ignored, i.e. it is assumed that the spacing in parameter space is uniform. */ VTK_Type = TETRAHEDRON; - nPoly = 4; - nDOFs = 35; + nPoly = 4; + nDOFs = 35; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 4; SU2ToCGNS[2] = 5; SU2ToCGNS[3] = 6; - SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 12; SU2ToCGNS[6] = 22; SU2ToCGNS[7] = 23; - SU2ToCGNS[8] = 7; SU2ToCGNS[9] = 11; SU2ToCGNS[10] = 24; SU2ToCGNS[11] = 8; - SU2ToCGNS[12] = 10; SU2ToCGNS[13] = 9; SU2ToCGNS[14] = 2; SU2ToCGNS[15] = 13; - SU2ToCGNS[16] = 25; SU2ToCGNS[17] = 26; SU2ToCGNS[18] = 16; SU2ToCGNS[19] = 32; - SU2ToCGNS[20] = 34; SU2ToCGNS[21] = 28; SU2ToCGNS[22] = 31; SU2ToCGNS[23] = 29; - SU2ToCGNS[24] = 19; SU2ToCGNS[25] = 14; SU2ToCGNS[26] = 27; SU2ToCGNS[27] = 17; - SU2ToCGNS[28] = 33; SU2ToCGNS[29] = 30; SU2ToCGNS[30] = 20; SU2ToCGNS[31] = 15; - SU2ToCGNS[32] = 18; SU2ToCGNS[33] = 21; SU2ToCGNS[34] = 3; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 4; + SU2ToCGNS[2] = 5; + SU2ToCGNS[3] = 6; + SU2ToCGNS[4] = 1; + SU2ToCGNS[5] = 12; + SU2ToCGNS[6] = 22; + SU2ToCGNS[7] = 23; + SU2ToCGNS[8] = 7; + SU2ToCGNS[9] = 11; + SU2ToCGNS[10] = 24; + SU2ToCGNS[11] = 8; + SU2ToCGNS[12] = 10; + SU2ToCGNS[13] = 9; + SU2ToCGNS[14] = 2; + SU2ToCGNS[15] = 13; + SU2ToCGNS[16] = 25; + SU2ToCGNS[17] = 26; + SU2ToCGNS[18] = 16; + SU2ToCGNS[19] = 32; + SU2ToCGNS[20] = 34; + SU2ToCGNS[21] = 28; + SU2ToCGNS[22] = 31; + SU2ToCGNS[23] = 29; + SU2ToCGNS[24] = 19; + SU2ToCGNS[25] = 14; + SU2ToCGNS[26] = 27; + SU2ToCGNS[27] = 17; + SU2ToCGNS[28] = 33; + SU2ToCGNS[29] = 30; + SU2ToCGNS[30] = 20; + SU2ToCGNS[31] = 15; + SU2ToCGNS[32] = 18; + SU2ToCGNS[33] = 21; + SU2ToCGNS[34] = 3; } -void CCGNSElementType::CreateDataPYRA_5(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataPYRA_5(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The PYRA_5 element is a linear pyramid. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes (not present in PYRA_5). @@ -487,19 +608,19 @@ void CCGNSElementType::CreateDataPYRA_5(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = PYRAMID; - nPoly = 1; - nDOFs = 5; + nPoly = 1; + nDOFs = 5; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 3; SU2ToCGNS[3] = 2; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 1; + SU2ToCGNS[2] = 3; + SU2ToCGNS[3] = 2; SU2ToCGNS[4] = 4; } -void CCGNSElementType::CreateDataPYRA_14(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataPYRA_14(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The PYRA_14 element is a quadratic pyramid. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -510,21 +631,28 @@ void CCGNSElementType::CreateDataPYRA_14(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = PYRAMID; - nPoly = 2; - nDOFs = 14; + nPoly = 2; + nDOFs = 14; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 5; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 8; - SU2ToCGNS[4] = 13; SU2ToCGNS[5] = 6; SU2ToCGNS[6] = 3; SU2ToCGNS[7] = 7; - SU2ToCGNS[8] = 2; SU2ToCGNS[9] = 9; SU2ToCGNS[10] = 10; SU2ToCGNS[11] = 12; - SU2ToCGNS[12] = 11; SU2ToCGNS[13] = 4; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 5; + SU2ToCGNS[2] = 1; + SU2ToCGNS[3] = 8; + SU2ToCGNS[4] = 13; + SU2ToCGNS[5] = 6; + SU2ToCGNS[6] = 3; + SU2ToCGNS[7] = 7; + SU2ToCGNS[8] = 2; + SU2ToCGNS[9] = 9; + SU2ToCGNS[10] = 10; + SU2ToCGNS[11] = 12; + SU2ToCGNS[12] = 11; + SU2ToCGNS[13] = 4; } -void CCGNSElementType::CreateDataPYRA_30(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataPYRA_30(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The PYRA_30 element is a cubic pyramid. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -535,25 +663,44 @@ void CCGNSElementType::CreateDataPYRA_30(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = PYRAMID; - nPoly = 3; - nDOFs = 30; + nPoly = 3; + nDOFs = 30; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 5; SU2ToCGNS[2] = 6; SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 12; SU2ToCGNS[5] = 21; SU2ToCGNS[6] = 22; SU2ToCGNS[7] = 7; - SU2ToCGNS[8] = 11; SU2ToCGNS[9] = 24; SU2ToCGNS[10] = 23; SU2ToCGNS[11] = 8; - SU2ToCGNS[12] = 3; SU2ToCGNS[13] = 10; SU2ToCGNS[14] = 9; SU2ToCGNS[15] = 2; - SU2ToCGNS[16] = 13; SU2ToCGNS[17] = 25; SU2ToCGNS[18] = 15; SU2ToCGNS[19] = 28; - SU2ToCGNS[20] = 29; SU2ToCGNS[21] = 26; SU2ToCGNS[22] = 19; SU2ToCGNS[23] = 27; - SU2ToCGNS[24] = 17; SU2ToCGNS[25] = 14; SU2ToCGNS[26] = 16; SU2ToCGNS[27] = 20; - SU2ToCGNS[28] = 18; SU2ToCGNS[29] = 4; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 5; + SU2ToCGNS[2] = 6; + SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 12; + SU2ToCGNS[5] = 21; + SU2ToCGNS[6] = 22; + SU2ToCGNS[7] = 7; + SU2ToCGNS[8] = 11; + SU2ToCGNS[9] = 24; + SU2ToCGNS[10] = 23; + SU2ToCGNS[11] = 8; + SU2ToCGNS[12] = 3; + SU2ToCGNS[13] = 10; + SU2ToCGNS[14] = 9; + SU2ToCGNS[15] = 2; + SU2ToCGNS[16] = 13; + SU2ToCGNS[17] = 25; + SU2ToCGNS[18] = 15; + SU2ToCGNS[19] = 28; + SU2ToCGNS[20] = 29; + SU2ToCGNS[21] = 26; + SU2ToCGNS[22] = 19; + SU2ToCGNS[23] = 27; + SU2ToCGNS[24] = 17; + SU2ToCGNS[25] = 14; + SU2ToCGNS[26] = 16; + SU2ToCGNS[27] = 20; + SU2ToCGNS[28] = 18; + SU2ToCGNS[29] = 4; } -void CCGNSElementType::CreateDataPYRA_55(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataPYRA_55(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The PYRA_55 element is a quartic pyramid. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -567,47 +714,86 @@ void CCGNSElementType::CreateDataPYRA_55(unsigned short &VTK_Type, effect is currently ignored, i.e. it is assumed that the spacing in parameter space is uniform.*/ VTK_Type = PYRAMID; - nPoly = 4; - nDOFs = 55; + nPoly = 4; + nDOFs = 55; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 5; SU2ToCGNS[2] = 6; SU2ToCGNS[3] = 7; - SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 16; SU2ToCGNS[6] = 29; SU2ToCGNS[7] = 30; - SU2ToCGNS[8] = 31; SU2ToCGNS[9] = 8; SU2ToCGNS[10] = 15; SU2ToCGNS[11] = 36; - SU2ToCGNS[12] = 37; SU2ToCGNS[13] = 32; SU2ToCGNS[14] = 9; SU2ToCGNS[15] = 14; - SU2ToCGNS[16] = 35; SU2ToCGNS[17] = 34; SU2ToCGNS[18] = 33; SU2ToCGNS[19] = 10; - SU2ToCGNS[20] = 3; SU2ToCGNS[21] = 13; SU2ToCGNS[22] = 12; SU2ToCGNS[23] = 11; - SU2ToCGNS[24] = 2; SU2ToCGNS[25] = 17; SU2ToCGNS[26] = 38; SU2ToCGNS[27] = 39; - SU2ToCGNS[28] = 20; SU2ToCGNS[29] = 48; SU2ToCGNS[30] = 50; SU2ToCGNS[31] = 51; - SU2ToCGNS[32] = 41; SU2ToCGNS[33] = 47; SU2ToCGNS[34] = 53; SU2ToCGNS[35] = 52; - SU2ToCGNS[36] = 42; SU2ToCGNS[37] = 26; SU2ToCGNS[38] = 45; SU2ToCGNS[39] = 44; - SU2ToCGNS[40] = 23; SU2ToCGNS[41] = 18; SU2ToCGNS[42] = 40; SU2ToCGNS[43] = 21; - SU2ToCGNS[44] = 49; SU2ToCGNS[45] = 54; SU2ToCGNS[46] = 43; SU2ToCGNS[47] = 27; - SU2ToCGNS[48] = 46; SU2ToCGNS[49] = 24; SU2ToCGNS[50] = 19; SU2ToCGNS[51] = 22; - SU2ToCGNS[52] = 28; SU2ToCGNS[53] = 25; SU2ToCGNS[54] = 4; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 5; + SU2ToCGNS[2] = 6; + SU2ToCGNS[3] = 7; + SU2ToCGNS[4] = 1; + SU2ToCGNS[5] = 16; + SU2ToCGNS[6] = 29; + SU2ToCGNS[7] = 30; + SU2ToCGNS[8] = 31; + SU2ToCGNS[9] = 8; + SU2ToCGNS[10] = 15; + SU2ToCGNS[11] = 36; + SU2ToCGNS[12] = 37; + SU2ToCGNS[13] = 32; + SU2ToCGNS[14] = 9; + SU2ToCGNS[15] = 14; + SU2ToCGNS[16] = 35; + SU2ToCGNS[17] = 34; + SU2ToCGNS[18] = 33; + SU2ToCGNS[19] = 10; + SU2ToCGNS[20] = 3; + SU2ToCGNS[21] = 13; + SU2ToCGNS[22] = 12; + SU2ToCGNS[23] = 11; + SU2ToCGNS[24] = 2; + SU2ToCGNS[25] = 17; + SU2ToCGNS[26] = 38; + SU2ToCGNS[27] = 39; + SU2ToCGNS[28] = 20; + SU2ToCGNS[29] = 48; + SU2ToCGNS[30] = 50; + SU2ToCGNS[31] = 51; + SU2ToCGNS[32] = 41; + SU2ToCGNS[33] = 47; + SU2ToCGNS[34] = 53; + SU2ToCGNS[35] = 52; + SU2ToCGNS[36] = 42; + SU2ToCGNS[37] = 26; + SU2ToCGNS[38] = 45; + SU2ToCGNS[39] = 44; + SU2ToCGNS[40] = 23; + SU2ToCGNS[41] = 18; + SU2ToCGNS[42] = 40; + SU2ToCGNS[43] = 21; + SU2ToCGNS[44] = 49; + SU2ToCGNS[45] = 54; + SU2ToCGNS[46] = 43; + SU2ToCGNS[47] = 27; + SU2ToCGNS[48] = 46; + SU2ToCGNS[49] = 24; + SU2ToCGNS[50] = 19; + SU2ToCGNS[51] = 22; + SU2ToCGNS[52] = 28; + SU2ToCGNS[53] = 25; + SU2ToCGNS[54] = 4; } -void CCGNSElementType::CreateDataPENTA_6(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataPENTA_6(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The PENTA_6 element is a linear prism. The node numbering is the same in SU2 and CGNS. */ VTK_Type = PRISM; - nPoly = 1; - nDOFs = 6; + nPoly = 1; + nDOFs = 6; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 2; - SU2ToCGNS[3] = 3; SU2ToCGNS[4] = 4; SU2ToCGNS[5] = 5; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 1; + SU2ToCGNS[2] = 2; + SU2ToCGNS[3] = 3; + SU2ToCGNS[4] = 4; + SU2ToCGNS[5] = 5; } -void CCGNSElementType::CreateDataPENTA_18(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataPENTA_18(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The PENTA_18 element is a quadratic prism. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -618,22 +804,32 @@ void CCGNSElementType::CreateDataPENTA_18(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = PRISM; - nPoly = 2; - nDOFs = 18; + nPoly = 2; + nDOFs = 18; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 6; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 8; - SU2ToCGNS[4] = 7; SU2ToCGNS[5] = 2; SU2ToCGNS[6] = 9; SU2ToCGNS[7] = 15; - SU2ToCGNS[8] = 10; SU2ToCGNS[9] = 17; SU2ToCGNS[10] = 16; SU2ToCGNS[11] = 11; - SU2ToCGNS[12] = 3; SU2ToCGNS[13] = 12; SU2ToCGNS[14] = 4; SU2ToCGNS[15] = 14; - SU2ToCGNS[16] = 13; SU2ToCGNS[17] = 5; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 6; + SU2ToCGNS[2] = 1; + SU2ToCGNS[3] = 8; + SU2ToCGNS[4] = 7; + SU2ToCGNS[5] = 2; + SU2ToCGNS[6] = 9; + SU2ToCGNS[7] = 15; + SU2ToCGNS[8] = 10; + SU2ToCGNS[9] = 17; + SU2ToCGNS[10] = 16; + SU2ToCGNS[11] = 11; + SU2ToCGNS[12] = 3; + SU2ToCGNS[13] = 12; + SU2ToCGNS[14] = 4; + SU2ToCGNS[15] = 14; + SU2ToCGNS[16] = 13; + SU2ToCGNS[17] = 5; } -void CCGNSElementType::CreateDataPENTA_40(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataPENTA_40(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The PENTA_40 element is a cubic prism. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -644,27 +840,54 @@ void CCGNSElementType::CreateDataPENTA_40(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = PRISM; - nPoly = 3; - nDOFs = 40; + nPoly = 3; + nDOFs = 40; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 6; SU2ToCGNS[2] = 7; SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 11; SU2ToCGNS[5] = 24; SU2ToCGNS[6] = 8; SU2ToCGNS[7] = 10; - SU2ToCGNS[8] = 9; SU2ToCGNS[9] = 2; SU2ToCGNS[10] = 12; SU2ToCGNS[11] = 25; - SU2ToCGNS[12] = 26; SU2ToCGNS[13] = 14; SU2ToCGNS[14] = 34; SU2ToCGNS[15] = 38; - SU2ToCGNS[16] = 29; SU2ToCGNS[17] = 33; SU2ToCGNS[18] = 30; SU2ToCGNS[19] = 16; - SU2ToCGNS[20] = 13; SU2ToCGNS[21] = 28; SU2ToCGNS[22] = 27; SU2ToCGNS[23] = 15; - SU2ToCGNS[24] = 35; SU2ToCGNS[25] = 39; SU2ToCGNS[26] = 32; SU2ToCGNS[27] = 36; - SU2ToCGNS[28] = 31; SU2ToCGNS[29] = 17; SU2ToCGNS[30] = 3; SU2ToCGNS[31] = 18; - SU2ToCGNS[32] = 19; SU2ToCGNS[33] = 4; SU2ToCGNS[34] = 23; SU2ToCGNS[35] = 37; - SU2ToCGNS[36] = 20; SU2ToCGNS[37] = 22; SU2ToCGNS[38] = 21; SU2ToCGNS[39] = 5; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 6; + SU2ToCGNS[2] = 7; + SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 11; + SU2ToCGNS[5] = 24; + SU2ToCGNS[6] = 8; + SU2ToCGNS[7] = 10; + SU2ToCGNS[8] = 9; + SU2ToCGNS[9] = 2; + SU2ToCGNS[10] = 12; + SU2ToCGNS[11] = 25; + SU2ToCGNS[12] = 26; + SU2ToCGNS[13] = 14; + SU2ToCGNS[14] = 34; + SU2ToCGNS[15] = 38; + SU2ToCGNS[16] = 29; + SU2ToCGNS[17] = 33; + SU2ToCGNS[18] = 30; + SU2ToCGNS[19] = 16; + SU2ToCGNS[20] = 13; + SU2ToCGNS[21] = 28; + SU2ToCGNS[22] = 27; + SU2ToCGNS[23] = 15; + SU2ToCGNS[24] = 35; + SU2ToCGNS[25] = 39; + SU2ToCGNS[26] = 32; + SU2ToCGNS[27] = 36; + SU2ToCGNS[28] = 31; + SU2ToCGNS[29] = 17; + SU2ToCGNS[30] = 3; + SU2ToCGNS[31] = 18; + SU2ToCGNS[32] = 19; + SU2ToCGNS[33] = 4; + SU2ToCGNS[34] = 23; + SU2ToCGNS[35] = 37; + SU2ToCGNS[36] = 20; + SU2ToCGNS[37] = 22; + SU2ToCGNS[38] = 21; + SU2ToCGNS[39] = 5; } -void CCGNSElementType::CreateDataPENTA_75(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataPENTA_75(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The PENTA_75 element is a quartic prism. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -678,36 +901,89 @@ void CCGNSElementType::CreateDataPENTA_75(unsigned short &VTK_Type, effect is currently ignored, i.e. it is assumed that the spacing in parameter space is uniform. */ VTK_Type = PRISM; - nPoly = 4; - nDOFs = 75; + nPoly = 4; + nDOFs = 75; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 6; SU2ToCGNS[2] = 7; SU2ToCGNS[3] = 8; - SU2ToCGNS[4] = 1; SU2ToCGNS[5] = 14; SU2ToCGNS[6] = 33; SU2ToCGNS[7] = 34; - SU2ToCGNS[8] = 9; SU2ToCGNS[9] = 13; SU2ToCGNS[10] = 35; SU2ToCGNS[11] = 10; - SU2ToCGNS[12] = 12; SU2ToCGNS[13] = 11; SU2ToCGNS[14] = 2; SU2ToCGNS[15] = 15; - SU2ToCGNS[16] = 36; SU2ToCGNS[17] = 37; SU2ToCGNS[18] = 38; SU2ToCGNS[19] = 18; - SU2ToCGNS[20] = 56; SU2ToCGNS[21] = 66; SU2ToCGNS[22] = 67; SU2ToCGNS[23] = 45; - SU2ToCGNS[24] = 55; SU2ToCGNS[25] = 68; SU2ToCGNS[26] = 46; SU2ToCGNS[27] = 54; - SU2ToCGNS[28] = 47; SU2ToCGNS[29] = 21; SU2ToCGNS[30] = 16; SU2ToCGNS[31] = 43; - SU2ToCGNS[32] = 44; SU2ToCGNS[33] = 39; SU2ToCGNS[34] = 19; SU2ToCGNS[35] = 57; - SU2ToCGNS[36] = 69; SU2ToCGNS[37] = 70; SU2ToCGNS[38] = 52; SU2ToCGNS[39] = 62; - SU2ToCGNS[40] = 71; SU2ToCGNS[41] = 53; SU2ToCGNS[42] = 61; SU2ToCGNS[43] = 48; - SU2ToCGNS[44] = 22; SU2ToCGNS[45] = 17; SU2ToCGNS[46] = 42; SU2ToCGNS[47] = 41; - SU2ToCGNS[48] = 40; SU2ToCGNS[49] = 20; SU2ToCGNS[50] = 58; SU2ToCGNS[51] = 72; - SU2ToCGNS[52] = 73; SU2ToCGNS[53] = 51; SU2ToCGNS[54] = 59; SU2ToCGNS[55] = 74; - SU2ToCGNS[56] = 50; SU2ToCGNS[57] = 60; SU2ToCGNS[58] = 49; SU2ToCGNS[59] = 23; - SU2ToCGNS[60] = 3; SU2ToCGNS[61] = 24; SU2ToCGNS[62] = 25; SU2ToCGNS[63] = 26; - SU2ToCGNS[64] = 4; SU2ToCGNS[65] = 32; SU2ToCGNS[66] = 63; SU2ToCGNS[67] = 64; - SU2ToCGNS[68] = 27; SU2ToCGNS[69] = 31; SU2ToCGNS[70] = 65; SU2ToCGNS[71] = 28; - SU2ToCGNS[72] = 30; SU2ToCGNS[73] = 29; SU2ToCGNS[74] = 5; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 6; + SU2ToCGNS[2] = 7; + SU2ToCGNS[3] = 8; + SU2ToCGNS[4] = 1; + SU2ToCGNS[5] = 14; + SU2ToCGNS[6] = 33; + SU2ToCGNS[7] = 34; + SU2ToCGNS[8] = 9; + SU2ToCGNS[9] = 13; + SU2ToCGNS[10] = 35; + SU2ToCGNS[11] = 10; + SU2ToCGNS[12] = 12; + SU2ToCGNS[13] = 11; + SU2ToCGNS[14] = 2; + SU2ToCGNS[15] = 15; + SU2ToCGNS[16] = 36; + SU2ToCGNS[17] = 37; + SU2ToCGNS[18] = 38; + SU2ToCGNS[19] = 18; + SU2ToCGNS[20] = 56; + SU2ToCGNS[21] = 66; + SU2ToCGNS[22] = 67; + SU2ToCGNS[23] = 45; + SU2ToCGNS[24] = 55; + SU2ToCGNS[25] = 68; + SU2ToCGNS[26] = 46; + SU2ToCGNS[27] = 54; + SU2ToCGNS[28] = 47; + SU2ToCGNS[29] = 21; + SU2ToCGNS[30] = 16; + SU2ToCGNS[31] = 43; + SU2ToCGNS[32] = 44; + SU2ToCGNS[33] = 39; + SU2ToCGNS[34] = 19; + SU2ToCGNS[35] = 57; + SU2ToCGNS[36] = 69; + SU2ToCGNS[37] = 70; + SU2ToCGNS[38] = 52; + SU2ToCGNS[39] = 62; + SU2ToCGNS[40] = 71; + SU2ToCGNS[41] = 53; + SU2ToCGNS[42] = 61; + SU2ToCGNS[43] = 48; + SU2ToCGNS[44] = 22; + SU2ToCGNS[45] = 17; + SU2ToCGNS[46] = 42; + SU2ToCGNS[47] = 41; + SU2ToCGNS[48] = 40; + SU2ToCGNS[49] = 20; + SU2ToCGNS[50] = 58; + SU2ToCGNS[51] = 72; + SU2ToCGNS[52] = 73; + SU2ToCGNS[53] = 51; + SU2ToCGNS[54] = 59; + SU2ToCGNS[55] = 74; + SU2ToCGNS[56] = 50; + SU2ToCGNS[57] = 60; + SU2ToCGNS[58] = 49; + SU2ToCGNS[59] = 23; + SU2ToCGNS[60] = 3; + SU2ToCGNS[61] = 24; + SU2ToCGNS[62] = 25; + SU2ToCGNS[63] = 26; + SU2ToCGNS[64] = 4; + SU2ToCGNS[65] = 32; + SU2ToCGNS[66] = 63; + SU2ToCGNS[67] = 64; + SU2ToCGNS[68] = 27; + SU2ToCGNS[69] = 31; + SU2ToCGNS[70] = 65; + SU2ToCGNS[71] = 28; + SU2ToCGNS[72] = 30; + SU2ToCGNS[73] = 29; + SU2ToCGNS[74] = 5; } -void CCGNSElementType::CreateDataHEXA_8(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataHEXA_8(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The HEXA_8 element is a linear hexahedron. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes (not present in HEXA_8). @@ -718,19 +994,22 @@ void CCGNSElementType::CreateDataHEXA_8(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = HEXAHEDRON; - nPoly = 1; - nDOFs = 8; + nPoly = 1; + nDOFs = 8; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 1; SU2ToCGNS[2] = 3; SU2ToCGNS[3] = 2; - SU2ToCGNS[4] = 4; SU2ToCGNS[5] = 5; SU2ToCGNS[6] = 7; SU2ToCGNS[7] = 6; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 1; + SU2ToCGNS[2] = 3; + SU2ToCGNS[3] = 2; + SU2ToCGNS[4] = 4; + SU2ToCGNS[5] = 5; + SU2ToCGNS[6] = 7; + SU2ToCGNS[7] = 6; } -void CCGNSElementType::CreateDataHEXA_27(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataHEXA_27(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The HEXA_27 element is a quadratic hexahedron. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -741,24 +1020,41 @@ void CCGNSElementType::CreateDataHEXA_27(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = HEXAHEDRON; - nPoly = 2; - nDOFs = 27; + nPoly = 2; + nDOFs = 27; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 8; SU2ToCGNS[2] = 1; SU2ToCGNS[3] = 11; - SU2ToCGNS[4] = 20; SU2ToCGNS[5] = 9; SU2ToCGNS[6] = 3; SU2ToCGNS[7] = 10; - SU2ToCGNS[8] = 2; SU2ToCGNS[9] = 12; SU2ToCGNS[10] = 21; SU2ToCGNS[11] = 13; - SU2ToCGNS[12] = 24; SU2ToCGNS[13] = 26; SU2ToCGNS[14] = 22; SU2ToCGNS[15] = 15; - SU2ToCGNS[16] = 23; SU2ToCGNS[17] = 14; SU2ToCGNS[18] = 4; SU2ToCGNS[19] = 16; - SU2ToCGNS[20] = 5; SU2ToCGNS[21] = 19; SU2ToCGNS[22] = 25; SU2ToCGNS[23] = 17; - SU2ToCGNS[24] = 7; SU2ToCGNS[25] = 18; SU2ToCGNS[26] = 6; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 8; + SU2ToCGNS[2] = 1; + SU2ToCGNS[3] = 11; + SU2ToCGNS[4] = 20; + SU2ToCGNS[5] = 9; + SU2ToCGNS[6] = 3; + SU2ToCGNS[7] = 10; + SU2ToCGNS[8] = 2; + SU2ToCGNS[9] = 12; + SU2ToCGNS[10] = 21; + SU2ToCGNS[11] = 13; + SU2ToCGNS[12] = 24; + SU2ToCGNS[13] = 26; + SU2ToCGNS[14] = 22; + SU2ToCGNS[15] = 15; + SU2ToCGNS[16] = 23; + SU2ToCGNS[17] = 14; + SU2ToCGNS[18] = 4; + SU2ToCGNS[19] = 16; + SU2ToCGNS[20] = 5; + SU2ToCGNS[21] = 19; + SU2ToCGNS[22] = 25; + SU2ToCGNS[23] = 17; + SU2ToCGNS[24] = 7; + SU2ToCGNS[25] = 18; + SU2ToCGNS[26] = 6; } -void CCGNSElementType::CreateDataHEXA_64(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataHEXA_64(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The HEXA_64 element is a cubic hexahedron. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -769,33 +1065,78 @@ void CCGNSElementType::CreateDataHEXA_64(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = HEXAHEDRON; - nPoly = 3; - nDOFs = 64; + nPoly = 3; + nDOFs = 64; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 8; SU2ToCGNS[2] = 9; SU2ToCGNS[3] = 1; - SU2ToCGNS[4] = 15; SU2ToCGNS[5] = 32; SU2ToCGNS[6] = 33; SU2ToCGNS[7] = 10; - SU2ToCGNS[8] = 14; SU2ToCGNS[9] = 35; SU2ToCGNS[10] = 34; SU2ToCGNS[11] = 11; - SU2ToCGNS[12] = 3; SU2ToCGNS[13] = 13; SU2ToCGNS[14] = 12; SU2ToCGNS[15] = 2; - SU2ToCGNS[16] = 16; SU2ToCGNS[17] = 36; SU2ToCGNS[18] = 37; SU2ToCGNS[19] = 18; - SU2ToCGNS[20] = 49; SU2ToCGNS[21] = 56; SU2ToCGNS[22] = 57; SU2ToCGNS[23] = 40; - SU2ToCGNS[24] = 48; SU2ToCGNS[25] = 59; SU2ToCGNS[26] = 58; SU2ToCGNS[27] = 41; - SU2ToCGNS[28] = 22; SU2ToCGNS[29] = 45; SU2ToCGNS[30] = 44; SU2ToCGNS[31] = 20; - SU2ToCGNS[32] = 17; SU2ToCGNS[33] = 39; SU2ToCGNS[34] = 38; SU2ToCGNS[35] = 19; - SU2ToCGNS[36] = 50; SU2ToCGNS[37] = 60; SU2ToCGNS[38] = 61; SU2ToCGNS[39] = 43; - SU2ToCGNS[40] = 51; SU2ToCGNS[41] = 63; SU2ToCGNS[42] = 62; SU2ToCGNS[43] = 42; - SU2ToCGNS[44] = 23; SU2ToCGNS[45] = 46; SU2ToCGNS[46] = 47; SU2ToCGNS[47] = 21; - SU2ToCGNS[48] = 4; SU2ToCGNS[49] = 24; SU2ToCGNS[50] = 25; SU2ToCGNS[51] = 5; - SU2ToCGNS[52] = 31; SU2ToCGNS[53] = 52; SU2ToCGNS[54] = 53; SU2ToCGNS[55] = 26; - SU2ToCGNS[56] = 30; SU2ToCGNS[57] = 55; SU2ToCGNS[58] = 54; SU2ToCGNS[59] = 27; - SU2ToCGNS[60] = 7; SU2ToCGNS[61] = 29; SU2ToCGNS[62] = 28; SU2ToCGNS[63] = 6; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 8; + SU2ToCGNS[2] = 9; + SU2ToCGNS[3] = 1; + SU2ToCGNS[4] = 15; + SU2ToCGNS[5] = 32; + SU2ToCGNS[6] = 33; + SU2ToCGNS[7] = 10; + SU2ToCGNS[8] = 14; + SU2ToCGNS[9] = 35; + SU2ToCGNS[10] = 34; + SU2ToCGNS[11] = 11; + SU2ToCGNS[12] = 3; + SU2ToCGNS[13] = 13; + SU2ToCGNS[14] = 12; + SU2ToCGNS[15] = 2; + SU2ToCGNS[16] = 16; + SU2ToCGNS[17] = 36; + SU2ToCGNS[18] = 37; + SU2ToCGNS[19] = 18; + SU2ToCGNS[20] = 49; + SU2ToCGNS[21] = 56; + SU2ToCGNS[22] = 57; + SU2ToCGNS[23] = 40; + SU2ToCGNS[24] = 48; + SU2ToCGNS[25] = 59; + SU2ToCGNS[26] = 58; + SU2ToCGNS[27] = 41; + SU2ToCGNS[28] = 22; + SU2ToCGNS[29] = 45; + SU2ToCGNS[30] = 44; + SU2ToCGNS[31] = 20; + SU2ToCGNS[32] = 17; + SU2ToCGNS[33] = 39; + SU2ToCGNS[34] = 38; + SU2ToCGNS[35] = 19; + SU2ToCGNS[36] = 50; + SU2ToCGNS[37] = 60; + SU2ToCGNS[38] = 61; + SU2ToCGNS[39] = 43; + SU2ToCGNS[40] = 51; + SU2ToCGNS[41] = 63; + SU2ToCGNS[42] = 62; + SU2ToCGNS[43] = 42; + SU2ToCGNS[44] = 23; + SU2ToCGNS[45] = 46; + SU2ToCGNS[46] = 47; + SU2ToCGNS[47] = 21; + SU2ToCGNS[48] = 4; + SU2ToCGNS[49] = 24; + SU2ToCGNS[50] = 25; + SU2ToCGNS[51] = 5; + SU2ToCGNS[52] = 31; + SU2ToCGNS[53] = 52; + SU2ToCGNS[54] = 53; + SU2ToCGNS[55] = 26; + SU2ToCGNS[56] = 30; + SU2ToCGNS[57] = 55; + SU2ToCGNS[58] = 54; + SU2ToCGNS[59] = 27; + SU2ToCGNS[60] = 7; + SU2ToCGNS[61] = 29; + SU2ToCGNS[62] = 28; + SU2ToCGNS[63] = 6; } -void CCGNSElementType::CreateDataHEXA_125(unsigned short &VTK_Type, - unsigned short &nPoly, - unsigned short &nDOFs, - vector &SU2ToCGNS) { - +void CCGNSElementType::CreateDataHEXA_125(unsigned short& VTK_Type, unsigned short& nPoly, unsigned short& nDOFs, + vector& SU2ToCGNS) { /* The HEXA_125 element is a quartic hexahedron. In CGNS the nodes are numbered as follows: - First the vertex nodes. - Second the edge nodes. @@ -806,35 +1147,135 @@ void CCGNSElementType::CreateDataHEXA_125(unsigned short &VTK_Type, from node 0 along the second edge and the k-direction from node 0 along the third edge. */ VTK_Type = HEXAHEDRON; - nPoly = 4; - nDOFs = 125; + nPoly = 4; + nDOFs = 125; SU2ToCGNS.resize(nDOFs); - SU2ToCGNS[0] = 0; SU2ToCGNS[1] = 8; SU2ToCGNS[2] = 9; SU2ToCGNS[3] = 10; SU2ToCGNS[4] = 1; - SU2ToCGNS[5] = 19; SU2ToCGNS[6] = 44; SU2ToCGNS[7] = 45; SU2ToCGNS[8] = 46; SU2ToCGNS[9] = 11; - SU2ToCGNS[10] = 18; SU2ToCGNS[11] = 51; SU2ToCGNS[12] = 52; SU2ToCGNS[13] = 47; SU2ToCGNS[14] = 12; - SU2ToCGNS[15] = 17; SU2ToCGNS[16] = 50; SU2ToCGNS[17] = 49; SU2ToCGNS[18] = 48; SU2ToCGNS[19] = 13; - SU2ToCGNS[20] = 3; SU2ToCGNS[21] = 16; SU2ToCGNS[22] = 15; SU2ToCGNS[23] = 14; SU2ToCGNS[24] = 2; - SU2ToCGNS[25] = 20; SU2ToCGNS[26] = 53; SU2ToCGNS[27] = 54; SU2ToCGNS[28] = 55; SU2ToCGNS[29] = 23; - SU2ToCGNS[30] = 82; SU2ToCGNS[31] = 98; SU2ToCGNS[32] = 99; SU2ToCGNS[33] = 100; SU2ToCGNS[34] = 62; - SU2ToCGNS[35] = 81; SU2ToCGNS[36] = 105; SU2ToCGNS[37] = 106; SU2ToCGNS[38] = 101; SU2ToCGNS[39] = 63; - SU2ToCGNS[40] = 80; SU2ToCGNS[41] = 104; SU2ToCGNS[42] = 103; SU2ToCGNS[43] = 102; SU2ToCGNS[44] = 64; - SU2ToCGNS[45] = 29; SU2ToCGNS[46] = 73; SU2ToCGNS[47] = 72; SU2ToCGNS[48] = 71; SU2ToCGNS[49] = 26; - SU2ToCGNS[50] = 21; SU2ToCGNS[51] = 60; SU2ToCGNS[52] = 61; SU2ToCGNS[53] = 56; SU2ToCGNS[54] = 24; - SU2ToCGNS[55] = 83; SU2ToCGNS[56] = 107; SU2ToCGNS[57] = 108; SU2ToCGNS[58] = 109; SU2ToCGNS[59] = 69; - SU2ToCGNS[60] = 88; SU2ToCGNS[61] = 114; SU2ToCGNS[62] = 115; SU2ToCGNS[63] = 110; SU2ToCGNS[64] = 70; - SU2ToCGNS[65] = 87; SU2ToCGNS[66] = 113; SU2ToCGNS[67] = 112; SU2ToCGNS[68] = 111; SU2ToCGNS[69] = 65; - SU2ToCGNS[70] = 30; SU2ToCGNS[71] = 74; SU2ToCGNS[72] = 79; SU2ToCGNS[73] = 78; SU2ToCGNS[74] = 27; - SU2ToCGNS[75] = 22; SU2ToCGNS[76] = 59; SU2ToCGNS[77] = 58; SU2ToCGNS[78] = 57; SU2ToCGNS[79] = 25; - SU2ToCGNS[80] = 84; SU2ToCGNS[81] = 116; SU2ToCGNS[82] = 117; SU2ToCGNS[83] = 118; SU2ToCGNS[84] = 68; - SU2ToCGNS[85] = 85; SU2ToCGNS[86] = 123; SU2ToCGNS[87] = 124; SU2ToCGNS[88] = 119; SU2ToCGNS[89] = 67; - SU2ToCGNS[90] = 86; SU2ToCGNS[91] = 122; SU2ToCGNS[92] = 121; SU2ToCGNS[93] = 120; SU2ToCGNS[94] = 66; - SU2ToCGNS[95] = 31; SU2ToCGNS[96] = 75; SU2ToCGNS[97] = 76; SU2ToCGNS[98] = 77; SU2ToCGNS[99] = 28; - SU2ToCGNS[100] = 4; SU2ToCGNS[101] = 32; SU2ToCGNS[102] = 33; SU2ToCGNS[103] = 34; SU2ToCGNS[104] = 5; - SU2ToCGNS[105] = 43; SU2ToCGNS[106] = 89; SU2ToCGNS[107] = 90; SU2ToCGNS[108] = 91; SU2ToCGNS[109] = 35; - SU2ToCGNS[110] = 42; SU2ToCGNS[111] = 96; SU2ToCGNS[112] = 97; SU2ToCGNS[113] = 92; SU2ToCGNS[114] = 36; - SU2ToCGNS[115] = 41; SU2ToCGNS[116] = 95; SU2ToCGNS[117] = 94; SU2ToCGNS[118] = 93; SU2ToCGNS[119] = 37; - SU2ToCGNS[120] = 7; SU2ToCGNS[121] = 40; SU2ToCGNS[122] = 39; SU2ToCGNS[123] = 38; SU2ToCGNS[124] = 6; + SU2ToCGNS[0] = 0; + SU2ToCGNS[1] = 8; + SU2ToCGNS[2] = 9; + SU2ToCGNS[3] = 10; + SU2ToCGNS[4] = 1; + SU2ToCGNS[5] = 19; + SU2ToCGNS[6] = 44; + SU2ToCGNS[7] = 45; + SU2ToCGNS[8] = 46; + SU2ToCGNS[9] = 11; + SU2ToCGNS[10] = 18; + SU2ToCGNS[11] = 51; + SU2ToCGNS[12] = 52; + SU2ToCGNS[13] = 47; + SU2ToCGNS[14] = 12; + SU2ToCGNS[15] = 17; + SU2ToCGNS[16] = 50; + SU2ToCGNS[17] = 49; + SU2ToCGNS[18] = 48; + SU2ToCGNS[19] = 13; + SU2ToCGNS[20] = 3; + SU2ToCGNS[21] = 16; + SU2ToCGNS[22] = 15; + SU2ToCGNS[23] = 14; + SU2ToCGNS[24] = 2; + SU2ToCGNS[25] = 20; + SU2ToCGNS[26] = 53; + SU2ToCGNS[27] = 54; + SU2ToCGNS[28] = 55; + SU2ToCGNS[29] = 23; + SU2ToCGNS[30] = 82; + SU2ToCGNS[31] = 98; + SU2ToCGNS[32] = 99; + SU2ToCGNS[33] = 100; + SU2ToCGNS[34] = 62; + SU2ToCGNS[35] = 81; + SU2ToCGNS[36] = 105; + SU2ToCGNS[37] = 106; + SU2ToCGNS[38] = 101; + SU2ToCGNS[39] = 63; + SU2ToCGNS[40] = 80; + SU2ToCGNS[41] = 104; + SU2ToCGNS[42] = 103; + SU2ToCGNS[43] = 102; + SU2ToCGNS[44] = 64; + SU2ToCGNS[45] = 29; + SU2ToCGNS[46] = 73; + SU2ToCGNS[47] = 72; + SU2ToCGNS[48] = 71; + SU2ToCGNS[49] = 26; + SU2ToCGNS[50] = 21; + SU2ToCGNS[51] = 60; + SU2ToCGNS[52] = 61; + SU2ToCGNS[53] = 56; + SU2ToCGNS[54] = 24; + SU2ToCGNS[55] = 83; + SU2ToCGNS[56] = 107; + SU2ToCGNS[57] = 108; + SU2ToCGNS[58] = 109; + SU2ToCGNS[59] = 69; + SU2ToCGNS[60] = 88; + SU2ToCGNS[61] = 114; + SU2ToCGNS[62] = 115; + SU2ToCGNS[63] = 110; + SU2ToCGNS[64] = 70; + SU2ToCGNS[65] = 87; + SU2ToCGNS[66] = 113; + SU2ToCGNS[67] = 112; + SU2ToCGNS[68] = 111; + SU2ToCGNS[69] = 65; + SU2ToCGNS[70] = 30; + SU2ToCGNS[71] = 74; + SU2ToCGNS[72] = 79; + SU2ToCGNS[73] = 78; + SU2ToCGNS[74] = 27; + SU2ToCGNS[75] = 22; + SU2ToCGNS[76] = 59; + SU2ToCGNS[77] = 58; + SU2ToCGNS[78] = 57; + SU2ToCGNS[79] = 25; + SU2ToCGNS[80] = 84; + SU2ToCGNS[81] = 116; + SU2ToCGNS[82] = 117; + SU2ToCGNS[83] = 118; + SU2ToCGNS[84] = 68; + SU2ToCGNS[85] = 85; + SU2ToCGNS[86] = 123; + SU2ToCGNS[87] = 124; + SU2ToCGNS[88] = 119; + SU2ToCGNS[89] = 67; + SU2ToCGNS[90] = 86; + SU2ToCGNS[91] = 122; + SU2ToCGNS[92] = 121; + SU2ToCGNS[93] = 120; + SU2ToCGNS[94] = 66; + SU2ToCGNS[95] = 31; + SU2ToCGNS[96] = 75; + SU2ToCGNS[97] = 76; + SU2ToCGNS[98] = 77; + SU2ToCGNS[99] = 28; + SU2ToCGNS[100] = 4; + SU2ToCGNS[101] = 32; + SU2ToCGNS[102] = 33; + SU2ToCGNS[103] = 34; + SU2ToCGNS[104] = 5; + SU2ToCGNS[105] = 43; + SU2ToCGNS[106] = 89; + SU2ToCGNS[107] = 90; + SU2ToCGNS[108] = 91; + SU2ToCGNS[109] = 35; + SU2ToCGNS[110] = 42; + SU2ToCGNS[111] = 96; + SU2ToCGNS[112] = 97; + SU2ToCGNS[113] = 92; + SU2ToCGNS[114] = 36; + SU2ToCGNS[115] = 41; + SU2ToCGNS[116] = 95; + SU2ToCGNS[117] = 94; + SU2ToCGNS[118] = 93; + SU2ToCGNS[119] = 37; + SU2ToCGNS[120] = 7; + SU2ToCGNS[121] = 40; + SU2ToCGNS[122] = 39; + SU2ToCGNS[123] = 38; + SU2ToCGNS[124] = 6; } #endif diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp index 379176ad6c9..53697f65958 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp @@ -29,8 +29,7 @@ #include "../../../include/toolboxes/CLinearPartitioner.hpp" #include "../../../include/geometry/meshreader/CCGNSMeshReaderBase.hpp" -CCGNSMeshReaderBase::CCGNSMeshReaderBase(const CConfig* val_config, unsigned short val_iZone, - unsigned short val_nZone) +CCGNSMeshReaderBase::CCGNSMeshReaderBase(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) : CMeshReaderBase(val_config, val_iZone, val_nZone) { #ifdef HAVE_CGNS /*--- Leave the option to do something in the future here. ---*/ @@ -355,42 +354,75 @@ string CCGNSMeshReaderBase::GetCGNSElementType(ElementType_t val_elem_type, int& val_vtk_type = 1; SU2_MPI::Error("Vertex elements detected. Please remove.", CURRENT_FUNCTION); break; - case BAR_2: case BAR_3: case BAR_4: case BAR_5: + case BAR_2: + case BAR_3: + case BAR_4: + case BAR_5: elem_name = "Line"; val_vtk_type = 3; - if (dimension == 3) - SU2_MPI::Error("Line elements detected in a 3D mesh. Please remove.", - CURRENT_FUNCTION); + if (dimension == 3) SU2_MPI::Error("Line elements detected in a 3D mesh. Please remove.", CURRENT_FUNCTION); break; - case TRI_3: case TRI_6: case TRI_9: case TRI_10: - case TRI_12: case TRI_15: + case TRI_3: + case TRI_6: + case TRI_9: + case TRI_10: + case TRI_12: + case TRI_15: elem_name = "Triangle"; val_vtk_type = 5; break; - case QUAD_4: case QUAD_8: case QUAD_9: case QUAD_12: - case QUAD_16: case QUAD_P4_16: case QUAD_25: + case QUAD_4: + case QUAD_8: + case QUAD_9: + case QUAD_12: + case QUAD_16: + case QUAD_P4_16: + case QUAD_25: elem_name = "Quadrilateral"; val_vtk_type = 9; break; - case TETRA_4: case TETRA_10: case TETRA_16: case TETRA_20: - case TETRA_22: case TETRA_34: case TETRA_35: + case TETRA_4: + case TETRA_10: + case TETRA_16: + case TETRA_20: + case TETRA_22: + case TETRA_34: + case TETRA_35: elem_name = "Tetrahedron"; val_vtk_type = 10; break; - case HEXA_8: case HEXA_20: case HEXA_27: case HEXA_32: - case HEXA_56: case HEXA_64: case HEXA_44: case HEXA_98: + case HEXA_8: + case HEXA_20: + case HEXA_27: + case HEXA_32: + case HEXA_56: + case HEXA_64: + case HEXA_44: + case HEXA_98: case HEXA_125: elem_name = "Hexahedron"; val_vtk_type = 12; break; - case PENTA_6: case PENTA_15: case PENTA_18: case PENTA_24: - case PENTA_38: case PENTA_40: case PENTA_33: case PENTA_66: + case PENTA_6: + case PENTA_15: + case PENTA_18: + case PENTA_24: + case PENTA_38: + case PENTA_40: + case PENTA_33: + case PENTA_66: case PENTA_75: elem_name = "Prism"; val_vtk_type = 13; break; - case PYRA_5: case PYRA_14: case PYRA_13: case PYRA_21: - case PYRA_29: case PYRA_30: case PYRA_P4_29: case PYRA_50: + case PYRA_5: + case PYRA_14: + case PYRA_13: + case PYRA_21: + case PYRA_29: + case PYRA_30: + case PYRA_P4_29: + case PYRA_50: case PYRA_55: elem_name = "Pyramid"; val_vtk_type = 14; diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp index 48c0b267cfb..1d2c1f22f01 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp @@ -30,8 +30,7 @@ #include "../../../include/geometry/meshreader/CCGNSMeshReaderFEM.hpp" #include "../../../include/geometry/meshreader/CCGNSElementType.hpp" -CCGNSMeshReaderFEM::CCGNSMeshReaderFEM(const CConfig* val_config, unsigned short val_iZone, - unsigned short val_nZone) +CCGNSMeshReaderFEM::CCGNSMeshReaderFEM(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) : CCGNSMeshReaderBase(val_config, val_iZone, val_nZone) { #ifdef HAVE_CGNS OpenCGNSFile(config->GetMesh_FileName()); @@ -65,65 +64,59 @@ CCGNSMeshReaderFEM::CCGNSMeshReaderFEM(const CConfig* val_config, unsigned short CCGNSMeshReaderFEM::~CCGNSMeshReaderFEM() = default; #ifdef HAVE_CGNS -void CCGNSMeshReaderFEM::ReadCGNSConnectivityRangeSection(const int val_section, - const unsigned long val_firstIndex, - const unsigned long val_lastIndex, - unsigned long &elemCount, - unsigned long &localElemCount, - vector &localConn) { - +void CCGNSMeshReaderFEM::ReadCGNSConnectivityRangeSection(const int val_section, const unsigned long val_firstIndex, + const unsigned long val_lastIndex, unsigned long& elemCount, + unsigned long& localElemCount, + vector& localConn) { /*--- Read the connectivity details for this section. ---*/ int nbndry, parent_flag; cgsize_t startE, endE; ElementType_t elemType; char sectionName[CGNS_STRING_SIZE]; - if(cg_section_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, sectionName, - &elemType, &startE, &endE, &nbndry, &parent_flag)) + if (cg_section_read(cgnsFileID, cgnsBase, cgnsZone, val_section + 1, sectionName, &elemType, &startE, &endE, &nbndry, + &parent_flag)) cg_error_exit(); /*--- Determine the number of elements in this section and update the element counters accordingly. ---*/ - const unsigned long nElemSection = (endE-startE+1); + const unsigned long nElemSection = (endE - startE + 1); const unsigned long elemCountOld = elemCount; elemCount += nElemSection; /*--- Check for overlap with the element range this rank is responsible for. ---*/ const unsigned long indBegOverlap = max(elemCountOld, val_firstIndex); - const unsigned long indEndOverlap = min(elemCount, val_lastIndex); - - if(indEndOverlap > indBegOverlap) { + const unsigned long indEndOverlap = min(elemCount, val_lastIndex); + if (indEndOverlap > indBegOverlap) { /*--- This rank must read element data from this connectivity section. Determine the offset relative to the start of this section and the number of elements to be read by this rank. ---*/ const unsigned long offsetRank = indBegOverlap - elemCountOld; - const unsigned long nElemRank = indEndOverlap - indBegOverlap; + const unsigned long nElemRank = indEndOverlap - indBegOverlap; nElems[val_section] = nElemRank; /*--- Determine the index range to be read for this rank. ---*/ const cgsize_t iBeg = startE + offsetRank; - const cgsize_t iEnd = iBeg + nElemRank -1; + const cgsize_t iEnd = iBeg + nElemRank - 1; /*--- Determine the size of the vector needed to read the connectivity data from the CGNS file. ---*/ cgsize_t sizeNeeded; - if (cg_ElementPartialSize(cgnsFileID, cgnsBase, cgnsZone, val_section+1, - iBeg, iEnd, &sizeNeeded) != CG_OK) + if (cg_ElementPartialSize(cgnsFileID, cgnsBase, cgnsZone, val_section + 1, iBeg, iEnd, &sizeNeeded) != CG_OK) cg_error_exit(); /*--- Allocate the memory for the connectivity and read the data. ---*/ vector connCGNSVec(sizeNeeded); if (elemType == MIXED) { - vector connCGNSOffsetVec(iEnd-iBeg+2); - if(cg_poly_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, - iBeg, iEnd, connCGNSVec.data(), - connCGNSOffsetVec.data(), NULL) != CG_OK) + vector connCGNSOffsetVec(iEnd - iBeg + 2); + if (cg_poly_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section + 1, iBeg, iEnd, connCGNSVec.data(), + connCGNSOffsetVec.data(), NULL) != CG_OK) cg_error_exit(); } else { - if(cg_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, - iBeg, iEnd, connCGNSVec.data(), NULL) != CG_OK) + if (cg_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section + 1, iBeg, iEnd, connCGNSVec.data(), + NULL) != CG_OK) cg_error_exit(); } @@ -132,15 +125,14 @@ void CCGNSMeshReaderFEM::ReadCGNSConnectivityRangeSection(const int CCGNSElementType CGNSElem; std::vector connSU2; ElementType_t typeElem = elemType; - const cgsize_t *connCGNS = connCGNSVec.data(); + const cgsize_t* connCGNS = connCGNSVec.data(); /*--- Loop over the elements just read. ---*/ - for(unsigned long i=0; i SINGLE_NODE) @@ -168,33 +159,29 @@ void CCGNSMeshReaderFEM::ReadCGNSVolumeElementConnectivity(void) { } /*--- Get a partitioner to help with linear partitioning. ---*/ - CLinearPartitioner elemPartitioner(numberOfGlobalElements,0); + CLinearPartitioner elemPartitioner(numberOfGlobalElements, 0); /*--- Determine the index of the first and last element to be stored on this rank and the number of local elements. ---*/ const unsigned long firstIndex = elemPartitioner.GetFirstIndexOnRank(rank); - const unsigned long lastIndex = elemPartitioner.GetLastIndexOnRank(rank); + const unsigned long lastIndex = elemPartitioner.GetLastIndexOnRank(rank); numberOfLocalElements = elemPartitioner.GetSizeOnRank(rank); /*--- Loop over the section and check for a section with volume elements. ---*/ unsigned long elemCount = 0, localElemCount = 0; - for(int s=0; s localFaces; @@ -213,19 +200,16 @@ void CCGNSMeshReaderFEM::ReadCGNSSurfaceElementConnectivity(void) { /*--- Loop over the number of sections and check for a surface. ---*/ int markerCount = 0; - for(int s=0; s &localFaces, - unsigned long &nSurfElem, - vector &surfConn) { - +void CCGNSMeshReaderFEM::ReadCGNSSurfaceSection(const int val_section, const vector& localFaces, + unsigned long& nSurfElem, vector& surfConn) { /*--- Initialize nSurfElem to zero. ---*/ nSurfElem = 0; @@ -249,46 +230,43 @@ void CCGNSMeshReaderFEM::ReadCGNSSurfaceSection(const int val ElementType_t elemType; char sectionName[CGNS_STRING_SIZE]; - if(cg_section_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, sectionName, - &elemType, &startE, &endE, &nbndry, &parent_flag)) + if (cg_section_read(cgnsFileID, cgnsBase, cgnsZone, val_section + 1, sectionName, &elemType, &startE, &endE, &nbndry, + &parent_flag)) cg_error_exit(); - const unsigned long nElemSection = (endE-startE+1); + const unsigned long nElemSection = (endE - startE + 1); /*--- Determine the number of chunks used for the reading of the surface elements. This is done to avoid a memory bottleneck for extremely big cases. For reasonably sized grids this connectivity can be read in a single call. ---*/ - unsigned long nChunks = nElemSection/localFaces.size(); - if(nChunks*localFaces.size() != nElemSection) ++nChunks; - const unsigned long nElemChunk = nElemSection/nChunks; + unsigned long nChunks = nElemSection / localFaces.size(); + if (nChunks * localFaces.size() != nElemSection) ++nChunks; + const unsigned long nElemChunk = nElemSection / nChunks; /*--- Loop over the number of chunks. ---*/ - for(unsigned long iChunk=0; iChunk connCGNSVec(sizeNeeded); if (elemType == MIXED) { - vector connCGNSOffsetVec(iEnd-iBeg+2); - if(cg_poly_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, - iBeg, iEnd, connCGNSVec.data(), - connCGNSOffsetVec.data(), NULL) != CG_OK) + vector connCGNSOffsetVec(iEnd - iBeg + 2); + if (cg_poly_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section + 1, iBeg, iEnd, connCGNSVec.data(), + connCGNSOffsetVec.data(), NULL) != CG_OK) cg_error_exit(); } else { - if(cg_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section+1, - iBeg, iEnd, connCGNSVec.data(), NULL) != CG_OK) + if (cg_elements_partial_read(cgnsFileID, cgnsBase, cgnsZone, val_section + 1, iBeg, iEnd, connCGNSVec.data(), + NULL) != CG_OK) cg_error_exit(); } @@ -297,72 +275,70 @@ void CCGNSMeshReaderFEM::ReadCGNSSurfaceSection(const int val CCGNSElementType CGNSElem; std::vector connSU2; ElementType_t typeElem = elemType; - const cgsize_t *connCGNS = connCGNSVec.data(); + const cgsize_t* connCGNS = connCGNSVec.data(); /*--- Loop over the elements just read. ---*/ - for(cgsize_t i=iBeg; i<=iEnd; ++i) { - + for (cgsize_t i = iBeg; i <= iEnd; ++i) { /*--- Determine the element type for this element if this is a mixed connectivity and set the pointer to the actual connectivity data. ---*/ - if(elemType == MIXED) { - typeElem = (ElementType_t) connCGNS[0]; + if (elemType == MIXED) { + typeElem = (ElementType_t)connCGNS[0]; ++connCGNS; } /*--- Convert the CGNS connectivity to SU2 connectivity and update the pointer for the next surface element. ---*/ - const unsigned long globalID = i-1; + const unsigned long globalID = i - 1; CGNSElem.CGNSToSU2(typeElem, globalID, connCGNS, connSU2); connCGNS += connSU2[3]; /*--- Easier storage of the VTK type, polynomial degree and number of DOFs of the surface element. ---*/ - const unsigned short VTK_Type = (unsigned short) connSU2[0]; - const unsigned short nPolyGrid = (unsigned short) connSU2[1]; - const unsigned short nDOFsGrid = (unsigned short) connSU2[3]; + const unsigned short VTK_Type = (unsigned short)connSU2[0]; + const unsigned short nPolyGrid = (unsigned short)connSU2[1]; + const unsigned short nDOFsGrid = (unsigned short)connSU2[3]; /*--- Make a distinction between the possible element surface types and determine the corner points in local numbering of the element. ---*/ const unsigned short nDOFEdgeGrid = nPolyGrid + 1; CFaceOfElement thisFace; - thisFace.cornerPoints[0] = 0; thisFace.cornerPoints[1] = nPolyGrid; + thisFace.cornerPoints[0] = 0; + thisFace.cornerPoints[1] = nPolyGrid; - switch( VTK_Type ) { + switch (VTK_Type) { case LINE: thisFace.nCornerPoints = 2; break; case TRIANGLE: thisFace.nCornerPoints = 3; - thisFace.cornerPoints[2] = nDOFsGrid -1; + thisFace.cornerPoints[2] = nDOFsGrid - 1; break; case QUADRILATERAL: thisFace.nCornerPoints = 4; - thisFace.cornerPoints[2] = nPolyGrid*nDOFEdgeGrid; - thisFace.cornerPoints[3] = nDOFsGrid -1; + thisFace.cornerPoints[2] = nPolyGrid * nDOFEdgeGrid; + thisFace.cornerPoints[3] = nDOFsGrid - 1; break; default: ostringstream message; - message << "Unsupported FEM boundary element value, " << typeElem - << ", in surface section " << sectionName; + message << "Unsupported FEM boundary element value, " << typeElem << ", in surface section " << sectionName; SU2_MPI::Error(message.str(), CURRENT_FUNCTION); } /*--- Convert the local numbering of thisFace to global numbering and create a unique numbering of corner points. ---*/ - for(unsigned short j=0; j::const_iterator low; low = lower_bound(localFaces.begin(), localFaces.end(), thisFace); - if(low != localFaces.end()) { - if( !(thisFace < *low) ) { - + if (low != localFaces.end()) { + if (!(thisFace < *low)) { /*--- Update the number of local surface elements. ---*/ ++nSurfElem; @@ -383,24 +359,22 @@ void CCGNSMeshReaderFEM::ReadCGNSSurfaceSection(const int val #endif void CCGNSMeshReaderFEM::CommPointCoordinates(void) { - /*--- Determine the linear partitioning of the points. ---*/ - CLinearPartitioner pointPartitioner(numberOfGlobalPoints,0); + CLinearPartitioner pointPartitioner(numberOfGlobalPoints, 0); /*--- Loop over the local elements to determine the global point IDs to be stored on this rank. --*/ unsigned long ind = 0; - for(unsigned long i=0; i > pointBuf(size, vector(0)); - for(unsigned long i=0; i sendToRank(size, 0); - vector startingIndRanksInPoint(size+1); + vector startingIndRanksInPoint(size + 1); startingIndRanksInPoint[0] = 0; - for(int i=0; i sizeRecv(size, 1); - SU2_MPI::Reduce_scatter(sendToRank.data(), &nRankRecv, sizeRecv.data(), - MPI_INT, MPI_SUM, SU2_MPI::GetComm()); + SU2_MPI::Reduce_scatter(sendToRank.data(), &nRankRecv, sizeRecv.data(), MPI_INT, MPI_SUM, SU2_MPI::GetComm()); /*--- Send out the messages with the global point numbers. Use nonblocking sends to avoid deadlock. ---*/ vector sendReqs(nRankSend); nRankSend = 0; - for(int i=0; i pointRecvBuf(sizeMess); - coorReturnBuf[i].resize(dimension*sizeMess); + coorReturnBuf[i].resize(dimension * sizeMess); /* Receive the message using a blocking receive. */ - SU2_MPI::Recv(pointRecvBuf.data(), sizeMess, MPI_UNSIGNED_LONG, - source, rank, SU2_MPI::GetComm(), &status); + SU2_MPI::Recv(pointRecvBuf.data(), sizeMess, MPI_UNSIGNED_LONG, source, rank, SU2_MPI::GetComm(), &status); /*--- Loop over the nodes just received and fill the return communication buffer with the coordinates of the requested nodes. ---*/ - for(int j=0; j= static_cast(nPointsRead)) + if (kk < 0 || kk >= static_cast(nPointsRead)) SU2_MPI::Error("Invalid point requested. This should not happen.", CURRENT_FUNCTION); - for(int k=0; k coorRecvBuf(dimension*pointBuf[source].size()); + vector coorRecvBuf(dimension * pointBuf[source].size()); /* Receive the message using a blocking receive. */ - SU2_MPI::Recv(coorRecvBuf.data(), coorRecvBuf.size(), MPI_DOUBLE, - source, rank+1, SU2_MPI::GetComm(), &status); + SU2_MPI::Recv(coorRecvBuf.data(), coorRecvBuf.size(), MPI_DOUBLE, source, rank + 1, SU2_MPI::GetComm(), &status); /*--- Loop over the points just received. ---*/ - for(unsigned long j=0; jGetMesh_FileName()); diff --git a/Common/src/geometry/meshreader/CMeshReaderBase.cpp b/Common/src/geometry/meshreader/CMeshReaderBase.cpp index 478aa9dc2e3..bb20e0d97b9 100644 --- a/Common/src/geometry/meshreader/CMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CMeshReaderBase.cpp @@ -31,30 +31,27 @@ CMeshReaderBase::CMeshReaderBase(const CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) : rank(SU2_MPI::GetRank()), size(SU2_MPI::GetSize()), config(val_config) {} -void CMeshReaderBase::DetermineFacesVolumeElements(vector &localFaces) { - +void CMeshReaderBase::DetermineFacesVolumeElements(vector& localFaces) { /*--- Loop over the locally stored volume elements. ---*/ unsigned long ind = 0; - for(unsigned long k=0; k &local } /*--- Update the index for the next element. ---*/ - const unsigned long nDOFsGrid = localVolumeElementConnectivity[ind+3]; - ind += nDOFsGrid+5; + const unsigned long nDOFsGrid = localVolumeElementConnectivity[ind + 3]; + ind += nDOFsGrid + 5; } /*--- Sort localFaces in increasing order and remove the double entities, @@ -74,29 +71,25 @@ void CMeshReaderBase::DetermineFacesVolumeElements(vector &local localFaces.erase(lastFace, localFaces.end()); } -void CMeshReaderBase::GetCornerPointsAllFaces(const unsigned long *elemInfo, - unsigned short &numFaces, - unsigned short nPointsPerFace[], - unsigned long faceConn[6][4]) { - +void CMeshReaderBase::GetCornerPointsAllFaces(const unsigned long* elemInfo, unsigned short& numFaces, + unsigned short nPointsPerFace[], unsigned long faceConn[6][4]) { /*--- Retrieve the element type, polynomial degree of the grid and number of DOFs for this element and set the pointer for the connectivity information. ---*/ - const unsigned short VTK_Type = (const unsigned short) elemInfo[0]; - const unsigned short nPolyGrid = (const unsigned short) elemInfo[1]; - const unsigned short nDOFsGrid = (const unsigned short) elemInfo[3]; - const unsigned long *conn = elemInfo + 5; + const unsigned short VTK_Type = (const unsigned short)elemInfo[0]; + const unsigned short nPolyGrid = (const unsigned short)elemInfo[1]; + const unsigned short nDOFsGrid = (const unsigned short)elemInfo[3]; + const unsigned long* conn = elemInfo + 5; /*--- Call the static function GetLocalCornerPointsAllFaces of CPrimalGridFEM to determine the local numbering of the corner points of the faces. ---*/ - CPrimalGridFEM::GetLocalCornerPointsAllFaces(VTK_Type, nPolyGrid, nDOFsGrid, - numFaces, nPointsPerFace, faceConn); + CPrimalGridFEM::GetLocalCornerPointsAllFaces(VTK_Type, nPolyGrid, nDOFsGrid, numFaces, nPointsPerFace, faceConn); /*--- Convert the local values of faceConn to global values. ---*/ - for(unsigned short i=0; i(rank)) { - + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[0].push_back(KindBound); // VTK type. @@ -184,7 +174,7 @@ void CRectangularMeshReaderFEM::ComputeRectangularSurfaceConnectivity() { surfaceElementConnectivity[0].push_back(globalElemID); // Global volume element ID. surfaceElementConnectivity[0].push_back(iNode); - surfaceElementConnectivity[0].push_back(iNode+1); + surfaceElementConnectivity[0].push_back(iNode + 1); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[0]; @@ -194,13 +184,11 @@ void CRectangularMeshReaderFEM::ComputeRectangularSurfaceConnectivity() { /*--- Loop over all faces on the xMax (= iMax) boundary. ---*/ markerNames[1] = "x_plus"; - for(unsigned long jNode = 0; jNode < mNode-1; ++jNode) { - + for (unsigned long jNode = 0; jNode < mNode - 1; ++jNode) { /*--- Determine the corresponding global element ID and check if it is stored on this rank. ---*/ - const unsigned long globalElemID = jNode*nElemI + nElemI-1; - if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { - + const unsigned long globalElemID = jNode * nElemI + nElemI - 1; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[1].push_back(KindBound); // VTK type. @@ -209,8 +197,8 @@ void CRectangularMeshReaderFEM::ComputeRectangularSurfaceConnectivity() { surfaceElementConnectivity[1].push_back(jNode); // Global surface element ID. surfaceElementConnectivity[1].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[1].push_back(jNode*nNode + (nNode-1)); - surfaceElementConnectivity[1].push_back((jNode+1)*nNode + (nNode-1)); + surfaceElementConnectivity[1].push_back(jNode * nNode + (nNode - 1)); + surfaceElementConnectivity[1].push_back((jNode + 1) * nNode + (nNode - 1)); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[1]; @@ -220,13 +208,11 @@ void CRectangularMeshReaderFEM::ComputeRectangularSurfaceConnectivity() { /*--- Loop over all faces on the yMax (= jMax) boundary. ---*/ markerNames[2] = "y_plus"; - for (unsigned long iNode = 0; iNode < nNode-1; ++iNode) { - - /*--- Determine the corresponding global element ID and check - if it is stored on this rank. ---*/ - const unsigned long globalElemID = (mNode-2)*nElemI + iNode; - if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { - + for (unsigned long iNode = 0; iNode < nNode - 1; ++iNode) { + /*--- Determine the corresponding global element ID and check + if it is stored on this rank. ---*/ + const unsigned long globalElemID = (mNode - 2) * nElemI + iNode; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[2].push_back(KindBound); // VTK type. @@ -235,8 +221,8 @@ void CRectangularMeshReaderFEM::ComputeRectangularSurfaceConnectivity() { surfaceElementConnectivity[2].push_back(iNode); // Global surface element ID. surfaceElementConnectivity[2].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[2].push_back((mNode-1)*nNode + iNode+1); - surfaceElementConnectivity[2].push_back((mNode-1)*nNode + iNode); + surfaceElementConnectivity[2].push_back((mNode - 1) * nNode + iNode + 1); + surfaceElementConnectivity[2].push_back((mNode - 1) * nNode + iNode); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[2]; @@ -246,13 +232,11 @@ void CRectangularMeshReaderFEM::ComputeRectangularSurfaceConnectivity() { /*--- Loop over all faces on the xMin (= iMin) boundary. ---*/ markerNames[3] = "x_minus"; - for(unsigned long jNode = 0; jNode < mNode-1; ++jNode) { - + for (unsigned long jNode = 0; jNode < mNode - 1; ++jNode) { /*--- Determine the corresponding global element ID and check if it is stored on this rank. ---*/ - const unsigned long globalElemID = jNode*nElemI; - if(elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { - + const unsigned long globalElemID = jNode * nElemI; + if (elemPartitioner.GetRankContainingIndex(globalElemID) == static_cast(rank)) { /*--- The corresponding volume element is stored on this rank, hence store the surface element as well. ---*/ surfaceElementConnectivity[3].push_back(KindBound); // VTK type. @@ -261,8 +245,8 @@ void CRectangularMeshReaderFEM::ComputeRectangularSurfaceConnectivity() { surfaceElementConnectivity[3].push_back(jNode); // Global surface element ID. surfaceElementConnectivity[3].push_back(globalElemID); // Global volume element ID. - surfaceElementConnectivity[3].push_back((jNode+1)*nNode); - surfaceElementConnectivity[3].push_back(jNode*nNode); + surfaceElementConnectivity[3].push_back((jNode + 1) * nNode); + surfaceElementConnectivity[3].push_back(jNode * nNode); /*--- Update the number of surface elements for this marker. ---*/ ++numberOfLocalSurfaceElements[3]; diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp index 1802cc9233e..d5087e6d2de 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp @@ -33,8 +33,7 @@ CSU2ASCIIMeshReaderBase::CSU2ASCIIMeshReaderBase(CConfig* val_config, unsigned s : CMeshReaderBase(val_config, val_iZone, val_nZone), myZone(val_iZone), nZones(val_nZone), - meshFilename(config->GetMesh_FileName()) { -} + meshFilename(config->GetMesh_FileName()) {} CSU2ASCIIMeshReaderBase::~CSU2ASCIIMeshReaderBase(void) = default; diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp index ec310aa35f2..f28ef82075b 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp @@ -30,10 +30,8 @@ #include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderFEM.hpp" #include "../../../include/fem/fem_standard_element.hpp" -CSU2ASCIIMeshReaderFEM::CSU2ASCIIMeshReaderFEM(CConfig *val_config, unsigned short val_iZone, - unsigned short val_nZone) +CSU2ASCIIMeshReaderFEM::CSU2ASCIIMeshReaderFEM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) : CSU2ASCIIMeshReaderBase(val_config, val_iZone, val_nZone) { - /* Read the basic metadata and perform some basic error checks. */ ReadMetadata(true, val_config); @@ -53,21 +51,19 @@ CSU2ASCIIMeshReaderFEM::CSU2ASCIIMeshReaderFEM(CConfig *val_config, unsigned sho CSU2ASCIIMeshReaderFEM::~CSU2ASCIIMeshReaderFEM() = default; void CSU2ASCIIMeshReaderFEM::ReadPointCoordinates() { - /*--- Loop over the local elements to determine the global point IDs to be stored on this rank. --*/ unsigned long ind = 0; - for(unsigned long i=0; i> nodeID; localVolumeElementConnectivity.push_back(nodeID); @@ -203,25 +191,20 @@ void CSU2ASCIIMeshReaderFEM::ReadVolumeElementConnectivity() { must be adapted. The reason is that compatability with the original SU2 format is maintained for linear elements, but for the FEM solver the nodes of the elements are stored row-wise. ---*/ - if(nPolyGrid == 1) { - switch( VTK_Type ) { - - case QUADRILATERAL: - swap(localVolumeElementConnectivity[ind+2], - localVolumeElementConnectivity[ind+3]); - break; - - case HEXAHEDRON: - swap(localVolumeElementConnectivity[ind+2], - localVolumeElementConnectivity[ind+3]); - swap(localVolumeElementConnectivity[ind+6], - localVolumeElementConnectivity[ind+7]); - break; - - case PYRAMID: - swap(localVolumeElementConnectivity[ind+2], - localVolumeElementConnectivity[ind+3]); - break; + if (nPolyGrid == 1) { + switch (VTK_Type) { + case QUADRILATERAL: + swap(localVolumeElementConnectivity[ind + 2], localVolumeElementConnectivity[ind + 3]); + break; + + case HEXAHEDRON: + swap(localVolumeElementConnectivity[ind + 2], localVolumeElementConnectivity[ind + 3]); + swap(localVolumeElementConnectivity[ind + 6], localVolumeElementConnectivity[ind + 7]); + break; + + case PYRAMID: + swap(localVolumeElementConnectivity[ind + 2], localVolumeElementConnectivity[ind + 3]); + break; } } } @@ -231,7 +214,6 @@ void CSU2ASCIIMeshReaderFEM::ReadVolumeElementConnectivity() { } void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { - /*--- Determine the vector to hold the faces of the local elements. ---*/ vector localFaces; DetermineFacesVolumeElements(localFaces); @@ -249,58 +231,57 @@ void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { /*--- Find the section containing the markers. ---*/ string text_line; - while (getline (mesh_file, text_line)) { - string::size_type position = text_line.find ("NMARK=",0); + while (getline(mesh_file, text_line)) { + string::size_type position = text_line.find("NMARK=", 0); if (position != string::npos) break; } /*--- Loop over the number of boundary markers. ---*/ - for(unsigned long iMarker=0; iMarker connFace(nDOFsGrid); - for(unsigned short j=0; j> connFace[j]; + for (unsigned short j = 0; j < nDOFsGrid; ++j) bound_line >> connFace[j]; /*--- If a linear quadrilateral is used, the node numbering must be adapted. The reason is that compatability with the original SU2 format is maintained for linear elements, but for the FEM solver the nodes of the elements are stored row-wise. ---*/ - if((nPolyGrid == 1) && (VTK_Type == QUADRILATERAL)) - swap(connFace[2], connFace[3]); + if ((nPolyGrid == 1) && (VTK_Type == QUADRILATERAL)) swap(connFace[2], connFace[3]); /*--- Convert the local numbering of thisFace to global numbering and create a unique numbering of corner points. ---*/ - for(unsigned short j=0; j::iterator low; low = lower_bound(localFaces.begin(), localFaces.end(), thisFace); - if(low != localFaces.end()) { - if( !(thisFace < *low) ) { - + if (low != localFaces.end()) { + if (!(thisFace < *low)) { /*--- Update the counter for this boundary marker and store the meta data in surfaceElementConnectivity. ---*/ ++numberOfLocalSurfaceElements[iMarker]; @@ -366,12 +345,12 @@ void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { surfaceElementConnectivity[iMarker].push_back(VTK_Type); surfaceElementConnectivity[iMarker].push_back(nPolyGrid); surfaceElementConnectivity[iMarker].push_back(nDOFsGrid); - surfaceElementConnectivity[iMarker].push_back(i); // Global surface elem ID. - surfaceElementConnectivity[iMarker].push_back(low->elemID0); // Global volume elem ID. + surfaceElementConnectivity[iMarker].push_back(i); // Global surface elem ID. + surfaceElementConnectivity[iMarker].push_back(low->elemID0); // Global volume elem ID. /*--- Copy the connectivity to surfaceElementConnectivity. ---*/ - surfaceElementConnectivity[iMarker].insert(surfaceElementConnectivity[iMarker].end(), - connFace.begin(), connFace.end()); + surfaceElementConnectivity[iMarker].insert(surfaceElementConnectivity[iMarker].end(), connFace.begin(), + connFace.end()); } } } diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp index 71fb595e0cb..8403c6af425 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp @@ -28,8 +28,7 @@ #include "../../../include/geometry/meshreader/CSU2ASCIIMeshReaderFVM.hpp" -CSU2ASCIIMeshReaderFVM::CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, - unsigned short val_nZone) +CSU2ASCIIMeshReaderFVM::CSU2ASCIIMeshReaderFVM(CConfig* val_config, unsigned short val_iZone, unsigned short val_nZone) : CSU2ASCIIMeshReaderBase(val_config, val_iZone, val_nZone) { actuator_disk = (((config->GetnMarker_ActDiskInlet() != 0) || (config->GetnMarker_ActDiskOutlet() != 0)) && ((config->GetKind_SU2() == SU2_COMPONENT::SU2_CFD) || diff --git a/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp b/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp index 562d6471cde..6b374960f46 100644 --- a/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp +++ b/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp @@ -27,24 +27,19 @@ #include "../../../include/geometry/primal_grid/CPrimalGridBoundFEM.hpp" -CPrimalGridBoundFEM::CPrimalGridBoundFEM(const unsigned long *dataElem) - :CPrimalGrid(true, dataElem[2], 1) -{ - +CPrimalGridBoundFEM::CPrimalGridBoundFEM(const unsigned long* dataElem) : CPrimalGrid(true, dataElem[2], 1) { /*--- Store the meta data for this element. ---*/ - VTK_Type = (unsigned short) dataElem[0]; - nPolyGrid = (unsigned short) dataElem[1]; - nDOFsGrid = (unsigned short) dataElem[2]; + VTK_Type = (unsigned short)dataElem[0]; + nPolyGrid = (unsigned short)dataElem[1]; + nDOFsGrid = (unsigned short)dataElem[2]; boundElemIDGlobal = dataElem[3]; - GlobalIndex_DomainElement = dataElem[4]; + GlobalIndex_DomainElement = dataElem[4]; /*--- Allocate the memory for the global nodes of the element to define the geometry and copy them from val_nodes. ---*/ - for(unsigned short i=0; i Date: Wed, 5 Feb 2025 17:27:11 +0100 Subject: [PATCH 126/129] Fixes from CodeQL --- Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp | 5 +++-- .../src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp | 2 +- Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp index 1d2c1f22f01..b9208f8ddd6 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp @@ -318,7 +318,8 @@ void CCGNSMeshReaderFEM::ReadCGNSSurfaceSection(const int val_section, const vec case QUADRILATERAL: thisFace.nCornerPoints = 4; - thisFace.cornerPoints[2] = nPolyGrid * nDOFEdgeGrid; + thisFace.cornerPoints[2] = static_cast (nPolyGrid) + * nDOFEdgeGrid; thisFace.cornerPoints[3] = nDOFsGrid - 1; break; @@ -456,7 +457,7 @@ void CCGNSMeshReaderFEM::CommPointCoordinates(void) { /*--- Allocate the memory for a buffer to receive this message and also for the buffer to return to coordinates. ---*/ vector pointRecvBuf(sizeMess); - coorReturnBuf[i].resize(dimension * sizeMess); + coorReturnBuf[i].resize(static_cast(dimension) * sizeMess); /* Receive the message using a blocking receive. */ SU2_MPI::Recv(pointRecvBuf.data(), sizeMess, MPI_UNSIGNED_LONG, source, rank, SU2_MPI::GetComm(), &status); diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp index d5087e6d2de..d8c524eff4c 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderBase.cpp @@ -393,7 +393,7 @@ void CSU2ASCIIMeshReaderBase::ReadSurfaceElementConnectivity(const bool single_p if (text_line.find("NMARK=", 0) == string::npos) continue; } - for (unsigned short iMarker = 0; iMarker < numberOfMarkers; ++iMarker) { + for (unsigned long iMarker = 0; iMarker < numberOfMarkers; ++iMarker) { getline(mesh_file, text_line); text_line.erase(0, 11); string::size_type position; diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp index f28ef82075b..e0ef76294a7 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp @@ -247,10 +247,9 @@ void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { /*--- Extract the marker name. Remove spaces returns and tabs and store the name in markerNames. ---*/ text_line.erase(0, 11); - string::size_type position; for (unsigned short iChar = 0; iChar < 20; iChar++) { - position = text_line.find(" ", 0); + auto position = text_line.find(" ", 0); if (position != string::npos) text_line.erase(position, 1); position = text_line.find("\r", 0); if (position != string::npos) text_line.erase(position, 1); @@ -262,7 +261,7 @@ void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { /*--- Find the section containing the number of surface elements for this marker and determine this number. ---*/ while (getline(mesh_file, text_line)) { - string::size_type position = text_line.find("MARKER_ELEMS=", 0); + auto position = text_line.find("MARKER_ELEMS=", 0); if (position != string::npos) break; } @@ -307,7 +306,8 @@ void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { case QUADRILATERAL: nDOFsGrid = nDOFEdgeGrid * nDOFEdgeGrid; thisFace.nCornerPoints = 4; - thisFace.cornerPoints[2] = nPolyGrid * nDOFEdgeGrid; + thisFace.cornerPoints[2] = static_cast(nPolyGrid) + * nDOFEdgeGrid; thisFace.cornerPoints[3] = nDOFsGrid - 1; break; From 6a659d7a078c791e700c518fe7da1863ed4aca3c Mon Sep 17 00:00:00 2001 From: vdweide Date: Wed, 5 Feb 2025 17:29:29 +0100 Subject: [PATCH 127/129] Result of running pre-commit --- Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp | 3 +-- Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp index b9208f8ddd6..3757a278478 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp @@ -318,8 +318,7 @@ void CCGNSMeshReaderFEM::ReadCGNSSurfaceSection(const int val_section, const vec case QUADRILATERAL: thisFace.nCornerPoints = 4; - thisFace.cornerPoints[2] = static_cast (nPolyGrid) - * nDOFEdgeGrid; + thisFace.cornerPoints[2] = static_cast(nPolyGrid) * nDOFEdgeGrid; thisFace.cornerPoints[3] = nDOFsGrid - 1; break; diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp index e0ef76294a7..78dc46b3f10 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFEM.cpp @@ -306,8 +306,7 @@ void CSU2ASCIIMeshReaderFEM::ReadSurfaceElementConnectivity() { case QUADRILATERAL: nDOFsGrid = nDOFEdgeGrid * nDOFEdgeGrid; thisFace.nCornerPoints = 4; - thisFace.cornerPoints[2] = static_cast(nPolyGrid) - * nDOFEdgeGrid; + thisFace.cornerPoints[2] = static_cast(nPolyGrid) * nDOFEdgeGrid; thisFace.cornerPoints[3] = nDOFsGrid - 1; break; From 53207abb9c032466787c1185c1e8832fe3335128 Mon Sep 17 00:00:00 2001 From: vdweide Date: Thu, 6 Feb 2025 09:57:34 +0100 Subject: [PATCH 128/129] Replaced the C-style cast by static_cast --- Common/src/fem/fem_geometry_structure.cpp | 36 +++++----- Common/src/fem/fem_standard_element.cpp | 8 +-- .../src/fem/geometry_structure_fem_part.cpp | 14 ++-- Common/src/geometry/CGeometry.cpp | 16 ++--- Common/src/geometry/CPhysicalGeometry.cpp | 70 +++++++++---------- .../geometry/meshreader/CBoxMeshReaderFVM.cpp | 6 +- .../meshreader/CCGNSMeshReaderBase.cpp | 2 +- .../meshreader/CCGNSMeshReaderFEM.cpp | 6 +- .../meshreader/CCGNSMeshReaderFVM.cpp | 24 +++---- .../meshreader/CRectangularMeshReaderFVM.cpp | 6 +- .../meshreader/CSU2ASCIIMeshReaderFVM.cpp | 24 +++---- .../primal_grid/CPrimalGridBoundFEM.cpp | 6 +- .../geometry/primal_grid/CPrimalGridFEM.cpp | 8 +-- 13 files changed, 113 insertions(+), 113 deletions(-) diff --git a/Common/src/fem/fem_geometry_structure.cpp b/Common/src/fem/fem_geometry_structure.cpp index e5580de752e..7a0b5177129 100644 --- a/Common/src/fem/fem_geometry_structure.cpp +++ b/Common/src/fem/fem_geometry_structure.cpp @@ -267,14 +267,14 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { map rankToIndCommBuf; for (int i = 0; i < size; ++i) { if (sendToRank[i]) { - int ind = (int)rankToIndCommBuf.size(); + int ind = static_cast(rankToIndCommBuf.size()); rankToIndCommBuf[i] = ind; } } /*--- Definition of the communication buffers, used to send the element data to the correct ranks. ---*/ - int nRankSend = (int)rankToIndCommBuf.size(); + int nRankSend = static_cast(rankToIndCommBuf.size()); vector > shortSendBuf(nRankSend, vector(0)); vector > longSendBuf(nRankSend, vector(0)); vector > doubleSendBuf(nRankSend, vector(0)); @@ -294,7 +294,7 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /*--- Loop over the local elements to fill the communication buffers with element data. ---*/ for (unsigned long i = 0; i < geometry->GetnElem(); ++i) { - int ind = (int)geometry->elem[i]->GetColor(); + int ind = static_cast(geometry->elem[i]->GetColor()); map::const_iterator MI = rankToIndCommBuf.find(ind); ind = MI->second; @@ -385,7 +385,7 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /* Determine to which rank this boundary element must be sent. That is the same as its corresponding domain element. Update the corresponding index in longSendBuf. */ - int ind = (int)geometry->elem[elemID]->GetColor(); + int ind = static_cast(geometry->elem[elemID]->GetColor()); const auto MI = rankToIndCommBuf.find(ind); ind = MI->second; @@ -566,8 +566,8 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { the elements with constant and non-constant Jacobians are considered the same. */ if (JacConstant) { - const auto orderExactStraight = (unsigned short)ceil(nPolySol * config->GetQuadrature_Factor_Straight()); - const auto orderExactCurved = (unsigned short)ceil(nPolySol * config->GetQuadrature_Factor_Curved()); + const auto orderExactStraight = static_cast(ceil(nPolySol * config->GetQuadrature_Factor_Straight())); + const auto orderExactCurved = static_cast(ceil(nPolySol * config->GetQuadrature_Factor_Curved())); if (orderExactStraight == orderExactCurved) JacConstant = false; } @@ -691,14 +691,14 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { rankToIndCommBuf.clear(); for (int i = 0; i < size; ++i) { if (sendToRank[i]) { - int ind = (int)rankToIndCommBuf.size(); + int ind = static_cast(rankToIndCommBuf.size()); rankToIndCommBuf[i] = ind; } } /* Resize the first index of the long send buffers for the communication of the halo data. */ - nRankSend = (int)rankToIndCommBuf.size(); + nRankSend = static_cast(rankToIndCommBuf.size()); longSendBuf.resize(nRankSend); /* Determine the number of ranks, from which this rank will receive elements. */ @@ -717,7 +717,7 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { if (*low > haloElements[i].long0) --ind; /* Convert this rank to the index in the send buffer. */ - MI = rankToIndCommBuf.find((int)ind); + MI = rankToIndCommBuf.find(static_cast(ind)); ind = MI->second; /* Store the global element ID and the periodic index in the long buffer. @@ -911,12 +911,12 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { for (int i = 0; i < size; ++i) { if (nHaloElemPerRank[i + 1] > nHaloElemPerRank[i]) { sendToRank[i] = 1; - int ind = (int)rankToIndCommBuf.size(); + int ind = static_cast(rankToIndCommBuf.size()); rankToIndCommBuf[i] = ind; } } - nRankSend = (int)rankToIndCommBuf.size(); + nRankSend = static_cast(rankToIndCommBuf.size()); /* Store the value of nRankSend for later use. */ const int nRankSendHaloInfo = nRankSend; @@ -1179,7 +1179,7 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /*--- Create the graph of local elements. The halo elements are ignored. ---*/ vector > neighElem(nVolElemOwned, vector(0)); - nRankRecv = (int)longRecvBuf.size(); + nRankRecv = static_cast(longRecvBuf.size()); for (int i = 0; i < nRankRecv; ++i) { unsigned long indL = 1, indS = 0; for (long j = 0; j < longRecvBuf[i][0]; ++j) { @@ -1452,7 +1452,7 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { /*--- Resize the first index of the send buffers to nRankRecv, because this number of messages must be sent back to the sending ranks with halo information. ---*/ - nRankRecv = (int)longSecondRecvBuf.size(); + nRankRecv = static_cast(longSecondRecvBuf.size()); shortSendBuf.resize(nRankRecv); longSendBuf.resize(nRankRecv); doubleSendBuf.resize(nRankRecv); @@ -2455,12 +2455,12 @@ void CMeshFEM_DG::CreateFaces(CConfig* config) { is set to false. Hence it is only needed to carry out this check for faces with a constant Jacobian. This is done to reduce the number of standard elements. */ if (thisFace.JacFaceIsConsideredConstant) { - auto orderExactStraight = (unsigned short)ceil(thisFace.nPolyGrid0 * config->GetQuadrature_Factor_Straight()); - auto orderExactCurved = (unsigned short)ceil(thisFace.nPolyGrid0 * config->GetQuadrature_Factor_Curved()); + auto orderExactStraight = static_cast(ceil(thisFace.nPolyGrid0 * config->GetQuadrature_Factor_Straight())); + auto orderExactCurved = static_cast(ceil(thisFace.nPolyGrid0 * config->GetQuadrature_Factor_Curved())); if (orderExactStraight == orderExactCurved) { - orderExactStraight = (unsigned short)ceil(thisFace.nPolySol0 * config->GetQuadrature_Factor_Straight()); - orderExactCurved = (unsigned short)ceil(thisFace.nPolySol0 * config->GetQuadrature_Factor_Curved()); + orderExactStraight = static_cast(ceil(thisFace.nPolySol0 * config->GetQuadrature_Factor_Straight())); + orderExactCurved = static_cast(ceil(thisFace.nPolySol0 * config->GetQuadrature_Factor_Curved())); if (orderExactStraight == orderExactCurved) thisFace.JacFaceIsConsideredConstant = false; } } @@ -3159,7 +3159,7 @@ void CMeshFEM_DG::SetSendReceive(const CConfig* config) { map rankToIndRecvBuf; for (int i = 0; i < size; ++i) { if (recvFromRank[i]) { - int ind = (int)rankToIndRecvBuf.size(); + int ind = static_cast(rankToIndRecvBuf.size()); rankToIndRecvBuf[i] = ind; } } diff --git a/Common/src/fem/fem_standard_element.cpp b/Common/src/fem/fem_standard_element.cpp index b24c7cacfaf..ab8e537ad9c 100644 --- a/Common/src/fem/fem_standard_element.cpp +++ b/Common/src/fem/fem_standard_element.cpp @@ -186,9 +186,9 @@ CFEMStandardElementBase::CFEMStandardElementBase(unsigned short val_VTK_Type, un orderExact = val_orderExact; } else { if (constJacobian) - orderExact = (unsigned short)ceil(val_nPoly * config->GetQuadrature_Factor_Straight()); + orderExact = static_cast(ceil(val_nPoly * config->GetQuadrature_Factor_Straight())); else - orderExact = (unsigned short)ceil(val_nPoly * config->GetQuadrature_Factor_Curved()); + orderExact = static_cast(ceil(val_nPoly * config->GetQuadrature_Factor_Curved())); } /*--- Determine the integration points. This depends on the element type. ---*/ @@ -903,7 +903,7 @@ void CFEMStandardElementBase::SubConnForPlottingLine(const unsigned short nPoly, /*--- Determine the local subconnectivity of the line element used for plotting purposes. This is rather trivial, because the line element is subdivided into nPoly linear line elements. ---*/ - unsigned short nnPoly = max(nPoly, (unsigned short)1); + unsigned short nnPoly = max(nPoly, static_cast(1)); for (unsigned short i = 0; i < nnPoly; ++i) { subConn.push_back(i); subConn.push_back(i + 1); @@ -916,7 +916,7 @@ void CFEMStandardElementBase::SubConnForPlottingQuadrilateral(const unsigned sho plotting purposes. Note that the connectivity of the linear subelements obey the VTK connectivity rule of a quadrilateral, which is different from the connectivity for the high order quadrilateral. ---*/ - unsigned short nnPoly = max(nPoly, (unsigned short)1); + unsigned short nnPoly = max(nPoly, static_cast(1)); for (unsigned short j = 0; j < nnPoly; ++j) { unsigned short jj = j * (nnPoly + 1); for (unsigned short i = 0; i < nnPoly; ++i) { diff --git a/Common/src/fem/geometry_structure_fem_part.cpp b/Common/src/fem/geometry_structure_fem_part.cpp index 1babb698f7d..a0309bf2233 100644 --- a/Common/src/fem/geometry_structure_fem_part.cpp +++ b/Common/src/fem/geometry_structure_fem_part.cpp @@ -609,7 +609,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { the points that occur in the faces of localFacesComm. ---*/ vector facePointsProc(size + 1, 0); unsigned long total_point_accounted = 0; - for (unsigned long i = 1; i <= (unsigned long)size; ++i) { + for (unsigned long i = 1; i <= static_cast(size); ++i) { facePointsProc[i] = maxPointID / size; total_point_accounted += facePointsProc[i]; } @@ -617,7 +617,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { unsigned long rem_point = maxPointID - total_point_accounted; for (unsigned long i = 1; i <= rem_point; ++i) ++facePointsProc[i]; - for (unsigned long i = 0; i < (unsigned long)size; ++i) facePointsProc[i + 1] += facePointsProc[i]; + for (unsigned long i = 0; i < static_cast(size); ++i) facePointsProc[i + 1] += facePointsProc[i]; /*--- Determine the number of faces that has to be sent to each rank. Note that the rank is stored in elemID1, such that the search @@ -637,7 +637,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { vector sendBufFace(9 * nFacesLocComm); vector counter(size); counter[0] = 0; - for (unsigned long i = 1; i < (unsigned long)size; ++i) counter[i] = counter[i - 1] + 9 * nFacesComm[i - 1]; + for (unsigned long i = 1; i < static_cast(size); ++i) counter[i] = counter[i - 1] + 9 * nFacesComm[i - 1]; for (unsigned long i = 0; i < nFacesLocComm; ++i) { unsigned long rankFace = localFacesComm[i].elemID1; @@ -657,7 +657,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { /*--- Determine the number of ranks from which I receive a message. */ unsigned long nMessSend = 0; - for (unsigned long i = 0; i < (unsigned long)size; ++i) { + for (unsigned long i = 0; i < static_cast(size); ++i) { if (nFacesComm[i]) { counter[i] = 1; ++nMessSend; @@ -674,7 +674,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { nMessSend = 0; unsigned long indSend = 0; - for (unsigned long i = 0; i < (unsigned long)size; ++i) { + for (unsigned long i = 0; i < static_cast(size); ++i) { if (nFacesComm[i]) { unsigned long count = 9 * nFacesComm[i]; SU2_MPI::Isend(&sendBufFace[indSend], count, MPI_UNSIGNED_LONG, i, i, SU2_MPI::GetComm(), &commReqs[nMessSend]); @@ -792,7 +792,7 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { sizeMess /= 9; unsigned long jj = 0; - for (unsigned long j = 0; j < (unsigned long)sizeMess; ++j, jj += 9) { + for (unsigned long j = 0; j < static_cast(sizeMess); ++j, jj += 9) { CFaceOfElement thisFace; thisFace.nCornerPoints = recvBuf[jj]; thisFace.cornerPoints[0] = recvBuf[jj + 1]; @@ -2240,7 +2240,7 @@ void CPhysicalGeometry::DetermineDonorElementsWallFunctions(CConfig* config) { carried out for each rank and store them in such a way that the info can be used directly in Allgatherv. */ vector recvCounts(size), displs(size); - int nLocalSearchPoints = (int)markerIDGlobalSearch.size(); + int nLocalSearchPoints = static_cast(markerIDGlobalSearch.size()); SU2_MPI::Allgather(&nLocalSearchPoints, 1, MPI_INT, recvCounts.data(), 1, MPI_INT, SU2_MPI::GetComm()); displs[0] = 0; diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index cf1a6948c5f..e771960b638 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -183,8 +183,8 @@ void CGeometry::PreprocessP2PComms(CGeometry* geometry, CConfig* config) { /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - if ((nPoint_Flag[iRank] != (int)iMarker)) { - nPoint_Flag[iRank] = (int)iMarker; + if ((nPoint_Flag[iRank] != static_cast(iMarker))) { + nPoint_Flag[iRank] = static_cast(iMarker); nPoint_Send_All[iRank + 1] += nVertexS; } } @@ -819,13 +819,13 @@ void CGeometry::PreprocessPeriodicComms(CGeometry* geometry, CConfig* config) { /*--- Get the rank that holds the matching periodic point on the other marker in the periodic pair. ---*/ - iRank = (int)geometry->vertex[iMarker][iVertex]->GetDonorProcessor(); + iRank = static_cast(geometry->vertex[iMarker][iVertex]->GetDonorProcessor()); /*--- If we have not visited this point last, increment our number of points that must be sent to a particular proc. ---*/ - if ((nPoint_Flag[iRank] != (int)iPoint)) { - nPoint_Flag[iRank] = (int)iPoint; + if ((nPoint_Flag[iRank] != static_cast(iPoint))) { + nPoint_Flag[iRank] = static_cast(iPoint); nPoint_Send_All[iRank + 1] += 1; } } @@ -962,7 +962,7 @@ void CGeometry::PreprocessPeriodicComms(CGeometry* geometry, CConfig* config) { /*--- Get the rank that holds the matching periodic point on the other marker in the periodic pair. ---*/ - iRank = (int)geometry->vertex[iMarker][iVertex]->GetDonorProcessor(); + iRank = static_cast(geometry->vertex[iMarker][iVertex]->GetDonorProcessor()); /*--- If the rank for the current periodic point matches the rank of the current send message, then store the local point @@ -971,11 +971,11 @@ void CGeometry::PreprocessPeriodicComms(CGeometry* geometry, CConfig* config) { if (iRank == Neighbors_PeriodicSend[iSend]) { Local_Point_PeriodicSend[ii] = iPoint; - Local_Marker_PeriodicSend[ii] = (unsigned long)iMarker; + Local_Marker_PeriodicSend[ii] = static_cast(iMarker); jj = ii * nPackets; idSend[jj] = geometry->vertex[iMarker][iVertex]->GetDonorPoint(); jj++; - idSend[jj] = (unsigned long)iPeriodic; + idSend[jj] = static_cast(iPeriodic); ii++; } } diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index 20c2b247510..1c53744b191 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -547,8 +547,8 @@ void CPhysicalGeometry::DistributeColoring(const CConfig* config, CGeometry* geo /*--- If we have not visited this node yet, increment our number of points that must be sent to a particular proc. ---*/ - if (nPoint_Flag[iProcessor] != (int)iPoint) { - nPoint_Flag[iProcessor] = (int)iPoint; + if (nPoint_Flag[iProcessor] != static_cast(iPoint)) { + nPoint_Flag[iProcessor] = static_cast(iPoint); nPoint_Send[iProcessor + 1]++; } } @@ -607,8 +607,8 @@ void CPhysicalGeometry::DistributeColoring(const CConfig* config, CGeometry* geo /*--- If we have not visited this node yet, increment our counters and load up the global ID and color. ---*/ - if (nPoint_Flag[iProcessor] != (int)iPoint) { - nPoint_Flag[iProcessor] = (int)iPoint; + if (nPoint_Flag[iProcessor] != static_cast(iPoint)) { + nPoint_Flag[iProcessor] = static_cast(iPoint); unsigned long nn = index[iProcessor]; /*--- Load the data values. ---*/ @@ -780,8 +780,8 @@ void CPhysicalGeometry::DistributeVolumeConnectivity(const CConfig* config, CGeo /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - if ((nElem_Flag[iProcessor] != (int)iElem)) { - nElem_Flag[iProcessor] = (int)iElem; + if ((nElem_Flag[iProcessor] != static_cast(iElem))) { + nElem_Flag[iProcessor] = static_cast(iElem); nElem_Send[iProcessor + 1]++; } } @@ -847,8 +847,8 @@ void CPhysicalGeometry::DistributeVolumeConnectivity(const CConfig* config, CGeo /*--- Load connectivity and IDs into the buffer for sending ---*/ - if (nElem_Flag[iProcessor] != (int)iElem) { - nElem_Flag[iProcessor] = (int)iElem; + if (nElem_Flag[iProcessor] != static_cast(iElem)) { + nElem_Flag[iProcessor] = static_cast(iElem); unsigned long nn = index[iProcessor]; unsigned long mm = idIndex[iProcessor]; @@ -1071,8 +1071,8 @@ void CPhysicalGeometry::DistributePoints(const CConfig* config, CGeometry* geome /*--- If we have not visited this node yet, increment our number of points that must be sent to a particular proc. ---*/ - if (nPoint_Flag[iProcessor] != (int)iPoint) { - nPoint_Flag[iProcessor] = (int)iPoint; + if (nPoint_Flag[iProcessor] != static_cast(iPoint)) { + nPoint_Flag[iProcessor] = static_cast(iPoint); nPoint_Send[iProcessor + 1]++; } } @@ -1140,8 +1140,8 @@ void CPhysicalGeometry::DistributePoints(const CConfig* config, CGeometry* geome /*--- If we have not visited this node yet, increment our counters and load up the colors, ids, and coords. ---*/ - if (nPoint_Flag[iProcessor] != (int)iPoint) { - nPoint_Flag[iProcessor] = (int)iPoint; + if (nPoint_Flag[iProcessor] != static_cast(iPoint)) { + nPoint_Flag[iProcessor] = static_cast(iPoint); unsigned long nn = index[iProcessor]; /*--- Load the global ID, color, and coordinate values. ---*/ @@ -1248,7 +1248,7 @@ void CPhysicalGeometry::DistributePoints(const CConfig* config, CGeometry* geome Local_Points[iRecv] = idRecv[iRecv]; Local_Colors[iRecv] = colorRecv[iRecv]; for (iDim = 0; iDim < nDim; iDim++) Local_Coords[iRecv * nDim + iDim] = coordRecv[iRecv * nDim + iDim]; - if (Local_Colors[iRecv] == (unsigned long)rank) + if (Local_Colors[iRecv] == static_cast(rank)) nLocal_PointDomain++; else nLocal_PointGhost++; @@ -1359,8 +1359,8 @@ void CPhysicalGeometry::PartitionSurfaceConnectivity(CConfig* config, CGeometry* /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - if ((nElem_Flag[iProcessor] != (int)iElem)) { - nElem_Flag[iProcessor] = (int)iElem; + if ((nElem_Flag[iProcessor] != static_cast(iElem))) { + nElem_Flag[iProcessor] = static_cast(iElem); nElem_Send[iProcessor + 1]++; } } @@ -1440,8 +1440,8 @@ void CPhysicalGeometry::PartitionSurfaceConnectivity(CConfig* config, CGeometry* /*--- Load connectivity into the buffer for sending ---*/ - if ((nElem_Flag[iProcessor] != (int)iElem)) { - nElem_Flag[iProcessor] = (int)iElem; + if ((nElem_Flag[iProcessor] != static_cast(iElem))) { + nElem_Flag[iProcessor] = static_cast(iElem); unsigned long nn = index[iProcessor]; unsigned long mm = markerIndex[iProcessor]; @@ -1712,8 +1712,8 @@ void CPhysicalGeometry::DistributeSurfaceConnectivity(CConfig* config, CGeometry /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - if ((nElem_Flag[iProcessor] != (int)iElem)) { - nElem_Flag[iProcessor] = (int)iElem; + if ((nElem_Flag[iProcessor] != static_cast(iElem))) { + nElem_Flag[iProcessor] = static_cast(iElem); nElem_Send[iProcessor + 1]++; } } @@ -1781,8 +1781,8 @@ void CPhysicalGeometry::DistributeSurfaceConnectivity(CConfig* config, CGeometry /*--- If we have not visited this element yet, load up the data for sending. ---*/ - if (nElem_Flag[iProcessor] != (int)iElem) { - nElem_Flag[iProcessor] = (int)iElem; + if (nElem_Flag[iProcessor] != static_cast(iElem)) { + nElem_Flag[iProcessor] = static_cast(iElem); unsigned long nn = index[iProcessor]; unsigned long mm = markerIndex[iProcessor]; @@ -1990,7 +1990,7 @@ void CPhysicalGeometry::DistributeMarkerTags(CConfig* config, CGeometry* geometr /*--- Broadcast the string names of the variables. ---*/ - SU2_MPI::Bcast(mpi_str_buf, (int)nMarker_Global * MAX_STRING_SIZE, MPI_CHAR, MASTER_NODE, SU2_MPI::GetComm()); + SU2_MPI::Bcast(mpi_str_buf, static_cast(nMarker_Global) * MAX_STRING_SIZE, MPI_CHAR, MASTER_NODE, SU2_MPI::GetComm()); /*--- Now parse the string names and load into our marker tag vector. We also need to set the values of all markers into the config. ---*/ @@ -2042,7 +2042,7 @@ void CPhysicalGeometry::LoadPoints(CConfig* config, CGeometry* geometry) { for (iPoint = 0; iPoint < nPoint; iPoint++) { /*--- Set the starting point to the correct counter for this point. ---*/ - if (Local_Colors[iPoint] == (unsigned long)rank) { + if (Local_Colors[iPoint] == static_cast(rank)) { if (Local_Points[iPoint] < geometry->GetGlobal_nPointDomain()) jPoint = iOwned; else @@ -2066,7 +2066,7 @@ void CPhysicalGeometry::LoadPoints(CConfig* config, CGeometry* geometry) { /*--- Increment the correct counter before moving to the next point. ---*/ - if (Local_Colors[iPoint] == (unsigned long)rank) { + if (Local_Colors[iPoint] == static_cast(rank)) { if (Local_Points[iPoint] < geometry->GetGlobal_nPointDomain()) iOwned++; else @@ -2875,7 +2875,7 @@ unsigned long CPhysicalGeometry::GetLinearPartition(unsigned long val_global_ind /*--- Guard against going over size. ---*/ - if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size - 1; + if (iProcessor >= static_cast(size)) iProcessor = static_cast(size) - 1; /*--- Move up or down until we find the processor. ---*/ @@ -2990,7 +2990,7 @@ void CPhysicalGeometry::SetSendReceive(const CConfig* config) { iPoint = elem[iElem]->GetNode(iNode); iDomain = nodes->GetColor(iPoint); - if (iDomain == (unsigned long)rank) { + if (iDomain == static_cast(rank)) { for (jNode = 0; jNode < elem[iElem]->GetnNodes(); jNode++) { jPoint = elem[iElem]->GetNode(jNode); jDomain = nodes->GetColor(jPoint); @@ -3717,11 +3717,11 @@ void CPhysicalGeometry::LoadUnpartitionedSurfaceElements(CConfig* config, CMeshR /*--- Not a mixed section. We already know the element type, which is stored ---*/ - vtk_type = (int)connElems[jElem * SU2_CONN_SIZE + 1]; + vtk_type = static_cast(connElems[jElem * SU2_CONN_SIZE + 1]); /*--- Store the loop size more easily. ---*/ - npe = (int)(SU2_CONN_SIZE - SU2_CONN_SKIP); + npe = static_cast(SU2_CONN_SIZE - SU2_CONN_SKIP); /*--- Store the nodes for this element more clearly. ---*/ @@ -5097,7 +5097,7 @@ void CPhysicalGeometry::SetTurboVertex(CConfig* config, unsigned short val_iZone if (config->GetMarker_All_TurbomachineryFlag(iMarker) == marker_flag) { /*--- compute the amount of vertexes for each span-wise section to initialize the CTurboVertex pointers and * auxiliary pointers ---*/ - for (iVertex = 0; (unsigned long)iVertex < nVertex[iMarker]; iVertex++) { + for (iVertex = 0; static_cast(iVertex) < nVertex[iMarker]; iVertex++) { iPoint = vertex[iMarker][iVertex]->GetNode(); if (nDim == 3) { dist = 10E+06; @@ -5197,7 +5197,7 @@ void CPhysicalGeometry::SetTurboVertex(CConfig* config, unsigned short val_iZone } /*--- store the vertexes in a ordered manner in span-wise directions but not yet ordered pitch-wise ---*/ - for (iVertex = 0; (unsigned long)iVertex < nVertex[iMarker]; iVertex++) { + for (iVertex = 0; static_cast(iVertex) < nVertex[iMarker]; iVertex++) { iPoint = vertex[iMarker][iVertex]->GetNode(); if (nDim == 3) { dist = 10E+06; @@ -5523,7 +5523,7 @@ void CPhysicalGeometry::SetTurboVertex(CConfig* config, unsigned short val_iZone SetnVertexSpanMax(marker_flag, nVert); } /*--- for all the processor should be known the amount of total turbovertex per span ---*/ - nTotVertex_gb[iSpan] = (int)nVert; + nTotVertex_gb[iSpan] = static_cast(nVert); for (iMarker = 0; iMarker < nMarker; iMarker++) { for (iMarkerTP = 1; iMarkerTP < config->GetnMarker_Turbomachinery() + 1; iMarkerTP++) { @@ -8275,7 +8275,7 @@ void CPhysicalGeometry::SetSensitivity(CConfig* config) { /*--- First, read the number of variables and points. ---*/ ret = fread(Restart_Vars, sizeof(int), nRestart_Vars, fhw); - if (ret != (unsigned long)nRestart_Vars) { + if (ret != static_cast(nRestart_Vars)) { SU2_MPI::Error("Error reading restart file.", CURRENT_FUNCTION); } @@ -8302,7 +8302,7 @@ void CPhysicalGeometry::SetSensitivity(CConfig* config) { config->fields.push_back("Point_ID"); for (iVar = 0; iVar < nFields; iVar++) { ret = fread(str_buf, sizeof(char), CGNS_STRING_SIZE, fhw); - if (ret != (unsigned long)CGNS_STRING_SIZE) { + if (ret != static_cast(CGNS_STRING_SIZE)) { SU2_MPI::Error("Error reading restart file.", CURRENT_FUNCTION); } config->fields.push_back(str_buf); @@ -8315,7 +8315,7 @@ void CPhysicalGeometry::SetSensitivity(CConfig* config) { /*--- Read in the data for the restart at all local points. ---*/ ret = fread(Restart_Data, sizeof(passivedouble), nFields * GetnPointDomain(), fhw); - if (ret != (unsigned long)nFields * GetnPointDomain()) { + if (ret != static_cast(nFields) * GetnPointDomain()) { SU2_MPI::Error("Error reading restart file.", CURRENT_FUNCTION); } @@ -8410,7 +8410,7 @@ void CPhysicalGeometry::SetSensitivity(CConfig* config) { config->fields.emplace_back("Point_ID"); for (iVar = 0; iVar < nFields; iVar++) { index = iVar * CGNS_STRING_SIZE; - for (iChar = 0; iChar < (unsigned long)CGNS_STRING_SIZE; iChar++) { + for (iChar = 0; iChar < static_cast(CGNS_STRING_SIZE); iChar++) { str_buf[iChar] = mpi_str_buf[index + iChar]; } field_buf.append(str_buf); diff --git a/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp index 962e32e478d..e2c0f52c3b1 100644 --- a/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CBoxMeshReaderFVM.cpp @@ -74,7 +74,7 @@ void CBoxMeshReaderFVM::ComputeBoxPointCoordinates() { /* Determine number of local points */ for (unsigned long globalIndex = 0; globalIndex < numberOfGlobalPoints; globalIndex++) { - if ((int)pointPartitioner.GetRankContainingIndex(globalIndex) == rank) { + if (static_cast(pointPartitioner.GetRankContainingIndex(globalIndex)) == rank) { numberOfLocalPoints++; } } @@ -88,7 +88,7 @@ void CBoxMeshReaderFVM::ComputeBoxPointCoordinates() { for (unsigned long kNode = 0; kNode < pNode; kNode++) { for (unsigned long jNode = 0; jNode < mNode; jNode++) { for (unsigned long iNode = 0; iNode < nNode; iNode++) { - if ((int)pointPartitioner.GetRankContainingIndex(globalIndex) == rank) { + if (static_cast(pointPartitioner.GetRankContainingIndex(globalIndex)) == rank) { /* Store the coordinates more clearly. */ const passivedouble x = SU2_TYPE::GetValue(Lx * ((su2double)iNode) / ((su2double)(nNode - 1)) + Ox); const passivedouble y = SU2_TYPE::GetValue(Ly * ((su2double)jNode) / ((su2double)(mNode - 1)) + Oy); @@ -133,7 +133,7 @@ void CBoxMeshReaderFVM::ComputeBoxVolumeConnectivity() { /* Check whether any of the points is in our linear partition. */ bool isOwned = false; for (unsigned short i = 0; i < N_POINTS_HEXAHEDRON; i++) { - if ((int)pointPartitioner.GetRankContainingIndex(connectivity[i]) == rank) { + if (static_cast(pointPartitioner.GetRankContainingIndex(connectivity[i])) == rank) { isOwned = true; } } diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp index 53697f65958..042ef3f9111 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderBase.cpp @@ -102,7 +102,7 @@ void CCGNSMeshReaderBase::ReadCGNSDatabaseMetadata() { /*--- Set the number of dimensions baed on cell_dim. ---*/ - dimension = (unsigned short)cell_dim; + dimension = static_cast(cell_dim); } void CCGNSMeshReaderBase::ReadCGNSZoneMetadata() { diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp index 3757a278478..32cb790291c 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFEM.cpp @@ -294,9 +294,9 @@ void CCGNSMeshReaderFEM::ReadCGNSSurfaceSection(const int val_section, const vec /*--- Easier storage of the VTK type, polynomial degree and number of DOFs of the surface element. ---*/ - const unsigned short VTK_Type = (unsigned short)connSU2[0]; - const unsigned short nPolyGrid = (unsigned short)connSU2[1]; - const unsigned short nDOFsGrid = (unsigned short)connSU2[3]; + const unsigned short VTK_Type = static_cast(connSU2[0]); + const unsigned short nPolyGrid = static_cast(connSU2[1]); + const unsigned short nDOFsGrid = static_cast(connSU2[3]); /*--- Make a distinction between the possible element surface types and determine the corner points in local numbering of the element. ---*/ diff --git a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp index 45025e6b4bf..2c0dabc8236 100644 --- a/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CCGNSMeshReaderFVM.cpp @@ -244,7 +244,7 @@ void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { entry if this is a mixed element section. ---*/ if (isMixed) counterCGNS++; - for (iNode = 0; iNode < (unsigned long)nPoinPerElem[iElem]; iNode++) { + for (iNode = 0; iNode < static_cast(nPoinPerElem[iElem]); iNode++) { connElemTemp[nn] = connElemCGNS[counterCGNS + iNode] - 1; nn++; } @@ -281,7 +281,7 @@ void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { CLinearPartitioner pointPartitioner(numberOfGlobalPoints, 0); for (iElem = 0; iElem < nElems[val_section]; iElem++) { - for (iNode = 0; iNode < (unsigned long)nPoinPerElem[iElem]; iNode++) { + for (iNode = 0; iNode < static_cast(nPoinPerElem[iElem]); iNode++) { /*--- Get the index of the current point. ---*/ iPoint = connElemTemp[iElem * SU2_CONN_SIZE + SU2_CONN_SKIP + iNode]; @@ -293,7 +293,7 @@ void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - if ((nElem_Flag[iProcessor] != (int)iElem)) { + if ((nElem_Flag[iProcessor] != static_cast(iElem))) { nElem_Flag[iProcessor] = iElem; nElem_Send[iProcessor + 1]++; } @@ -329,7 +329,7 @@ void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { + 2 extra values for the ID and VTK. ---*/ unsigned long *connSend = nullptr, iSend = 0; - unsigned long sendSize = (unsigned long)SU2_CONN_SIZE * nElem_Send[size]; + unsigned long sendSize = static_cast(SU2_CONN_SIZE) * nElem_Send[size]; connSend = new unsigned long[sendSize]; for (iSend = 0; iSend < sendSize; iSend++) connSend[iSend] = 0; @@ -342,8 +342,8 @@ void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { /*--- Loop through our elements and load the elems and their additional data that we will send to the other procs. ---*/ - for (iElem = 0; iElem < (unsigned long)nElems[val_section]; iElem++) { - for (iNode = 0; iNode < (unsigned long)nPoinPerElem[iElem]; iNode++) { + for (iElem = 0; iElem < static_cast(nElems[val_section]); iElem++) { + for (iNode = 0; iNode < static_cast(nPoinPerElem[iElem]); iNode++) { /*--- Get the index of the current point. ---*/ iPoint = connElemTemp[iElem * SU2_CONN_SIZE + SU2_CONN_SKIP + iNode]; @@ -354,7 +354,7 @@ void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { /*--- Load connectivity into the buffer for sending ---*/ - if (nElem_Flag[iProcessor] != (int)iElem) { + if (nElem_Flag[iProcessor] != static_cast(iElem)) { nElem_Flag[iProcessor] = iElem; unsigned long nn = index[iProcessor]; @@ -388,7 +388,7 @@ void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { directly copy our own data later. ---*/ unsigned long *connRecv = nullptr, iRecv = 0; - unsigned long recvSize = (unsigned long)SU2_CONN_SIZE * nElem_Recv[size]; + unsigned long recvSize = static_cast(SU2_CONN_SIZE) * nElem_Recv[size]; connRecv = new unsigned long[recvSize]; for (iRecv = 0; iRecv < recvSize; iRecv++) connRecv[iRecv] = 0; @@ -430,7 +430,7 @@ void CCGNSMeshReaderFVM::ReadCGNSVolumeSection(int val_section) { if (nElem_Recv[size] > 0) { connElems[val_section].resize(nElem_Recv[size] * SU2_CONN_SIZE, 0); unsigned long count = 0; - for (iElem = 0; iElem < (unsigned long)nElem_Recv[size]; iElem++) { + for (iElem = 0; iElem < static_cast(nElem_Recv[size]); iElem++) { for (iNode = 0; iNode < SU2_CONN_SIZE; iNode++) { unsigned long nn = iElem * SU2_CONN_SIZE + iNode; connElems[val_section][count] = (cgsize_t)connRecv[nn]; @@ -573,7 +573,7 @@ void CCGNSMeshReaderFVM::ReadCGNSSurfaceSection(int val_section) { connElems[val_section][iElem * SU2_CONN_SIZE + 0] = 0; connElems[val_section][iElem * SU2_CONN_SIZE + 1] = vtk_type; - for (iNode = 0; iNode < (unsigned long)npe; iNode++) { + for (iNode = 0; iNode < static_cast(npe); iNode++) { unsigned long nn = iElem * SU2_CONN_SIZE + SU2_CONN_SKIP + iNode; connElems[val_section][nn] = connElemTemp[counterCGNS] - 1; counterCGNS++; @@ -606,7 +606,7 @@ void CCGNSMeshReaderFVM::ReformatCGNSVolumeConnectivity() { 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; - localVolumeElementConnectivity[count] = (unsigned long)connElems[s][nn]; + localVolumeElementConnectivity[count] = static_cast(connElems[s][nn]); count++; } } @@ -640,7 +640,7 @@ void CCGNSMeshReaderFVM::ReformatCGNSSurfaceConnectivity() { 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] = (unsigned long)connElems[s][nn]; + surfaceElementConnectivity[markerCount][elementCount] = static_cast(connElems[s][nn]); elementCount++; } } diff --git a/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp index 59d6bb74cfc..f1e8f6177a2 100644 --- a/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CRectangularMeshReaderFVM.cpp @@ -72,7 +72,7 @@ void CRectangularMeshReaderFVM::ComputeRectangularPointCoordinates() { /* Determine number of local points */ for (unsigned long globalIndex = 0; globalIndex < numberOfGlobalPoints; globalIndex++) { - if ((int)pointPartitioner.GetRankContainingIndex(globalIndex) == rank) { + if (static_cast(pointPartitioner.GetRankContainingIndex(globalIndex)) == rank) { numberOfLocalPoints++; } } @@ -84,7 +84,7 @@ void CRectangularMeshReaderFVM::ComputeRectangularPointCoordinates() { unsigned long globalIndex = 0; for (unsigned long jNode = 0; jNode < mNode; jNode++) { for (unsigned long iNode = 0; iNode < nNode; iNode++) { - if ((int)pointPartitioner.GetRankContainingIndex(globalIndex) == rank) { + if (static_cast(pointPartitioner.GetRankContainingIndex(globalIndex)) == rank) { /* Store the coordinates more clearly. */ const passivedouble x = SU2_TYPE::GetValue(Lx * ((su2double)iNode) / ((su2double)(nNode - 1)) + Ox); const passivedouble y = SU2_TYPE::GetValue(Ly * ((su2double)jNode) / ((su2double)(mNode - 1)) + Oy); @@ -121,7 +121,7 @@ void CRectangularMeshReaderFVM::ComputeRectangularVolumeConnectivity() { /* Check whether any of the points is in our linear partition. */ bool isOwned = false; for (unsigned short i = 0; i < N_POINTS_QUADRILATERAL; i++) { - if ((int)pointPartitioner.GetRankContainingIndex(connectivity[i]) == rank) { + if (static_cast(pointPartitioner.GetRankContainingIndex(connectivity[i])) == rank) { isOwned = true; } } diff --git a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp index 8403c6af425..6801123dd03 100644 --- a/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp +++ b/Common/src/geometry/meshreader/CSU2ASCIIMeshReaderFVM.cpp @@ -405,14 +405,14 @@ void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { elem_line >> connectivity[1]; elem_line >> connectivity[2]; InElem = false; - for (unsigned long i = 0; i < (unsigned long)N_POINTS_TRIANGLE; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_TRIANGLE); i++) { if (ActDisk_Bool[connectivity[i]]) { InElem = true; break; } } if (InElem) { - for (unsigned long i = 0; i < (unsigned long)N_POINTS_TRIANGLE; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_TRIANGLE); i++) { VolumePoint.push_back(connectivity[i]); } } @@ -423,14 +423,14 @@ void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { elem_line >> connectivity[2]; elem_line >> connectivity[3]; InElem = false; - for (unsigned long i = 0; i < (unsigned long)N_POINTS_QUADRILATERAL; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_QUADRILATERAL); i++) { if (ActDisk_Bool[connectivity[i]]) { InElem = true; break; } } if (InElem) { - for (unsigned long i = 0; i < (unsigned long)N_POINTS_QUADRILATERAL; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_QUADRILATERAL); i++) { VolumePoint.push_back(connectivity[i]); } } @@ -441,14 +441,14 @@ void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { elem_line >> connectivity[2]; elem_line >> connectivity[3]; InElem = false; - for (unsigned long i = 0; i < (unsigned long)N_POINTS_TETRAHEDRON; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_TETRAHEDRON); i++) { if (ActDisk_Bool[connectivity[i]]) { InElem = true; break; } } if (InElem) { - for (unsigned long i = 0; i < (unsigned long)N_POINTS_TETRAHEDRON; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_TETRAHEDRON); i++) { VolumePoint.push_back(connectivity[i]); } } @@ -463,14 +463,14 @@ void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { elem_line >> connectivity[6]; elem_line >> connectivity[7]; InElem = false; - for (unsigned long i = 0; i < (unsigned long)N_POINTS_HEXAHEDRON; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_HEXAHEDRON); i++) { if (ActDisk_Bool[connectivity[i]]) { InElem = true; break; } } if (InElem) { - for (unsigned long i = 0; i < (unsigned long)N_POINTS_HEXAHEDRON; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_HEXAHEDRON); i++) { VolumePoint.push_back(connectivity[i]); } } @@ -483,14 +483,14 @@ void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { elem_line >> connectivity[4]; elem_line >> connectivity[5]; InElem = false; - for (unsigned long i = 0; i < (unsigned long)N_POINTS_PRISM; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_PRISM); i++) { if (ActDisk_Bool[connectivity[i]]) { InElem = true; break; } } if (InElem) { - for (unsigned long i = 0; i < (unsigned long)N_POINTS_PRISM; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_PRISM); i++) { VolumePoint.push_back(connectivity[i]); } } @@ -502,14 +502,14 @@ void CSU2ASCIIMeshReaderFVM::SplitActuatorDiskSurface() { elem_line >> connectivity[3]; elem_line >> connectivity[4]; InElem = false; - for (unsigned long i = 0; i < (unsigned long)N_POINTS_PYRAMID; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_PYRAMID); i++) { if (ActDisk_Bool[connectivity[i]]) { InElem = true; break; } } if (InElem) { - for (unsigned long i = 0; i < (unsigned long)N_POINTS_PYRAMID; i++) { + for (unsigned long i = 0; i < static_cast(N_POINTS_PYRAMID); i++) { VolumePoint.push_back(connectivity[i]); } } diff --git a/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp b/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp index 6b374960f46..43fd3606a09 100644 --- a/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp +++ b/Common/src/geometry/primal_grid/CPrimalGridBoundFEM.cpp @@ -29,9 +29,9 @@ CPrimalGridBoundFEM::CPrimalGridBoundFEM(const unsigned long* dataElem) : CPrimalGrid(true, dataElem[2], 1) { /*--- Store the meta data for this element. ---*/ - VTK_Type = (unsigned short)dataElem[0]; - nPolyGrid = (unsigned short)dataElem[1]; - nDOFsGrid = (unsigned short)dataElem[2]; + VTK_Type = static_cast(dataElem[0]); + nPolyGrid = static_cast(dataElem[1]); + nDOFsGrid = static_cast(dataElem[2]); boundElemIDGlobal = dataElem[3]; GlobalIndex_DomainElement = dataElem[4]; diff --git a/Common/src/geometry/primal_grid/CPrimalGridFEM.cpp b/Common/src/geometry/primal_grid/CPrimalGridFEM.cpp index dbe2e4e3a03..738c443f3e8 100644 --- a/Common/src/geometry/primal_grid/CPrimalGridFEM.cpp +++ b/Common/src/geometry/primal_grid/CPrimalGridFEM.cpp @@ -31,10 +31,10 @@ CPrimalGridFEM::CPrimalGridFEM(const unsigned long* dataElem, unsigned long& offsetSolDOFs) : CPrimalGrid(true, dataElem[3], nFacesOfElementType(dataElem[0])) { /*--- Store the meta data for this element. ---*/ - VTK_Type = (unsigned short)dataElem[0]; - nPolyGrid = (unsigned short)dataElem[1]; - nPolySol = (unsigned short)dataElem[2]; - nDOFsGrid = (unsigned short)dataElem[3]; + VTK_Type = static_cast(dataElem[0]); + nPolyGrid = static_cast(dataElem[1]); + nPolySol = static_cast(dataElem[2]); + nDOFsGrid = static_cast(dataElem[3]); nDOFsSol = CFEMStandardElementBase::GetNDOFsStatic(VTK_Type, nPolySol); elemIDGlobal = dataElem[4]; From bd5999fb9a60a10bbb6c70181fe93dcf4b2b48d1 Mon Sep 17 00:00:00 2001 From: vdweide Date: Thu, 6 Feb 2025 09:58:34 +0100 Subject: [PATCH 129/129] Result of running pre-commit --- Common/src/fem/fem_geometry_structure.cpp | 18 ++++++++++++------ Common/src/fem/geometry_structure_fem_part.cpp | 3 ++- Common/src/geometry/CPhysicalGeometry.cpp | 3 ++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Common/src/fem/fem_geometry_structure.cpp b/Common/src/fem/fem_geometry_structure.cpp index 7a0b5177129..c6e52dbea81 100644 --- a/Common/src/fem/fem_geometry_structure.cpp +++ b/Common/src/fem/fem_geometry_structure.cpp @@ -566,8 +566,10 @@ CMeshFEM::CMeshFEM(CGeometry* geometry, CConfig* config) { the elements with constant and non-constant Jacobians are considered the same. */ if (JacConstant) { - const auto orderExactStraight = static_cast(ceil(nPolySol * config->GetQuadrature_Factor_Straight())); - const auto orderExactCurved = static_cast(ceil(nPolySol * config->GetQuadrature_Factor_Curved())); + const auto orderExactStraight = + static_cast(ceil(nPolySol * config->GetQuadrature_Factor_Straight())); + const auto orderExactCurved = + static_cast(ceil(nPolySol * config->GetQuadrature_Factor_Curved())); if (orderExactStraight == orderExactCurved) JacConstant = false; } @@ -2455,12 +2457,16 @@ void CMeshFEM_DG::CreateFaces(CConfig* config) { is set to false. Hence it is only needed to carry out this check for faces with a constant Jacobian. This is done to reduce the number of standard elements. */ if (thisFace.JacFaceIsConsideredConstant) { - auto orderExactStraight = static_cast(ceil(thisFace.nPolyGrid0 * config->GetQuadrature_Factor_Straight())); - auto orderExactCurved = static_cast(ceil(thisFace.nPolyGrid0 * config->GetQuadrature_Factor_Curved())); + auto orderExactStraight = + static_cast(ceil(thisFace.nPolyGrid0 * config->GetQuadrature_Factor_Straight())); + auto orderExactCurved = + static_cast(ceil(thisFace.nPolyGrid0 * config->GetQuadrature_Factor_Curved())); if (orderExactStraight == orderExactCurved) { - orderExactStraight = static_cast(ceil(thisFace.nPolySol0 * config->GetQuadrature_Factor_Straight())); - orderExactCurved = static_cast(ceil(thisFace.nPolySol0 * config->GetQuadrature_Factor_Curved())); + orderExactStraight = + static_cast(ceil(thisFace.nPolySol0 * config->GetQuadrature_Factor_Straight())); + orderExactCurved = + static_cast(ceil(thisFace.nPolySol0 * config->GetQuadrature_Factor_Curved())); if (orderExactStraight == orderExactCurved) thisFace.JacFaceIsConsideredConstant = false; } } diff --git a/Common/src/fem/geometry_structure_fem_part.cpp b/Common/src/fem/geometry_structure_fem_part.cpp index a0309bf2233..f4734eed85d 100644 --- a/Common/src/fem/geometry_structure_fem_part.cpp +++ b/Common/src/fem/geometry_structure_fem_part.cpp @@ -637,7 +637,8 @@ void CPhysicalGeometry::SetColorFEMGrid_Parallel(CConfig* config) { vector sendBufFace(9 * nFacesLocComm); vector counter(size); counter[0] = 0; - for (unsigned long i = 1; i < static_cast(size); ++i) counter[i] = counter[i - 1] + 9 * nFacesComm[i - 1]; + for (unsigned long i = 1; i < static_cast(size); ++i) + counter[i] = counter[i - 1] + 9 * nFacesComm[i - 1]; for (unsigned long i = 0; i < nFacesLocComm; ++i) { unsigned long rankFace = localFacesComm[i].elemID1; diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index 1c53744b191..eab91fca43c 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -1990,7 +1990,8 @@ void CPhysicalGeometry::DistributeMarkerTags(CConfig* config, CGeometry* geometr /*--- Broadcast the string names of the variables. ---*/ - SU2_MPI::Bcast(mpi_str_buf, static_cast(nMarker_Global) * MAX_STRING_SIZE, MPI_CHAR, MASTER_NODE, SU2_MPI::GetComm()); + SU2_MPI::Bcast(mpi_str_buf, static_cast(nMarker_Global) * MAX_STRING_SIZE, MPI_CHAR, MASTER_NODE, + SU2_MPI::GetComm()); /*--- Now parse the string names and load into our marker tag vector. We also need to set the values of all markers into the config. ---*/