diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index 8e625b719b6e..c477d884e6dc 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -762,6 +762,7 @@ class CConfig { Wrt_Performance, /*!< \brief Write the performance summary at the end of a calculation. */ Wrt_AD_Statistics, /*!< \brief Write the tape statistics (discrete adjoint). */ Wrt_MeshQuality, /*!< \brief Write the mesh quality statistics to the visualization files. */ + Wrt_MultiGrid, /*!< \brief Write the coarse grids to the visualization files. */ Wrt_Projected_Sensitivity, /*!< \brief Write projected sensitivities (dJ/dx) on surfaces to ASCII file. */ Plot_Section_Forces; /*!< \brief Write sectional forces for specified markers. */ unsigned short @@ -3043,6 +3044,11 @@ class CConfig { */ bool GetWrt_MeshQuality(void) const { return Wrt_MeshQuality; } + /*! + * \brief Write coarse grids to the visualization files. + */ + bool GetWrt_MultiGrid(void) const { return Wrt_MultiGrid; } + /*! * \brief Get information about writing projected sensitivities on surfaces to an ASCII file with rows as x, y, z, dJ/dx, dJ/dy, dJ/dz for each vertex. * \return TRUE means that projected sensitivities on surfaces in an ASCII file with rows as x, y, z, dJ/dx, dJ/dy, dJ/dz for each vertex will be written. diff --git a/Common/include/geometry/CGeometry.hpp b/Common/include/geometry/CGeometry.hpp index 93ed622fa815..8b78e9b8445c 100644 --- a/Common/include/geometry/CGeometry.hpp +++ b/Common/include/geometry/CGeometry.hpp @@ -185,6 +185,8 @@ class CGeometry { unsigned long edgeColorGroupSize{1}; /*!< \brief Size of the edge groups within each color. */ unsigned long elemColorGroupSize{1}; /*!< \brief Size of the element groups within each color. */ + ColMajorMatrix CoarseGridColor_; /*!< \brief Coarse grid levels, colorized. */ + public: /*--- Main geometric elements of the grid. ---*/ @@ -258,6 +260,8 @@ class CGeometry { vector Aspect_Ratio; /*!< \brief Measure of dual CV aspect ratio (max face area / min face area). */ vector Volume_Ratio; /*!< \brief Measure of dual CV volume ratio (max sub-element volume / min sub-element volume). */ + const ColMajorMatrix& CoarseGridColor = CoarseGridColor_; /*!< \brief Coarse grid levels, colorized. */ + /*! * \brief Constructor of the class. */ @@ -1597,6 +1601,13 @@ class CGeometry { */ inline virtual void ComputeMeshQualityStatistics(const CConfig *config) {} + /*! + * \brief Color multigrid levels for visualization. + * \param nMGLevels - Number of levels + * \param geometry - The levels + */ + void ColorMGLevels(unsigned short nMGLevels, const CGeometry* const* geometry); + /*! * \brief Get the sparse pattern of "type" with given level of fill. * \note This method builds the pattern if that has not been done yet. diff --git a/Common/include/linear_algebra/CSysMatrix.hpp b/Common/include/linear_algebra/CSysMatrix.hpp index 7f79858541c4..75ab1a052c39 100644 --- a/Common/include/linear_algebra/CSysMatrix.hpp +++ b/Common/include/linear_algebra/CSysMatrix.hpp @@ -108,7 +108,7 @@ struct CSysMatrixComms { template class CSysMatrix { private: - friend class CSysMatrixComms; + friend struct CSysMatrixComms; const int rank; /*!< \brief MPI Rank. */ const int size; /*!< \brief MPI Size. */ diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 93b63f40f52b..3e1474ed409c 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -3207,6 +3207,14 @@ void CConfig::SetPostprocessing(SU2_COMPONENT val_software, unsigned short val_i } } + /*--- Check if MULTIGRID is requested in VOLUME_OUTPUT and set the config boolean accordingly. ---*/ + Wrt_MultiGrid = false; + for (unsigned short iField = 0; iField < nVolumeOutput; iField++) { + if(VolumeOutput[iField].find("MULTIGRID") != string::npos) { + Wrt_MultiGrid = true; + } + } + if (Kind_Solver == NAVIER_STOKES && Kind_Turb_Model != NONE){ SU2_MPI::Error("KIND_TURB_MODEL must be NONE if SOLVER= NAVIER_STOKES", CURRENT_FUNCTION); } @@ -4996,9 +5004,9 @@ void CConfig::SetPostprocessing(SU2_COMPONENT val_software, unsigned short val_i if (GetGasModel() == "ARGON") monoatomic = true; // This option is deprecated. After a grace period until 7.2.0 the usage warning should become an error. - if(OptionIsSet("CONV_CRITERIA")) { - cout << string("\n\nWARNING: CONV_CRITERIA is deprecated. SU2 will choose the criteria automatically based on the CONV_FIELD.\n") + - string("RESIDUAL for any RMS_* BGS_* value. CAUCHY for coefficients like DRAG etc.\n\n"); + if(OptionIsSet("CONV_CRITERIA") && rank == MASTER_NODE) { + cout << "\n\nWARNING: CONV_CRITERIA is deprecated. SU2 will choose the criteria automatically based on the CONV_FIELD.\n" + "That is, RESIDUAL for any RMS_* BGS_* value, and CAUCHY for coefficients such as DRAG etc.\n" << endl; } } diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index e238bfeac2ab..175d30bff821 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -3823,6 +3823,33 @@ void CGeometry::SetNaturalElementColoring() if (omp_get_max_threads() > 1) elemColorGroupSize = nElem; } +void CGeometry::ColorMGLevels(unsigned short nMGLevels, const CGeometry* const* geometry) { + + using tColor = uint8_t; + constexpr auto nColor = numeric_limits::max(); + + if (nMGLevels) CoarseGridColor_.resize(nPoint,nMGLevels) = 0; + + for (auto iMesh = nMGLevels; iMesh >= 1; --iMesh) { + /*--- Color the coarse points. ---*/ + vector color; + const auto& adjacency = geometry[iMesh]->nodes->GetPoints(); + if (colorSparsePattern(adjacency, 1, false, &color).empty()) + continue; + + /*--- Propagate colors to fine mesh. ---*/ + for (auto step = 0u; step < iMesh; ++step) { + auto coarseMesh = geometry[iMesh-1-step]; + if (step) + for (auto iPoint = 0ul; iPoint < coarseMesh->GetnPoint(); ++iPoint) + CoarseGridColor_(iPoint,step) = CoarseGridColor_(coarseMesh->nodes->GetParent_CV(iPoint), step-1); + else + for (auto iPoint = 0ul; iPoint < coarseMesh->GetnPoint(); ++iPoint) + CoarseGridColor_(iPoint,step) = color[coarseMesh->nodes->GetParent_CV(iPoint)]; + } + } +} + void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeometry ****geometry_container){ int nZone = config_container[ZONE_0]->GetnZone(); diff --git a/SU2_CFD/include/output/CFlowOutput.hpp b/SU2_CFD/include/output/CFlowOutput.hpp index 694ff2843638..8e15d607ae1d 100644 --- a/SU2_CFD/include/output/CFlowOutput.hpp +++ b/SU2_CFD/include/output/CFlowOutput.hpp @@ -141,4 +141,15 @@ class CFlowOutput : public COutput{ * \param node_flow */ void LoadTimeAveragedData(unsigned long iPoint, CVariable *node_flow); + + /*! + * \brief Add common FVM outputs. + */ + void AddCommonFVMOutputs(const CConfig* config); + + /*! + * \brief Load common FVM outputs. + */ + void LoadCommonFVMOutputs(const CConfig* config, const CGeometry* geometry, unsigned long iPoint); + }; diff --git a/SU2_CFD/src/drivers/CDriver.cpp b/SU2_CFD/src/drivers/CDriver.cpp index 87c3c2b58f23..c37c6283d924 100644 --- a/SU2_CFD/src/drivers/CDriver.cpp +++ b/SU2_CFD/src/drivers/CDriver.cpp @@ -898,6 +898,8 @@ void CDriver::Geometrical_Preprocessing_FVM(CConfig *config, CGeometry **&geomet } + if (config->GetWrt_MultiGrid()) geometry[MESH_0]->ColorMGLevels(config->GetnMGLevels(), geometry); + /*--- For unsteady simulations, initialize the grid volumes and coordinates for previous solutions. Loop over all zones/grids ---*/ diff --git a/SU2_CFD/src/output/CFlowCompOutput.cpp b/SU2_CFD/src/output/CFlowCompOutput.cpp index 3e8f85e9dc86..077aa5b988f9 100644 --- a/SU2_CFD/src/output/CFlowCompOutput.cpp +++ b/SU2_CFD/src/output/CFlowCompOutput.cpp @@ -415,13 +415,7 @@ void CFlowCompOutput::SetVolumeOutputFields(CConfig *config){ AddVolumeOutput("Q_CRITERION", "Q_Criterion", "VORTEX_IDENTIFICATION", "Value of the Q-Criterion"); } - // Mesh quality metrics, computed in CPhysicalGeometry::ComputeMeshQualityStatistics. - AddVolumeOutput("ORTHOGONALITY", "Orthogonality", "MESH_QUALITY", "Orthogonality Angle (deg.)"); - AddVolumeOutput("ASPECT_RATIO", "Aspect_Ratio", "MESH_QUALITY", "CV Face Area Aspect Ratio"); - AddVolumeOutput("VOLUME_RATIO", "Volume_Ratio", "MESH_QUALITY", "CV Sub-Volume Ratio"); - - // MPI-Rank - AddVolumeOutput("RANK", "rank", "MPI", "Rank of the MPI-partition"); + AddCommonFVMOutputs(config); if (config->GetTime_Domain()){ SetTimeAveragedFields(); @@ -567,15 +561,7 @@ void CFlowCompOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolv SetVolumeOutputValue("Q_CRITERION", iPoint, GetQ_Criterion(&(Node_Flow->GetGradient_Primitive(iPoint)[1]))); } - // Mesh quality metrics - if (config->GetWrt_MeshQuality()) { - SetVolumeOutputValue("ORTHOGONALITY", iPoint, geometry->Orthogonality[iPoint]); - SetVolumeOutputValue("ASPECT_RATIO", iPoint, geometry->Aspect_Ratio[iPoint]); - SetVolumeOutputValue("VOLUME_RATIO", iPoint, geometry->Volume_Ratio[iPoint]); - } - - // MPI-Rank - SetVolumeOutputValue("RANK", iPoint, rank); + LoadCommonFVMOutputs(config, geometry, iPoint); if (config->GetTime_Domain()){ LoadTimeAveragedData(iPoint, Node_Flow); diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp index 1a46865d4dbd..8b279613a501 100644 --- a/SU2_CFD/src/output/CFlowIncOutput.cpp +++ b/SU2_CFD/src/output/CFlowIncOutput.cpp @@ -498,11 +498,6 @@ void CFlowIncOutput::SetVolumeOutputFields(CConfig *config){ AddVolumeOutput("Q_CRITERION", "Q_Criterion", "VORTEX_IDENTIFICATION", "Value of the Q-Criterion"); } - // Mesh quality metrics, computed in CPhysicalGeometry::ComputeMeshQualityStatistics. - AddVolumeOutput("ORTHOGONALITY", "Orthogonality", "MESH_QUALITY", "Orthogonality Angle (deg.)"); - AddVolumeOutput("ASPECT_RATIO", "Aspect_Ratio", "MESH_QUALITY", "CV Face Area Aspect Ratio"); - AddVolumeOutput("VOLUME_RATIO", "Volume_Ratio", "MESH_QUALITY", "CV Sub-Volume Ratio"); - // Streamwise Periodicity if(streamwisePeriodic) { AddVolumeOutput("RECOVERED_PRESSURE", "Recovered_Pressure", "SOLUTION", "Recovered physical pressure"); @@ -510,8 +505,7 @@ void CFlowIncOutput::SetVolumeOutputFields(CConfig *config){ AddVolumeOutput("RECOVERED_TEMPERATURE", "Recovered_Temperature", "SOLUTION", "Recovered physical temperature"); } - // MPI-Rank - AddVolumeOutput("RANK", "Rank", "MPI", "Rank of the MPI-partition"); + AddCommonFVMOutputs(config); } void CFlowIncOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned long iPoint){ @@ -669,15 +663,7 @@ void CFlowIncOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolve SetVolumeOutputValue("RECOVERED_TEMPERATURE", iPoint, Node_Flow->GetStreamwise_Periodic_RecoveredTemperature(iPoint)); } - // Mesh quality metrics - if (config->GetWrt_MeshQuality()) { - SetVolumeOutputValue("ORTHOGONALITY", iPoint, geometry->Orthogonality[iPoint]); - SetVolumeOutputValue("ASPECT_RATIO", iPoint, geometry->Aspect_Ratio[iPoint]); - SetVolumeOutputValue("VOLUME_RATIO", iPoint, geometry->Volume_Ratio[iPoint]); - } - - // MPI-Rank - SetVolumeOutputValue("RANK", iPoint, rank); + LoadCommonFVMOutputs(config, geometry, iPoint); } void CFlowIncOutput::LoadSurfaceData(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned long iPoint, unsigned short iMarker, unsigned long iVertex){ diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 7a6f2992a4b4..815b400b13a4 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -2735,6 +2735,41 @@ bool CFlowOutput::WriteVolume_Output(CConfig *config, unsigned long Iter, bool f return false || force_writing; } +void CFlowOutput::AddCommonFVMOutputs(const CConfig *config) { + + AddVolumeOutput("ORTHOGONALITY", "Orthogonality", "MESH_QUALITY", "Orthogonality Angle (deg.)"); + AddVolumeOutput("ASPECT_RATIO", "Aspect_Ratio", "MESH_QUALITY", "CV Face Area Aspect Ratio"); + AddVolumeOutput("VOLUME_RATIO", "Volume_Ratio", "MESH_QUALITY", "CV Sub-Volume Ratio"); + + AddVolumeOutput("RANK", "rank", "MPI", "Rank of the MPI-partition"); + + for (auto iMesh = 1u; iMesh <= config->GetnMGLevels(); ++iMesh) { + stringstream key, name; + key << "MG_" << iMesh; + name << "Coarse_Grid_" << iMesh; + AddVolumeOutput(key.str(), name.str(), "MULTIGRID", "Coarse mesh"); + } +} + +void CFlowOutput::LoadCommonFVMOutputs(const CConfig* config, const CGeometry* geometry, unsigned long iPoint) { + + if (config->GetWrt_MeshQuality()) { + SetVolumeOutputValue("ORTHOGONALITY", iPoint, geometry->Orthogonality[iPoint]); + SetVolumeOutputValue("ASPECT_RATIO", iPoint, geometry->Aspect_Ratio[iPoint]); + SetVolumeOutputValue("VOLUME_RATIO", iPoint, geometry->Volume_Ratio[iPoint]); + } + + SetVolumeOutputValue("RANK", iPoint, rank); + + if (config->GetWrt_MultiGrid()) { + for (auto iMesh = 1u; iMesh <= config->GetnMGLevels(); ++iMesh) { + stringstream key; + key << "MG_" << iMesh; + SetVolumeOutputValue(key.str(), iPoint, geometry->CoarseGridColor(iPoint,iMesh-1)); + } + } +} + void CFlowOutput::SetTimeAveragedFields(){ AddVolumeOutput("MEAN_DENSITY", "MeanDensity", "TIME_AVERAGE", "Mean density"); AddVolumeOutput("MEAN_VELOCITY-X", "MeanVelocity_x", "TIME_AVERAGE", "Mean velocity x-component"); diff --git a/SU2_CFD/src/output/CNEMOCompOutput.cpp b/SU2_CFD/src/output/CNEMOCompOutput.cpp index b4709a3de6a3..1aae0b381ac0 100644 --- a/SU2_CFD/src/output/CNEMOCompOutput.cpp +++ b/SU2_CFD/src/output/CNEMOCompOutput.cpp @@ -419,6 +419,8 @@ void CNEMOCompOutput::SetVolumeOutputFields(CConfig *config){ AddVolumeOutput("VORTICITY_Z", "Vorticity_z", "VORTEX_IDENTIFICATION", "z-component of the vorticity vector"); } + AddCommonFVMOutputs(config); + if (config->GetTime_Domain()){ SetTimeAveragedFields(); } @@ -555,6 +557,8 @@ void CNEMOCompOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolv SetVolumeOutputValue("ROE_DISSIPATION", iPoint, Node_Flow->GetRoe_Dissipation(iPoint)); } + LoadCommonFVMOutputs(config, geometry, iPoint); + if (config->GetTime_Domain()){ LoadTimeAveragedData(iPoint, Node_Flow); }