From 0cb655e5eec06f2d53ee45edfc7a90159642837e Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Sat, 25 Mar 2023 19:10:27 +0000 Subject: [PATCH 1/2] expose all history outputs --- SU2_CFD/include/drivers/CDriver.hpp | 154 ++++++++------------- SU2_CFD/include/drivers/CDriverBase.hpp | 53 ++++++- SU2_CFD/include/output/COutput.hpp | 17 ++- SU2_CFD/src/output/CFlowOutput.cpp | 3 + SU2_CFD/src/python_wrapper_structure.cpp | 100 ------------- SU2_DEF/src/drivers/CDeformationDriver.cpp | 8 +- 6 files changed, 121 insertions(+), 214 deletions(-) diff --git a/SU2_CFD/include/drivers/CDriver.hpp b/SU2_CFD/include/drivers/CDriver.hpp index 9b3eae14a3a9..44258e8bb4f8 100644 --- a/SU2_CFD/include/drivers/CDriver.hpp +++ b/SU2_CFD/include/drivers/CDriver.hpp @@ -356,6 +356,58 @@ class CDriver : public CDriverBase { */ void Print_DirectResidual(RECORDING kind_recording); + /*! + * \brief Set the solution of all solvers (adjoint or primal) in a zone. + * \param[in] iZone - Index of the zone. + * \param[in] adjoint - True to consider adjoint solvers instead of primal. + * \param[in] solution - Solution object with interface (iPoint,iVar). + * \tparam Old - If true set "old solutions" instead. + */ + template + void SetAllSolutions(unsigned short iZone, bool adjoint, const Container& solution) { + const auto nPoint = geometry_container[iZone][INST_0][MESH_0]->GetnPoint(); + for (auto iSol = 0u, offset = 0u; iSol < MAX_SOLS; ++iSol) { + auto solver = solver_container[iZone][INST_0][MESH_0][iSol]; + if (!(solver && (solver->GetAdjoint() == adjoint))) continue; + for (auto iPoint = 0ul; iPoint < nPoint; ++iPoint) + for (auto iVar = 0ul; iVar < solver->GetnVar(); ++iVar) + if (!Old) { + solver->GetNodes()->SetSolution(iPoint, iVar, solution(iPoint, offset + iVar)); + } else { + solver->GetNodes()->SetSolution_Old(iPoint, iVar, solution(iPoint, offset + iVar)); + } + offset += solver->GetnVar(); + } + } + + /*! + * \brief Set the "old solution" of all solvers (adjoint or primal) in a zone. + */ + template + void SetAllSolutionsOld(unsigned short iZone, bool adjoint, const Container& solution) { + SetAllSolutions(iZone, adjoint, solution); + } + + /*! + * \brief Get the solution of all solvers (adjoint or primal) in a zone. + * \param[in] iZone - Index of the zone. + * \param[in] adjoint - True to consider adjoint solvers instead of primal. + * \param[out] solution - Solution object with interface (iPoint,iVar). + */ + template + void GetAllSolutions(unsigned short iZone, bool adjoint, Container& solution) const { + const auto nPoint = geometry_container[iZone][INST_0][MESH_0]->GetnPoint(); + for (auto iSol = 0u, offset = 0u; iSol < MAX_SOLS; ++iSol) { + auto solver = solver_container[iZone][INST_0][MESH_0][iSol]; + if (!(solver && (solver->GetAdjoint() == adjoint))) continue; + const auto& sol = solver->GetNodes()->GetSolution(); + for (auto iPoint = 0ul; iPoint < nPoint; ++iPoint) + for (auto iVar = 0ul; iVar < solver->GetnVar(); ++iVar) + solution(iPoint, offset + iVar) = SU2_TYPE::GetValue(sol(iPoint, iVar)); + offset += solver->GetnVar(); + } + } + public: /*! * \brief Launch the computation for all zones and all physics. @@ -413,56 +465,14 @@ class CDriver : public CDriverBase { void BoundaryConditionsUpdate(); /*! - * \brief Get the total drag. - * \return Total drag. - */ - passivedouble Get_Drag() const; - - /*! - * \brief Get the total lift. - * \return Total lift. - */ - passivedouble Get_Lift() const; - - /*! - * \brief Get the total x moment. - * \return Total x moment. - */ - passivedouble Get_Mx() const; - - /*! - * \brief Get the total y moment. - * \return Total y moment. - */ - passivedouble Get_My() const; - - /*! - * \brief Get the total z moment. - * \return Total z moment. - */ - passivedouble Get_Mz() const; - - /*! - * \brief Get the total drag coefficient. - * \return Total drag coefficient. - */ - passivedouble Get_DragCoeff() const; - - /*! - * \brief Get the total lift coefficient. - * \return Total lift coefficient. - */ - passivedouble Get_LiftCoeff() const; - - /*! - * \brief Get the number of external iterations. - * \return Number of external iterations. + * \brief Get the number of time iterations. + * \return Number of time iterations. */ unsigned long GetNumberTimeIter() const; /*! - * \brief Get the current external iteration. - * \return Current external iteration. + * \brief Get the current time iteration. + * \return Current time iteration. */ unsigned long GetTimeIter() const; @@ -518,58 +528,6 @@ class CDriver : public CDriverBase { } return nVar; } - - /*! - * \brief Set the solution of all solvers (adjoint or primal) in a zone. - * \param[in] iZone - Index of the zone. - * \param[in] adjoint - True to consider adjoint solvers instead of primal. - * \param[in] solution - Solution object with interface (iPoint,iVar). - * \tparam Old - If true set "old solutions" instead. - */ - template - void SetAllSolutions(unsigned short iZone, bool adjoint, const Container& solution) { - const auto nPoint = geometry_container[iZone][INST_0][MESH_0]->GetnPoint(); - for (auto iSol = 0u, offset = 0u; iSol < MAX_SOLS; ++iSol) { - auto solver = solver_container[iZone][INST_0][MESH_0][iSol]; - if (!(solver && (solver->GetAdjoint() == adjoint))) continue; - for (auto iPoint = 0ul; iPoint < nPoint; ++iPoint) - for (auto iVar = 0ul; iVar < solver->GetnVar(); ++iVar) - if (!Old) { - solver->GetNodes()->SetSolution(iPoint, iVar, solution(iPoint, offset + iVar)); - } else { - solver->GetNodes()->SetSolution_Old(iPoint, iVar, solution(iPoint, offset + iVar)); - } - offset += solver->GetnVar(); - } - } - - /*! - * \brief Set the "old solution" of all solvers (adjoint or primal) in a zone. - */ - template - void SetAllSolutionsOld(unsigned short iZone, bool adjoint, const Container& solution) { - SetAllSolutions(iZone, adjoint, solution); - } - - /*! - * \brief Get the solution of all solvers (adjoint or primal) in a zone. - * \param[in] iZone - Index of the zone. - * \param[in] adjoint - True to consider adjoint solvers instead of primal. - * \param[out] solution - Solution object with interface (iPoint,iVar). - */ - template - void GetAllSolutions(unsigned short iZone, bool adjoint, Container& solution) const { - const auto nPoint = geometry_container[iZone][INST_0][MESH_0]->GetnPoint(); - for (auto iSol = 0u, offset = 0u; iSol < MAX_SOLS; ++iSol) { - auto solver = solver_container[iZone][INST_0][MESH_0][iSol]; - if (!(solver && (solver->GetAdjoint() == adjoint))) continue; - const auto& sol = solver->GetNodes()->GetSolution(); - for (auto iPoint = 0ul; iPoint < nPoint; ++iPoint) - for (auto iVar = 0ul; iVar < solver->GetnVar(); ++iVar) - solution(iPoint, offset + iVar) = SU2_TYPE::GetValue(sol(iPoint, iVar)); - offset += solver->GetnVar(); - } - } }; /*! diff --git a/SU2_CFD/include/drivers/CDriverBase.hpp b/SU2_CFD/include/drivers/CDriverBase.hpp index b6ceafcd4dcc..ae4581c74b2e 100644 --- a/SU2_CFD/include/drivers/CDriverBase.hpp +++ b/SU2_CFD/include/drivers/CDriverBase.hpp @@ -107,11 +107,6 @@ class CDriverBase { */ virtual void Update(){} - /*! - * \brief A virtual member. - */ - virtual void Update_Legacy(){} - /*! * \brief A virtual member. */ @@ -125,6 +120,54 @@ class CDriverBase { /// \addtogroup PySU2 /// @{ + /*! + * \brief Get the list of available outputs. + * \return List of output names. + */ + inline vector GetOutputNames() const { return output_container[MESH_0]->GetHistoryOutput_List(); } + + /*! + * \brief Get the value of one of the available history outputs. + * \return Value of the output. + */ + inline passivedouble GetOutputValue(std::string output_name) const { + return SU2_TYPE::GetValue(output_container[MESH_0]->GetHistoryFieldValue(output_name)); + } + + /*! + * \brief Get the list of available surface outputs on **both** MARKER_MONITORING and MARKER_ANALYZE. + * \return List of surface output names. + */ + inline vector GetMarkerOutputNames() const { + return output_container[MESH_0]->GetHistoryOutputPerSurface_List(); + } + + /*! + * \brief Get the value of one of the available surface outputs at a given MARKER_MONITORING. + * \return Value of the output. + */ + inline passivedouble GetMarkerMonitoringOutputValue(std::string output_name, std::string marker_monitoring) const { + for (auto iMarker = 0u; iMarker < main_config->GetnMarker_Monitoring(); ++iMarker) { + if (marker_monitoring == main_config->GetMarker_Monitoring_TagBound(iMarker)) + return SU2_TYPE::GetValue(output_container[MESH_0]->GetHistoryFieldValuePerSurface(output_name, iMarker)); + } + SU2_MPI::Error(marker_monitoring + " is not in MARKER_MONITORING.", CURRENT_FUNCTION); + return 0; + } + + /*! + * \brief Get the value of one of the available surface outputs at a given MARKER_ANALYZE. + * \return Value of the output. + */ + inline passivedouble GetMarkerAnalyzeOutputValue(std::string output_name, std::string marker_analyze) const { + for (auto iMarker = 0u; iMarker < main_config->GetnMarker_Analyze(); ++iMarker) { + if (marker_analyze == main_config->GetMarker_Analyze_TagBound(iMarker)) + return SU2_TYPE::GetValue(output_container[MESH_0]->GetHistoryFieldValuePerSurface(output_name, iMarker)); + } + SU2_MPI::Error(marker_analyze + " is not in MARKER_ANALYZE.", CURRENT_FUNCTION); + return 0; + } + /*! * \brief Get the number of design variables. * \return Number of design variables. diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp index 2dfe06835637..7163dd5dd45a 100644 --- a/SU2_CFD/include/output/COutput.hpp +++ b/SU2_CFD/include/output/COutput.hpp @@ -446,8 +446,11 @@ class COutput { * \param[in] field - Name of the field * \return Value of the field */ - su2double GetHistoryFieldValue(const string& field) const { - return historyOutput_Map.at(field).value; + su2double GetHistoryFieldValue(const string& name) const { + auto it = historyOutput_Map.find(name); + if (it != historyOutput_Map.end()) return it->second.value; + SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION); + return 0; } /*! @@ -456,8 +459,11 @@ class COutput { * \param[in] iMarker - Index of the surface marker * \return Value of the field */ - su2double GetHistoryFieldValuePerSurface(const string& field, unsigned short iMarker) const { - return historyOutputPerSurface_Map.at(field)[iMarker].value; + su2double GetHistoryFieldValuePerSurface(const string& name, unsigned short iMarker) const { + auto it = historyOutputPerSurface_Map.find(name); + if (it != historyOutputPerSurface_Map.end()) return it->second[iMarker].value; + SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION); + return 0; } /*! @@ -634,7 +640,7 @@ class COutput { if (it != historyOutput_Map.end()){ it->second.value = 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); } } @@ -718,7 +724,6 @@ class COutput { volumeOutput_List.push_back(name); } - /*! * \brief Set the value of a volume output field * \param[in] name - Name of the field. diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index ed0fb0f3a163..6abcdf13620c 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -1352,6 +1352,8 @@ void CFlowOutput::LoadSurfaceData(CConfig *config, CGeometry *geometry, CSolver void CFlowOutput::AddAerodynamicCoefficients(const CConfig* config) { /// BEGIN_GROUP: AERO_COEFF, DESCRIPTION: Sum of the aerodynamic coefficients and forces on all surfaces (markers) set with MARKER_MONITORING. + /// DESCRIPTION: Reference force for aerodynamic coefficients + AddHistoryOutput("REFERENCE_FORCE", "RefForce", ScreenOutputFormat::FIXED, "AERO_COEFF", "Reference force used to compute aerodynamic coefficients", HistoryFieldType::COEFFICIENT); /// DESCRIPTION: Drag coefficient AddHistoryOutput("DRAG", "CD", ScreenOutputFormat::FIXED, "AERO_COEFF", "Total drag coefficient on all surfaces set with MARKER_MONITORING", HistoryFieldType::COEFFICIENT); /// DESCRIPTION: Lift coefficient @@ -1409,6 +1411,7 @@ void CFlowOutput::AddAerodynamicCoefficients(const CConfig* config) { void CFlowOutput::SetAerodynamicCoefficients(const CConfig* config, const CSolver* flow_solver){ + SetHistoryOutputValue("REFERENCE_FORCE", flow_solver->GetAeroCoeffsReferenceForce()); SetHistoryOutputValue("DRAG", flow_solver->GetTotal_CD()); SetHistoryOutputValue("LIFT", flow_solver->GetTotal_CL()); if (nDim == 3) diff --git a/SU2_CFD/src/python_wrapper_structure.cpp b/SU2_CFD/src/python_wrapper_structure.cpp index 2585121a29e3..675c24e045a3 100644 --- a/SU2_CFD/src/python_wrapper_structure.cpp +++ b/SU2_CFD/src/python_wrapper_structure.cpp @@ -58,106 +58,6 @@ void CDriver::PythonInterfacePreprocessing(CConfig** config, CGeometry**** geome } } -///////////////////////////////////////////////////////////////////////////// -/* Functions related to the global performance indices (Lift, Drag, etc.) */ -///////////////////////////////////////////////////////////////////////////// - -passivedouble CDriver::Get_Drag() const { - unsigned short val_iZone = ZONE_0; - unsigned short FinestMesh = config_container[val_iZone]->GetFinestMesh(); - su2double CDrag, factor, val_Drag; - - /*--- Calculate drag force based on drag coefficient ---*/ - factor = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAeroCoeffsReferenceForce(); - CDrag = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CD(); - - val_Drag = CDrag * factor; - - return SU2_TYPE::GetValue(val_Drag); -} - -passivedouble CDriver::Get_Lift() const { - unsigned short val_iZone = ZONE_0; - unsigned short FinestMesh = config_container[val_iZone]->GetFinestMesh(); - su2double CLift, factor, val_Lift; - - /*--- Calculate drag force based on drag coefficient ---*/ - factor = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAeroCoeffsReferenceForce(); - CLift = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CL(); - - val_Lift = CLift * factor; - - return SU2_TYPE::GetValue(val_Lift); -} - -passivedouble CDriver::Get_Mx() const { - unsigned short val_iZone = ZONE_0; - unsigned short FinestMesh = config_container[val_iZone]->GetFinestMesh(); - su2double CMx, RefLengthCoeff, factor, val_Mx; - - RefLengthCoeff = config_container[val_iZone]->GetRefLength(); - - /*--- Calculate moment around x-axis based on coefficients ---*/ - factor = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAeroCoeffsReferenceForce(); - CMx = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMx(); - - val_Mx = CMx * factor * RefLengthCoeff; - - return SU2_TYPE::GetValue(val_Mx); -} - -passivedouble CDriver::Get_My() const { - unsigned short val_iZone = ZONE_0; - unsigned short FinestMesh = config_container[val_iZone]->GetFinestMesh(); - su2double CMy, RefLengthCoeff, factor, val_My; - - RefLengthCoeff = config_container[val_iZone]->GetRefLength(); - - /*--- Calculate moment around x-axis based on coefficients ---*/ - factor = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAeroCoeffsReferenceForce(); - CMy = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMy(); - - val_My = CMy * factor * RefLengthCoeff; - - return SU2_TYPE::GetValue(val_My); -} - -passivedouble CDriver::Get_Mz() const { - unsigned short val_iZone = ZONE_0; - unsigned short FinestMesh = config_container[val_iZone]->GetFinestMesh(); - su2double CMz, RefLengthCoeff, factor, val_Mz; - - RefLengthCoeff = config_container[val_iZone]->GetRefLength(); - - /*--- Calculate moment around z-axis based on coefficients ---*/ - factor = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAeroCoeffsReferenceForce(); - CMz = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMz(); - - val_Mz = CMz * factor * RefLengthCoeff; - - return SU2_TYPE::GetValue(val_Mz); -} - -passivedouble CDriver::Get_DragCoeff() const { - unsigned short val_iZone = ZONE_0; - unsigned short FinestMesh = config_container[val_iZone]->GetFinestMesh(); - su2double CDrag; - - CDrag = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CD(); - - return SU2_TYPE::GetValue(CDrag); -} - -passivedouble CDriver::Get_LiftCoeff() const { - unsigned short val_iZone = ZONE_0; - unsigned short FinestMesh = config_container[val_iZone]->GetFinestMesh(); - su2double CLift; - - CLift = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CL(); - - return SU2_TYPE::GetValue(CLift); -} - ////////////////////////////////////////////////////////////////////////////////// /* Functions to obtain global parameters from SU2 (time steps, delta t, etc.) */ ////////////////////////////////////////////////////////////////////////////////// diff --git a/SU2_DEF/src/drivers/CDeformationDriver.cpp b/SU2_DEF/src/drivers/CDeformationDriver.cpp index 6aa13a0d6c3e..3fab1454e095 100644 --- a/SU2_DEF/src/drivers/CDeformationDriver.cpp +++ b/SU2_DEF/src/drivers/CDeformationDriver.cpp @@ -268,11 +268,7 @@ void CDeformationDriver::Run() { /*--- Surface grid deformation using design variables. ---*/ - if (driver_config->GetDeform_Mesh()) { - Update(); - } else { - Update_Legacy(); - } + Update(); /*--- Synchronization point after a single solver iteration. Compute the wall clock time required. ---*/ @@ -294,6 +290,8 @@ void CDeformationDriver::Run() { } void CDeformationDriver::Update() { + if (!driver_config->GetDeform_Mesh()) return Update_Legacy(); + for (iZone = 0; iZone < nZone; iZone++) { /*--- Set the stiffness of each element mesh into the mesh numerics. ---*/ From 6647e7bcffd89bd09cdbe47a5cd23836cb5971ba Mon Sep 17 00:00:00 2001 From: Pedro Gomes Date: Wed, 29 Mar 2023 20:59:15 +0100 Subject: [PATCH 2/2] const& and use functions in test --- SU2_CFD/include/drivers/CDriverBase.hpp | 12 +++++++----- .../py_wrapper/deforming_bump_in_channel/run.py | 5 +++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/SU2_CFD/include/drivers/CDriverBase.hpp b/SU2_CFD/include/drivers/CDriverBase.hpp index ae4581c74b2e..0ca229de19de 100644 --- a/SU2_CFD/include/drivers/CDriverBase.hpp +++ b/SU2_CFD/include/drivers/CDriverBase.hpp @@ -124,13 +124,13 @@ class CDriverBase { * \brief Get the list of available outputs. * \return List of output names. */ - inline vector GetOutputNames() const { return output_container[MESH_0]->GetHistoryOutput_List(); } + inline vector GetOutputNames() const { return output_container[MESH_0]->GetHistoryOutputList(); } /*! * \brief Get the value of one of the available history outputs. * \return Value of the output. */ - inline passivedouble GetOutputValue(std::string output_name) const { + inline passivedouble GetOutputValue(const std::string& output_name) const { return SU2_TYPE::GetValue(output_container[MESH_0]->GetHistoryFieldValue(output_name)); } @@ -139,14 +139,15 @@ class CDriverBase { * \return List of surface output names. */ inline vector GetMarkerOutputNames() const { - return output_container[MESH_0]->GetHistoryOutputPerSurface_List(); + return output_container[MESH_0]->GetHistoryOutputPerSurfaceList(); } /*! * \brief Get the value of one of the available surface outputs at a given MARKER_MONITORING. * \return Value of the output. */ - inline passivedouble GetMarkerMonitoringOutputValue(std::string output_name, std::string marker_monitoring) const { + inline passivedouble GetMarkerMonitoringOutputValue(const std::string& output_name, + const std::string& marker_monitoring) const { for (auto iMarker = 0u; iMarker < main_config->GetnMarker_Monitoring(); ++iMarker) { if (marker_monitoring == main_config->GetMarker_Monitoring_TagBound(iMarker)) return SU2_TYPE::GetValue(output_container[MESH_0]->GetHistoryFieldValuePerSurface(output_name, iMarker)); @@ -159,7 +160,8 @@ class CDriverBase { * \brief Get the value of one of the available surface outputs at a given MARKER_ANALYZE. * \return Value of the output. */ - inline passivedouble GetMarkerAnalyzeOutputValue(std::string output_name, std::string marker_analyze) const { + inline passivedouble GetMarkerAnalyzeOutputValue(const std::string& output_name, + const std::string& marker_analyze) const { for (auto iMarker = 0u; iMarker < main_config->GetnMarker_Analyze(); ++iMarker) { if (marker_analyze == main_config->GetMarker_Analyze_TagBound(iMarker)) return SU2_TYPE::GetValue(output_container[MESH_0]->GetHistoryFieldValuePerSurface(output_name, iMarker)); diff --git a/TestCases/py_wrapper/deforming_bump_in_channel/run.py b/TestCases/py_wrapper/deforming_bump_in_channel/run.py index 3228b6ae9a43..894315baff06 100755 --- a/TestCases/py_wrapper/deforming_bump_in_channel/run.py +++ b/TestCases/py_wrapper/deforming_bump_in_channel/run.py @@ -88,6 +88,11 @@ def main(): TimeIter += 1 time += deltaT + # Check the value of an output to cover the functionality in a regression test. + assert 'DRAG' in SU2Driver.GetOutputNames() + assert abs(SU2Driver.GetOutputValue('DRAG') - + SU2Driver.GetMarkerMonitoringOutputValue('DRAG_ON_SURFACE', MarkerName)) < np.finfo(float).eps + # Finalize the solver and exit cleanly SU2Driver.Finalize()