diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index f8c3bde89bd5..c203c00285ba 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -396,7 +396,6 @@ class CConfig { unsigned long OuterIter; /*!< \brief Current Outer iterations for multizone problems. */ unsigned long InnerIter; /*!< \brief Current inner iterations for multizone problems. */ unsigned long TimeIter; /*!< \brief Current time iterations for multizone problems. */ - unsigned long Unst_nIntIter; /*!< \brief Number of internal iterations (Dual time Method). */ long Unst_RestartIter; /*!< \brief Iteration number to restart an unsteady simulation (Dual time Method). */ long Unst_AdjointIter; /*!< \brief Iteration number to begin the reverse time integration in the direct solver for the unsteady adjoint. */ long Iter_Avg_Objective; /*!< \brief Iteration the number of time steps to be averaged, counting from the back */ @@ -729,7 +728,6 @@ class CConfig { RefElemLength, /*!< \brief Reference element length for computing the slope limiting epsilon. */ RefSharpEdges, /*!< \brief Reference coefficient for detecting sharp edges. */ RefLength, /*!< \brief Reference length for moment computation. */ - *RefOriginMoment, /*!< \brief Origin for moment computation. */ *RefOriginMoment_X, /*!< \brief X Origin for moment computation. */ *RefOriginMoment_Y, /*!< \brief Y Origin for moment computation. */ *RefOriginMoment_Z, /*!< \brief Z Origin for moment computation. */ @@ -1370,7 +1368,8 @@ class CConfig { * \param[in] val_marker - the marker we are monitoring. * \return Reference origin (in cartesians coordinates) for moment computation. */ - su2double *GetRefOriginMoment(unsigned short val_marker) { + std::array GetRefOriginMoment(unsigned short val_marker) const { + std::array RefOriginMoment{{0.0}}; if(val_marker < nMarker_Monitoring) { RefOriginMoment[0] = RefOriginMoment_X[val_marker]; RefOriginMoment[1] = RefOriginMoment_Y[val_marker]; @@ -2937,12 +2936,6 @@ class CConfig { */ void SetnMarker_All(unsigned short val_nmarker) { nMarker_All = val_nmarker; } - /*! - * \brief Get the number of internal iterations. - * \return Number of internal iterations. - */ - unsigned long GetUnst_nIntIter(void) const { return Unst_nIntIter; } - /*! * \brief Get the starting direct iteration number for the unsteady adjoint (reverse time integration). * \return Starting direct iteration number for the unsteady adjoint. @@ -5388,12 +5381,6 @@ class CConfig { */ string GetVolume_FileName(void) const { return Volume_FileName; } - /*! - * \brief Get the name of the restart file for the heat variables. - * \return Name of the restart file for the flow variables. - */ - string GetRestart_HeatFileName(void); - /*! * \brief Add any numbers necessary to the filename (iteration number, zone ID ...) * \param[in] config - Definition of the particular problem. @@ -5401,7 +5388,7 @@ class CConfig { * \param[in] ext - the extension to be added. * \return The new filename */ - string GetFilename(string filename, string ext, unsigned long Iter); + string GetFilename(string filename, string ext, unsigned long Iter) const; /*! * \brief Append the zone index to the restart or the solution files. @@ -5419,13 +5406,13 @@ class CConfig { * \brief Append the instance index to the restart or the solution files. * \return Name of the restart file for the flow variables. */ - string GetMultiInstance_FileName(string val_filename, int val_iInst, string ext); + string GetMultiInstance_FileName(string val_filename, int val_iInst, string ext) const; /*! * \brief Append the instance index to the restart or the solution files. * \return Name of the restart file for the flow variables. */ - string GetMultiInstance_HistoryFileName(string val_filename, int val_iInst); + string GetMultiInstance_HistoryFileName(string val_filename, int val_iInst) const; /*! * \brief Get the name of the restart file for the flow variables. @@ -5494,7 +5481,7 @@ class CConfig { * \param[in] val_filename - String value of the base filename. * \return Name of the file with the appropriate objective function extension. */ - string GetObjFunc_Extension(string val_filename); + string GetObjFunc_Extension(string val_filename) const; /*! * \brief Get the criteria for structural residual (relative/absolute). @@ -6566,7 +6553,7 @@ class CConfig { * \param[in] val_index - Index corresponding to the inlet boundary. * \return The flow direction vector. */ - su2double* GetInlet_FlowDir(string val_index); + const su2double* GetInlet_FlowDir(string val_index) const; /*! * \brief Get the back pressure (static) at an outlet boundary. @@ -8367,14 +8354,14 @@ class CConfig { * \brief Start the timer for profiling subroutines. * \param[in] val_start_time - the value of the start time. */ - void GEMM_Tick(double *val_start_time); + void GEMM_Tick(double *val_start_time) const; /*! * \brief Stop the timer for the GEMM profiling and store results. * \param[in] val_start_time - The value of the start time. * \param[in] M, N, K - Matrix size of the GEMM call. */ - void GEMM_Tock(double val_start_time, int M, int N, int K); + void GEMM_Tock(double val_start_time, int M, int N, int K) const; /*! * \brief Write a CSV file containing the results of the profiling. diff --git a/Common/include/blas_structure.hpp b/Common/include/blas_structure.hpp index 0d9a4a7c90d6..8d26a09382e6 100644 --- a/Common/include/blas_structure.hpp +++ b/Common/include/blas_structure.hpp @@ -29,13 +29,13 @@ #pragma once -#include "CConfig.hpp" - /* LIBXSMM include files, if supported. */ #ifdef HAVE_LIBXSMM #include "libxsmm.h" #endif +class CConfig; + /*! * \class CBlasStructure * \brief Class, which serves as an interface to the BLAS functionalities needed. @@ -66,7 +66,7 @@ class CBlasStructure { */ void gemm(const int M, const int N, const int K, const su2double *A, const su2double *B, su2double *C, - CConfig *config); + const CConfig *config); /*! * \brief Function, which carries out a dense matrix vector product diff --git a/Common/include/omp_structure.hpp b/Common/include/omp_structure.hpp index 813c2f760260..5ed0fbbceb2b 100644 --- a/Common/include/omp_structure.hpp +++ b/Common/include/omp_structure.hpp @@ -39,6 +39,7 @@ #pragma once #include +#include #if defined(_MSC_VER) #define PRAGMIZE(X) __pragma(X) diff --git a/Common/include/toolboxes/geometry_toolbox.hpp b/Common/include/toolboxes/geometry_toolbox.hpp index 17e6a19cbd93..43c5475a4675 100644 --- a/Common/include/toolboxes/geometry_toolbox.hpp +++ b/Common/include/toolboxes/geometry_toolbox.hpp @@ -26,6 +26,8 @@ #pragma once +#include + namespace GeometryToolbox { /*! \return ||a-b||^2 */ diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 1d50138f570d..c5db0cd8367b 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -911,7 +911,6 @@ void CConfig::SetPointersNull(void) { Velocity_FreeStream = nullptr; Inc_Velocity_Init = nullptr; - RefOriginMoment = nullptr; CFL_AdaptParam = nullptr; CFL = nullptr; HTP_Axis = nullptr; @@ -3856,10 +3855,6 @@ void CConfig::SetPostprocessing(unsigned short val_software, unsigned short val_ }*/ - /*--- Initialize the RefOriginMoment Pointer ---*/ - - RefOriginMoment = new su2double[3](); - /*--- In case the moment origin coordinates have not been declared in the config file, set them equal to zero for safety. Also check to make sure that for each marker, a value has been declared for the moment origin. @@ -6216,11 +6211,11 @@ void CConfig::SetOutput(unsigned short val_software, unsigned short val_izone) { case TIME_STEPPING: cout << "Unsteady simulation using a time stepping strategy."<< endl; if (Unst_CFL != 0.0) { - cout << "Time step computed by the code. Unsteady CFL number: " << Unst_CFL <<"."<< endl; - if (Delta_UnstTime != 0.0) { - cout << "Synchronization time provided by the user (s): "<< Delta_UnstTime << "." << endl; - } - } + cout << "Time step computed by the code. Unsteady CFL number: " << Unst_CFL <<"."<< endl; + if (Delta_UnstTime != 0.0) { + cout << "Synchronization time provided by the user (s): "<< Delta_UnstTime << "." << endl; + } + } else cout << "Unsteady time step provided by the user (s): "<< Delta_UnstTime << "." << endl; break; case DT_STEPPING_1ST: case DT_STEPPING_2ND: @@ -6228,16 +6223,16 @@ void CConfig::SetOutput(unsigned short val_software, unsigned short val_izone) { if (TimeMarching == DT_STEPPING_2ND) cout << "Unsteady simulation, dual time stepping strategy (second order in time)."<< endl; if (Unst_CFL != 0.0) cout << "Time step computed by the code. Unsteady CFL number: " << Unst_CFL <<"."<< endl; else cout << "Unsteady time step provided by the user (s): "<< Delta_UnstTime << "." << endl; - cout << "Total number of internal Dual Time iterations: "<< Unst_nIntIter <<"." << endl; + cout << "Total number of internal Dual Time iterations: "<< InnerIter <<"." << endl; break; } } else { if (Time_Domain) { - cout << "Dynamic structural analysis."<< endl; - cout << "Time step provided by the user for the dynamic analysis(s): "<< Delta_DynTime << "." << endl; - } else { - cout << "Static structural analysis." << endl; + cout << "Dynamic structural analysis."<< endl; + cout << "Time step provided by the user for the dynamic analysis(s): "<< Delta_DynTime << "." << endl; + } else { + cout << "Static structural analysis." << endl; } } @@ -7296,7 +7291,6 @@ CConfig::~CConfig(void) { /*--- reference origin for moments ---*/ - delete [] RefOriginMoment; delete [] RefOriginMoment_X; delete [] RefOriginMoment_Y; delete [] RefOriginMoment_Z; @@ -7667,7 +7661,7 @@ CConfig::~CConfig(void) { } -string CConfig::GetFilename(string filename, string ext, unsigned long Iter){ +string CConfig::GetFilename(string filename, string ext, unsigned long Iter) const { /*--- Remove any extension --- */ @@ -7755,33 +7749,33 @@ string CConfig::GetMultizone_HistoryFileName(string val_filename, int val_iZone, return multizone_filename; } -string CConfig::GetMultiInstance_FileName(string val_filename, int val_iInst, string ext) { +string CConfig::GetMultiInstance_FileName(string val_filename, int val_iInst, string ext) const { - string multizone_filename = val_filename; - char buffer[50]; + string multizone_filename = val_filename; + char buffer[50]; - unsigned short lastindex = multizone_filename.find_last_of("."); - multizone_filename = multizone_filename.substr(0, lastindex); - SPRINTF (buffer, "_%d", SU2_TYPE::Int(val_iInst)); - multizone_filename.append(string(buffer)); - multizone_filename += ext; - return multizone_filename; + unsigned short lastindex = multizone_filename.find_last_of("."); + multizone_filename = multizone_filename.substr(0, lastindex); + SPRINTF (buffer, "_%d", SU2_TYPE::Int(val_iInst)); + multizone_filename.append(string(buffer)); + multizone_filename += ext; + return multizone_filename; } -string CConfig::GetMultiInstance_HistoryFileName(string val_filename, int val_iInst) { +string CConfig::GetMultiInstance_HistoryFileName(string val_filename, int val_iInst) const { - string multizone_filename = val_filename; - char buffer[50]; + string multizone_filename = val_filename; + char buffer[50]; - unsigned short lastindex = multizone_filename.find_last_of("."); - multizone_filename = multizone_filename.substr(0, lastindex); - SPRINTF (buffer, "_%d", SU2_TYPE::Int(val_iInst)); - multizone_filename.append(string(buffer)); + unsigned short lastindex = multizone_filename.find_last_of("."); + multizone_filename = multizone_filename.substr(0, lastindex); + SPRINTF (buffer, "_%d", SU2_TYPE::Int(val_iInst)); + multizone_filename.append(string(buffer)); - return multizone_filename; + return multizone_filename; } -string CConfig::GetObjFunc_Extension(string val_filename) { +string CConfig::GetObjFunc_Extension(string val_filename) const { string AdjExt, Filename = val_filename; @@ -8359,7 +8353,7 @@ void CConfig::SetInlet_Ptotal(su2double val_pressure, string val_marker) { Inlet_Ptotal[iMarker_Inlet] = val_pressure; } -su2double* CConfig::GetInlet_FlowDir(string val_marker) { +const su2double* CConfig::GetInlet_FlowDir(string val_marker) const { unsigned short iMarker_Inlet; for (iMarker_Inlet = 0; iMarker_Inlet < nMarker_Inlet; iMarker_Inlet++) if (Marker_Inlet[iMarker_Inlet] == val_marker) break; @@ -9263,7 +9257,7 @@ void CConfig::SetProfilingCSV(void) { } -void CConfig::GEMM_Tick(double *val_start_time) { +void CConfig::GEMM_Tick(double *val_start_time) const { #ifdef PROFILE @@ -9277,7 +9271,7 @@ void CConfig::GEMM_Tick(double *val_start_time) { } -void CConfig::GEMM_Tock(double val_start_time, int M, int N, int K) { +void CConfig::GEMM_Tock(double val_start_time, int M, int N, int K) const { #ifdef PROFILE diff --git a/Common/src/blas_structure.cpp b/Common/src/blas_structure.cpp index 6b8c1dde63bc..8a61091f9564 100644 --- a/Common/src/blas_structure.cpp +++ b/Common/src/blas_structure.cpp @@ -7,7 +7,7 @@ * * SU2 Project Website: https://su2code.github.io * - * The SU2 Project is maintained by the SU2 Foundation + * The SU2 Project is maintained by the SU2 Foundation * (http://su2foundation.org) * * Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md) @@ -26,6 +26,7 @@ * License along with SU2. If not, see . */ +#include "../include/CConfig.hpp" #include "../include/blas_structure.hpp" #include @@ -46,7 +47,7 @@ extern "C" void dgemv_(char*, const int*, const int*, const passivedouble*, /* Constructor. Initialize the const member variables, if needed. */ CBlasStructure::CBlasStructure(void) #if !(defined(HAVE_LIBXSMM) || defined(HAVE_BLAS) || defined(HAVE_MKL)) || (defined(CODI_REVERSE_TYPE) || defined(CODI_FORWARD_TYPE)) - : mc (256), kc (128), nc (128) + : mc (256), kc (128), nc (128) #endif {} @@ -56,7 +57,7 @@ CBlasStructure::~CBlasStructure(void) {} /* Dense matrix multiplication, gemm functionality. */ void CBlasStructure::gemm(const int M, const int N, const int K, const su2double *A, const su2double *B, su2double *C, - CConfig *config) { + const CConfig *config) { /* Initialize the variable for the timing, if profiling is active. */ #ifdef PROFILE @@ -124,7 +125,7 @@ void CBlasStructure::gemv(const int M, const int N, const su2double *A, /* Native implementation of the matix vector product. Initialize the elements of y to zero. */ - memset(y, 0, M*sizeof(su2double)); + memset(y, 0, M*sizeof(su2double)); /* Carry out the matrix vector product. */ for(int k=0; kval_marker where the coefficient is evaluated. * \return Value of the pressure coefficient. */ - inline su2double *GetDonorAdjVar(unsigned short val_marker, unsigned long val_vertex) const final { + inline su2double *GetDonorAdjVar(unsigned short val_marker, unsigned long val_vertex) const { return DonorAdjVar[val_marker][val_vertex]; } @@ -249,7 +249,7 @@ class CAdjEulerSolver : public CSolver { inline void SetDonorAdjVar(unsigned short val_marker, unsigned long val_vertex, unsigned short val_var, - su2double val_value) final { + su2double val_value) { DonorAdjVar[val_marker][val_vertex][val_var] = val_value; } @@ -261,7 +261,7 @@ class CAdjEulerSolver : public CSolver { */ inline su2double GetDonorAdjVar(unsigned short val_marker, unsigned long val_vertex, - unsigned short val_var) const final { + unsigned short val_var) const { return DonorAdjVar[val_marker][val_vertex][val_var]; } diff --git a/SU2_CFD/include/solvers/CBaselineSolver.hpp b/SU2_CFD/include/solvers/CBaselineSolver.hpp index 6a18187d13c2..179158381a5e 100644 --- a/SU2_CFD/include/solvers/CBaselineSolver.hpp +++ b/SU2_CFD/include/solvers/CBaselineSolver.hpp @@ -100,4 +100,4 @@ class CBaselineSolver final : public CSolver { */ void SetOutputVariables(CGeometry *geometry, CConfig *config); -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CEulerSolver.hpp b/SU2_CFD/include/solvers/CEulerSolver.hpp index 8d973b101eec..76fcca510f51 100644 --- a/SU2_CFD/include/solvers/CEulerSolver.hpp +++ b/SU2_CFD/include/solvers/CEulerSolver.hpp @@ -27,9 +27,8 @@ #pragma once -#include "CSolver.hpp" +#include "CFVMFlowSolverBase.hpp" #include "../variables/CEulerVariable.hpp" -#include "../../../Common/include/omp_structure.hpp" /*! * \class CSolver @@ -37,100 +36,16 @@ * a child class for each particular solver (Euler, Navier-Stokes, etc.) * \author F. Palacios */ -class CEulerSolver : public CSolver { +class CEulerSolver : public CFVMFlowSolverBase { protected: - enum : size_t {MAXNDIM = 3}; /*!< \brief Max number of space dimensions, used in some static arrays. */ - enum : size_t {MAXNVAR = 12}; /*!< \brief Max number of variables, used in some static arrays. */ - - enum : size_t {OMP_MAX_SIZE = 512}; /*!< \brief Max chunk size for light point loops. */ - enum : size_t {OMP_MIN_SIZE = 32}; /*!< \brief Min chunk size for edge loops (max is color group size). */ - - unsigned long omp_chunk_size; /*!< \brief Chunk size used in light point loops. */ - - su2double - Mach_Inf = 0.0, /*!< \brief Mach number at the infinity. */ - Density_Inf = 0.0, /*!< \brief Density at the infinity. */ - Energy_Inf = 0.0, /*!< \brief Energy at the infinity. */ - Temperature_Inf = 0.0, /*!< \brief Energy at the infinity. */ - Pressure_Inf = 0.0, /*!< \brief Pressure at the infinity. */ - *Velocity_Inf = nullptr; /*!< \brief Flow Velocity vector at the infinity. */ - su2double Prandtl_Lam = 0.0, /*!< \brief Laminar Prandtl number. */ Prandtl_Turb = 0.0; /*!< \brief Turbulent Prandtl number. */ - /*! - * \brief Auxilary types to store common aero coefficients (avoids repeating oneself so much). - */ - struct AeroCoeffsArray { - su2double* CD = nullptr; /*!< \brief Drag coefficient. */ - su2double* CL = nullptr; /*!< \brief Lift coefficient. */ - su2double* CSF = nullptr; /*!< \brief Sideforce coefficient. */ - su2double* CEff = nullptr; /*!< \brief Efficiency (Cl/Cd). */ - su2double* CFx = nullptr; /*!< \brief x Force coefficient. */ - su2double* CFy = nullptr; /*!< \brief y Force coefficient. */ - su2double* CFz = nullptr; /*!< \brief z Force coefficient. */ - su2double* CMx = nullptr; /*!< \brief x Moment coefficient. */ - su2double* CMy = nullptr; /*!< \brief y Moment coefficient. */ - su2double* CMz = nullptr; /*!< \brief z Moment coefficient. */ - su2double* CoPx = nullptr; /*!< \brief x Moment coefficient. */ - su2double* CoPy = nullptr; /*!< \brief y Moment coefficient. */ - su2double* CoPz = nullptr; /*!< \brief z Moment coefficient. */ - su2double* CT = nullptr; /*!< \brief Thrust coefficient. */ - su2double* CQ = nullptr; /*!< \brief Torque coefficient. */ - su2double* CMerit = nullptr; /*!< \brief Rotor Figure of Merit. */ - int _size = 0; /*!< \brief Array size. */ - - void allocate(int size); /*!< \brief Allocates arrays. */ - - void setZero(int i); /*!< \brief Sets all values to zero at a particular index. */ - void setZero() { /*!< \brief Sets all values to zero for all indices. */ - for(int i=0; i<_size; ++i) setZero(i); - } - - AeroCoeffsArray(int size = 0) : _size(size) { if(size) allocate(size); } - - ~AeroCoeffsArray(); - }; - /*! - * \brief Scalar version of the coefficients type. - */ - struct AeroCoeffs { - su2double CD,CL,CSF,CEff,CFx,CFy,CFz,CMx,CMy,CMz,CoPx,CoPy,CoPz,CT,CQ,CMerit; - - void setZero() { - CD=CL=CSF=CEff=CFx=CFy=CFz=CMx=CMy=CMz=CoPx=CoPy=CoPz=CT=CQ=CMerit=0.0; - } - - AeroCoeffs() { setZero(); } - }; - - AeroCoeffsArray InvCoeff; /*!< \brief Inviscid pressure contributions for each boundary. */ - AeroCoeffsArray SurfaceInvCoeff; /*!< \brief Inviscid pressure contributions for each monitoring boundary. */ - AeroCoeffs AllBoundInvCoeff; /*!< \brief Total pressure contribution for all the boundaries. */ - - AeroCoeffsArray MntCoeff; /*!< \brief Inviscid momentum contributions for each boundary. */ - AeroCoeffsArray SurfaceMntCoeff; /*!< \brief Inviscid momentum contributions for each monitoring boundary. */ - AeroCoeffs AllBoundMntCoeff; /*!< \brief Total momentum contribution for all the boundaries. */ - - AeroCoeffsArray SurfaceCoeff; /*!< \brief Totals for each monitoring surface. */ - AeroCoeffs TotalCoeff; /*!< \brief Totals for all boundaries. */ - - su2double - AllBound_CEquivArea_Inv = 0.0, /*!< \brief equivalent area coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CNearFieldOF_Inv = 0.0, /*!< \brief Near-Field press coefficient (inviscid contribution) for all the boundaries. */ - *CEquivArea_Inv = nullptr, /*!< \brief Equivalent area (inviscid contribution) for each boundary. */ - *CNearFieldOF_Inv = nullptr; /*!< \brief Near field pressure (inviscid contribution) for each boundary. */ - su2double + AllBound_CEquivArea_Inv = 0.0, /*!< \brief equivalent area coefficient (inviscid contribution) for all the boundaries. */ *CEquivArea_Mnt = nullptr, /*!< \brief Equivalent area (inviscid contribution) for each boundary. */ - **CPressure = nullptr, /*!< \brief Pressure coefficient for each boundary and vertex. */ - **CPressureTarget = nullptr, /*!< \brief Target Pressure coefficient for each boundary and vertex. */ - **HeatFlux = nullptr, /*!< \brief Heat transfer coefficient for each boundary and vertex. */ - **HeatFluxTarget = nullptr, /*!< \brief Heat transfer coefficient for each boundary and vertex. */ - **YPlus = nullptr, /*!< \brief Yplus for each boundary and vertex. */ - ***CharacPrimVar = nullptr, /*!< \brief Value of the characteristic variables at each boundary. */ - ***DonorPrimVar = nullptr; /*!< \brief Value of the donor variables at each boundary. */ + *CEquivArea_Inv = nullptr; /*!< \brief Equivalent area (inviscid contribution) for each boundary. */ su2double *Inflow_MassFlow = nullptr, /*!< \brief Mass flow rate for each boundary. */ @@ -149,11 +64,9 @@ class CEulerSolver : public CSolver { unsigned long **DonorGlobalIndex = nullptr; /*!< \brief Value of the donor global index. */ su2double + ***DonorPrimVar = nullptr, /*!< \brief Value of the donor variables at each boundary. */ **ActDisk_DeltaP = nullptr, /*!< \brief Value of the Delta P. */ - **ActDisk_DeltaT = nullptr, /*!< \brief Value of the Delta T. */ - **Inlet_Ptotal = nullptr, /*!< \brief Value of the Total P. */ - **Inlet_Ttotal = nullptr, /*!< \brief Value of the Total T. */ - ***Inlet_FlowDir = nullptr; /*!< \brief Value of the Flow Direction. */ + **ActDisk_DeltaT = nullptr; /*!< \brief Value of the Delta T. */ su2activevector ActDisk_R; /*!< \brief Value of the actuator disk Radius. */ @@ -167,7 +80,6 @@ class CEulerSolver : public CSolver { **ActDisk_Fz; /*!< \brief Value of the actuator disk Z component of the radial and tangential forces per Unit Area resultant. */ su2double - Total_ComboObj = 0.0, /*!< \brief Total 'combo' objective for all monitored boundaries */ Total_CL_Prev = 0.0, /*!< \brief Total lift coefficient for all the boundaries (fixed lift mode). */ Total_SolidCD = 0.0, /*!< \brief Total drag coefficient for all the boundaries. */ Total_CD_Prev = 0.0, /*!< \brief Total drag coefficient for all the boundaries (fixed lift mode). */ @@ -183,28 +95,11 @@ class CEulerSolver : public CSolver { Total_ByPassProp_Eff = 0.0, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ Total_Adiab_Eff = 0.0, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ Total_Poly_Eff = 0.0, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ - Total_Custom_ObjFunc = 0.0, /*!< \brief Total custom objective function for all the boundaries. */ Total_CMx_Prev = 0.0, /*!< \brief Total drag coefficient for all the boundaries (fixed lift mode). */ Total_CMy_Prev = 0.0, /*!< \brief Total drag coefficient for all the boundaries (fixed lift mode). */ Total_CMz_Prev = 0.0, /*!< \brief Total drag coefficient for all the boundaries (fixed lift mode). */ - Total_Heat = 0.0, /*!< \brief Total heat load for all the boundaries. */ - Total_MaxHeat = 0.0, /*!< \brief Maximum heat flux on all boundaries. */ Total_AeroCD = 0.0, /*!< \brief Total aero drag coefficient for all the boundaries. */ - Total_CEquivArea = 0.0, /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ - Total_CNearFieldOF = 0.0, /*!< \brief Total Near-Field Pressure coefficient for all the boundaries. */ - Total_CpDiff = 0.0, /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ - Total_HeatFluxDiff = 0.0, /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ - Total_MassFlowRate = 0.0; /*!< \brief Total Mass Flow Rate on monitored boundaries. */ - - su2double - *Surface_HF_Visc = nullptr, /*!< \brief Total (integrated) heat flux for each monitored surface. */ - *Surface_MaxHF_Visc = nullptr; /*!< \brief Maximum heat flux for each monitored surface. */ - - bool space_centered, /*!< \brief True if space centered scheeme used. */ - euler_implicit, /*!< \brief True if euler implicit scheme used. */ - least_squares; /*!< \brief True if computing gradients by least squares. */ - su2double Gamma; /*!< \brief Fluid's Gamma constant (ratio of specific heats). */ - su2double Gamma_Minus_One; /*!< \brief Fluids's Gamma - 1.0 . */ + Total_CEquivArea = 0.0; /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ su2double AoA_Prev, /*!< \brief Old value of the angle of attack (monitored). */ AoA_inc; @@ -266,40 +161,6 @@ class CEulerSolver : public CSolver { /*--- End of Turbomachinery Solver Variables ---*/ - /*--- Sliding meshes variables ---*/ - - su2double ****SlidingState = nullptr; - int **SlidingStateNodes = nullptr; - - /*--- Shallow copy of grid coloring for OpenMP parallelization. ---*/ - -#ifdef HAVE_OMP - vector > EdgeColoring; /*!< \brief Edge colors. */ - bool ReducerStrategy = false; /*!< \brief If the reducer strategy is in use. */ -#else - array,1> EdgeColoring; - /*--- Never use the reducer strategy if compiling for MPI-only. ---*/ - static constexpr bool ReducerStrategy = false; -#endif - - /*--- Edge fluxes, for OpenMP parallelization off difficult-to-color grids. - * We first store the fluxes and then compute the sum for each cell. - * This strategy is thread-safe but lower performance than writting to both - * end points of each edge, so we only use it when necessary, i.e. when the - * coloring does not allow "enough" parallelism. ---*/ - - CSysVector EdgeFluxes; /*!< \brief Flux across each edge. */ - - /*! - * \brief The highest level in the variable hierarchy this solver can safely use. - */ - CEulerVariable* nodes = nullptr; - - /*! - * \brief Return nodes to allow CSolver::base_nodes to be set. - */ - inline CVariable* GetBaseClassPointerToNodes() final { return nodes; } - /*! * \brief Generic implementation of explicit iterations (RK, Classic RK and EULER). */ @@ -412,14 +273,17 @@ class CEulerSolver : public CSolver { virtual unsigned long SetPrimitive_Variables(CSolver **solver_container, CConfig *config, bool Output); -protected: + /*! + * \brief Set gradients of coefficients for fixed CL mode + * \param[in] config - Definition of the particular problem. + */ + void SetCoefficient_Gradients(CConfig *config) const; public: - /*! * \brief Constructor of the class. */ - CEulerSolver(void); + CEulerSolver() : CFVMFlowSolverBase() {} /*! * \overload Main constructor of this class. @@ -448,55 +312,6 @@ class CEulerSolver : public CSolver { */ inline CFluidModel* GetFluidModel(void) const final { return FluidModel[omp_get_thread_num()]; } - /*! - * \brief Compute the density at the infinity. - * \return Value of the density at the infinity. - */ - inline su2double GetDensity_Inf(void) const final { return Density_Inf; } - - /*! - * \brief Compute 2-norm of the velocity at the infinity. - * \return Value of the 2-norm of the velocity at the infinity. - */ - inline su2double GetModVelocity_Inf(void) const final { - su2double Vel2 = 0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Vel2 += Velocity_Inf[iDim]*Velocity_Inf[iDim]; - return sqrt(Vel2); - } - - /*! - * \brief Compute the density multiply by energy at the infinity. - * \return Value of the density multiply by energy at the infinity. - */ - inline su2double GetDensity_Energy_Inf(void) const final { return Density_Inf*Energy_Inf; } - - /*! - * \brief Compute the pressure at the infinity. - * \return Value of the pressure at the infinity. - */ - inline su2double GetPressure_Inf(void) const final { return Pressure_Inf; } - - /*! - * \brief Compute the density multiply by velocity at the infinity. - * \param[in] val_dim - Index of the velocity vector. - * \return Value of the density multiply by the velocity at the infinity. - */ - inline su2double GetDensity_Velocity_Inf(unsigned short val_dim) const final { return Density_Inf*Velocity_Inf[val_dim]; } - - /*! - * \brief Get the velocity at the infinity. - * \param[in] val_dim - Index of the velocity vector. - * \return Value of the velocity at the infinity. - */ - inline su2double GetVelocity_Inf(unsigned short val_dim) const final { return Velocity_Inf[val_dim]; } - - /*! - * \brief Get the velocity at the infinity. - * \return Value of the velocity at the infinity. - */ - inline su2double *GetVelocity_Inf(void) final { return Velocity_Inf; } - /*! * \brief Compute the time step for solving the Euler equations. * \param[in] geometry - Geometrical definition of the problem. @@ -629,35 +444,6 @@ class CEulerSolver : public CSolver { unsigned short RunTime_EqSystem, bool Output) override; - /*! - * \brief Compute the gradient of the primitive variables using Green-Gauss method, - * and stores the result in the Gradient_Primitive variable. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] reconstruction - indicator that the gradient being computed is for upwind reconstruction. - */ - void SetPrimitive_Gradient_GG(CGeometry *geometry, - const CConfig *config, - bool reconstruction = false) final; - - /*! - * \brief Compute the gradient of the primitive variables using a Least-Squares method, - * and stores the result in the Gradient_Primitive variable. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] reconstruction - indicator that the gradient being computed is for upwind reconstruction. - */ - void SetPrimitive_Gradient_LS(CGeometry *geometry, - const CConfig *config, - bool reconstruction = false) final; - - /*! - * \brief Compute the limiter of the primitive variables. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void SetPrimitive_Limiter(CGeometry *geometry, const CConfig *config) final; - /*! * \brief Compute the preconditioner for convergence acceleration by Roe-Turkel method. * \param[in] config - Definition of the particular problem. @@ -673,7 +459,7 @@ class CEulerSolver : public CSolver { * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - void Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) final; + void Set_MPI_Nearfield(CGeometry *geometry, CConfig *config); /*! * \author H. Kline @@ -682,24 +468,6 @@ class CEulerSolver : public CSolver { */ void Evaluate_ObjFunc(CConfig *config) override; - /*! - * \author: T. Kattmann - * - * \brief Impose via the residual the Euler wall boundary condition. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Euler_Wall(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) override; - /*! * \brief Impose the far-field boundary condition using characteristics. * \param[in] geometry - Geometrical definition of the problem. @@ -716,36 +484,6 @@ class CEulerSolver : public CSolver { CConfig *config, unsigned short val_marker) final; - /*! - * \brief Impose the symmetry boundary condition using the residual. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Sym_Plane(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) final; - - /*! - * \brief Impose the interface state across sliding meshes. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - */ - void BC_Fluid_Interface(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config) final; - /*! * \brief Impose the engine inflow boundary condition. * \param[in] geometry - Geometrical definition of the problem. @@ -839,18 +577,6 @@ class CEulerSolver : public CSolver { CConfig *config, unsigned short val_marker) final; - /*! - * \brief Impose a periodic boundary condition by summing contributions from the complete control volume. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - */ - void BC_Periodic(CGeometry *geometry, - CSolver **solver_container, - CNumerics *numerics, - CConfig *config) final; - /*! * \author: G.Gori, S.Vitale, M.Pini, A.Guardone, P.Colonna * @@ -963,22 +689,6 @@ class CEulerSolver : public CSolver { CConfig *config, unsigned short val_marker) final; - /*! - * \brief Impose a custom or verification boundary condition. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the convective numerical method. - * \param[in] visc_numerics - Description of the viscous numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Custom(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) final; - /*! * \brief Impose the outlet boundary condition. * \param[in] geometry - Geometrical definition of the problem. @@ -1095,12 +805,6 @@ class CEulerSolver : public CSolver { */ inline su2double GetAoA_inc(void) const final { return AoA_inc; } - /*! - * \brief Set gradients of coefficients for fixed CL mode - * \param[in] config - Definition of the particular problem. - */ - void SetCoefficient_Gradients(CConfig *config) const; - /*! * \brief Update the solution using the explicit Euler scheme. * \param[in] geometry - Geometrical definition of the problem. @@ -1122,956 +826,225 @@ class CEulerSolver : public CSolver { CConfig *config) final; /*! - * \brief Compute a suitable under-relaxation parameter to limit the change in the solution variables over a nonlinear iteration for stability. - * \param[in] solver - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. + * \brief Provide the mass flow rate. + * \param val_marker Surface where the coeficient is going to be computed. + * \return Value of the mass flow rate on the surface val_marker. */ - void ComputeUnderRelaxationFactor(CSolver **solver, CConfig *config) final; + inline su2double GetInflow_MassFlow(unsigned short val_marker) const final { return Inflow_MassFlow[val_marker]; } /*! - * \brief Compute the pressure forces and all the adimensional coefficients. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. + * \brief Provide the mass flow rate. + * \param val_marker Surface where the coeficient is going to be computed. + * \return Value of the mass flow rate on the surface val_marker. */ - void Pressure_Forces(CGeometry *geometry, CConfig *config) final; + inline su2double GetExhaust_MassFlow(unsigned short val_marker) const final { return Exhaust_MassFlow[val_marker]; } /*! - * \brief Compute the pressure forces and all the adimensional coefficients. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. + * \brief Provide the mass flow rate. + * \param val_marker Surface where the coeficient is going to be computed. + * \return Value of the fan face pressure on the surface val_marker. */ - void Momentum_Forces(CGeometry *geometry, CConfig *config) final; - - /*! - * \brief Get the outer state for fluid interface nodes. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] val_state - requested state component - * \param[in] donor_index- index of the donor node to get - */ - inline su2double GetSlidingState(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_state, - unsigned long donor_index) const final { - return SlidingState[val_marker][val_vertex][val_state][donor_index]; - } + inline su2double GetInflow_Pressure(unsigned short val_marker) const final { return Inflow_Pressure[val_marker]; } /*! - * \brief Provide the non dimensional lift coefficient (inviscid contribution). - * \param val_marker Surface where the coefficient is going to be computed. - * \return Value of the lift coefficient (inviscid contribution) on the surface val_marker. + * \brief Provide the mass flow rate. + * \param val_marker Surface where the coeficient is going to be computed. + * \return Value of the fan face mach on the surface val_marker. */ - inline su2double GetCL_Inv(unsigned short val_marker) const final { return InvCoeff.CL[val_marker]; } + inline su2double GetInflow_Mach(unsigned short val_marker) const final { return Inflow_Mach[val_marker]; } /*! - * \brief Provide the non dimensional drag coefficient (inviscid contribution). - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the drag coefficient (inviscid contribution) on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. + * \return Value of the Equivalent Area coefficient (inviscid + viscous contribution). */ - inline su2double GetCD_Inv(unsigned short val_marker) const final { return InvCoeff.CD[val_marker]; } + inline su2double GetTotal_CEquivArea() const final { return Total_CEquivArea; } /*! - * \brief Provide the non dimensional lift coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional aero CD. + * \return Value of the Aero CD coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CL(unsigned short val_marker) const final { return SurfaceCoeff.CL[val_marker]; } + inline su2double GetTotal_AeroCD() const final { return Total_AeroCD; } /*! - * \brief Provide the non dimensional drag coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional Near-Field pressure coefficient. + * \return Value of the NearField pressure coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CD(unsigned short val_marker) const final { return SurfaceCoeff.CD[val_marker]; } + inline su2double GetTotal_CNearFieldOF() const final { return Total_CNearFieldOF; } /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. + * \author H. Kline + * \brief Add to the value of the total 'combo' objective. + * \param[in] val_obj - Value of the contribution to the 'combo' objective. */ - inline su2double GetSurface_CSF(unsigned short val_marker) const final { return SurfaceCoeff.CSF[val_marker]; } + inline void AddTotal_ComboObj(su2double val_obj) final {Total_ComboObj +=val_obj;} /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. + * \brief Set the value of the Equivalent Area coefficient. + * \param[in] val_cequivarea - Value of the Equivalent Area coefficient. */ - inline su2double GetSurface_CEff(unsigned short val_marker) const final { return SurfaceCoeff.CEff[val_marker]; } + inline void SetTotal_CEquivArea(su2double val_cequivarea) final { Total_CEquivArea = val_cequivarea; } /*! - * \brief Provide the non dimensional x force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x force coefficient on the surface val_marker. + * \brief Set the value of the Aero drag. + * \param[in] val_cequivarea - Value of the aero drag. */ - inline su2double GetSurface_CFx(unsigned short val_marker) const final { return SurfaceCoeff.CFx[val_marker]; } + inline void SetTotal_AeroCD(su2double val_aerocd) final { Total_AeroCD = val_aerocd; } /*! - * \brief Provide the non dimensional y force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y force coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CFy(unsigned short val_marker) const final { return SurfaceCoeff.CFy[val_marker]; } + inline su2double GetTotal_NetThrust() const final { return Total_NetThrust; } /*! - * \brief Provide the non dimensional z force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z force coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CFz(unsigned short val_marker) const final { return SurfaceCoeff.CFz[val_marker]; } + inline su2double GetTotal_Power() const final { return Total_Power; } /*! - * \brief Provide the non dimensional x moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x moment coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CMx(unsigned short val_marker) const final { return SurfaceCoeff.CMx[val_marker]; } + inline su2double GetTotal_SolidCD() const final { return Total_SolidCD; } /*! - * \brief Provide the non dimensional y moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y moment coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CMy(unsigned short val_marker) const final { return SurfaceCoeff.CMy[val_marker]; } + inline su2double GetTotal_ReverseFlow() const final { return Total_ReverseFlow; } /*! - * \brief Provide the non dimensional z moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z moment coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CMz(unsigned short val_marker) const final { return SurfaceCoeff.CMz[val_marker]; } + inline su2double GetTotal_MFR() const final { return Total_MFR; } /*! - * \brief Provide the non dimensional lift coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CL_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CL[val_marker]; } + inline su2double GetTotal_Prop_Eff() const final { return Total_Prop_Eff; } /*! - * \brief Provide the non dimensional drag coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CD_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CD[val_marker]; } + inline su2double GetTotal_ByPassProp_Eff() const final { return Total_ByPassProp_Eff; } /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CSF_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CSF[val_marker]; } + inline su2double GetTotal_Adiab_Eff() const final { return Total_Adiab_Eff; } /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CEff_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CEff[val_marker]; } + inline su2double GetTotal_Poly_Eff() const final { return Total_Poly_Eff; } /*! - * \brief Provide the non dimensional x force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x force coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CFx_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CFx[val_marker]; } + inline su2double GetTotal_IDC() const final { return Total_IDC; } /*! - * \brief Provide the non dimensional y force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y force coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CFy_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CFy[val_marker]; } + inline su2double GetTotal_IDC_Mach() const final { return Total_IDC_Mach; } /*! - * \brief Provide the non dimensional z force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z force coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CFz_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CFz[val_marker]; } + inline su2double GetTotal_IDR() const final { return Total_IDR; } /*! - * \brief Provide the non dimensional x moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x moment coefficient on the surface val_marker. + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). */ - inline su2double GetSurface_CMx_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CMx[val_marker]; } + inline su2double GetTotal_DC60() const final { return Total_DC60; } /*! - * \brief Provide the non dimensional y moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y moment coefficient on the surface val_marker. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetSurface_CMy_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CMy[val_marker]; } + inline void SetTotal_NetThrust(su2double val_Total_NetThrust) final { Total_NetThrust = val_Total_NetThrust; } /*! - * \brief Provide the non dimensional z moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z moment coefficient on the surface val_marker. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetSurface_CMz_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CMz[val_marker]; } + inline void SetTotal_Power(su2double val_Total_Power) final { Total_Power = val_Total_Power; } /*! - * \brief Provide the non dimensional lift coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient on the surface val_marker. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetSurface_CL_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CL[val_marker]; } + inline void SetTotal_SolidCD(su2double val_Total_SolidCD) final { Total_SolidCD = val_Total_SolidCD; } /*! - * \brief Provide the non dimensional drag coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient on the surface val_marker. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetSurface_CD_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CD[val_marker]; } + inline void SetTotal_ReverseFlow(su2double val_Total_ReverseFlow) final { Total_ReverseFlow = val_Total_ReverseFlow; } /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetSurface_CSF_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CSF[val_marker]; } + inline void SetTotal_MFR(su2double val_Total_MFR) final { Total_MFR = val_Total_MFR; } /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetSurface_CEff_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CEff[val_marker]; } + inline void SetTotal_Prop_Eff(su2double val_Total_Prop_Eff) final { Total_Prop_Eff = val_Total_Prop_Eff; } /*! - * \brief Provide the non dimensional x force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x force coefficient on the surface val_marker. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetSurface_CFx_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CFx[val_marker]; } + inline void SetTotal_ByPassProp_Eff(su2double val_Total_ByPassProp_Eff) final { Total_ByPassProp_Eff = val_Total_ByPassProp_Eff; } /*! - * \brief Provide the non dimensional y force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y force coefficient on the surface val_marker. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetSurface_CFy_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CFy[val_marker]; } + inline void SetTotal_Adiab_Eff(su2double val_Total_Adiab_Eff) final { Total_Adiab_Eff = val_Total_Adiab_Eff; } /*! - * \brief Provide the non dimensional z force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFz_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CFz[val_marker]; } - - /*! - * \brief Provide the non dimensional x moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMx_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CMx[val_marker]; } - - /*! - * \brief Provide the non dimensional y moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMy_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CMy[val_marker]; } - - /*! - * \brief Provide the non dimensional z moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMz_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CMz[val_marker]; } - - /*! - * \brief Provide the mass flow rate. - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the mass flow rate on the surface val_marker. - */ - inline su2double GetInflow_MassFlow(unsigned short val_marker) const final { return Inflow_MassFlow[val_marker]; } - - /*! - * \brief Provide the mass flow rate. - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the mass flow rate on the surface val_marker. - */ - inline su2double GetExhaust_MassFlow(unsigned short val_marker) const final { return Exhaust_MassFlow[val_marker]; } - - /*! - * \brief Provide the mass flow rate. - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the fan face pressure on the surface val_marker. - */ - inline su2double GetInflow_Pressure(unsigned short val_marker) const final { return Inflow_Pressure[val_marker]; } - - /*! - * \brief Provide the mass flow rate. - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the fan face mach on the surface val_marker. - */ - inline su2double GetInflow_Mach(unsigned short val_marker) const final { return Inflow_Mach[val_marker]; } - - /*! - * \brief Provide the non dimensional sideforce coefficient (inviscid contribution). - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the sideforce coefficient (inviscid contribution) on the surface val_marker. - */ - inline su2double GetCSF_Inv(unsigned short val_marker) const final { return InvCoeff.CSF[val_marker]; } - - /*! - * \brief Provide the non dimensional efficiency coefficient (inviscid contribution). - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the efficiency coefficient (inviscid contribution) on the surface val_marker. - */ - inline su2double GetCEff_Inv(unsigned short val_marker) const final { return InvCoeff.CEff[val_marker]; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional sideforce coefficient. - * \return Value of the sideforce coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CSF() const final { return TotalCoeff.CSF; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CEff() const final { return TotalCoeff.CEff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. - * \return Value of the Equivalent Area coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CEquivArea() const final { return Total_CEquivArea; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional aero CD. - * \return Value of the Aero CD coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_AeroCD() const final { return Total_AeroCD; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. - * \return Value of the Equivalent Area coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CpDiff() const final { return Total_CpDiff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. - * \return Value of the Equivalent Area coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_HeatFluxDiff() const final { return Total_HeatFluxDiff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional Near-Field pressure coefficient. - * \return Value of the NearField pressure coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CNearFieldOF() const final { return Total_CNearFieldOF; } - - /*! - * \author H. Kline - * \brief Add to the value of the total 'combo' objective. - * \param[in] val_obj - Value of the contribution to the 'combo' objective. - */ - inline void AddTotal_ComboObj(su2double val_obj) final {Total_ComboObj +=val_obj;} - - /*! - * \brief Set the value of the Equivalent Area coefficient. - * \param[in] val_cequivarea - Value of the Equivalent Area coefficient. - */ - inline void SetTotal_CEquivArea(su2double val_cequivarea) final { Total_CEquivArea = val_cequivarea; } - - /*! - * \brief Set the value of the Aero drag. - * \param[in] val_cequivarea - Value of the aero drag. - */ - inline void SetTotal_AeroCD(su2double val_aerocd) final { Total_AeroCD = val_aerocd; } - - /*! - * \brief Set the value of the Equivalent Area coefficient. - * \param[in] val_cequivarea - Value of the Equivalent Area coefficient. - */ - inline void SetTotal_CpDiff(su2double val_pressure) final { Total_CpDiff = val_pressure; } - - /*! - * \brief Set the value of the Equivalent Area coefficient. - * \param[in] val_cequivarea - Value of the Equivalent Area coefficient. - */ - inline void SetTotal_HeatFluxDiff(su2double val_heat) final { Total_HeatFluxDiff = val_heat; } - - /*! - * \brief Set the value of the Near-Field pressure oefficient. - * \param[in] val_cnearfieldpress - Value of the Near-Field pressure coefficient. - */ - inline void SetTotal_CNearFieldOF(su2double val_cnearfieldpress) final { Total_CNearFieldOF = val_cnearfieldpress; } - - /*! - * \author H. Kline - * \brief Set the total "combo" objective (weighted sum of other values). - * \param[in] ComboObj - Value of the combined objective. - */ - inline void SetTotal_ComboObj(su2double ComboObj) final {Total_ComboObj = ComboObj; } - - /*! - * \author H. Kline - * \brief Provide the total "combo" objective (weighted sum of other values). - * \return Value of the "combo" objective values. - */ - inline su2double GetTotal_ComboObj() const final { return Total_ComboObj; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional lift coefficient. - * \return Value of the lift coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CL() const final { return TotalCoeff.CL; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CD() const final { return TotalCoeff.CD; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_NetThrust() const final { return Total_NetThrust; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_Power() const final { return Total_Power; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_SolidCD() const final { return Total_SolidCD; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_ReverseFlow() const final { return Total_ReverseFlow; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_MFR() const final { return Total_MFR; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_Prop_Eff() const final { return Total_Prop_Eff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_ByPassProp_Eff() const final { return Total_ByPassProp_Eff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_Adiab_Eff() const final { return Total_Adiab_Eff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_Poly_Eff() const final { return Total_Poly_Eff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_IDC() const final { return Total_IDC; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_IDC_Mach() const final { return Total_IDC_Mach; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_IDR() const final { return Total_IDR; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_DC60() const final { return Total_DC60; } - - /*! - * \brief Provide the total custom objective function. - * \return Value of the custom objective function. - */ - inline su2double GetTotal_Custom_ObjFunc() const final { return Total_Custom_ObjFunc; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional x moment coefficient. - * \return Value of the moment x coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CMx() const final { return TotalCoeff.CMx; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional y moment coefficient. - * \return Value of the moment y coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CMy() const final { return TotalCoeff.CMy; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional z moment coefficient. - * \return Value of the moment z coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CMz() const final { return TotalCoeff.CMz; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional x moment coefficient. - * \return Value of the moment x coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CoPx() const final { return TotalCoeff.CoPx; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional y moment coefficient. - * \return Value of the moment y coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CoPy() const final { return TotalCoeff.CoPy; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional z moment coefficient. - * \return Value of the moment z coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CoPz() const final { return TotalCoeff.CoPz; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional x force coefficient. - * \return Value of the force x coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CFx() const final { return TotalCoeff.CFx; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional y force coefficient. - * \return Value of the force y coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CFy() const final { return TotalCoeff.CFy; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional z force coefficient. - * \return Value of the force z coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CFz() const final { return TotalCoeff.CFz; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional thrust coefficient. - * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CT() const final { return TotalCoeff.CT; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional thrust coefficient. - * \param[in] val_Total_CT - Value of the total thrust coefficient. - */ - inline void SetTotal_CT(su2double val_Total_CT) final { TotalCoeff.CT = val_Total_CT; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional torque coefficient. - * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CQ() const final { return TotalCoeff.CQ; } - - /*! - * \brief Provide the total heat load. - * \return Value of the heat load (viscous contribution). - */ - inline su2double GetTotal_HeatFlux(void) const final { return Total_Heat; } - - /*! - * \brief Provide the total heat load. - * \return Value of the heat load (viscous contribution). - */ - inline su2double GetTotal_MaxHeatFlux() const final { return Total_MaxHeat; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional torque coefficient. - * \param[in] val_Total_CQ - Value of the total torque coefficient. - */ - inline void SetTotal_CQ(su2double val_Total_CQ) final { TotalCoeff.CQ = val_Total_CQ; } - - /*! - * \brief Store the total heat load. - * \param[in] val_Total_Heat - Value of the heat load. - */ - inline void SetTotal_HeatFlux(su2double val_Total_Heat) final { Total_Heat = val_Total_Heat; } - - /*! - * \brief Store the total heat load. - * \param[in] val_Total_Heat - Value of the heat load. - */ - inline void SetTotal_MaxHeatFlux(su2double val_Total_MaxHeat) final { Total_MaxHeat = val_Total_MaxHeat; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional rotor Figure of Merit. - * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CMerit() const final { return TotalCoeff.CMerit; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_CD(su2double val_Total_CD) final { TotalCoeff.CD = val_Total_CD; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional lift coefficient. - * \param[in] val_Total_CL - Value of the total lift coefficient. - */ - inline void SetTotal_CL(su2double val_Total_CL) final { TotalCoeff.CL = val_Total_CL; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_NetThrust(su2double val_Total_NetThrust) final { Total_NetThrust = val_Total_NetThrust; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_Power(su2double val_Total_Power) final { Total_Power = val_Total_Power; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_SolidCD(su2double val_Total_SolidCD) final { Total_SolidCD = val_Total_SolidCD; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_ReverseFlow(su2double val_Total_ReverseFlow) final { Total_ReverseFlow = val_Total_ReverseFlow; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_MFR(su2double val_Total_MFR) final { Total_MFR = val_Total_MFR; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_Prop_Eff(su2double val_Total_Prop_Eff) final { Total_Prop_Eff = val_Total_Prop_Eff; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_ByPassProp_Eff(su2double val_Total_ByPassProp_Eff) final { Total_ByPassProp_Eff = val_Total_ByPassProp_Eff; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_Adiab_Eff(su2double val_Total_Adiab_Eff) final { Total_Adiab_Eff = val_Total_Adiab_Eff; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_Poly_Eff(su2double val_Total_Poly_Eff) final { Total_Poly_Eff = val_Total_Poly_Eff; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_IDC(su2double val_Total_IDC) final { Total_IDC = val_Total_IDC; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_IDC_Mach(su2double val_Total_IDC_Mach) final { Total_IDC_Mach = val_Total_IDC_Mach; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_IDR(su2double val_Total_IDR) final { Total_IDR = val_Total_IDR; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CD - Value of the total drag coefficient. - */ - inline void SetTotal_DC60(su2double val_Total_DC60) final { Total_DC60 = val_Total_DC60; } - - /*! - * \brief Set the value of the custom objective function. - * \param[in] val_Total_Custom_ObjFunc - Value of the total custom objective function. - * \param[in] val_weight - Value of the weight for the custom objective function. - */ - inline void SetTotal_Custom_ObjFunc(su2double val_total_custom_objfunc, su2double val_weight) final { - Total_Custom_ObjFunc = val_total_custom_objfunc*val_weight; - } - - /*! - * \brief Add the value of the custom objective function. - * \param[in] val_Total_Custom_ObjFunc - Value of the total custom objective function. - * \param[in] val_weight - Value of the weight for the custom objective function. - */ - inline void AddTotal_Custom_ObjFunc(su2double val_total_custom_objfunc, su2double val_weight) final { - Total_Custom_ObjFunc += val_total_custom_objfunc*val_weight; - } - - /*! - * \brief Get the inviscid contribution to the lift coefficient. - * \return Value of the lift coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CL_Inv() const final { return AllBoundInvCoeff.CL; } - - /*! - * \brief Get the inviscid contribution to the drag coefficient. - * \return Value of the drag coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CD_Inv() const final { return AllBoundInvCoeff.CD; } - - /*! - * \brief Get the inviscid contribution to the sideforce coefficient. - * \return Value of the sideforce coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CSF_Inv() const final { return AllBoundInvCoeff.CSF; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CEff_Inv() const final { return AllBoundInvCoeff.CEff; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMx_Inv() const final { return AllBoundInvCoeff.CMx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMy_Inv() const final { return AllBoundInvCoeff.CMy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMz_Inv() const final { return AllBoundInvCoeff.CMz; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPx_Inv() const final { return AllBoundInvCoeff.CoPx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPy_Inv() const final { return AllBoundInvCoeff.CoPy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPz_Inv() const final { return AllBoundInvCoeff.CoPz; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFx_Inv() const final { return AllBoundInvCoeff.CFx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFy_Inv() const final { return AllBoundInvCoeff.CFy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFz_Inv() const final { return AllBoundInvCoeff.CFz; } - - /*! - * \brief Get the inviscid contribution to the lift coefficient. - * \return Value of the lift coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CL_Mnt() const final { return AllBoundMntCoeff.CL; } - - /*! - * \brief Get the inviscid contribution to the drag coefficient. - * \return Value of the drag coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CD_Mnt() const final { return AllBoundMntCoeff.CD; } - - /*! - * \brief Get the inviscid contribution to the sideforce coefficient. - * \return Value of the sideforce coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CSF_Mnt() const final { return AllBoundMntCoeff.CSF; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CEff_Mnt() const final { return AllBoundMntCoeff.CEff; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMx_Mnt() const final { return AllBoundMntCoeff.CMx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMy_Mnt() const final { return AllBoundMntCoeff.CMy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMz_Mnt() const final { return AllBoundMntCoeff.CMz; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPx_Mnt() const final { return AllBoundMntCoeff.CoPx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPy_Mnt() const final { return AllBoundMntCoeff.CoPy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPz_Mnt() const final { return AllBoundMntCoeff.CoPz; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFx_Mnt() const final { return AllBoundMntCoeff.CFx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFy_Mnt() const final { return AllBoundMntCoeff.CFy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFz_Mnt() const final { return AllBoundMntCoeff.CFz; } - - /*! - * \brief Provide the Pressure coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline su2double GetCPressure(unsigned short val_marker, unsigned long val_vertex) const final { - return CPressure[val_marker][val_vertex]; - } - - /*! - * \brief Provide the Target Pressure coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline su2double GetCPressureTarget(unsigned short val_marker, unsigned long val_vertex) const final { - return CPressureTarget[val_marker][val_vertex]; - } - - /*! - * \brief Set the value of the target Pressure coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline void SetCPressureTarget(unsigned short val_marker, - unsigned long val_vertex, - su2double val_pressure) final { - CPressureTarget[val_marker][val_vertex] = val_pressure; - } - - /*! - * \brief Value of the characteristic variables at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double *GetCharacPrimVar(unsigned short val_marker, unsigned long val_vertex) const final { - return CharacPrimVar[val_marker][val_vertex]; - } + inline void SetTotal_Poly_Eff(su2double val_Total_Poly_Eff) final { Total_Poly_Eff = val_Total_Poly_Eff; } /*! - * \brief Value of the characteristic variables at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline void SetCharacPrimVar(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_var, - su2double val_value) final { - CharacPrimVar[val_marker][val_vertex][val_var] = val_value; - } + inline void SetTotal_IDC(su2double val_Total_IDC) final { Total_IDC = val_Total_IDC; } /*! - * \brief Value of the characteristic variables at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double *GetDonorPrimVar(unsigned short val_marker, unsigned long val_vertex) const final{ - return DonorPrimVar[val_marker][val_vertex]; - } + inline void SetTotal_IDC_Mach(su2double val_Total_IDC_Mach) final { Total_IDC_Mach = val_Total_IDC_Mach; } /*! - * \brief Value of the characteristic variables at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline void SetDonorPrimVar(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_var, - su2double val_value) final { - DonorPrimVar[val_marker][val_vertex][val_var] = val_value; - } + inline void SetTotal_IDR(su2double val_Total_IDR) final { Total_IDR = val_Total_IDR; } /*! - * \brief Value of the characteristic variables at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. */ - inline su2double GetDonorPrimVar(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_var) const final { - return DonorPrimVar[val_marker][val_vertex][val_var]; - } + inline void SetTotal_DC60(su2double val_Total_DC60) final { Total_DC60 = val_Total_DC60; } /*! * \brief Value of the characteristic global index at the boundaries. @@ -2096,267 +1069,6 @@ class CEulerSolver : public CSolver { DonorGlobalIndex[val_marker][val_vertex] = val_index; } - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the axial force per unit area. - */ - inline su2double GetActDisk_Fa(unsigned short val_marker, - unsigned long val_vertex) const { - return ActDisk_Fa[val_marker][val_vertex]; - } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the axial force per unit area. - */ - inline void SetActDisk_Fa(unsigned short val_marker, - unsigned long val_vertex, - su2double val_fa) { ActDisk_Fa[val_marker][val_vertex] = val_fa; } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the x component of the radial and tangential forces per unit area resultant. - */ - inline su2double GetActDisk_Fx(unsigned short val_marker, - unsigned long val_vertex) const { - return ActDisk_Fx[val_marker][val_vertex]; - } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the x component of the radial and tangential forces per unit area resultant. - */ - inline void SetActDisk_Fx(unsigned short val_marker, - unsigned long val_vertex, - su2double val_fx) { ActDisk_Fx[val_marker][val_vertex] = val_fx; } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the y component of the radial and tangential forces per unit area resultant. - */ - inline su2double GetActDisk_Fy(unsigned short val_marker, - unsigned long val_vertex) const { - return ActDisk_Fy[val_marker][val_vertex]; - } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the y component of the radial and tangential forces per unit area resultant. - */ - inline void SetActDisk_Fy(unsigned short val_marker, - unsigned long val_vertex, - su2double val_fy) { ActDisk_Fy[val_marker][val_vertex] = val_fy; } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the z component of the radial and tangential forces per unit area resultant. - */ - inline su2double GetActDisk_Fz(unsigned short val_marker, - unsigned long val_vertex) const { - return ActDisk_Fz[val_marker][val_vertex]; - } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the z component of the radial and tangential forces per unit area resultant. - */ - inline void SetActDisk_Fz(unsigned short val_marker, - unsigned long val_vertex, - su2double val_fz) { ActDisk_Fz[val_marker][val_vertex] = val_fz; } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline su2double GetActDisk_DeltaP(unsigned short val_marker, - unsigned long val_vertex) const final { - return ActDisk_DeltaP[val_marker][val_vertex]; - } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline void SetActDisk_DeltaP(unsigned short val_marker, - unsigned long val_vertex, - su2double val_deltap) final { ActDisk_DeltaP[val_marker][val_vertex] = val_deltap; } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline su2double GetActDisk_DeltaT(unsigned short val_marker, unsigned long val_vertex) final { - return ActDisk_DeltaT[val_marker][val_vertex]; - } - - /*! - * \brief Value of the characteristic global index at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline void SetActDisk_DeltaT(unsigned short val_marker, - unsigned long val_vertex, - su2double val_deltat) final { - ActDisk_DeltaT[val_marker][val_vertex] = val_deltat; - } - - /*! - * \brief Value of the total temperature at an inlet boundary. - * \param[in] val_marker - Surface marker where the total temperature is evaluated. - * \param[in] val_vertex - Vertex of the marker val_marker where the total temperature is evaluated. - * \return Value of the total temperature - */ - inline su2double GetInlet_Ttotal(unsigned short val_marker, unsigned long val_vertex) const final { return Inlet_Ttotal[val_marker][val_vertex]; } - - /*! - * \brief Value of the total pressure at an inlet boundary. - * \param[in] val_marker - Surface marker where the total pressure is evaluated. - * \param[in] val_vertex - Vertex of the marker val_marker where the total pressure is evaluated. - * \return Value of the total pressure - */ - inline su2double GetInlet_Ptotal(unsigned short val_marker, unsigned long val_vertex) const final { return Inlet_Ptotal[val_marker][val_vertex]; } - - /*! - * \brief A component of the unit vector representing the flow direction at an inlet boundary. - * \param[in] val_marker - Surface marker where the flow direction is evaluated - * \param[in] val_vertex - Vertex of the marker val_marker where the flow direction is evaluated - * \param[in] val_dim - The component of the flow direction unit vector to be evaluated - * \return Component of a unit vector representing the flow direction. - */ - inline su2double GetInlet_FlowDir(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_dim) const final { - return Inlet_FlowDir[val_marker][val_vertex][val_dim]; - } - - /*! - * \brief Set the value of the total temperature at an inlet boundary. - * \param[in] val_marker - Surface marker where the total temperature is set. - * \param[in] val_vertex - Vertex of the marker val_marker where the total temperature is set. - * \param[in] val_ttotal - Value of the total temperature - */ - inline void SetInlet_Ttotal(unsigned short val_marker, - unsigned long val_vertex, - su2double val_ttotal) final { - /*--- Since this call can be accessed indirectly using python, do some error - * checking to prevent segmentation faults ---*/ - if (val_marker >= nMarker) - SU2_MPI::Error("Out-of-bounds marker index used on inlet.", CURRENT_FUNCTION); - else if (Inlet_Ttotal == nullptr || Inlet_Ttotal[val_marker] == nullptr) - SU2_MPI::Error("Tried to set custom inlet BC on an invalid marker.", CURRENT_FUNCTION); - else if (val_vertex >= nVertex[val_marker]) - SU2_MPI::Error("Out-of-bounds vertex index used on inlet.", CURRENT_FUNCTION); - else - Inlet_Ttotal[val_marker][val_vertex] = val_ttotal; - } - - - /*! - * \brief Set the value of the total pressure at an inlet boundary. - * \param[in] val_marker - Surface marker where the total pressure is set. - * \param[in] val_vertex - Vertex of the marker val_marker where the total pressure is set. - * \param[in] val_ptotal - Value of the total pressure - */ - inline void SetInlet_Ptotal(unsigned short val_marker, - unsigned long val_vertex, - su2double val_ptotal) final { - /*--- Since this call can be accessed indirectly using python, do some error - * checking to prevent segmentation faults ---*/ - if (val_marker >= nMarker) - SU2_MPI::Error("Out-of-bounds marker index used on inlet.", CURRENT_FUNCTION); - else if (Inlet_Ptotal == nullptr || Inlet_Ptotal[val_marker] == nullptr) - SU2_MPI::Error("Tried to set custom inlet BC on an invalid marker.", CURRENT_FUNCTION); - else if (val_vertex >= nVertex[val_marker]) - SU2_MPI::Error("Out-of-bounds vertex index used on inlet.", CURRENT_FUNCTION); - else - Inlet_Ptotal[val_marker][val_vertex] = val_ptotal; - } - - - /*! - * \brief Set a component of the unit vector representing the flow direction at an inlet boundary. - * \param[in] val_marker - Surface marker where the flow direction is set. - * \param[in] val_vertex - Vertex of the marker val_marker where the flow direction is set. - * \param[in] val_dim - The component of the flow direction unit vector to be set - * \param[in] val_flowdir - Component of a unit vector representing the flow direction. - */ - inline void SetInlet_FlowDir(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_dim, - su2double val_flowdir) final { - /*--- Since this call can be accessed indirectly using python, do some error - * checking to prevent segmentation faults ---*/ - if (val_marker >= nMarker) - SU2_MPI::Error("Out-of-bounds marker index used on inlet.", CURRENT_FUNCTION); - else if (Inlet_FlowDir == nullptr || Inlet_FlowDir[val_marker] == nullptr) - SU2_MPI::Error("Tried to set custom inlet BC on an invalid marker.", CURRENT_FUNCTION); - else if (val_vertex >= nVertex[val_marker]) - SU2_MPI::Error("Out-of-bounds vertex index used on inlet.", CURRENT_FUNCTION); - else - Inlet_FlowDir[val_marker][val_vertex][val_dim] = val_flowdir; - } - - - /*! - * \brief Set a uniform inlet profile - * - * The values at the inlet are set to match the values specified for - * inlets in the configuration file. - * - * \param[in] config - Definition of the particular problem. - * \param[in] iMarker - Surface marker where the coefficient is computed. - */ - void SetUniformInlet(CConfig* config, unsigned short iMarker) final; - - /*! - * \brief Store of a set of provided inlet profile values at a vertex. - * \param[in] val_inlet - vector containing the inlet values for the current vertex. - * \param[in] iMarker - Surface marker where the coefficient is computed. - * \param[in] iVertex - Vertex of the marker iMarker where the inlet is being set. - */ - void SetInletAtVertex(su2double *val_inlet, - unsigned short iMarker, - unsigned long iVertex) final; - - /*! - * \brief Get the set of value imposed at an inlet. - * \param[in] val_inlet - vector returning the inlet values for the current vertex. - * \param[in] val_inlet_point - Node index where the inlet is being set. - * \param[in] val_kind_marker - Enumerated type for the particular inlet type. - * \param[in] geometry - Geometrical definition of the problem. - * \param config - Definition of the particular problem. - * \return Value of the face area at the vertex. - */ - su2double GetInletAtVertex(su2double *val_inlet, - unsigned long val_inlet_point, - unsigned short val_kind_marker, - string val_marker, - CGeometry *geometry, - CConfig *config) const final; - /*! * \brief Update the multi-grid structure for the customized boundary conditions * \param geometry_container - Geometrical definition. @@ -2394,61 +1106,6 @@ class CEulerSolver : public CSolver { int val_iter, bool val_update_geo) final; - /*! - * \brief Allocates the final pointer of SlidingState depending on how many donor vertex donate to it. That number is stored in SlidingStateNodes[val_marker][val_vertex]. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - */ - inline void SetSlidingStateStructure(unsigned short val_marker, unsigned long val_vertex) final { - int iVar; - - for( iVar = 0; iVar < nPrimVar+1; iVar++){ - if( SlidingState[val_marker][val_vertex][iVar] != nullptr ) - delete [] SlidingState[val_marker][val_vertex][iVar]; - } - - for( iVar = 0; iVar < nPrimVar+1; iVar++) - SlidingState[val_marker][val_vertex][iVar] = new su2double[ GetnSlidingStates(val_marker, val_vertex) ]; - } - - - - /*! - * \brief Set the outer state for fluid interface nodes. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] val_state - requested state component - * \param[in] donor_index - index of the donor node to set - * \param[in] component - set value - */ - inline void SetSlidingState(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_state, - unsigned long donor_index, - su2double component) final { - SlidingState[val_marker][val_vertex][val_state][donor_index] = component; - } - - - /*! - * \brief Set the number of outer state for fluid interface nodes. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] value - number of outer states - */ - inline void SetnSlidingStates(unsigned short val_marker, - unsigned long val_vertex, - int value) final { SlidingStateNodes[val_marker][val_vertex] = value; } - - /*! - * \brief Get the number of outer state for fluid interface nodes. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - */ - inline int GetnSlidingStates(unsigned short val_marker, unsigned long val_vertex) const final { - return SlidingStateNodes[val_marker][val_vertex]; - } - /*! * \brief Set the initial condition for the Euler Equations. * \param[in] geometry - Geometrical definition of the problem. @@ -2461,18 +1118,6 @@ class CEulerSolver : public CSolver { CConfig *config, unsigned long TimeIter) final; - /*! - * \brief Set the freestream pressure. - * \param[in] Value of freestream pressure. - */ - inline void SetPressure_Inf(su2double p_inf) final {Pressure_Inf = p_inf;} - - /*! - * \brief Set the freestream temperature. - * \param[in] Value of freestream temperature. - */ - inline void SetTemperature_Inf(su2double t_inf) final {Temperature_Inf = t_inf;} - /*! * \brief Set the solution using the Freestream values. * \param[in] config - Definition of the particular problem. @@ -2997,11 +1642,10 @@ class CEulerSolver : public CSolver { } /*! - * \brief Compute the global error measures (L2, Linf) for verification cases. - * \param[in] geometry - Geometrical definition. - * \param[in] config - Definition of the particular problem. + * \brief Print verification error to screen. + * \param[in] config - Definition of the particular problem. */ - void ComputeVerificationError(CGeometry *geometry, CConfig *config) final; + void PrintVerificationError(const CConfig* config) const final; /*! * \brief The Euler and NS solvers support MPI+OpenMP (except the BC bits). diff --git a/SU2_CFD/include/solvers/CFEM_DG_EulerSolver.hpp b/SU2_CFD/include/solvers/CFEM_DG_EulerSolver.hpp index 77ff18f843a4..a58ecd871141 100644 --- a/SU2_CFD/include/solvers/CFEM_DG_EulerSolver.hpp +++ b/SU2_CFD/include/solvers/CFEM_DG_EulerSolver.hpp @@ -926,7 +926,7 @@ class CFEM_DG_EulerSolver : public CSolver { * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - void Pressure_Forces(CGeometry *geometry, CConfig *config) final; + void Pressure_Forces(const CGeometry* geometry, const CConfig* config) final; /*! * \brief Load a solution from a restart file. diff --git a/SU2_CFD/include/solvers/CFEM_DG_NSSolver.hpp b/SU2_CFD/include/solvers/CFEM_DG_NSSolver.hpp index 2dad84255506..e13ec0476bf9 100644 --- a/SU2_CFD/include/solvers/CFEM_DG_NSSolver.hpp +++ b/SU2_CFD/include/solvers/CFEM_DG_NSSolver.hpp @@ -398,7 +398,7 @@ class CFEM_DG_NSSolver final : public CFEM_DG_EulerSolver { * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - void Friction_Forces(CGeometry *geometry, CConfig *config) override; + void Friction_Forces(const CGeometry* geometry, const CConfig* config) override; /*! * \brief Get the non dimensional lift coefficient (viscous contribution). diff --git a/SU2_CFD/include/solvers/CFVMFlowSolverBase.hpp b/SU2_CFD/include/solvers/CFVMFlowSolverBase.hpp new file mode 100644 index 000000000000..3bbab2f153c0 --- /dev/null +++ b/SU2_CFD/include/solvers/CFVMFlowSolverBase.hpp @@ -0,0 +1,1589 @@ +/*! + * \file CFVMFlowSolverBase.hpp + * \brief Base class template for all FVM flow solvers. + * \version 7.0.6 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2020, 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 "../../../Common/include/omp_structure.hpp" +#include "../../../Common/include/toolboxes/geometry_toolbox.hpp" +#include "CSolver.hpp" + +namespace detail { +template +constexpr size_t flowSolMaxnVar() { + return 12; +} +// template<> +// constexpr size_t flowSolMaxnVar<"your variable type">() { return "your size"; } +} // namespace detail + +template +class CFVMFlowSolverBase : public CSolver { + protected: + enum : size_t { MAXNDIM = 3 }; /*!< \brief Max number of space dimensions, used in some static arrays. */ + enum : size_t { + MAXNVAR = detail::flowSolMaxnVar() + }; /*!< \brief Max number of variables, used in some static arrays. */ + + enum : size_t { OMP_MAX_SIZE = 512 }; /*!< \brief Max chunk size for light point loops. */ + enum : size_t { OMP_MIN_SIZE = 32 }; /*!< \brief Min chunk size for edge loops (max is color group size). */ + + unsigned long omp_chunk_size; /*!< \brief Chunk size used in light point loops. */ + + su2double Mach_Inf = 0.0; /*!< \brief Mach number at the infinity. */ + su2double Density_Inf = 0.0; /*!< \brief Density at the infinity. */ + su2double Energy_Inf = 0.0; /*!< \brief Energy at the infinity. */ + su2double Temperature_Inf = 0.0; /*!< \brief Energy at the infinity. */ + su2double Pressure_Inf = 0.0; /*!< \brief Pressure at the infinity. */ + su2double* Velocity_Inf = nullptr; /*!< \brief Flow Velocity vector at the infinity. */ + + su2double Viscosity_Inf; /*!< \brief Viscosity at the infinity. */ + su2double Tke_Inf; /*!< \brief Turbulent kinetic energy at the infinity. */ + + su2double StrainMag_Max; /*!< \brief Maximum Strain Rate magnitude. */ + su2double Omega_Max; /*!< \brief Maximum Omega. */ + + /*! + * \brief Auxilary types to store common aero coefficients (avoids repeating oneself so much). + */ + struct AeroCoeffsArray { + su2double* CD = nullptr; /*!< \brief Drag coefficient. */ + su2double* CL = nullptr; /*!< \brief Lift coefficient. */ + su2double* CSF = nullptr; /*!< \brief Sideforce coefficient. */ + su2double* CEff = nullptr; /*!< \brief Efficiency (Cl/Cd). */ + su2double* CFx = nullptr; /*!< \brief x Force coefficient. */ + su2double* CFy = nullptr; /*!< \brief y Force coefficient. */ + su2double* CFz = nullptr; /*!< \brief z Force coefficient. */ + su2double* CMx = nullptr; /*!< \brief x Moment coefficient. */ + su2double* CMy = nullptr; /*!< \brief y Moment coefficient. */ + su2double* CMz = nullptr; /*!< \brief z Moment coefficient. */ + su2double* CoPx = nullptr; /*!< \brief x Moment coefficient. */ + su2double* CoPy = nullptr; /*!< \brief y Moment coefficient. */ + su2double* CoPz = nullptr; /*!< \brief z Moment coefficient. */ + su2double* CT = nullptr; /*!< \brief Thrust coefficient. */ + su2double* CQ = nullptr; /*!< \brief Torque coefficient. */ + su2double* CMerit = nullptr; /*!< \brief Rotor Figure of Merit. */ + int _size = 0; /*!< \brief Array size. */ + + void allocate(int size); /*!< \brief Allocates arrays. */ + + void setZero(int i); /*!< \brief Sets all values to zero at a particular index. */ + void setZero() { /*!< \brief Sets all values to zero for all indices. */ + for (int i = 0; i < _size; ++i) setZero(i); + } + + AeroCoeffsArray(int size = 0) : _size(size) { + if (size) allocate(size); + } + + ~AeroCoeffsArray(); + }; + + /*! + * \brief Scalar version of the coefficients type. + */ + struct AeroCoeffs { + su2double CD, CL, CSF, CEff, CFx, CFy, CFz, CMx, CMy, CMz, CoPx, CoPy, CoPz, CT, CQ, CMerit; + + void setZero() { + CD = CL = CSF = CEff = CFx = CFy = CFz = CMx = CMy = CMz = CoPx = CoPy = CoPz = CT = CQ = CMerit = 0.0; + } + + AeroCoeffs() { setZero(); } + }; + + AeroCoeffsArray InvCoeff; /*!< \brief Inviscid pressure contributions for each boundary. */ + AeroCoeffsArray SurfaceInvCoeff; /*!< \brief Inviscid pressure contributions for each monitoring boundary. */ + AeroCoeffs AllBoundInvCoeff; /*!< \brief Total pressure contribution for all the boundaries. */ + + AeroCoeffsArray MntCoeff; /*!< \brief Inviscid momentum contributions for each boundary. */ + AeroCoeffsArray SurfaceMntCoeff; /*!< \brief Inviscid momentum contributions for each monitoring boundary. */ + AeroCoeffs AllBoundMntCoeff; /*!< \brief Total momentum contribution for all the boundaries. */ + + AeroCoeffsArray ViscCoeff; /*!< \brief Viscous contributions for each boundary. */ + AeroCoeffsArray SurfaceViscCoeff; /*!< \brief Viscous contributions for each monitoring boundary. */ + AeroCoeffs AllBoundViscCoeff; /*!< \brief Total pressure contribution for all the boundaries. */ + + AeroCoeffsArray SurfaceCoeff; /*!< \brief Totals for each monitoring surface. */ + AeroCoeffs TotalCoeff; /*!< \brief Totals for all boundaries. */ + + su2double InverseDesign = 0.0; /*!< \brief Inverse design functional for each boundary. */ + su2double Total_ComboObj = 0.0; /*!< \brief Total 'combo' objective for all monitored boundaries */ + su2double Total_Custom_ObjFunc = 0.0; /*!< \brief Total custom objective function for all the boundaries. */ + su2double Total_CpDiff = 0.0; /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ + su2double Total_HeatFluxDiff = 0.0; /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ + su2double Total_MassFlowRate = 0.0; /*!< \brief Total Mass Flow Rate on monitored boundaries. */ + su2double Total_CNearFieldOF = 0.0; /*!< \brief Total Near-Field Pressure coefficient for all the boundaries. */ + su2double Total_Heat = 0.0; /*!< \brief Total heat load for all the boundaries. */ + su2double Total_MaxHeat = 0.0; /*!< \brief Maximum heat flux on all boundaries. */ + su2double AllBound_CNearFieldOF_Inv = 0.0; /*!< \brief Near-Field press coeff (inviscid) for all the boundaries. */ + su2double* CNearFieldOF_Inv = nullptr; /*!< \brief Near field pressure (inviscid) for each boundary. */ + su2double* Surface_HF_Visc = nullptr; /*!< \brief Total (integrated) heat flux for each monitored surface. */ + su2double* Surface_MaxHF_Visc = nullptr; /*!< \brief Maximum heat flux for each monitored surface. */ + su2double* HF_Visc = nullptr; /*!< \brief Heat load (viscous contribution) for each boundary. */ + su2double* MaxHF_Visc = nullptr; /*!< \brief Maximum heat flux (viscous contribution) for each boundary. */ + su2double AllBound_HF_Visc = 0.0; /*!< \brief Heat load (viscous contribution) for all the boundaries. */ + su2double AllBound_MaxHF_Visc = 0.0; /*!< \brief Maximum heat flux (viscous contribution) for all boundaries. */ + + su2double** Inlet_Ptotal = nullptr; /*!< \brief Value of the Total P. */ + su2double** Inlet_Ttotal = nullptr; /*!< \brief Value of the Total T. */ + su2double*** Inlet_FlowDir = nullptr; /*!< \brief Value of the Flow Direction. */ + su2double** HeatFlux = nullptr; /*!< \brief Heat transfer coefficient for each boundary and vertex. */ + su2double** HeatFluxTarget = nullptr; /*!< \brief Heat transfer coefficient for each boundary and vertex. */ + su2double*** CharacPrimVar = nullptr; /*!< \brief Value of the characteristic variables at each boundary. */ + su2double*** CSkinFriction = nullptr; /*!< \brief Skin friction coefficient for each boundary and vertex. */ + su2double*** HeatConjugateVar = nullptr; /*!< \brief CHT variables for each boundary and vertex. */ + su2double** CPressure = nullptr; /*!< \brief Pressure coefficient for each boundary and vertex. */ + su2double** CPressureTarget = nullptr; /*!< \brief Target Pressure coefficient for each boundary and vertex. */ + su2double** YPlus = nullptr; /*!< \brief Yplus for each boundary and vertex. */ + + bool space_centered; /*!< \brief True if space centered scheeme used. */ + bool euler_implicit; /*!< \brief True if euler implicit scheme used. */ + bool least_squares; /*!< \brief True if computing gradients by least squares. */ + su2double Gamma; /*!< \brief Fluid's Gamma constant (ratio of specific heats). */ + su2double Gamma_Minus_One; /*!< \brief Fluids's Gamma - 1.0 . */ + + /*--- Sliding meshes variables ---*/ + + su2double**** SlidingState = nullptr; + int** SlidingStateNodes = nullptr; + + /*--- Shallow copy of grid coloring for OpenMP parallelization. ---*/ + +#ifdef HAVE_OMP + vector > EdgeColoring; /*!< \brief Edge colors. */ + bool ReducerStrategy = false; /*!< \brief If the reducer strategy is in use. */ +#else + array, 1> EdgeColoring; + /*--- Never use the reducer strategy if compiling for MPI-only. ---*/ + static constexpr bool ReducerStrategy = false; +#endif + + /*--- Edge fluxes, for OpenMP parallelization off difficult-to-color grids. + * We first store the fluxes and then compute the sum for each cell. + * This strategy is thread-safe but lower performance than writting to both + * end points of each edge, so we only use it when necessary, i.e. when the + * coloring does not allow "enough" parallelism. ---*/ + + CSysVector EdgeFluxes; /*!< \brief Flux across each edge. */ + + VariableType* nodes = nullptr; /*!< \brief The highest level in the variable hierarchy this solver can safely use. */ + + /*! + * \brief Return nodes to allow CSolver::base_nodes to be set. + */ + inline CVariable* GetBaseClassPointerToNodes() final { return nodes; } + + /*! + * \brief Default constructor, this class is not directly instantiable. + */ + CFVMFlowSolverBase() : CSolver() {} + + /*! + * \brief Allocate member variables. + */ + void Allocate(const CConfig& config); + + /*! + * \brief Allocate small member variables that ideally should not be used. + */ + void AllocateTerribleLegacyTemporaryVariables(); + + /*! + * \brief Communicate the initial solver state. + */ + void CommunicateInitialState(CGeometry* geometry, const CConfig* config); + + /*! + * \brief Initialize thread parallel variables. + */ + void HybridParallelInitialization(const CConfig& config, CGeometry& geometry); + + /*! + * \brief Move solution to previous time levels (for restarts). + */ + void PushSolutionBackInTime(unsigned long TimeIter, bool restart, bool rans, CSolver*** solver_container, + CGeometry** geometry, CConfig* config); + + /*! + * \brief Evaluate common part of objective function to all solvers. + */ + su2double EvaluateCommonObjFunc(const CConfig& config) const; + + /*! + * \brief Destructor. + */ + ~CFVMFlowSolverBase(); + + public: + /*! + * \brief Compute the gradient of the primitive variables using Green-Gauss method, + * and stores the result in the Gradient_Primitive variable. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + * \param[in] reconstruction - indicator that the gradient being computed is for upwind reconstruction. + */ + void SetPrimitive_Gradient_GG(CGeometry* geometry, const CConfig* config, bool reconstruction = false) final; + + /*! + * \brief Compute the gradient of the primitive variables using a Least-Squares method, + * and stores the result in the Gradient_Primitive variable. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + * \param[in] reconstruction - indicator that the gradient being computed is for upwind reconstruction. + */ + void SetPrimitive_Gradient_LS(CGeometry* geometry, const CConfig* config, bool reconstruction = false) final; + + /*! + * \brief Compute the limiter of the primitive variables. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + */ + void SetPrimitive_Limiter(CGeometry* geometry, const CConfig* config) final; + + /*! + * \brief Compute a suitable under-relaxation parameter to limit the change in the solution variables over a nonlinear + * iteration for stability. \param[in] solver - Container vector with all the solutions. \param[in] config - + * Definition of the particular problem. + */ + void ComputeUnderRelaxationFactor(CSolver** solver, const CConfig* config) final; + + /*! + * \brief Set a uniform inlet profile + * + * The values at the inlet are set to match the values specified for + * inlets in the configuration file. + * + * \param[in] config - Definition of the particular problem. + * \param[in] iMarker - Surface marker where the coefficient is computed. + */ + void SetUniformInlet(const CConfig* config, unsigned short iMarker) final; + + /*! + * \brief Store of a set of provided inlet profile values at a vertex. + * \param[in] val_inlet - vector containing the inlet values for the current vertex. + * \param[in] iMarker - Surface marker where the coefficient is computed. + * \param[in] iVertex - Vertex of the marker iMarker where the inlet is being set. + */ + void SetInletAtVertex(const su2double* val_inlet, unsigned short iMarker, unsigned long iVertex) final; + + /*! + * \brief Get the set of value imposed at an inlet. + * \param[in] val_inlet - vector returning the inlet values for the current vertex. + * \param[in] val_inlet_point - Node index where the inlet is being set. + * \param[in] val_kind_marker - Enumerated type for the particular inlet type. + * \param[in] geometry - Geometrical definition of the problem. + * \param config - Definition of the particular problem. + * \return Value of the face area at the vertex. + */ + su2double GetInletAtVertex(su2double* val_inlet, unsigned long val_inlet_point, unsigned short val_kind_marker, + string val_marker, const CGeometry* geometry, const CConfig* config) const final; + + /*! + * \author T. Kattmann + * \brief Impose via the residual the Euler wall boundary condition. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the numerical method. + * \param[in] visc_numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] val_marker - Surface marker where the boundary condition is applied. + */ + inline void BC_Euler_Wall(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics, + CNumerics* visc_numerics, CConfig* config, unsigned short val_marker) final { + /*--- Call the equivalent symmetry plane boundary condition. ---*/ + BC_Sym_Plane(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker); + } + + /*! + * \author T. Kattmann + * \brief Impose the symmetry boundary condition using the residual. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the numerical method. + * \param[in] visc_numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] val_marker - Surface marker where the boundary condition is applied. + */ + void BC_Sym_Plane(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics, CNumerics* visc_numerics, + CConfig* config, unsigned short val_marker) final; + + /*! + * \brief Impose a periodic boundary condition by summing contributions from the complete control volume. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + */ + void BC_Periodic(CGeometry* geometry, CSolver** solver_container, CNumerics* numerics, CConfig* config) final; + + /*! + * \brief Impose the interface state across sliding meshes. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the numerical method. + * \param[in] visc_numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + */ + void BC_Fluid_Interface(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics, + CNumerics* visc_numerics, CConfig* config) final; + + /*! + * \brief Impose a custom or verification boundary condition. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the convective numerical method. + * \param[in] visc_numerics - Description of the viscous numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] val_marker - Surface marker where the boundary condition is applied. + */ + void BC_Custom(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics, CNumerics* visc_numerics, + CConfig* config, unsigned short val_marker) final; + + /*! + * \brief Compute the density at the infinity. + * \return Value of the density at the infinity. + */ + inline su2double GetDensity_Inf(void) const final { return Density_Inf; } + + /*! + * \brief Compute 2-norm of the velocity at the infinity. + * \return Value of the 2-norm of the velocity at the infinity. + */ + inline su2double GetModVelocity_Inf(void) const final { return GeometryToolbox::Norm(nDim, Velocity_Inf); } + + /*! + * \brief Compute the pressure at the infinity. + * \return Value of the pressure at the infinity. + */ + inline su2double GetPressure_Inf(void) const final { return Pressure_Inf; } + + /*! + * \brief Get the temperature value at infinity. + * \return Value of the temperature at infinity. + */ + inline su2double GetTemperature_Inf(void) const { return Temperature_Inf; } + + /*! + * \brief Compute the density multiply by velocity at the infinity. + * \param[in] val_dim - Index of the velocity vector. + * \return Value of the density multiply by the velocity at the infinity. + */ + inline su2double GetDensity_Velocity_Inf(unsigned short val_dim) const final { + return Density_Inf * Velocity_Inf[val_dim]; + } + + /*! + * \brief Get the velocity at the infinity. + * \param[in] val_dim - Index of the velocity vector. + * \return Value of the velocity at the infinity. + */ + inline su2double GetVelocity_Inf(unsigned short val_dim) const final { return Velocity_Inf[val_dim]; } + + /*! + * \brief Get the velocity at the infinity. + * \return Value of the velocity at the infinity. + */ + inline su2double* GetVelocity_Inf(void) final { return Velocity_Inf; } + + /*! + * \brief Set the velocity at infinity. + * \param[in] val_dim - Index of the velocity vector. + * \param[in] val_velocity - Value of the velocity. + */ + inline void SetVelocity_Inf(unsigned short val_dim, su2double val_velocity) final { + Velocity_Inf[val_dim] = val_velocity; + } + + /*! + * \brief Compute the density multiply by energy at the infinity. + * \return Value of the density multiply by energy at the infinity. + */ + inline su2double GetDensity_Energy_Inf(void) const final { return Density_Inf * Energy_Inf; } + + /*! + * \brief Set the freestream pressure. + * \param[in] Value of freestream pressure. + */ + inline void SetPressure_Inf(su2double p_inf) final { Pressure_Inf = p_inf; } + + /*! + * \brief Set the freestream temperature. + * \param[in] Value of freestream temperature. + */ + inline void SetTemperature_Inf(su2double t_inf) final { Temperature_Inf = t_inf; } + + /*! + * \brief Set the freestream temperature. + * \param[in] Value of freestream temperature. + */ + inline void SetDensity_Inf(su2double rho_inf) final { Density_Inf = rho_inf; } + + /*! + * \brief Compute the viscosity at the infinity. + * \return Value of the viscosity at the infinity. + */ + inline su2double GetViscosity_Inf(void) const final { return Viscosity_Inf; } + + /*! + * \brief Get the turbulent kinetic energy at the infinity. + * \return Value of the turbulent kinetic energy at the infinity. + */ + inline su2double GetTke_Inf(void) const final { return Tke_Inf; } + + /*! + * \brief Get the max Omega. + * \return Value of the max Omega. + */ + inline su2double GetOmega_Max(void) const final { return Omega_Max; } + + /*! + * \brief Get the max Strain rate magnitude. + * \return Value of the max Strain rate magnitude. + */ + inline su2double GetStrainMag_Max(void) const final { return StrainMag_Max; } + + /*! + * \brief Provide the non dimensional lift coefficient (inviscid contribution). + * \param val_marker Surface where the coefficient is going to be computed. + * \return Value of the lift coefficient (inviscid contribution) on the surface val_marker. + */ + inline su2double GetCL_Inv(unsigned short val_marker) const final { return InvCoeff.CL[val_marker]; } + + /*! + * \brief Provide the non dimensional drag coefficient (inviscid contribution). + * \param val_marker Surface where the coeficient is going to be computed. + * \return Value of the drag coefficient (inviscid contribution) on the surface val_marker. + */ + inline su2double GetCD_Inv(unsigned short val_marker) const final { return InvCoeff.CD[val_marker]; } + + /*! + * \brief Provide the non dimensional lift coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the lift coefficient on the surface val_marker. + */ + inline su2double GetSurface_CL(unsigned short val_marker) const final { return SurfaceCoeff.CL[val_marker]; } + + /*! + * \brief Provide the non dimensional drag coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the drag coefficient on the surface val_marker. + */ + inline su2double GetSurface_CD(unsigned short val_marker) const final { return SurfaceCoeff.CD[val_marker]; } + + /*! + * \brief Provide the non dimensional side-force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the side-force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CSF(unsigned short val_marker) const final { return SurfaceCoeff.CSF[val_marker]; } + + /*! + * \brief Provide the non dimensional side-force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the side-force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CEff(unsigned short val_marker) const final { return SurfaceCoeff.CEff[val_marker]; } + + /*! + * \brief Provide the non dimensional x force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the x force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFx(unsigned short val_marker) const final { return SurfaceCoeff.CFx[val_marker]; } + + /*! + * \brief Provide the non dimensional y force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the y force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFy(unsigned short val_marker) const final { return SurfaceCoeff.CFy[val_marker]; } + + /*! + * \brief Provide the non dimensional z force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the z force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFz(unsigned short val_marker) const final { return SurfaceCoeff.CFz[val_marker]; } + + /*! + * \brief Provide the non dimensional x moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the x moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMx(unsigned short val_marker) const final { return SurfaceCoeff.CMx[val_marker]; } + + /*! + * \brief Provide the non dimensional y moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the y moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMy(unsigned short val_marker) const final { return SurfaceCoeff.CMy[val_marker]; } + + /*! + * \brief Provide the non dimensional z moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the z moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMz(unsigned short val_marker) const final { return SurfaceCoeff.CMz[val_marker]; } + + /*! + * \brief Provide the non dimensional lift coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the lift coefficient on the surface val_marker. + */ + inline su2double GetSurface_CL_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CL[val_marker]; } + + /*! + * \brief Provide the non dimensional drag coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the drag coefficient on the surface val_marker. + */ + inline su2double GetSurface_CD_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CD[val_marker]; } + + /*! + * \brief Provide the non dimensional side-force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the side-force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CSF_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CSF[val_marker]; } + + /*! + * \brief Provide the non dimensional side-force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the side-force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CEff_Inv(unsigned short val_marker) const final { + return SurfaceInvCoeff.CEff[val_marker]; + } + + /*! + * \brief Provide the non dimensional x force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the x force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFx_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CFx[val_marker]; } + + /*! + * \brief Provide the non dimensional y force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the y force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFy_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CFy[val_marker]; } + + /*! + * \brief Provide the non dimensional z force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the z force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFz_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CFz[val_marker]; } + + /*! + * \brief Provide the non dimensional x moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the x moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMx_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CMx[val_marker]; } + + /*! + * \brief Provide the non dimensional y moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the y moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMy_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CMy[val_marker]; } + + /*! + * \brief Provide the non dimensional z moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the z moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMz_Inv(unsigned short val_marker) const final { return SurfaceInvCoeff.CMz[val_marker]; } + + /*! + * \brief Provide the non dimensional lift coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the lift coefficient on the surface val_marker. + */ + inline su2double GetSurface_CL_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CL[val_marker]; } + + /*! + * \brief Provide the non dimensional drag coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the drag coefficient on the surface val_marker. + */ + inline su2double GetSurface_CD_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CD[val_marker]; } + + /*! + * \brief Provide the non dimensional side-force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the side-force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CSF_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CSF[val_marker]; } + + /*! + * \brief Provide the non dimensional side-force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the side-force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CEff_Mnt(unsigned short val_marker) const final { + return SurfaceMntCoeff.CEff[val_marker]; + } + + /*! + * \brief Provide the non dimensional x force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the x force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFx_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CFx[val_marker]; } + + /*! + * \brief Provide the non dimensional y force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the y force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFy_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CFy[val_marker]; } + + /*! + * \brief Provide the non dimensional z force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the z force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFz_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CFz[val_marker]; } + + /*! + * \brief Provide the non dimensional x moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the x moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMx_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CMx[val_marker]; } + + /*! + * \brief Provide the non dimensional y moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the y moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMy_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CMy[val_marker]; } + + /*! + * \brief Provide the non dimensional z moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the z moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMz_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CMz[val_marker]; } + + /*! + * \brief Provide the non dimensional sideforce coefficient (inviscid contribution). + * \param val_marker Surface where the coeficient is going to be computed. + * \return Value of the sideforce coefficient (inviscid contribution) on the surface val_marker. + */ + inline su2double GetCSF_Inv(unsigned short val_marker) const final { return InvCoeff.CSF[val_marker]; } + + /*! + * \brief Provide the non dimensional efficiency coefficient (inviscid contribution). + * \param val_marker Surface where the coeficient is going to be computed. + * \return Value of the efficiency coefficient (inviscid contribution) on the surface val_marker. + */ + inline su2double GetCEff_Inv(unsigned short val_marker) const final { return InvCoeff.CEff[val_marker]; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional sideforce coefficient. + * \return Value of the sideforce coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CSF() const final { return TotalCoeff.CSF; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CEff() const final { return TotalCoeff.CEff; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional lift coefficient. + * \return Value of the lift coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CL() const final { return TotalCoeff.CL; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. + * \return Value of the drag coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CD() const final { return TotalCoeff.CD; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional x moment coefficient. + * \return Value of the moment x coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CMx() const final { return TotalCoeff.CMx; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional y moment coefficient. + * \return Value of the moment y coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CMy() const final { return TotalCoeff.CMy; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional z moment coefficient. + * \return Value of the moment z coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CMz() const final { return TotalCoeff.CMz; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional x moment coefficient. + * \return Value of the moment x coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CoPx() const final { return TotalCoeff.CoPx; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional y moment coefficient. + * \return Value of the moment y coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CoPy() const final { return TotalCoeff.CoPy; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional z moment coefficient. + * \return Value of the moment z coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CoPz() const final { return TotalCoeff.CoPz; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional x force coefficient. + * \return Value of the force x coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CFx() const final { return TotalCoeff.CFx; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional y force coefficient. + * \return Value of the force y coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CFy() const final { return TotalCoeff.CFy; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional z force coefficient. + * \return Value of the force z coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CFz() const final { return TotalCoeff.CFz; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional thrust coefficient. + * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CT() const final { return TotalCoeff.CT; } + + /*! + * \brief Store the total (inviscid + viscous) non dimensional thrust coefficient. + * \param[in] val_Total_CT - Value of the total thrust coefficient. + */ + inline void SetTotal_CT(su2double val_Total_CT) final { TotalCoeff.CT = val_Total_CT; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional torque coefficient. + * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CQ() const final { return TotalCoeff.CQ; } + + /*! + * \brief Store the total (inviscid + viscous) non dimensional torque coefficient. + * \param[in] val_Total_CQ - Value of the total torque coefficient. + */ + inline void SetTotal_CQ(su2double val_Total_CQ) final { TotalCoeff.CQ = val_Total_CQ; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional rotor Figure of Merit. + * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CMerit() const final { return TotalCoeff.CMerit; } + + /*! + * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. + * \param[in] val_Total_CD - Value of the total drag coefficient. + */ + inline void SetTotal_CD(su2double val_Total_CD) final { TotalCoeff.CD = val_Total_CD; } + + /*! + * \brief Store the total (inviscid + viscous) non dimensional lift coefficient. + * \param[in] val_Total_CL - Value of the total lift coefficient. + */ + inline void SetTotal_CL(su2double val_Total_CL) final { TotalCoeff.CL = val_Total_CL; } + + /*! + * \brief Get the inviscid contribution to the lift coefficient. + * \return Value of the lift coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CL_Inv() const final { return AllBoundInvCoeff.CL; } + + /*! + * \brief Get the inviscid contribution to the drag coefficient. + * \return Value of the drag coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CD_Inv() const final { return AllBoundInvCoeff.CD; } + + /*! + * \brief Get the inviscid contribution to the sideforce coefficient. + * \return Value of the sideforce coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CSF_Inv() const final { return AllBoundInvCoeff.CSF; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CEff_Inv() const final { return AllBoundInvCoeff.CEff; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMx_Inv() const final { return AllBoundInvCoeff.CMx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMy_Inv() const final { return AllBoundInvCoeff.CMy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMz_Inv() const final { return AllBoundInvCoeff.CMz; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPx_Inv() const final { return AllBoundInvCoeff.CoPx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPy_Inv() const final { return AllBoundInvCoeff.CoPy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPz_Inv() const final { return AllBoundInvCoeff.CoPz; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFx_Inv() const final { return AllBoundInvCoeff.CFx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFy_Inv() const final { return AllBoundInvCoeff.CFy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFz_Inv() const final { return AllBoundInvCoeff.CFz; } + + /*! + * \brief Get the inviscid contribution to the lift coefficient. + * \return Value of the lift coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CL_Mnt() const final { return AllBoundMntCoeff.CL; } + + /*! + * \brief Get the inviscid contribution to the drag coefficient. + * \return Value of the drag coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CD_Mnt() const final { return AllBoundMntCoeff.CD; } + + /*! + * \brief Get the inviscid contribution to the sideforce coefficient. + * \return Value of the sideforce coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CSF_Mnt() const final { return AllBoundMntCoeff.CSF; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CEff_Mnt() const final { return AllBoundMntCoeff.CEff; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMx_Mnt() const final { return AllBoundMntCoeff.CMx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMy_Mnt() const final { return AllBoundMntCoeff.CMy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMz_Mnt() const final { return AllBoundMntCoeff.CMz; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPx_Mnt() const final { return AllBoundMntCoeff.CoPx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPy_Mnt() const final { return AllBoundMntCoeff.CoPy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPz_Mnt() const final { return AllBoundMntCoeff.CoPz; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFx_Mnt() const final { return AllBoundMntCoeff.CFx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFy_Mnt() const final { return AllBoundMntCoeff.CFy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFz_Mnt() const final { return AllBoundMntCoeff.CFz; } + + /*! + * \brief Provide the non dimensional lift coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the lift coefficient on the surface val_marker. + */ + inline su2double GetSurface_CL_Visc(unsigned short val_marker) const final { return SurfaceViscCoeff.CL[val_marker]; } + + /*! + * \brief Provide the non dimensional drag coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the drag coefficient on the surface val_marker. + */ + inline su2double GetSurface_CD_Visc(unsigned short val_marker) const final { return SurfaceViscCoeff.CD[val_marker]; } + + /*! + * \brief Provide the non dimensional side-force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the side-force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CSF_Visc(unsigned short val_marker) const final { + return SurfaceViscCoeff.CSF[val_marker]; + } + + /*! + * \brief Provide the non dimensional side-force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the side-force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CEff_Visc(unsigned short val_marker) const final { + return SurfaceViscCoeff.CEff[val_marker]; + } + + /*! + * \brief Provide the non dimensional x force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the x force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFx_Visc(unsigned short val_marker) const final { + return SurfaceViscCoeff.CFx[val_marker]; + } + + /*! + * \brief Provide the non dimensional y force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the y force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFy_Visc(unsigned short val_marker) const final { + return SurfaceViscCoeff.CFy[val_marker]; + } + + /*! + * \brief Provide the non dimensional z force coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the z force coefficient on the surface val_marker. + */ + inline su2double GetSurface_CFz_Visc(unsigned short val_marker) const final { + return SurfaceViscCoeff.CFz[val_marker]; + } + + /*! + * \brief Provide the non dimensional x moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the x moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMx_Visc(unsigned short val_marker) const final { + return SurfaceViscCoeff.CMx[val_marker]; + } + + /*! + * \brief Provide the non dimensional y moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the y moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMy_Visc(unsigned short val_marker) const final { + return SurfaceViscCoeff.CMy[val_marker]; + } + + /*! + * \brief Provide the non dimensional z moment coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the z moment coefficient on the surface val_marker. + */ + inline su2double GetSurface_CMz_Visc(unsigned short val_marker) const final { + return SurfaceViscCoeff.CMz[val_marker]; + } + + /*! + * \brief Get the inviscid contribution to the lift coefficient. + * \return Value of the lift coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CL_Visc() const final { return AllBoundViscCoeff.CL; } + + /*! + * \brief Get the inviscid contribution to the drag coefficient. + * \return Value of the drag coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CD_Visc() const final { return AllBoundViscCoeff.CD; } + + /*! + * \brief Get the inviscid contribution to the sideforce coefficient. + * \return Value of the sideforce coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CSF_Visc() const final { return AllBoundViscCoeff.CSF; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CEff_Visc() const final { return AllBoundViscCoeff.CEff; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMx_Visc() const final { return AllBoundViscCoeff.CMx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMy_Visc() const final { return AllBoundViscCoeff.CMy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CMz_Visc() const final { return AllBoundViscCoeff.CMz; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPx_Visc() const final { return AllBoundViscCoeff.CoPx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPy_Visc() const final { return AllBoundViscCoeff.CoPy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CoPz_Visc() const final { return AllBoundViscCoeff.CoPz; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFx_Visc() const final { return AllBoundViscCoeff.CFx; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFy_Visc() const final { return AllBoundViscCoeff.CFy; } + + /*! + * \brief Get the inviscid contribution to the efficiency coefficient. + * \return Value of the efficiency coefficient (inviscid contribution). + */ + inline su2double GetAllBound_CFz_Visc() const final { return AllBoundViscCoeff.CFz; } + + /*! + * \brief Get the non dimensional lift coefficient (viscous contribution). + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the lift coefficient (viscous contribution) on the surface val_marker. + */ + inline su2double GetCL_Visc(unsigned short val_marker) const final { return ViscCoeff.CL[val_marker]; } + + /*! + * \brief Get the non dimensional sideforce coefficient (viscous contribution). + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the sideforce coefficient (viscous contribution) on the surface val_marker. + */ + inline su2double GetCSF_Visc(unsigned short val_marker) const final { return ViscCoeff.CSF[val_marker]; } + + /*! + * \brief Get the non dimensional drag coefficient (viscous contribution). + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \return Value of the drag coefficient (viscous contribution) on the surface val_marker. + */ + inline su2double GetCD_Visc(unsigned short val_marker) const final { return ViscCoeff.CD[val_marker]; } + + /*! + * \brief Get the total heat flux. + * \param[in] val_marker - Surface marker where the heat flux is computed. + * \return Value of the integrated heat flux (viscous contribution) on the surface val_marker. + */ + inline su2double GetSurface_HF_Visc(unsigned short val_marker) const final { return Surface_HF_Visc[val_marker]; } + + /*! + * \brief Get the maximum (per surface) heat flux. + * \param[in] val_marker - Surface marker where the heat flux is computed. + * \return Value of the maximum heat flux (viscous contribution) on the surface val_marker. + */ + inline su2double GetSurface_MaxHF_Visc(unsigned short val_marker) const final { + return Surface_MaxHF_Visc[val_marker]; + } + + /*! + * \brief Set the value of the Equivalent Area coefficient. + * \param[in] val_cequivarea - Value of the Equivalent Area coefficient. + */ + inline void SetTotal_CpDiff(su2double val_pressure) final { Total_CpDiff = val_pressure; } + + /*! + * \brief Set the value of the Equivalent Area coefficient. + * \param[in] val_cequivarea - Value of the Equivalent Area coefficient. + */ + inline void SetTotal_HeatFluxDiff(su2double val_heat) final { Total_HeatFluxDiff = val_heat; } + + /*! + * \brief Set the value of the Near-Field pressure oefficient. + * \param[in] val_cnearfieldpress - Value of the Near-Field pressure coefficient. + */ + inline void SetTotal_CNearFieldOF(su2double val_cnearfieldpress) final { Total_CNearFieldOF = val_cnearfieldpress; } + + /*! + * \author H. Kline + * \brief Set the total "combo" objective (weighted sum of other values). + * \param[in] ComboObj - Value of the combined objective. + */ + inline void SetTotal_ComboObj(su2double ComboObj) final { Total_ComboObj = ComboObj; } + + /*! + * \author H. Kline + * \brief Provide the total "combo" objective (weighted sum of other values). + * \return Value of the "combo" objective values. + */ + inline su2double GetTotal_ComboObj() const final { return Total_ComboObj; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. + * \return Value of the Equivalent Area coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_CpDiff() const final { return Total_CpDiff; } + + /*! + * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. + * \return Value of the Equivalent Area coefficient (inviscid + viscous contribution). + */ + inline su2double GetTotal_HeatFluxDiff() const final { return Total_HeatFluxDiff; } + + /*! + * \brief Set the value of the custom objective function. + * \param[in] val_Total_Custom_ObjFunc - Value of the total custom objective function. + * \param[in] val_weight - Value of the weight for the custom objective function. + */ + inline void SetTotal_Custom_ObjFunc(su2double val_total_custom_objfunc, su2double val_weight) final { + Total_Custom_ObjFunc = val_total_custom_objfunc * val_weight; + } + + /*! + * \brief Add the value of the custom objective function. + * \param[in] val_Total_Custom_ObjFunc - Value of the total custom objective function. + * \param[in] val_weight - Value of the weight for the custom objective function. + */ + inline void AddTotal_Custom_ObjFunc(su2double val_total_custom_objfunc, su2double val_weight) final { + Total_Custom_ObjFunc += val_total_custom_objfunc * val_weight; + } + + /*! + * \brief Provide the total heat load. + * \return Value of the heat load (viscous contribution). + */ + inline su2double GetTotal_HeatFlux(void) const final { return Total_Heat; } + + /*! + * \brief Provide the total heat load. + * \return Value of the heat load (viscous contribution). + */ + inline su2double GetTotal_MaxHeatFlux() const final { return Total_MaxHeat; } + + /*! + * \brief Store the total heat load. + * \param[in] val_Total_Heat - Value of the heat load. + */ + inline void SetTotal_HeatFlux(su2double val_Total_Heat) final { Total_Heat = val_Total_Heat; } + + /*! + * \brief Store the total heat load. + * \param[in] val_Total_Heat - Value of the heat load. + */ + inline void SetTotal_MaxHeatFlux(su2double val_Total_MaxHeat) final { Total_MaxHeat = val_Total_MaxHeat; } + + /*! + * \brief Provide the total custom objective function. + * \return Value of the custom objective function. + */ + inline su2double GetTotal_Custom_ObjFunc() const final { return Total_Custom_ObjFunc; } + + /*! + * \brief Provide the Pressure coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the pressure coefficient. + */ + inline su2double GetCPressure(unsigned short val_marker, unsigned long val_vertex) const final { + return CPressure[val_marker][val_vertex]; + } + + /*! + * \brief Provide the Target Pressure coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the pressure coefficient. + */ + inline su2double GetCPressureTarget(unsigned short val_marker, unsigned long val_vertex) const final { + return CPressureTarget[val_marker][val_vertex]; + } + + /*! + * \brief Set the value of the target Pressure coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the pressure coefficient. + */ + inline void SetCPressureTarget(unsigned short val_marker, unsigned long val_vertex, su2double val_pressure) final { + CPressureTarget[val_marker][val_vertex] = val_pressure; + } + + /*! + * \brief Value of the characteristic variables at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the pressure coefficient. + */ + inline su2double* GetCharacPrimVar(unsigned short val_marker, unsigned long val_vertex) const final { + return CharacPrimVar[val_marker][val_vertex]; + } + + /*! + * \brief Value of the characteristic variables at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the pressure coefficient. + */ + inline void SetCharacPrimVar(unsigned short val_marker, unsigned long val_vertex, unsigned short val_var, + su2double val_value) final { + CharacPrimVar[val_marker][val_vertex][val_var] = val_value; + } + + /*! + * \brief Value of the total temperature at an inlet boundary. + * \param[in] val_marker - Surface marker where the total temperature is evaluated. + * \param[in] val_vertex - Vertex of the marker val_marker where the total temperature is evaluated. + * \return Value of the total temperature + */ + inline su2double GetInlet_Ttotal(unsigned short val_marker, unsigned long val_vertex) const final { + return Inlet_Ttotal[val_marker][val_vertex]; + } + + /*! + * \brief Value of the total pressure at an inlet boundary. + * \param[in] val_marker - Surface marker where the total pressure is evaluated. + * \param[in] val_vertex - Vertex of the marker val_marker where the total pressure is evaluated. + * \return Value of the total pressure + */ + inline su2double GetInlet_Ptotal(unsigned short val_marker, unsigned long val_vertex) const final { + return Inlet_Ptotal[val_marker][val_vertex]; + } + + /*! + * \brief A component of the unit vector representing the flow direction at an inlet boundary. + * \param[in] val_marker - Surface marker where the flow direction is evaluated + * \param[in] val_vertex - Vertex of the marker val_marker where the flow direction is evaluated + * \param[in] val_dim - The component of the flow direction unit vector to be evaluated + * \return Component of a unit vector representing the flow direction. + */ + inline su2double GetInlet_FlowDir(unsigned short val_marker, unsigned long val_vertex, + unsigned short val_dim) const final { + return Inlet_FlowDir[val_marker][val_vertex][val_dim]; + } + + /*! + * \brief Set the value of the total temperature at an inlet boundary. + * \param[in] val_marker - Surface marker where the total temperature is set. + * \param[in] val_vertex - Vertex of the marker val_marker where the total temperature is set. + * \param[in] val_ttotal - Value of the total temperature + */ + inline void SetInlet_Ttotal(unsigned short val_marker, unsigned long val_vertex, su2double val_ttotal) final { + /*--- Since this call can be accessed indirectly using python, do some error + * checking to prevent segmentation faults ---*/ + if (val_marker >= nMarker) + SU2_MPI::Error("Out-of-bounds marker index used on inlet.", CURRENT_FUNCTION); + else if (Inlet_Ttotal == nullptr || Inlet_Ttotal[val_marker] == nullptr) + SU2_MPI::Error("Tried to set custom inlet BC on an invalid marker.", CURRENT_FUNCTION); + else if (val_vertex >= nVertex[val_marker]) + SU2_MPI::Error("Out-of-bounds vertex index used on inlet.", CURRENT_FUNCTION); + else + Inlet_Ttotal[val_marker][val_vertex] = val_ttotal; + } + + /*! + * \brief Set the value of the total pressure at an inlet boundary. + * \param[in] val_marker - Surface marker where the total pressure is set. + * \param[in] val_vertex - Vertex of the marker val_marker where the total pressure is set. + * \param[in] val_ptotal - Value of the total pressure + */ + inline void SetInlet_Ptotal(unsigned short val_marker, unsigned long val_vertex, su2double val_ptotal) final { + /*--- Since this call can be accessed indirectly using python, do some error + * checking to prevent segmentation faults ---*/ + if (val_marker >= nMarker) + SU2_MPI::Error("Out-of-bounds marker index used on inlet.", CURRENT_FUNCTION); + else if (Inlet_Ptotal == nullptr || Inlet_Ptotal[val_marker] == nullptr) + SU2_MPI::Error("Tried to set custom inlet BC on an invalid marker.", CURRENT_FUNCTION); + else if (val_vertex >= nVertex[val_marker]) + SU2_MPI::Error("Out-of-bounds vertex index used on inlet.", CURRENT_FUNCTION); + else + Inlet_Ptotal[val_marker][val_vertex] = val_ptotal; + } + + /*! + * \brief Set a component of the unit vector representing the flow direction at an inlet boundary. + * \param[in] val_marker - Surface marker where the flow direction is set. + * \param[in] val_vertex - Vertex of the marker val_marker where the flow direction is set. + * \param[in] val_dim - The component of the flow direction unit vector to be set + * \param[in] val_flowdir - Component of a unit vector representing the flow direction. + */ + inline void SetInlet_FlowDir(unsigned short val_marker, unsigned long val_vertex, unsigned short val_dim, + su2double val_flowdir) final { + /*--- Since this call can be accessed indirectly using python, do some error + * checking to prevent segmentation faults ---*/ + if (val_marker >= nMarker) + SU2_MPI::Error("Out-of-bounds marker index used on inlet.", CURRENT_FUNCTION); + else if (Inlet_FlowDir == nullptr || Inlet_FlowDir[val_marker] == nullptr) + SU2_MPI::Error("Tried to set custom inlet BC on an invalid marker.", CURRENT_FUNCTION); + else if (val_vertex >= nVertex[val_marker]) + SU2_MPI::Error("Out-of-bounds vertex index used on inlet.", CURRENT_FUNCTION); + else + Inlet_FlowDir[val_marker][val_vertex][val_dim] = val_flowdir; + } + + /*! + * \brief Compute the global error measures (L2, Linf) for verification cases. + * \param[in] geometry - Geometrical definition. + * \param[in] config - Definition of the particular problem. + */ + void ComputeVerificationError(CGeometry* geometry, CConfig* config) final; + + /*! + * \brief Print verification error to screen, derived solvers must define this. + * \param[in] config - Definition of the particular problem. + */ + virtual void PrintVerificationError(const CConfig* config) const = 0; + + /*! + * \brief Compute the pressure forces and all the adimensional coefficients. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + */ + void Pressure_Forces(const CGeometry* geometry, const CConfig* config) final; + + /*! + * \brief Compute the pressure forces and all the adimensional coefficients. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + */ + void Momentum_Forces(const CGeometry* geometry, const CConfig* config) final; + + /*! + * \brief Compute the viscous forces and all the addimensional coefficients. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + */ + void Friction_Forces(const CGeometry* geometry, const CConfig* config) final; + + /*! + * \brief Allocates the final pointer of SlidingState depending on how many donor vertex donate to it. + * That number is stored in SlidingStateNodes[val_marker][val_vertex]. + * \param[in] val_marker - marker index + * \param[in] val_vertex - vertex index + */ + inline void SetSlidingStateStructure(unsigned short val_marker, unsigned long val_vertex) final { + for (int iVar = 0; iVar < nPrimVar + 1; iVar++) { + if (SlidingState[val_marker][val_vertex][iVar] != nullptr) delete[] SlidingState[val_marker][val_vertex][iVar]; + } + + for (int iVar = 0; iVar < nPrimVar + 1; iVar++) + SlidingState[val_marker][val_vertex][iVar] = new su2double[GetnSlidingStates(val_marker, val_vertex)]; + } + + /*! + * \brief Set the outer state for fluid interface nodes. + * \param[in] val_marker - marker index + * \param[in] val_vertex - vertex index + * \param[in] val_state - requested state component + * \param[in] donor_index - index of the donor node to set + * \param[in] component - set value + */ + inline void SetSlidingState(unsigned short val_marker, unsigned long val_vertex, unsigned short val_state, + unsigned long donor_index, su2double component) final { + SlidingState[val_marker][val_vertex][val_state][donor_index] = component; + } + + /*! + * \brief Set the number of outer state for fluid interface nodes. + * \param[in] val_marker - marker index + * \param[in] val_vertex - vertex index + * \param[in] value - number of outer states + */ + inline void SetnSlidingStates(unsigned short val_marker, unsigned long val_vertex, int value) final { + SlidingStateNodes[val_marker][val_vertex] = value; + } + + /*! + * \brief Get the number of outer state for fluid interface nodes. + * \param[in] val_marker - marker index + * \param[in] val_vertex - vertex index + */ + inline int GetnSlidingStates(unsigned short val_marker, unsigned long val_vertex) const final { + return SlidingStateNodes[val_marker][val_vertex]; + } + + /*! + * \brief Get the outer state for fluid interface nodes. + * \param[in] val_marker - marker index + * \param[in] val_vertex - vertex index + * \param[in] val_state - requested state component + * \param[in] donor_index- index of the donor node to get + */ + inline su2double GetSlidingState(unsigned short val_marker, unsigned long val_vertex, unsigned short val_state, + unsigned long donor_index) const final { + return SlidingState[val_marker][val_vertex][val_state][donor_index]; + } + + /*! + * \brief Set the conjugate heat variables. + * \param[in] val_marker - marker index + * \param[in] val_vertex - vertex index + * \param[in] pos_var - variable position (in vector of all conjugate heat variables) + * \param[in] relaxation factor - relaxation factor for the change of the variables + * \param[in] val_var - value of the variable + */ + inline void SetConjugateHeatVariable(unsigned short val_marker, unsigned long val_vertex, unsigned short pos_var, + su2double relaxation_factor, su2double val_var) final { + HeatConjugateVar[val_marker][val_vertex][pos_var] = + relaxation_factor * val_var + (1.0 - relaxation_factor) * HeatConjugateVar[val_marker][val_vertex][pos_var]; + } + + /*! + * \brief Set the conjugate heat variables. + * \param[in] val_marker - marker index + * \param[in] val_vertex - vertex index + * \param[in] pos_var - variable position (in vector of all conjugate heat variables) + */ + inline su2double GetConjugateHeatVariable(unsigned short val_marker, unsigned long val_vertex, + unsigned short pos_var) const final { + return HeatConjugateVar[val_marker][val_vertex][pos_var]; + } + + /*! + * \brief Get the skin friction coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the skin friction coefficient. + */ + inline su2double GetCSkinFriction(unsigned short val_marker, unsigned long val_vertex, + unsigned short val_dim) const final { + return CSkinFriction[val_marker][val_dim][val_vertex]; + } + + /*! + * \brief Get the skin friction coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the heat transfer coefficient. + */ + inline su2double GetHeatFlux(unsigned short val_marker, unsigned long val_vertex) const final { + return HeatFlux[val_marker][val_vertex]; + } + + /*! + * \brief Get the skin friction coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the heat transfer coefficient. + */ + inline su2double GetHeatFluxTarget(unsigned short val_marker, unsigned long val_vertex) const final { + return HeatFluxTarget[val_marker][val_vertex]; + } + + /*! + * \brief Set the value of the target Pressure coefficient. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the pressure coefficient. + */ + inline void SetHeatFluxTarget(unsigned short val_marker, unsigned long val_vertex, su2double val_heat) final { + HeatFluxTarget[val_marker][val_vertex] = val_heat; + } + + /*! + * \brief Get the y plus. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the y plus. + */ + inline su2double GetYPlus(unsigned short val_marker, unsigned long val_vertex) const final { + return YPlus[val_marker][val_vertex]; + } +}; diff --git a/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl b/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl new file mode 100644 index 000000000000..c6373fa0361e --- /dev/null +++ b/SU2_CFD/include/solvers/CFVMFlowSolverBase.inl @@ -0,0 +1,2550 @@ +/*! + * \file CFVMFlowSolverBase.inl + * \brief Base class template for all FVM flow solvers. + * \version 7.0.6 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2020, 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 "../gradients/computeGradientsGreenGauss.hpp" +#include "../gradients/computeGradientsLeastSquares.hpp" +#include "../limiters/computeLimiters.hpp" +#include "CFVMFlowSolverBase.hpp" + +template +void CFVMFlowSolverBase::AeroCoeffsArray::allocate(int size) { + _size = size; + CD = new su2double[size]; + CL = new su2double[size]; + CSF = new su2double[size]; + CEff = new su2double[size]; + CFx = new su2double[size]; + CFy = new su2double[size]; + CFz = new su2double[size]; + CMx = new su2double[size]; + CMy = new su2double[size]; + CMz = new su2double[size]; + CoPx = new su2double[size]; + CoPy = new su2double[size]; + CoPz = new su2double[size]; + CT = new su2double[size]; + CQ = new su2double[size]; + CMerit = new su2double[size]; + setZero(); +} + +template +CFVMFlowSolverBase::AeroCoeffsArray::~AeroCoeffsArray() { + delete[] CD; + delete[] CL; + delete[] CSF; + delete[] CEff; + delete[] CFx; + delete[] CFy; + delete[] CFz; + delete[] CMx; + delete[] CMy; + delete[] CMz; + delete[] CoPx; + delete[] CoPy; + delete[] CoPz; + delete[] CT; + delete[] CQ; + delete[] CMerit; +} + +template +void CFVMFlowSolverBase::AeroCoeffsArray::setZero(int i) { + CD[i] = CL[i] = CSF[i] = CEff[i] = 0.0; + CFx[i] = CFy[i] = CFz[i] = CMx[i] = 0.0; + CMy[i] = CMz[i] = CoPx[i] = CoPy[i] = 0.0; + CoPz[i] = CT[i] = CQ[i] = CMerit[i] = 0.0; +} + +template +void CFVMFlowSolverBase::Allocate(const CConfig& config) { + unsigned short iDim, iVar, iMarker; + unsigned long iPoint, iVertex; + + /*--- Define some auxiliar vector related with the residual ---*/ + + Residual_RMS = new su2double[nVar](); + Residual_Max = new su2double[nVar](); + + /*--- Define some structures for locating max residuals ---*/ + + Point_Max = new unsigned long[nVar](); + Point_Max_Coord = new su2double*[nVar]; + for (iVar = 0; iVar < nVar; iVar++) { + Point_Max_Coord[iVar] = new su2double[nDim](); + } + + /*--- Define some auxiliar vector related with the undivided lapalacian computation ---*/ + + if (config.GetKind_ConvNumScheme_Flow() == SPACE_CENTERED) { + iPoint_UndLapl = new su2double[nPoint]; + jPoint_UndLapl = new su2double[nPoint]; + } + + /*--- Initialize the solution and right hand side vectors for storing + the residuals and updating the solution (always needed even for + explicit schemes). ---*/ + + LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0); + LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0); + + /*--- Allocates a 2D array with variable "outer" sizes and init to 0. ---*/ + + auto Alloc2D = [](unsigned long M, const unsigned long* N, su2double**& X) { + X = new su2double*[M]; + for (unsigned long i = 0; i < M; ++i) X[i] = new su2double[N[i]](); + }; + + /*--- Allocates a 3D array with variable "middle" sizes and init to 0. ---*/ + + auto Alloc3D = [](unsigned long M, const unsigned long* N, unsigned long P, su2double***& X) { + X = new su2double**[M]; + for (unsigned long i = 0; i < M; ++i) { + X[i] = new su2double*[N[i]]; + for (unsigned long j = 0; j < N[i]; ++j) X[i][j] = new su2double[P](); + } + }; + + /*--- Store the value of the characteristic primitive variables at the boundaries ---*/ + + Alloc3D(nMarker, nVertex, nPrimVar, CharacPrimVar); + + /*--- Store the value of the Total Pressure at the inlet BC ---*/ + + Alloc2D(nMarker, nVertex, Inlet_Ttotal); + + /*--- Store the value of the Total Temperature at the inlet BC ---*/ + + Alloc2D(nMarker, nVertex, Inlet_Ptotal); + + /*--- Store the value of the Flow direction at the inlet BC ---*/ + + Alloc3D(nMarker, nVertex, nDim, Inlet_FlowDir); + + /*--- Force definition and coefficient arrays for all of the markers ---*/ + + Alloc2D(nMarker, nVertex, CPressure); + Alloc2D(nMarker, nVertex, CPressureTarget); + + /*--- Non dimensional aerodynamic coefficients ---*/ + + InvCoeff.allocate(nMarker); + MntCoeff.allocate(nMarker); + ViscCoeff.allocate(nMarker); + SurfaceInvCoeff.allocate(config.GetnMarker_Monitoring()); + SurfaceMntCoeff.allocate(config.GetnMarker_Monitoring()); + SurfaceViscCoeff.allocate(config.GetnMarker_Monitoring()); + SurfaceCoeff.allocate(config.GetnMarker_Monitoring()); + + /*--- Heat flux coefficients. ---*/ + + HF_Visc = new su2double[nMarker]; + MaxHF_Visc = new su2double[nMarker]; + + Surface_HF_Visc = new su2double[config.GetnMarker_Monitoring()]; + Surface_MaxHF_Visc = new su2double[config.GetnMarker_Monitoring()]; + + /*--- Supersonic coefficients ---*/ + + CNearFieldOF_Inv = new su2double[nMarker]; + + /*--- Initializate quantities for SlidingMesh Interface ---*/ + + SlidingState = new su2double***[nMarker](); + SlidingStateNodes = new int*[nMarker](); + + for (iMarker = 0; iMarker < nMarker; iMarker++) { + if (config.GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) { + SlidingState[iMarker] = new su2double**[nVertex[iMarker]](); + SlidingStateNodes[iMarker] = new int[nVertex[iMarker]](); + + for (iPoint = 0; iPoint < nVertex[iMarker]; iPoint++) + SlidingState[iMarker][iPoint] = new su2double*[nPrimVar + 1](); + } + } + + /*--- Heat flux in all the markers ---*/ + + Alloc2D(nMarker, nVertex, HeatFlux); + Alloc2D(nMarker, nVertex, HeatFluxTarget); + + /*--- Y plus in all the markers ---*/ + + Alloc2D(nMarker, nVertex, YPlus); + + /*--- Skin friction in all the markers ---*/ + + CSkinFriction = new su2double**[nMarker]; + for (iMarker = 0; iMarker < nMarker; iMarker++) { + CSkinFriction[iMarker] = new su2double*[nDim]; + for (iDim = 0; iDim < nDim; iDim++) { + CSkinFriction[iMarker][iDim] = new su2double[nVertex[iMarker]](); + } + } + + /*--- Store the values of the temperature and the heat flux density at the boundaries, + used for coupling with a solid donor cell ---*/ + constexpr auto nHeatConjugateVar = 4u; + + HeatConjugateVar = new su2double**[nMarker]; + for (iMarker = 0; iMarker < nMarker; iMarker++) { + HeatConjugateVar[iMarker] = new su2double*[nVertex[iMarker]]; + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { + HeatConjugateVar[iMarker][iVertex] = new su2double[nHeatConjugateVar](); + HeatConjugateVar[iMarker][iVertex][0] = config.GetTemperature_FreeStreamND(); + } + } + + /*--- Only initialize when there is a Marker_Fluid_Load defined + *--- (this avoids overhead in all other cases while a more permanent structure is being developed) ---*/ + if ((config.GetnMarker_Fluid_Load() > 0) && (MGLevel == MESH_0)) { + InitVertexTractionContainer(); + + if (config.GetDiscrete_Adjoint()) InitVertexTractionAdjointContainer(); + } + + /*--- Initialize the BGS residuals in FSI problems. ---*/ + if (config.GetMultizone_Residual()) { + Residual_BGS = new su2double[nVar]; + for (iVar = 0; iVar < nVar; iVar++) Residual_BGS[iVar] = 1.0; + + Residual_Max_BGS = new su2double[nVar]; + for (iVar = 0; iVar < nVar; iVar++) Residual_Max_BGS[iVar] = 1.0; + + /*--- Define some structures for locating max residuals ---*/ + + Point_Max_BGS = new unsigned long[nVar](); + Point_Max_Coord_BGS = new su2double*[nVar]; + for (iVar = 0; iVar < nVar; iVar++) { + Point_Max_Coord_BGS[iVar] = new su2double[nDim](); + } + } +} + +template +void CFVMFlowSolverBase::AllocateTerribleLegacyTemporaryVariables() { + /*--- Define some auxiliary vectors related to the residual ---*/ + + Residual = new su2double[nVar](); + Res_Conv = new su2double[nVar](); + Res_Visc = new su2double[nVar](); + Res_Sour = new su2double[nVar](); + + /*--- Define some auxiliary vectors related to the solution ---*/ + + Solution = new su2double[nVar](); + Solution_i = new su2double[nVar](); + Solution_j = new su2double[nVar](); + + /*--- Define some auxiliary vectors related to the geometry ---*/ + + Vector = new su2double[nDim](); + Vector_i = new su2double[nDim](); + Vector_j = new su2double[nDim](); + + /*--- Jacobian temporaries. ---*/ + + Jacobian_i = new su2double*[nVar]; + Jacobian_j = new su2double*[nVar]; + for (auto iVar = 0u; iVar < nVar; iVar++) { + Jacobian_i[iVar] = new su2double[nVar]; + Jacobian_j[iVar] = new su2double[nVar]; + } +} + +template +void CFVMFlowSolverBase::CommunicateInitialState(CGeometry* geometry, const CConfig* config) { + /*--- Define solver parameters needed for execution of destructor ---*/ + + space_centered = (config->GetKind_ConvNumScheme_Flow() == SPACE_CENTERED); + euler_implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + least_squares = (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES); + + /*--- Communicate and store volume and the number of neighbors for + any dual CVs that lie on on periodic markers. ---*/ + + for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic() / 2; iPeriodic++) { + InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME); + CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME); + InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS); + CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS); + } + SetImplicitPeriodic(euler_implicit); + if (MGLevel == MESH_0) SetRotatePeriodic(true); + + /*--- Perform the MPI communication of the solution ---*/ + + InitiateComms(geometry, config, SOLUTION); + CompleteComms(geometry, config, SOLUTION); + + /* Store the initial CFL number for all grid points. */ + + const auto CFL = config->GetCFL(MGLevel); + for (auto iPoint = 0ul; iPoint < nPoint; iPoint++) { + nodes->SetLocalCFL(iPoint, CFL); + } + Min_CFL_Local = CFL; + Max_CFL_Local = CFL; + Avg_CFL_Local = CFL; +} + +template +void CFVMFlowSolverBase::HybridParallelInitialization(const CConfig& config, CGeometry& geometry) { +#ifdef HAVE_OMP + /*--- Get the edge coloring. If the expected parallel efficiency becomes too low setup the + * reducer strategy. Where one loop is performed over edges followed by a point loop to + * sum the fluxes for each cell and set the diagonal of the system matrix. ---*/ + + su2double parallelEff = 1.0; + const auto& coloring = geometry.GetEdgeColoring(¶llelEff); + + /*--- The decision to use the strategy is local to each rank. ---*/ + ReducerStrategy = parallelEff < COLORING_EFF_THRESH; + + /*--- When using the reducer force a single color to reduce the color loop overhead. ---*/ + if (ReducerStrategy && (coloring.getOuterSize() > 1)) geometry.SetNaturalEdgeColoring(); + + if (!coloring.empty()) { + /*--- If the reducer strategy is used we are not constrained by group + * size as we have no other edge loops in the Euler/NS solvers. ---*/ + auto groupSize = ReducerStrategy ? 1ul : geometry.GetEdgeColorGroupSize(); + auto nColor = coloring.getOuterSize(); + EdgeColoring.reserve(nColor); + + for (auto iColor = 0ul; iColor < nColor; ++iColor) + EdgeColoring.emplace_back(coloring.innerIdx(iColor), coloring.getNumNonZeros(iColor), groupSize); + } + + /*--- If the reducer strategy is not being forced (by EDGE_COLORING_GROUP_SIZE=0) print some messages. ---*/ + if (config.GetEdgeColoringGroupSize() != 1 << 30) { + su2double minEff = 1.0; + SU2_MPI::Reduce(¶llelEff, &minEff, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, MPI_COMM_WORLD); + + int tmp = ReducerStrategy, numRanksUsingReducer = 0; + SU2_MPI::Reduce(&tmp, &numRanksUsingReducer, 1, MPI_INT, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD); + + if (minEff < COLORING_EFF_THRESH) { + cout << "WARNING: On " << numRanksUsingReducer << " MPI ranks the coloring efficiency was less than " + << COLORING_EFF_THRESH << " (min value was " << minEff << ").\n" + << " Those ranks will now use a fallback strategy, better performance may be possible\n" + << " with a different value of config option EDGE_COLORING_GROUP_SIZE (default 512)." << endl; + } + } + + if (ReducerStrategy) EdgeFluxes.Initialize(geometry.GetnEdge(), geometry.GetnEdge(), nVar, nullptr); + + omp_chunk_size = computeStaticChunkSize(nPoint, omp_get_max_threads(), OMP_MAX_SIZE); +#else + EdgeColoring[0] = DummyGridColor<>(geometry.GetnEdge()); +#endif +} + +template +CFVMFlowSolverBase::~CFVMFlowSolverBase() { + unsigned short iMarker, iVar, iDim; + unsigned long iVertex; + + delete[] CNearFieldOF_Inv; + delete[] HF_Visc; + delete[] MaxHF_Visc; + delete[] Surface_HF_Visc; + delete[] Surface_MaxHF_Visc; + + if (SlidingState != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + if (SlidingState[iMarker] != nullptr) { + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) + if (SlidingState[iMarker][iVertex] != nullptr) { + for (iVar = 0; iVar < nPrimVar + 1; iVar++) delete[] SlidingState[iMarker][iVertex][iVar]; + delete[] SlidingState[iMarker][iVertex]; + } + delete[] SlidingState[iMarker]; + } + } + delete[] SlidingState; + } + + if (SlidingStateNodes != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + if (SlidingStateNodes[iMarker] != nullptr) delete[] SlidingStateNodes[iMarker]; + } + delete[] SlidingStateNodes; + } + + if (CPressure != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) delete[] CPressure[iMarker]; + delete[] CPressure; + } + + if (CPressureTarget != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) delete[] CPressureTarget[iMarker]; + delete[] CPressureTarget; + } + + if (CharacPrimVar != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) delete[] CharacPrimVar[iMarker][iVertex]; + delete[] CharacPrimVar[iMarker]; + } + delete[] CharacPrimVar; + } + + if (Inlet_Ttotal != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) + if (Inlet_Ttotal[iMarker] != nullptr) delete[] Inlet_Ttotal[iMarker]; + delete[] Inlet_Ttotal; + } + + if (Inlet_Ptotal != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) + if (Inlet_Ptotal[iMarker] != nullptr) delete[] Inlet_Ptotal[iMarker]; + delete[] Inlet_Ptotal; + } + + if (Inlet_FlowDir != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + if (Inlet_FlowDir[iMarker] != nullptr) { + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) delete[] Inlet_FlowDir[iMarker][iVertex]; + delete[] Inlet_FlowDir[iMarker]; + } + } + delete[] Inlet_FlowDir; + } + + if (HeatFlux != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + delete[] HeatFlux[iMarker]; + } + delete[] HeatFlux; + } + + if (HeatFluxTarget != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + delete[] HeatFluxTarget[iMarker]; + } + delete[] HeatFluxTarget; + } + + if (YPlus != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + delete[] YPlus[iMarker]; + } + delete[] YPlus; + } + + if (CSkinFriction != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + for (iDim = 0; iDim < nDim; iDim++) { + delete[] CSkinFriction[iMarker][iDim]; + } + delete[] CSkinFriction[iMarker]; + } + delete[] CSkinFriction; + } + + if (HeatConjugateVar != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) { + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { + delete[] HeatConjugateVar[iMarker][iVertex]; + } + delete[] HeatConjugateVar[iMarker]; + } + delete[] HeatConjugateVar; + } + + delete nodes; +} + +template +void CFVMFlowSolverBase::SetPrimitive_Gradient_GG(CGeometry* geometry, const CConfig* config, + bool reconstruction) { + const auto& primitives = nodes->GetPrimitive(); + auto& gradient = reconstruction ? nodes->GetGradient_Reconstruction() : nodes->GetGradient_Primitive(); + + computeGradientsGreenGauss(this, PRIMITIVE_GRADIENT, PERIODIC_PRIM_GG, *geometry, *config, primitives, 0, + nPrimVarGrad, gradient); +} + +template +void CFVMFlowSolverBase::SetPrimitive_Gradient_LS(CGeometry* geometry, const CConfig* config, + bool reconstruction) { + /*--- Set a flag for unweighted or weighted least-squares. ---*/ + bool weighted; + + if (reconstruction) + weighted = (config->GetKind_Gradient_Method_Recon() == WEIGHTED_LEAST_SQUARES); + else + weighted = (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES); + + const auto& primitives = nodes->GetPrimitive(); + auto& rmatrix = nodes->GetRmatrix(); + auto& gradient = reconstruction ? nodes->GetGradient_Reconstruction() : nodes->GetGradient_Primitive(); + PERIODIC_QUANTITIES kindPeriodicComm = weighted ? PERIODIC_PRIM_LS : PERIODIC_PRIM_ULS; + + computeGradientsLeastSquares(this, PRIMITIVE_GRADIENT, kindPeriodicComm, *geometry, *config, weighted, primitives, 0, + nPrimVarGrad, gradient, rmatrix); +} + +template +void CFVMFlowSolverBase::SetPrimitive_Limiter(CGeometry* geometry, const CConfig* config) { + auto kindLimiter = static_cast(config->GetKind_SlopeLimit_Flow()); + const auto& primitives = nodes->GetPrimitive(); + const auto& gradient = nodes->GetGradient_Reconstruction(); + auto& primMin = nodes->GetSolution_Min(); + auto& primMax = nodes->GetSolution_Max(); + auto& limiter = nodes->GetLimiter_Primitive(); + + computeLimiters(kindLimiter, this, PRIMITIVE_LIMITER, PERIODIC_LIM_PRIM_1, PERIODIC_LIM_PRIM_2, *geometry, *config, 0, + nPrimVarGrad, primitives, gradient, primMin, primMax, limiter); +} + +template +void CFVMFlowSolverBase::ComputeVerificationError(CGeometry* geometry, CConfig* config) { + /*--- The errors only need to be computed on the finest grid. ---*/ + if (MGLevel != MESH_0) return; + + /*--- If this is a verification case, we can compute the global + error metrics by using the difference between the local error + and the known solution at each DOF. This is then collected into + RMS (L2) and maximum (Linf) global error norms. From these + global measures, one can compute the order of accuracy. ---*/ + + bool write_heads = + ((((config->GetInnerIter() % (config->GetWrt_Con_Freq() * 40)) == 0) && (config->GetInnerIter() != 0)) || + (config->GetInnerIter() == 1)); + if (!write_heads) return; + + /*--- Check if there actually is an exact solution for this + verification case, if computed at all. ---*/ + if (VerificationSolution && VerificationSolution->ExactSolutionKnown()) { + /*--- Get the physical time if necessary. ---*/ + su2double time = 0.0; + if (config->GetTime_Marching()) time = config->GetPhysicalTime(); + + /*--- Reset the global error measures to zero. ---*/ + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + VerificationSolution->SetError_RMS(iVar, 0.0); + VerificationSolution->SetError_Max(iVar, 0.0, 0); + } + + /*--- Loop over all owned points. ---*/ + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { + /* Set the pointers to the coordinates and solution of this DOF. */ + const su2double* coor = geometry->nodes->GetCoord(iPoint); + su2double* solDOF = nodes->GetSolution(iPoint); + + /* Get local error from the verification solution class. */ + vector error(nVar, 0.0); + VerificationSolution->GetLocalError(coor, time, solDOF, error.data()); + + /* Increment the global error measures */ + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + VerificationSolution->AddError_RMS(iVar, error[iVar] * error[iVar]); + VerificationSolution->AddError_Max(iVar, fabs(error[iVar]), geometry->nodes->GetGlobalIndex(iPoint), + geometry->nodes->GetCoord(iPoint)); + } + } + + /* Finalize the calculation of the global error measures. */ + VerificationSolution->SetVerificationError(geometry->GetGlobal_nPointDomain(), config); + + /*--- Screen output of the error metrics. This can be improved + once the new output classes are in place. ---*/ + + PrintVerificationError(config); + } +} + +template +void CFVMFlowSolverBase::ComputeUnderRelaxationFactor(CSolver** solver_container, const CConfig* config) { + /* Loop over the solution update given by relaxing the linear + system for this nonlinear iteration. */ + + const su2double allowableRatio = 0.2; + + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { + su2double localUnderRelaxation = 1.0; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + /* We impose a limit on the maximum percentage that the + density and energy can change over a nonlinear iteration. */ + + if ((iVar == 0) || (iVar == nVar - 1)) { + const unsigned long index = iPoint * nVar + iVar; + su2double ratio = fabs(LinSysSol[index]) / (nodes->GetSolution(iPoint, iVar) + EPS); + if (ratio > allowableRatio) { + localUnderRelaxation = min(allowableRatio / ratio, localUnderRelaxation); + } + } + } + + /* In case of turbulence, take the min of the under-relaxation factor + between the mean flow and the turb model. */ + + if (config->GetKind_Turb_Model() != NONE) + localUnderRelaxation = + min(localUnderRelaxation, solver_container[TURB_SOL]->GetNodes()->GetUnderRelaxation(iPoint)); + + /* Threshold the relaxation factor in the event that there is + a very small value. This helps avoid catastrophic crashes due + to non-realizable states by canceling the update. */ + + if (localUnderRelaxation < 1e-10) localUnderRelaxation = 0.0; + + /* Store the under-relaxation factor for this point. */ + + nodes->SetUnderRelaxation(iPoint, localUnderRelaxation); + } +} + +template +void CFVMFlowSolverBase::SetInletAtVertex(const su2double* val_inlet, unsigned short iMarker, + unsigned long iVertex) { + /*--- Alias positions within inlet file for readability ---*/ + + unsigned short T_position = nDim; + unsigned short P_position = nDim + 1; + unsigned short FlowDir_position = nDim + 2; + + /*--- Check that the norm of the flow unit vector is actually 1 ---*/ + + su2double norm = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + norm += pow(val_inlet[FlowDir_position + iDim], 2); + } + norm = sqrt(norm); + + /*--- The tolerance here needs to be loose. When adding a very + * small number (1e-10 or smaller) to a number close to 1.0, floating + * point roundoff errors can occur. ---*/ + + if (abs(norm - 1.0) > 1e-6) { + ostringstream error_msg; + error_msg << "ERROR: Found these values in columns "; + error_msg << FlowDir_position << " - "; + error_msg << FlowDir_position + nDim - 1 << endl; + error_msg << std::scientific; + error_msg << " [" << val_inlet[FlowDir_position]; + error_msg << ", " << val_inlet[FlowDir_position + 1]; + if (nDim == 3) error_msg << ", " << val_inlet[FlowDir_position + 2]; + error_msg << "]" << endl; + error_msg << " These values should be components of a unit vector for direction," << endl; + error_msg << " but their magnitude is: " << norm << endl; + SU2_MPI::Error(error_msg.str(), CURRENT_FUNCTION); + } + + /*--- Store the values in our inlet data structures. ---*/ + + Inlet_Ttotal[iMarker][iVertex] = val_inlet[T_position]; + Inlet_Ptotal[iMarker][iVertex] = val_inlet[P_position]; + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + Inlet_FlowDir[iMarker][iVertex][iDim] = val_inlet[FlowDir_position + iDim]; + } +} + +template +su2double CFVMFlowSolverBase::GetInletAtVertex(su2double* val_inlet, unsigned long val_inlet_point, + unsigned short val_kind_marker, string val_marker, + const CGeometry* geometry, const CConfig* config) const { + /*--- Local variables ---*/ + + unsigned short iMarker, iDim; + unsigned long iPoint, iVertex; + su2double Area = 0.0; + su2double Normal[3] = {0.0, 0.0, 0.0}; + + /*--- Alias positions within inlet file for readability ---*/ + + unsigned short T_position = nDim; + unsigned short P_position = nDim + 1; + unsigned short FlowDir_position = nDim + 2; + + if (val_kind_marker == INLET_FLOW) { + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + if ((config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) && + (config->GetMarker_All_TagBound(iMarker) == val_marker)) { + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + + if (iPoint == val_inlet_point) { + /*-- Compute boundary face area for this vertex. ---*/ + + geometry->vertex[iMarker][iVertex]->GetNormal(Normal); + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim] * Normal[iDim]; + Area = sqrt(Area); + + /*--- Access and store the inlet variables for this vertex. ---*/ + + val_inlet[T_position] = Inlet_Ttotal[iMarker][iVertex]; + val_inlet[P_position] = Inlet_Ptotal[iMarker][iVertex]; + for (iDim = 0; iDim < nDim; iDim++) { + val_inlet[FlowDir_position + iDim] = Inlet_FlowDir[iMarker][iVertex][iDim]; + } + + /*--- Exit once we find the point. ---*/ + + return Area; + } + } + } + } + } + + /*--- If we don't find a match, then the child point is not on the + current inlet boundary marker. Return zero area so this point does + not contribute to the restriction operator and continue. ---*/ + + return Area; +} + +template +void CFVMFlowSolverBase::SetUniformInlet(const CConfig* config, unsigned short iMarker) { + if (config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) { + string Marker_Tag = config->GetMarker_All_TagBound(iMarker); + su2double p_total = config->GetInlet_Ptotal(Marker_Tag); + su2double t_total = config->GetInlet_Ttotal(Marker_Tag); + auto flow_dir = config->GetInlet_FlowDir(Marker_Tag); + + for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { + Inlet_Ttotal[iMarker][iVertex] = t_total; + Inlet_Ptotal[iMarker][iVertex] = p_total; + for (unsigned short iDim = 0; iDim < nDim; iDim++) Inlet_FlowDir[iMarker][iVertex][iDim] = flow_dir[iDim]; + } + + } else { + /*--- For now, non-inlets just get set to zero. In the future, we + can do more customization for other boundary types here. ---*/ + + for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { + Inlet_Ttotal[iMarker][iVertex] = 0.0; + Inlet_Ptotal[iMarker][iVertex] = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) Inlet_FlowDir[iMarker][iVertex][iDim] = 0.0; + } + } +} + +template +void CFVMFlowSolverBase::PushSolutionBackInTime(unsigned long TimeIter, bool restart, bool rans, + CSolver*** solver_container, CGeometry** geometry, + CConfig* config) { + /*--- Push back the initial condition to previous solution containers + for a 1st-order restart or when simply intitializing to freestream. ---*/ + + for (unsigned short iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { + solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n(); + solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n1(); + if (rans) { + solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n(); + solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n1(); + } + } + + if (restart && (TimeIter == config->GetRestart_Iter()) && (config->GetTime_Marching() == DT_STEPPING_2ND)) { + /*--- Load an additional restart file for a 2nd-order restart ---*/ + + solver_container[MESH_0][FLOW_SOL]->LoadRestart(geometry, solver_container, config, config->GetRestart_Iter() - 1, + true); + + /*--- Load an additional restart file for the turbulence model ---*/ + if (rans) + solver_container[MESH_0][TURB_SOL]->LoadRestart(geometry, solver_container, config, config->GetRestart_Iter() - 1, + false); + + /*--- Push back this new solution to time level N. ---*/ + + for (unsigned short iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { + solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n(); + if (rans) { + solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n(); + } + } + } +} + +template +void CFVMFlowSolverBase::BC_Sym_Plane(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics, + CNumerics* visc_numerics, CConfig* config, unsigned short val_marker) { + unsigned short iDim, iVar; + unsigned long iVertex, iPoint; + + bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + bool viscous = config->GetViscous(); + bool preprocessed = false; + + /*--- Allocation of variables necessary for convective fluxes. ---*/ + su2double Area, ProjVelocity_i, *V_reflected, *V_domain, Normal[MAXNDIM] = {0.0}, UnitNormal[MAXNDIM] = {0.0}; + + /*--- Allocation of variables necessary for viscous fluxes. ---*/ + su2double ProjGradient, ProjNormVelGrad, ProjTangVelGrad, TangentialNorm, + Tangential[MAXNDIM] = {0.0}, GradNormVel[MAXNDIM] = {0.0}, GradTangVel[MAXNDIM] = {0.0}; + + /*--- Allocation of primitive gradient arrays for viscous fluxes. ---*/ + su2double** Grad_Reflected = new su2double*[nPrimVarGrad]; + for (iVar = 0; iVar < nPrimVarGrad; iVar++) Grad_Reflected[iVar] = new su2double[nDim]; + + /*--- Loop over all the vertices on this boundary marker. ---*/ + + SU2_OMP_FOR_DYN(OMP_MIN_SIZE) + for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { + if (!preprocessed || geometry->bound_is_straight[val_marker] != true) { + /*----------------------------------------------------------------------------------------------*/ + /*--- Preprocessing: ---*/ + /*--- Compute the unit normal and (in case of viscous flow) a corresponding unit tangential ---*/ + /*--- to that normal. On a straight(2D)/plane(3D) boundary these two vectors are constant. ---*/ + /*--- This circumstance is checked in gemoetry->ComputeSurf_Straightness(...) and stored ---*/ + /*--- such that the recomputation does not occur for each node. On true symmetry planes, the ---*/ + /*--- normal is constant but this routines is used for Symmetry, Euler-Wall in inviscid flow ---*/ + /*--- and Euler Wall in viscous flow as well. In the latter curvy boundaries are likely to ---*/ + /*--- happen. In doubt, the conditional above which checks straightness can be thrown out ---*/ + /*--- such that the recomputation is done for each node (which comes with a tiny performance ---*/ + /*--- penalty). ---*/ + /*----------------------------------------------------------------------------------------------*/ + + preprocessed = true; + + /*--- Normal vector for a random vertex (zero) on this marker (negate for outward convention). ---*/ + geometry->vertex[val_marker][iVertex]->GetNormal(Normal); + for (iDim = 0; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim]; + + /*--- Compute unit normal, to be used for unit tangential, projected velocity and velocity + component gradients. ---*/ + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim] * Normal[iDim]; + Area = sqrt(Area); + + for (iDim = 0; iDim < nDim; iDim++) UnitNormal[iDim] = -Normal[iDim] / Area; + + /*--- Preprocessing: Compute unit tangential, the direction is arbitrary as long as + t*n=0 && |t|_2 = 1 ---*/ + if (viscous) { + switch (nDim) { + case 2: { + Tangential[0] = -UnitNormal[1]; + Tangential[1] = UnitNormal[0]; + break; + } + case 3: { + /*--- n = ai + bj + ck, if |b| > |c| ---*/ + if (abs(UnitNormal[1]) > abs(UnitNormal[2])) { + /*--- t = bi + (c-a)j - bk ---*/ + Tangential[0] = UnitNormal[1]; + Tangential[1] = UnitNormal[2] - UnitNormal[0]; + Tangential[2] = -UnitNormal[1]; + } else { + /*--- t = ci - cj + (b-a)k ---*/ + Tangential[0] = UnitNormal[2]; + Tangential[1] = -UnitNormal[2]; + Tangential[2] = UnitNormal[1] - UnitNormal[0]; + } + /*--- Make it a unit vector. ---*/ + TangentialNorm = sqrt(pow(Tangential[0], 2) + pow(Tangential[1], 2) + pow(Tangential[2], 2)); + Tangential[0] = Tangential[0] / TangentialNorm; + Tangential[1] = Tangential[1] / TangentialNorm; + Tangential[2] = Tangential[2] / TangentialNorm; + break; + } + } // switch + } // if viscous + } // if bound_is_straight + + iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); + + /*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/ + if (geometry->nodes->GetDomain(iPoint)) { + /*-------------------------------------------------------------------------------*/ + /*--- Step 1: For the convective fluxes, create a reflected state of the ---*/ + /*--- Primitive variables by copying all interior values to the ---*/ + /*--- reflected. Only the velocity is mirrored along the symmetry ---*/ + /*--- axis. Based on the Upwind_Residual routine. ---*/ + /*-------------------------------------------------------------------------------*/ + + /*--- Allocate the reflected state at the symmetry boundary. ---*/ + V_reflected = GetCharacPrimVar(val_marker, iVertex); + + /*--- Grid movement ---*/ + if (dynamic_grid) + conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint)); + + /*--- Normal vector for this vertex (negate for outward convention). ---*/ + geometry->vertex[val_marker][iVertex]->GetNormal(Normal); + for (iDim = 0; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim]; + conv_numerics->SetNormal(Normal); + + /*--- Get current solution at this boundary node ---*/ + V_domain = nodes->GetPrimitive(iPoint); + + /*--- Set the reflected state based on the boundary node. Scalars are copied and + the velocity is mirrored along the symmetry boundary, i.e. the velocity in + normal direction is substracted twice. ---*/ + for (iVar = 0; iVar < nPrimVar; iVar++) V_reflected[iVar] = nodes->GetPrimitive(iPoint, iVar); + + /*--- Compute velocity in normal direction (ProjVelcity_i=(v*n)) und substract twice from + velocity in normal direction: v_r = v - 2 (v*n)n ---*/ + ProjVelocity_i = nodes->GetProjVel(iPoint, UnitNormal); + + /*--- Adjustment to v.n due to grid movement. ---*/ + if (dynamic_grid) { + ProjVelocity_i -= GeometryToolbox::DotProduct(nDim, geometry->nodes->GetGridVel(iPoint), UnitNormal); + } + + for (iDim = 0; iDim < nDim; iDim++) + V_reflected[iDim + 1] = nodes->GetVelocity(iPoint, iDim) - 2.0 * ProjVelocity_i * UnitNormal[iDim]; + + /*--- Set Primitive and Secondary for numerics class. ---*/ + conv_numerics->SetPrimitive(V_domain, V_reflected); + conv_numerics->SetSecondary(nodes->GetSecondary(iPoint), nodes->GetSecondary(iPoint)); + + /*--- Compute the residual using an upwind scheme. ---*/ + + auto residual = conv_numerics->ComputeResidual(config); + + /*--- Update residual value ---*/ + LinSysRes.AddBlock(iPoint, residual); + + /*--- Jacobian contribution for implicit integration. ---*/ + if (implicit) { + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); + } + + if (viscous) { + /*-------------------------------------------------------------------------------*/ + /*--- Step 2: The viscous fluxes of the Navier-Stokes equations depend on the ---*/ + /*--- Primitive variables and their gradients. The viscous numerics ---*/ + /*--- container is filled just as the convective numerics container, ---*/ + /*--- but the primitive gradients of the reflected state have to be ---*/ + /*--- determined additionally such that symmetry at the boundary is ---*/ + /*--- enforced. Based on the Viscous_Residual routine. ---*/ + /*-------------------------------------------------------------------------------*/ + + /*--- Set the normal vector and the coordinates. ---*/ + visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), geometry->nodes->GetCoord(iPoint)); + visc_numerics->SetNormal(Normal); + + /*--- Set the primitive and Secondary variables. ---*/ + visc_numerics->SetPrimitive(V_domain, V_reflected); + visc_numerics->SetSecondary(nodes->GetSecondary(iPoint), nodes->GetSecondary(iPoint)); + + /*--- For viscous Fluxes also the gradients of the primitives need to be determined. + 1. The gradients of scalars are mirrored along the sym plane just as velocity for the primitives + 2. The gradients of the velocity components need more attention, i.e. the gradient of the + normal velocity in tangential direction is mirrored and the gradient of the tangential velocity in + normal direction is mirrored. ---*/ + + /*--- Get gradients of primitives of boundary cell ---*/ + for (iVar = 0; iVar < nPrimVarGrad; iVar++) + for (iDim = 0; iDim < nDim; iDim++) + Grad_Reflected[iVar][iDim] = nodes->GetGradient_Primitive(iPoint, iVar, iDim); + + /*--- Reflect the gradients for all scalars including the velocity components. + The gradients of the velocity components are set later with the + correct values: grad(V)_r = grad(V) - 2 [grad(V)*n]n, V beeing any primitive ---*/ + for (iVar = 0; iVar < nPrimVarGrad; iVar++) { + if (iVar == 0 || iVar > nDim) { // Exclude velocity component gradients + + /*--- Compute projected part of the gradient in a dot product ---*/ + ProjGradient = 0.0; + for (iDim = 0; iDim < nDim; iDim++) ProjGradient += Grad_Reflected[iVar][iDim] * UnitNormal[iDim]; + + for (iDim = 0; iDim < nDim; iDim++) + Grad_Reflected[iVar][iDim] = Grad_Reflected[iVar][iDim] - 2.0 * ProjGradient * UnitNormal[iDim]; + } + } + + /*--- Compute gradients of normal and tangential velocity: + grad(v*n) = grad(v_x) n_x + grad(v_y) n_y (+ grad(v_z) n_z) + grad(v*t) = grad(v_x) t_x + grad(v_y) t_y (+ grad(v_z) t_z) ---*/ + for (iVar = 0; iVar < nDim; iVar++) { // counts gradient components + GradNormVel[iVar] = 0.0; + GradTangVel[iVar] = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { // counts sum with unit normal/tangential + GradNormVel[iVar] += Grad_Reflected[iDim + 1][iVar] * UnitNormal[iDim]; + GradTangVel[iVar] += Grad_Reflected[iDim + 1][iVar] * Tangential[iDim]; + } + } + + /*--- Refelect gradients in tangential and normal direction by substracting the normal/tangential + component twice, just as done with velocity above. + grad(v*n)_r = grad(v*n) - 2 {grad([v*n])*t}t + grad(v*t)_r = grad(v*t) - 2 {grad([v*t])*n}n ---*/ + ProjNormVelGrad = 0.0; + ProjTangVelGrad = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjNormVelGrad += GradNormVel[iDim] * Tangential[iDim]; // grad([v*n])*t + ProjTangVelGrad += GradTangVel[iDim] * UnitNormal[iDim]; // grad([v*t])*n + } + + for (iDim = 0; iDim < nDim; iDim++) { + GradNormVel[iDim] = GradNormVel[iDim] - 2.0 * ProjNormVelGrad * Tangential[iDim]; + GradTangVel[iDim] = GradTangVel[iDim] - 2.0 * ProjTangVelGrad * UnitNormal[iDim]; + } + + /*--- Transfer reflected gradients back into the Cartesian Coordinate system: + grad(v_x)_r = grad(v*n)_r n_x + grad(v*t)_r t_x + grad(v_y)_r = grad(v*n)_r n_y + grad(v*t)_r t_y + ( grad(v_z)_r = grad(v*n)_r n_z + grad(v*t)_r t_z ) ---*/ + for (iVar = 0; iVar < nDim; iVar++) // loops over the velocity component gradients + for (iDim = 0; iDim < nDim; iDim++) // loops over the entries of the above + Grad_Reflected[iVar + 1][iDim] = + GradNormVel[iDim] * UnitNormal[iVar] + GradTangVel[iDim] * Tangential[iVar]; + + /*--- Set the primitive gradients of the boundary and reflected state. ---*/ + visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), Grad_Reflected); + + /*--- Turbulent kinetic energy. ---*/ + if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) + visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint, 0), + solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint, 0)); + + /*--- Compute and update residual. Note that the viscous shear stress tensor is computed in the + following routine based upon the velocity-component gradients. ---*/ + auto residual = visc_numerics->ComputeResidual(config); + + LinSysRes.SubtractBlock(iPoint, residual); + + /*--- Jacobian contribution for implicit integration. ---*/ + if (implicit) Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); + } // if viscous + } // if GetDomain + } // for iVertex + + /*--- Free locally allocated memory ---*/ + for (iVar = 0; iVar < nPrimVarGrad; iVar++) delete[] Grad_Reflected[iVar]; + delete[] Grad_Reflected; +} + +template +void CFVMFlowSolverBase::BC_Periodic(CGeometry* geometry, CSolver** solver_container, CNumerics* numerics, + CConfig* config) { + /*--- Complete residuals for periodic boundary conditions. We loop over + the periodic BCs in matching pairs so that, in the event that there are + adjacent periodic markers, the repeated points will have their residuals + accumulated correctly during the communications. For implicit calculations, + the Jacobians and linear system are also correctly adjusted here. ---*/ + + for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic() / 2; iPeriodic++) { + InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL); + CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL); + } +} + +template +void CFVMFlowSolverBase::BC_Fluid_Interface(CGeometry* geometry, CSolver** solver_container, + CNumerics* conv_numerics, CNumerics* visc_numerics, + CConfig* config) { + unsigned long iVertex, jVertex, iPoint, Point_Normal = 0; + unsigned short iDim, iVar, jVar, iMarker, nDonorVertex; + + bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + bool viscous = config->GetViscous(); + + su2double Normal[MAXNDIM] = {0.0}; + su2double PrimVar_i[MAXNVAR] = {0.0}; + su2double PrimVar_j[MAXNVAR] = {0.0}; + su2double Secondary_j[MAXNVAR] = {0.0}; + su2double Residual[MAXNVAR] = {0.0}; + su2double** Jacobian_i = new su2double*[nVar]; + for (iVar = 0; iVar < nVar; iVar++) Jacobian_i[iVar] = new su2double[nVar]; + + su2double weight; + su2double P_static, rho_static; + + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) { + SU2_OMP_FOR_DYN(OMP_MIN_SIZE) + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + + if (geometry->nodes->GetDomain(iPoint)) { + nDonorVertex = GetnSlidingStates(iMarker, iVertex); + + /*--- Initialize Residual, this will serve to accumulate the average ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Residual[iVar] = 0.0; + for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] = 0.0; + } + + /*--- Loop over the nDonorVertexes and compute the averaged flux ---*/ + + for (jVertex = 0; jVertex < nDonorVertex; jVertex++) { + Point_Normal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); + + for (iVar = 0; iVar < nPrimVar; iVar++) { + PrimVar_i[iVar] = nodes->GetPrimitive(iPoint, iVar); + PrimVar_j[iVar] = GetSlidingState(iMarker, iVertex, iVar, jVertex); + } + + /*--- Get the weight computed in the interpolator class for the j-th donor vertex ---*/ + + weight = GetSlidingState(iMarker, iVertex, nPrimVar, jVertex); + + /*--- Set primitive variables ---*/ + + conv_numerics->SetPrimitive(PrimVar_i, PrimVar_j); + + if (FlowRegime == COMPRESSIBLE) { + if (!(config->GetKind_FluidModel() == STANDARD_AIR || config->GetKind_FluidModel() == IDEAL_GAS)) { + auto Secondary_i = nodes->GetSecondary(iPoint); + + P_static = PrimVar_j[nDim + 1]; + rho_static = PrimVar_j[nDim + 2]; + GetFluidModel()->SetTDState_Prho(P_static, rho_static); + + Secondary_j[0] = GetFluidModel()->GetdPdrho_e(); + Secondary_j[1] = GetFluidModel()->GetdPde_rho(); + + conv_numerics->SetSecondary(Secondary_i, Secondary_j); + } + } + + /*--- Set the normal vector ---*/ + + geometry->vertex[iMarker][iVertex]->GetNormal(Normal); + for (iDim = 0; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim]; + + conv_numerics->SetNormal(Normal); + + if (dynamic_grid) + conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint)); + + /*--- Compute the convective residual using an upwind scheme ---*/ + + auto residual = conv_numerics->ComputeResidual(config); + + /*--- Accumulate the residuals to compute the average ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Residual[iVar] += weight * residual.residual[iVar]; + for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] += weight * residual.jacobian_i[iVar][jVar]; + } + } + + /*--- Add Residuals and Jacobians ---*/ + + LinSysRes.AddBlock(iPoint, Residual); + + if (implicit) Jacobian.AddBlock2Diag(iPoint, Jacobian_i); + + if (viscous) { + /*--- Initialize Residual, this will serve to accumulate the average ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Residual[iVar] = 0.0; + for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] = 0.0; + } + + /*--- Loop over the nDonorVertexes and compute the averaged flux ---*/ + + for (jVertex = 0; jVertex < nDonorVertex; jVertex++) { + PrimVar_j[nDim + 5] = GetSlidingState(iMarker, iVertex, nDim + 5, jVertex); + PrimVar_j[nDim + 6] = GetSlidingState(iMarker, iVertex, nDim + 6, jVertex); + + /*--- Get the weight computed in the interpolator class for the j-th donor vertex ---*/ + + weight = GetSlidingState(iMarker, iVertex, nPrimVar, jVertex); + + /*--- Set the normal vector and the coordinates ---*/ + + visc_numerics->SetNormal(Normal); + visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), geometry->nodes->GetCoord(Point_Normal)); + + /*--- Primitive variables, and gradient ---*/ + + visc_numerics->SetPrimitive(PrimVar_i, PrimVar_j); + visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), + nodes->GetGradient_Primitive(iPoint)); + + /*--- Turbulent kinetic energy ---*/ + + if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) + visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint, 0), + solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint, 0)); + + /*--- Set the wall shear stress values (wall functions) to -1 (no evaluation using wall functions) ---*/ + + visc_numerics->SetTauWall(-1.0, -1.0); + + /*--- Compute and update residual ---*/ + + auto residual = visc_numerics->ComputeResidual(config); + + /*--- Accumulate the residuals to compute the average ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Residual[iVar] += weight * residual.residual[iVar]; + for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] += weight * residual.jacobian_i[iVar][jVar]; + } + } + + LinSysRes.SubtractBlock(iPoint, Residual); + + /*--- Jacobian contribution for implicit integration ---*/ + + if (implicit) Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); + } + } + } + } + } + + for (iVar = 0; iVar < nVar; iVar++) delete[] Jacobian_i[iVar]; + delete[] Jacobian_i; +} + +template +void CFVMFlowSolverBase::BC_Custom(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics, + CNumerics* visc_numerics, CConfig* config, unsigned short val_marker) { + /* Check for a verification solution. */ + + if (VerificationSolution) { + unsigned short iVar; + unsigned long iVertex, iPoint, total_index; + + bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + + /*--- Get the physical time. ---*/ + + su2double time = 0.0; + if (config->GetTime_Marching()) time = config->GetPhysicalTime(); + + /*--- Loop over all the vertices on this boundary marker ---*/ + + SU2_OMP_FOR_STAT(OMP_MIN_SIZE) + for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { + /*--- Get the point index for the current node. ---*/ + + iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); + + /*--- Check if the node belongs to the domain (i.e, not a halo node) ---*/ + + if (geometry->nodes->GetDomain(iPoint)) { + /*--- Get the coordinates for the current node. ---*/ + + const su2double* coor = geometry->nodes->GetCoord(iPoint); + + /*--- Get the conservative state from the verification solution. ---*/ + + su2double Solution[MAXNVAR] = {0.0}; + VerificationSolution->GetBCState(coor, time, Solution); + + /*--- For verification cases, we will apply a strong Dirichlet + condition by setting the solution values at the boundary nodes + directly and setting the residual to zero at those nodes. ---*/ + + nodes->SetSolution_Old(iPoint, Solution); + nodes->SetSolution(iPoint, Solution); + nodes->SetRes_TruncErrorZero(iPoint); + LinSysRes.SetBlock_Zero(iPoint); + + /*--- Adjust rows of the Jacobian (includes 1 in the diagonal) ---*/ + + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) { + total_index = iPoint * nVar + iVar; + Jacobian.DeleteValsRowi(total_index); + } + } + } + } + + } else { + /* The user must specify the custom BC's here. */ + SU2_MPI::Error("Implement customized boundary conditions here.", CURRENT_FUNCTION); + } +} + +template +void CFVMFlowSolverBase::Pressure_Forces(const CGeometry* geometry, const CConfig* config) { + unsigned long iVertex, iPoint; + unsigned short iDim, iMarker, Boundary, Monitoring, iMarker_Monitoring; + su2double Pressure = 0.0, factor, NFPressOF, RefVel2 = 0.0, RefTemp, RefDensity = 0.0, RefPressure, Mach2Vel, + Mach_Motion; + const su2double *Normal = nullptr, *Coord = nullptr; + string Marker_Tag, Monitoring_Tag; + su2double AxiFactor; + + su2double Alpha = config->GetAoA() * PI_NUMBER / 180.0; + su2double Beta = config->GetAoS() * PI_NUMBER / 180.0; + su2double RefArea = config->GetRefArea(); + su2double RefLength = config->GetRefLength(); + su2double Gas_Constant = config->GetGas_ConstantND(); + auto Origin = config->GetRefOriginMoment(0); + bool axisymmetric = config->GetAxisymmetric(); + + /// TODO: Move these ifs to specialized functions. + + if (FlowRegime == COMPRESSIBLE) { + /*--- Evaluate reference values for non-dimensionalization. + For dynamic meshes, use the motion Mach number as a reference value + for computing the force coefficients. Otherwise, use the freestream values, + which is the standard convention. ---*/ + + RefTemp = Temperature_Inf; + RefDensity = Density_Inf; + if (dynamic_grid) { + Mach2Vel = sqrt(Gamma * Gas_Constant * RefTemp); + Mach_Motion = config->GetMach_Motion(); + RefVel2 = (Mach_Motion * Mach2Vel) * (Mach_Motion * Mach2Vel); + } else { + RefVel2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim]; + } + } + + if (FlowRegime == INCOMPRESSIBLE) { + /*--- Evaluate reference values for non-dimensionalization. + For dimensional or non-dim based on initial values, use + the far-field state (inf). For a custom non-dim based + on user-provided reference values, use the ref values + to compute the forces. ---*/ + + if ((config->GetRef_Inc_NonDim() == DIMENSIONAL) || (config->GetRef_Inc_NonDim() == INITIAL_VALUES)) { + RefDensity = Density_Inf; + RefVel2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim]; + } else if (config->GetRef_Inc_NonDim() == REFERENCE_VALUES) { + RefDensity = config->GetInc_Density_Ref(); + RefVel2 = config->GetInc_Velocity_Ref() * config->GetInc_Velocity_Ref(); + } + } + + factor = 1.0 / (0.5 * RefDensity * RefArea * RefVel2); + + /*--- Reference pressure is always the far-field value. ---*/ + + RefPressure = Pressure_Inf; + + /*-- Variables initialization ---*/ + + TotalCoeff.setZero(); + + Total_CNearFieldOF = 0.0; + Total_Heat = 0.0; + Total_MaxHeat = 0.0; + + AllBoundInvCoeff.setZero(); + + AllBound_CNearFieldOF_Inv = 0.0; + + SurfaceInvCoeff.setZero(); + SurfaceCoeff.setZero(); + + /*--- Loop over the Euler and Navier-Stokes markers ---*/ + + for (iMarker = 0; iMarker < nMarker; iMarker++) { + Boundary = config->GetMarker_All_KindBC(iMarker); + Monitoring = config->GetMarker_All_Monitoring(iMarker); + + /*--- Obtain the origin for the moment computation for a particular marker ---*/ + + if (Monitoring == YES) { + 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); + if (Marker_Tag == Monitoring_Tag) Origin = config->GetRefOriginMoment(iMarker_Monitoring); + } + } + + if (config->GetSolid_Wall(iMarker) || (Boundary == NEARFIELD_BOUNDARY) || (Boundary == INLET_FLOW) || + (Boundary == OUTLET_FLOW) || (Boundary == ACTDISK_INLET) || (Boundary == ACTDISK_OUTLET) || + (Boundary == ENGINE_INFLOW) || (Boundary == ENGINE_EXHAUST)) { + /*--- Forces initialization at each Marker ---*/ + + InvCoeff.setZero(iMarker); + + CNearFieldOF_Inv[iMarker] = 0.0; + + su2double ForceInviscid[MAXNDIM] = {0.0}, MomentInviscid[MAXNDIM] = {0.0}; + su2double MomentX_Force[MAXNDIM] = {0.0}, MomentY_Force[MAXNDIM] = {0.0}, MomentZ_Force[MAXNDIM] = {0.0}; + + NFPressOF = 0.0; + + /*--- Loop over the vertices to compute the forces ---*/ + + for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + + Pressure = nodes->GetPressure(iPoint); + + CPressure[iMarker][iVertex] = (Pressure - RefPressure) * factor * RefArea; + + /*--- Note that the pressure coefficient is computed at the + halo cells (for visualization purposes), but not the forces ---*/ + + if ((geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES)) { + Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); + Coord = geometry->nodes->GetCoord(iPoint); + + /*--- Quadratic objective function for the near-field. + This uses the infinity pressure regardless of Mach number. ---*/ + + NFPressOF += 0.5 * (Pressure - Pressure_Inf) * (Pressure - Pressure_Inf) * Normal[nDim - 1]; + + su2double MomentDist[MAXNDIM] = {0.0}; + for (iDim = 0; iDim < nDim; iDim++) { + MomentDist[iDim] = Coord[iDim] - Origin[iDim]; + } + + /*--- Axisymmetric simulations ---*/ + + if (axisymmetric) + AxiFactor = 2.0 * PI_NUMBER * geometry->nodes->GetCoord(iPoint, 1); + else + AxiFactor = 1.0; + + /*--- Force computation, note the minus sign due to the + orientation of the normal (outward) ---*/ + + su2double Force[MAXNDIM] = {0.0}; + for (iDim = 0; iDim < nDim; iDim++) { + Force[iDim] = -(Pressure - Pressure_Inf) * Normal[iDim] * factor * AxiFactor; + ForceInviscid[iDim] += Force[iDim]; + } + + /*--- Moment with respect to the reference axis ---*/ + + if (nDim == 3) { + MomentInviscid[0] += (Force[2] * MomentDist[1] - Force[1] * MomentDist[2]) / RefLength; + MomentX_Force[1] += (-Force[1] * Coord[2]); + MomentX_Force[2] += (Force[2] * Coord[1]); + + MomentInviscid[1] += (Force[0] * MomentDist[2] - Force[2] * MomentDist[0]) / RefLength; + MomentY_Force[2] += (-Force[2] * Coord[0]); + MomentY_Force[0] += (Force[0] * Coord[2]); + } + MomentInviscid[2] += (Force[1] * MomentDist[0] - Force[0] * MomentDist[1]) / RefLength; + MomentZ_Force[0] += (-Force[0] * Coord[1]); + MomentZ_Force[1] += (Force[1] * Coord[0]); + } + } + + /*--- Project forces and store the non-dimensional coefficients ---*/ + + if (Monitoring == YES) { + if (Boundary != NEARFIELD_BOUNDARY) { + if (nDim == 2) { + InvCoeff.CD[iMarker] = ForceInviscid[0] * cos(Alpha) + ForceInviscid[1] * sin(Alpha); + InvCoeff.CL[iMarker] = -ForceInviscid[0] * sin(Alpha) + ForceInviscid[1] * cos(Alpha); + InvCoeff.CEff[iMarker] = InvCoeff.CL[iMarker] / (InvCoeff.CD[iMarker] + EPS); + InvCoeff.CMz[iMarker] = MomentInviscid[2]; + InvCoeff.CoPx[iMarker] = MomentZ_Force[1]; + InvCoeff.CoPy[iMarker] = -MomentZ_Force[0]; + InvCoeff.CFx[iMarker] = ForceInviscid[0]; + InvCoeff.CFy[iMarker] = ForceInviscid[1]; + InvCoeff.CT[iMarker] = -InvCoeff.CFx[iMarker]; + InvCoeff.CQ[iMarker] = -InvCoeff.CMz[iMarker]; + InvCoeff.CMerit[iMarker] = InvCoeff.CT[iMarker] / (InvCoeff.CQ[iMarker] + EPS); + } + if (nDim == 3) { + InvCoeff.CD[iMarker] = ForceInviscid[0] * cos(Alpha) * cos(Beta) + ForceInviscid[1] * sin(Beta) + + ForceInviscid[2] * sin(Alpha) * cos(Beta); + InvCoeff.CL[iMarker] = -ForceInviscid[0] * sin(Alpha) + ForceInviscid[2] * cos(Alpha); + InvCoeff.CSF[iMarker] = -ForceInviscid[0] * sin(Beta) * cos(Alpha) + ForceInviscid[1] * cos(Beta) - + ForceInviscid[2] * sin(Beta) * sin(Alpha); + InvCoeff.CEff[iMarker] = InvCoeff.CL[iMarker] / (InvCoeff.CD[iMarker] + EPS); + InvCoeff.CMx[iMarker] = MomentInviscid[0]; + InvCoeff.CMy[iMarker] = MomentInviscid[1]; + InvCoeff.CMz[iMarker] = MomentInviscid[2]; + InvCoeff.CoPx[iMarker] = -MomentY_Force[0]; + InvCoeff.CoPz[iMarker] = MomentY_Force[2]; + InvCoeff.CFx[iMarker] = ForceInviscid[0]; + InvCoeff.CFy[iMarker] = ForceInviscid[1]; + InvCoeff.CFz[iMarker] = ForceInviscid[2]; + InvCoeff.CT[iMarker] = -InvCoeff.CFz[iMarker]; + InvCoeff.CQ[iMarker] = -InvCoeff.CMz[iMarker]; + InvCoeff.CMerit[iMarker] = InvCoeff.CT[iMarker] / (InvCoeff.CQ[iMarker] + EPS); + } + + AllBoundInvCoeff.CD += InvCoeff.CD[iMarker]; + AllBoundInvCoeff.CL += InvCoeff.CL[iMarker]; + AllBoundInvCoeff.CSF += InvCoeff.CSF[iMarker]; + AllBoundInvCoeff.CEff = AllBoundInvCoeff.CL / (AllBoundInvCoeff.CD + EPS); + AllBoundInvCoeff.CMx += InvCoeff.CMx[iMarker]; + AllBoundInvCoeff.CMy += InvCoeff.CMy[iMarker]; + AllBoundInvCoeff.CMz += InvCoeff.CMz[iMarker]; + AllBoundInvCoeff.CoPx += InvCoeff.CoPx[iMarker]; + AllBoundInvCoeff.CoPy += InvCoeff.CoPy[iMarker]; + AllBoundInvCoeff.CoPz += InvCoeff.CoPz[iMarker]; + AllBoundInvCoeff.CFx += InvCoeff.CFx[iMarker]; + AllBoundInvCoeff.CFy += InvCoeff.CFy[iMarker]; + AllBoundInvCoeff.CFz += InvCoeff.CFz[iMarker]; + AllBoundInvCoeff.CT += InvCoeff.CT[iMarker]; + AllBoundInvCoeff.CQ += InvCoeff.CQ[iMarker]; + AllBoundInvCoeff.CMerit = AllBoundInvCoeff.CT / (AllBoundInvCoeff.CQ + EPS); + + /*--- 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); + if (Marker_Tag == Monitoring_Tag) { + SurfaceInvCoeff.CL[iMarker_Monitoring] += InvCoeff.CL[iMarker]; + SurfaceInvCoeff.CD[iMarker_Monitoring] += InvCoeff.CD[iMarker]; + SurfaceInvCoeff.CSF[iMarker_Monitoring] += InvCoeff.CSF[iMarker]; + SurfaceInvCoeff.CEff[iMarker_Monitoring] = InvCoeff.CL[iMarker] / (InvCoeff.CD[iMarker] + EPS); + SurfaceInvCoeff.CFx[iMarker_Monitoring] += InvCoeff.CFx[iMarker]; + SurfaceInvCoeff.CFy[iMarker_Monitoring] += InvCoeff.CFy[iMarker]; + SurfaceInvCoeff.CFz[iMarker_Monitoring] += InvCoeff.CFz[iMarker]; + SurfaceInvCoeff.CMx[iMarker_Monitoring] += InvCoeff.CMx[iMarker]; + SurfaceInvCoeff.CMy[iMarker_Monitoring] += InvCoeff.CMy[iMarker]; + SurfaceInvCoeff.CMz[iMarker_Monitoring] += InvCoeff.CMz[iMarker]; + } + } + + } + + /*--- At the Nearfield SU2 only cares about the pressure coeffient ---*/ + + else { + CNearFieldOF_Inv[iMarker] = NFPressOF; + AllBound_CNearFieldOF_Inv += CNearFieldOF_Inv[iMarker]; + } + } + } + } + +#ifdef HAVE_MPI + + /*--- Add AllBound information using all the nodes ---*/ + + if (config->GetComm_Level() == COMM_FULL) { + auto Allreduce = [](su2double x) { + su2double tmp = x; + x = 0.0; + SU2_MPI::Allreduce(&tmp, &x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + return x; + }; + AllBoundInvCoeff.CD = Allreduce(AllBoundInvCoeff.CD); + AllBoundInvCoeff.CL = Allreduce(AllBoundInvCoeff.CL); + AllBoundInvCoeff.CSF = Allreduce(AllBoundInvCoeff.CSF); + AllBoundInvCoeff.CEff = AllBoundInvCoeff.CL / (AllBoundInvCoeff.CD + EPS); + + AllBoundInvCoeff.CMx = Allreduce(AllBoundInvCoeff.CMx); + AllBoundInvCoeff.CMy = Allreduce(AllBoundInvCoeff.CMy); + AllBoundInvCoeff.CMz = Allreduce(AllBoundInvCoeff.CMz); + + AllBoundInvCoeff.CoPx = Allreduce(AllBoundInvCoeff.CoPx); + AllBoundInvCoeff.CoPy = Allreduce(AllBoundInvCoeff.CoPy); + AllBoundInvCoeff.CoPz = Allreduce(AllBoundInvCoeff.CoPz); + + AllBoundInvCoeff.CFx = Allreduce(AllBoundInvCoeff.CFx); + AllBoundInvCoeff.CFy = Allreduce(AllBoundInvCoeff.CFy); + AllBoundInvCoeff.CFz = Allreduce(AllBoundInvCoeff.CFz); + + AllBoundInvCoeff.CT = Allreduce(AllBoundInvCoeff.CT); + AllBoundInvCoeff.CQ = Allreduce(AllBoundInvCoeff.CQ); + AllBoundInvCoeff.CMerit = AllBoundInvCoeff.CT / (AllBoundInvCoeff.CQ + EPS); + AllBound_CNearFieldOF_Inv = Allreduce(AllBound_CNearFieldOF_Inv); + } + + /*--- Add the forces on the surfaces using all the nodes ---*/ + + if (config->GetComm_Level() == COMM_FULL) { + int nMarkerMon = config->GetnMarker_Monitoring(); + + /*--- Use the same buffer for all reductions. We could avoid the copy back into + * the original variable by swaping pointers, but it is safer this way... ---*/ + + su2double* buffer = new su2double[nMarkerMon]; + + auto Allreduce_inplace = [buffer](int size, su2double* x) { + SU2_MPI::Allreduce(x, buffer, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + for (int i = 0; i < size; ++i) x[i] = buffer[i]; + }; + + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CL); + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CD); + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CSF); + + for (iMarker_Monitoring = 0; iMarker_Monitoring < nMarkerMon; iMarker_Monitoring++) + SurfaceInvCoeff.CEff[iMarker_Monitoring] = + SurfaceInvCoeff.CL[iMarker_Monitoring] / (SurfaceInvCoeff.CD[iMarker_Monitoring] + EPS); + + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CFx); + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CFy); + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CFz); + + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CMx); + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CMy); + Allreduce_inplace(nMarkerMon, SurfaceInvCoeff.CMz); + + delete[] buffer; + } + +#endif + + /*--- Update the total coefficients (note that all the nodes have the same value) ---*/ + + TotalCoeff.CD = AllBoundInvCoeff.CD; + TotalCoeff.CL = AllBoundInvCoeff.CL; + TotalCoeff.CSF = AllBoundInvCoeff.CSF; + TotalCoeff.CEff = TotalCoeff.CL / (TotalCoeff.CD + EPS); + TotalCoeff.CFx = AllBoundInvCoeff.CFx; + TotalCoeff.CFy = AllBoundInvCoeff.CFy; + TotalCoeff.CFz = AllBoundInvCoeff.CFz; + TotalCoeff.CMx = AllBoundInvCoeff.CMx; + TotalCoeff.CMy = AllBoundInvCoeff.CMy; + TotalCoeff.CMz = AllBoundInvCoeff.CMz; + TotalCoeff.CoPx = AllBoundInvCoeff.CoPx; + TotalCoeff.CoPy = AllBoundInvCoeff.CoPy; + TotalCoeff.CoPz = AllBoundInvCoeff.CoPz; + TotalCoeff.CT = AllBoundInvCoeff.CT; + TotalCoeff.CQ = AllBoundInvCoeff.CQ; + TotalCoeff.CMerit = TotalCoeff.CT / (TotalCoeff.CQ + EPS); + Total_CNearFieldOF = AllBound_CNearFieldOF_Inv; + + /*--- Update the total coefficients per surface (note that all the nodes have the same value)---*/ + + for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { + SurfaceCoeff.CL[iMarker_Monitoring] = SurfaceInvCoeff.CL[iMarker_Monitoring]; + SurfaceCoeff.CD[iMarker_Monitoring] = SurfaceInvCoeff.CD[iMarker_Monitoring]; + SurfaceCoeff.CSF[iMarker_Monitoring] = SurfaceInvCoeff.CSF[iMarker_Monitoring]; + SurfaceCoeff.CEff[iMarker_Monitoring] = + SurfaceInvCoeff.CL[iMarker_Monitoring] / (SurfaceInvCoeff.CD[iMarker_Monitoring] + EPS); + SurfaceCoeff.CFx[iMarker_Monitoring] = SurfaceInvCoeff.CFx[iMarker_Monitoring]; + SurfaceCoeff.CFy[iMarker_Monitoring] = SurfaceInvCoeff.CFy[iMarker_Monitoring]; + SurfaceCoeff.CFz[iMarker_Monitoring] = SurfaceInvCoeff.CFz[iMarker_Monitoring]; + SurfaceCoeff.CMx[iMarker_Monitoring] = SurfaceInvCoeff.CMx[iMarker_Monitoring]; + SurfaceCoeff.CMy[iMarker_Monitoring] = SurfaceInvCoeff.CMy[iMarker_Monitoring]; + SurfaceCoeff.CMz[iMarker_Monitoring] = SurfaceInvCoeff.CMz[iMarker_Monitoring]; + } +} + +template +void CFVMFlowSolverBase::Momentum_Forces(const CGeometry* geometry, const CConfig* config) { + unsigned long iVertex, iPoint; + unsigned short iDim, iMarker, Boundary, Monitoring, iMarker_Monitoring; + su2double Area, factor, RefVel2 = 0.0, RefTemp, RefDensity = 0.0, Mach2Vel, Mach_Motion, MassFlow, Density; + const su2double *Normal = nullptr, *Coord = nullptr; + string Marker_Tag, Monitoring_Tag; + su2double AxiFactor; + + su2double Alpha = config->GetAoA() * PI_NUMBER / 180.0; + su2double Beta = config->GetAoS() * PI_NUMBER / 180.0; + su2double RefArea = config->GetRefArea(); + su2double RefLength = config->GetRefLength(); + su2double Gas_Constant = config->GetGas_ConstantND(); + auto Origin = config->GetRefOriginMoment(0); + bool axisymmetric = config->GetAxisymmetric(); + + /// TODO: Move these ifs to specialized functions. + + if (FlowRegime == COMPRESSIBLE) { + /*--- Evaluate reference values for non-dimensionalization. + For dynamic meshes, use the motion Mach number as a reference value + for computing the force coefficients. Otherwise, use the freestream values, + which is the standard convention. ---*/ + + RefTemp = Temperature_Inf; + RefDensity = Density_Inf; + if (dynamic_grid) { + Mach2Vel = sqrt(Gamma * Gas_Constant * RefTemp); + Mach_Motion = config->GetMach_Motion(); + RefVel2 = (Mach_Motion * Mach2Vel) * (Mach_Motion * Mach2Vel); + } else { + RefVel2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim]; + } + } + + if (FlowRegime == INCOMPRESSIBLE) { + /*--- Evaluate reference values for non-dimensionalization. + For dimensional or non-dim based on initial values, use + the far-field state (inf). For a custom non-dim based + on user-provided reference values, use the ref values + to compute the forces. ---*/ + + if ((config->GetRef_Inc_NonDim() == DIMENSIONAL) || (config->GetRef_Inc_NonDim() == INITIAL_VALUES)) { + RefDensity = Density_Inf; + RefVel2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim]; + } else if (config->GetRef_Inc_NonDim() == REFERENCE_VALUES) { + RefDensity = config->GetInc_Density_Ref(); + RefVel2 = config->GetInc_Velocity_Ref() * config->GetInc_Velocity_Ref(); + } + } + + factor = 1.0 / (0.5 * RefDensity * RefArea * RefVel2); + + /*-- Variables initialization ---*/ + + AllBoundMntCoeff.setZero(); + SurfaceMntCoeff.setZero(); + + /*--- Loop over the Inlet -Outlet Markers ---*/ + + for (iMarker = 0; iMarker < nMarker; iMarker++) { + Boundary = config->GetMarker_All_KindBC(iMarker); + Monitoring = config->GetMarker_All_Monitoring(iMarker); + + /*--- Obtain the origin for the moment computation for a particular marker ---*/ + + if (Monitoring == YES) { + 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); + if (Marker_Tag == Monitoring_Tag) Origin = config->GetRefOriginMoment(iMarker_Monitoring); + } + } + + if ((Boundary == INLET_FLOW) || (Boundary == OUTLET_FLOW) || (Boundary == ACTDISK_INLET) || + (Boundary == ACTDISK_OUTLET) || (Boundary == ENGINE_INFLOW) || (Boundary == ENGINE_EXHAUST)) { + /*--- Forces initialization at each Marker ---*/ + + MntCoeff.setZero(iMarker); + + su2double ForceMomentum[MAXNDIM] = {0.0}, MomentMomentum[MAXNDIM] = {0.0}; + su2double MomentX_Force[3] = {0.0}, MomentY_Force[3] = {0.0}, MomentZ_Force[3] = {0.0}; + + /*--- Loop over the vertices to compute the forces ---*/ + + for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + + /*--- Note that the pressure coefficient is computed at the + halo cells (for visualization purposes), but not the forces ---*/ + + if ((geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES)) { + Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); + Coord = geometry->nodes->GetCoord(iPoint); + Density = nodes->GetDensity(iPoint); + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim] * Normal[iDim]; + Area = sqrt(Area); + + MassFlow = 0.0; + su2double Velocity[MAXNDIM] = {0.0}, MomentDist[MAXNDIM] = {0.0}; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity[iDim] = nodes->GetVelocity(iPoint, iDim); + MomentDist[iDim] = Coord[iDim] - Origin[iDim]; + MassFlow -= Normal[iDim] * Velocity[iDim] * Density; + } + + /*--- Axisymmetric simulations ---*/ + + if (axisymmetric) + AxiFactor = 2.0 * PI_NUMBER * geometry->nodes->GetCoord(iPoint, 1); + else + AxiFactor = 1.0; + + /*--- Force computation, note the minus sign due to the + orientation of the normal (outward) ---*/ + + su2double Force[MAXNDIM] = {0.0}; + for (iDim = 0; iDim < nDim; iDim++) { + Force[iDim] = MassFlow * Velocity[iDim] * factor * AxiFactor; + ForceMomentum[iDim] += Force[iDim]; + } + + /*--- Moment with respect to the reference axis ---*/ + + if (iDim == 3) { + MomentMomentum[0] += (Force[2] * MomentDist[1] - Force[1] * MomentDist[2]) / RefLength; + MomentX_Force[1] += (-Force[1] * Coord[2]); + MomentX_Force[2] += (Force[2] * Coord[1]); + + MomentMomentum[1] += (Force[0] * MomentDist[2] - Force[2] * MomentDist[0]) / RefLength; + MomentY_Force[2] += (-Force[2] * Coord[0]); + MomentY_Force[0] += (Force[0] * Coord[2]); + } + MomentMomentum[2] += (Force[1] * MomentDist[0] - Force[0] * MomentDist[1]) / RefLength; + MomentZ_Force[0] += (-Force[0] * Coord[1]); + MomentZ_Force[1] += (Force[1] * Coord[0]); + } + } + + /*--- Project forces and store the non-dimensional coefficients ---*/ + + if (Monitoring == YES) { + if (nDim == 2) { + MntCoeff.CD[iMarker] = ForceMomentum[0] * cos(Alpha) + ForceMomentum[1] * sin(Alpha); + MntCoeff.CL[iMarker] = -ForceMomentum[0] * sin(Alpha) + ForceMomentum[1] * cos(Alpha); + MntCoeff.CEff[iMarker] = MntCoeff.CL[iMarker] / (MntCoeff.CD[iMarker] + EPS); + MntCoeff.CFx[iMarker] = ForceMomentum[0]; + MntCoeff.CFy[iMarker] = ForceMomentum[1]; + MntCoeff.CMz[iMarker] = MomentMomentum[2]; + MntCoeff.CoPx[iMarker] = MomentZ_Force[1]; + MntCoeff.CoPy[iMarker] = -MomentZ_Force[0]; + MntCoeff.CT[iMarker] = -MntCoeff.CFx[iMarker]; + MntCoeff.CQ[iMarker] = -MntCoeff.CMz[iMarker]; + MntCoeff.CMerit[iMarker] = MntCoeff.CT[iMarker] / (MntCoeff.CQ[iMarker] + EPS); + } + if (nDim == 3) { + MntCoeff.CD[iMarker] = ForceMomentum[0] * cos(Alpha) * cos(Beta) + ForceMomentum[1] * sin(Beta) + + ForceMomentum[2] * sin(Alpha) * cos(Beta); + MntCoeff.CL[iMarker] = -ForceMomentum[0] * sin(Alpha) + ForceMomentum[2] * cos(Alpha); + MntCoeff.CSF[iMarker] = -ForceMomentum[0] * sin(Beta) * cos(Alpha) + ForceMomentum[1] * cos(Beta) - + ForceMomentum[2] * sin(Beta) * sin(Alpha); + MntCoeff.CEff[iMarker] = MntCoeff.CL[iMarker] / (MntCoeff.CD[iMarker] + EPS); + MntCoeff.CFx[iMarker] = ForceMomentum[0]; + MntCoeff.CFy[iMarker] = ForceMomentum[1]; + MntCoeff.CFz[iMarker] = ForceMomentum[2]; + MntCoeff.CMx[iMarker] = MomentMomentum[0]; + MntCoeff.CMy[iMarker] = MomentMomentum[1]; + MntCoeff.CMz[iMarker] = MomentMomentum[2]; + MntCoeff.CoPx[iMarker] = -MomentY_Force[0]; + MntCoeff.CoPz[iMarker] = MomentY_Force[2]; + MntCoeff.CT[iMarker] = -MntCoeff.CFz[iMarker]; + MntCoeff.CQ[iMarker] = -MntCoeff.CMz[iMarker]; + MntCoeff.CMerit[iMarker] = MntCoeff.CT[iMarker] / (MntCoeff.CQ[iMarker] + EPS); + } + + AllBoundMntCoeff.CD += MntCoeff.CD[iMarker]; + AllBoundMntCoeff.CL += MntCoeff.CL[iMarker]; + AllBoundMntCoeff.CSF += MntCoeff.CSF[iMarker]; + AllBoundMntCoeff.CEff = AllBoundMntCoeff.CL / (AllBoundMntCoeff.CD + EPS); + AllBoundMntCoeff.CFx += MntCoeff.CFx[iMarker]; + AllBoundMntCoeff.CFy += MntCoeff.CFy[iMarker]; + AllBoundMntCoeff.CFz += MntCoeff.CFz[iMarker]; + AllBoundMntCoeff.CMx += MntCoeff.CMx[iMarker]; + AllBoundMntCoeff.CMy += MntCoeff.CMy[iMarker]; + AllBoundMntCoeff.CMx += MntCoeff.CMz[iMarker]; + AllBoundMntCoeff.CoPx += MntCoeff.CoPx[iMarker]; + AllBoundMntCoeff.CoPy += MntCoeff.CoPy[iMarker]; + AllBoundMntCoeff.CoPz += MntCoeff.CoPz[iMarker]; + AllBoundMntCoeff.CT += MntCoeff.CT[iMarker]; + AllBoundMntCoeff.CQ += MntCoeff.CQ[iMarker]; + AllBoundMntCoeff.CMerit += AllBoundMntCoeff.CT / (AllBoundMntCoeff.CQ + EPS); + + /*--- 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); + if (Marker_Tag == Monitoring_Tag) { + SurfaceMntCoeff.CL[iMarker_Monitoring] += MntCoeff.CL[iMarker]; + SurfaceMntCoeff.CD[iMarker_Monitoring] += MntCoeff.CD[iMarker]; + SurfaceMntCoeff.CSF[iMarker_Monitoring] += MntCoeff.CSF[iMarker]; + SurfaceMntCoeff.CEff[iMarker_Monitoring] = MntCoeff.CL[iMarker] / (MntCoeff.CD[iMarker] + EPS); + SurfaceMntCoeff.CFx[iMarker_Monitoring] += MntCoeff.CFx[iMarker]; + SurfaceMntCoeff.CFy[iMarker_Monitoring] += MntCoeff.CFy[iMarker]; + SurfaceMntCoeff.CFz[iMarker_Monitoring] += MntCoeff.CFz[iMarker]; + SurfaceMntCoeff.CMx[iMarker_Monitoring] += MntCoeff.CMx[iMarker]; + SurfaceMntCoeff.CMy[iMarker_Monitoring] += MntCoeff.CMy[iMarker]; + SurfaceMntCoeff.CMz[iMarker_Monitoring] += MntCoeff.CMz[iMarker]; + } + } + } + } + } + +#ifdef HAVE_MPI + + /*--- Add AllBound information using all the nodes ---*/ + + if (config->GetComm_Level() == COMM_FULL) { + auto Allreduce = [](su2double x) { + su2double tmp = x; + x = 0.0; + SU2_MPI::Allreduce(&tmp, &x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + return x; + }; + + AllBoundMntCoeff.CD = Allreduce(AllBoundMntCoeff.CD); + AllBoundMntCoeff.CL = Allreduce(AllBoundMntCoeff.CL); + AllBoundMntCoeff.CSF = Allreduce(AllBoundMntCoeff.CSF); + AllBoundMntCoeff.CEff = AllBoundMntCoeff.CL / (AllBoundMntCoeff.CD + EPS); + + AllBoundMntCoeff.CFx = Allreduce(AllBoundMntCoeff.CFx); + AllBoundMntCoeff.CFy = Allreduce(AllBoundMntCoeff.CFy); + AllBoundMntCoeff.CFz = Allreduce(AllBoundMntCoeff.CFz); + + AllBoundMntCoeff.CMx = Allreduce(AllBoundMntCoeff.CMx); + AllBoundMntCoeff.CMy = Allreduce(AllBoundMntCoeff.CMy); + AllBoundMntCoeff.CMz = Allreduce(AllBoundMntCoeff.CMz); + + AllBoundMntCoeff.CoPx = Allreduce(AllBoundMntCoeff.CoPx); + AllBoundMntCoeff.CoPy = Allreduce(AllBoundMntCoeff.CoPy); + AllBoundMntCoeff.CoPz = Allreduce(AllBoundMntCoeff.CoPz); + + AllBoundMntCoeff.CT = Allreduce(AllBoundMntCoeff.CT); + AllBoundMntCoeff.CQ = Allreduce(AllBoundMntCoeff.CQ); + AllBoundMntCoeff.CMerit = AllBoundMntCoeff.CT / (AllBoundMntCoeff.CQ + EPS); + } + + /*--- Add the forces on the surfaces using all the nodes ---*/ + + if (config->GetComm_Level() == COMM_FULL) { + int nMarkerMon = config->GetnMarker_Monitoring(); + + /*--- Use the same buffer for all reductions. We could avoid the copy back into + * the original variable by swaping pointers, but it is safer this way... ---*/ + + su2double* buffer = new su2double[nMarkerMon]; + + auto Allreduce_inplace = [buffer](int size, su2double* x) { + SU2_MPI::Allreduce(x, buffer, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + for (int i = 0; i < size; ++i) x[i] = buffer[i]; + }; + + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CL); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CD); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CSF); + + for (iMarker_Monitoring = 0; iMarker_Monitoring < nMarkerMon; iMarker_Monitoring++) + SurfaceMntCoeff.CEff[iMarker_Monitoring] = + SurfaceMntCoeff.CL[iMarker_Monitoring] / (SurfaceMntCoeff.CD[iMarker_Monitoring] + EPS); + + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CFx); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CFy); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CFz); + + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CMx); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CMy); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CMz); + + delete[] buffer; + } + +#endif + + /*--- Update the total coefficients (note that all the nodes have the same value) ---*/ + + TotalCoeff.CD += AllBoundMntCoeff.CD; + TotalCoeff.CL += AllBoundMntCoeff.CL; + TotalCoeff.CSF += AllBoundMntCoeff.CSF; + TotalCoeff.CEff = TotalCoeff.CL / (TotalCoeff.CD + EPS); + TotalCoeff.CFx += AllBoundMntCoeff.CFx; + TotalCoeff.CFy += AllBoundMntCoeff.CFy; + TotalCoeff.CFz += AllBoundMntCoeff.CFz; + TotalCoeff.CMx += AllBoundMntCoeff.CMx; + TotalCoeff.CMy += AllBoundMntCoeff.CMy; + TotalCoeff.CMz += AllBoundMntCoeff.CMz; + TotalCoeff.CoPx += AllBoundMntCoeff.CoPx; + TotalCoeff.CoPy += AllBoundMntCoeff.CoPy; + TotalCoeff.CoPz += AllBoundMntCoeff.CoPz; + TotalCoeff.CT += AllBoundMntCoeff.CT; + TotalCoeff.CQ += AllBoundMntCoeff.CQ; + TotalCoeff.CMerit = TotalCoeff.CT / (TotalCoeff.CQ + EPS); + + /*--- Update the total coefficients per surface (note that all the nodes have the same value)---*/ + + for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { + SurfaceCoeff.CL[iMarker_Monitoring] += SurfaceMntCoeff.CL[iMarker_Monitoring]; + SurfaceCoeff.CD[iMarker_Monitoring] += SurfaceMntCoeff.CD[iMarker_Monitoring]; + SurfaceCoeff.CSF[iMarker_Monitoring] += SurfaceMntCoeff.CSF[iMarker_Monitoring]; + SurfaceCoeff.CEff[iMarker_Monitoring] += + SurfaceMntCoeff.CL[iMarker_Monitoring] / (SurfaceMntCoeff.CD[iMarker_Monitoring] + EPS); + SurfaceCoeff.CFx[iMarker_Monitoring] += SurfaceMntCoeff.CFx[iMarker_Monitoring]; + SurfaceCoeff.CFy[iMarker_Monitoring] += SurfaceMntCoeff.CFy[iMarker_Monitoring]; + SurfaceCoeff.CFz[iMarker_Monitoring] += SurfaceMntCoeff.CFz[iMarker_Monitoring]; + SurfaceCoeff.CMx[iMarker_Monitoring] += SurfaceMntCoeff.CMx[iMarker_Monitoring]; + SurfaceCoeff.CMy[iMarker_Monitoring] += SurfaceMntCoeff.CMy[iMarker_Monitoring]; + SurfaceCoeff.CMz[iMarker_Monitoring] += SurfaceMntCoeff.CMz[iMarker_Monitoring]; + } +} + +template +void CFVMFlowSolverBase::Friction_Forces(const CGeometry* geometry, const CConfig* config) { + /// TODO: Major cleanup needed. + + if (!config->GetViscous()) return; + + unsigned long iVertex, iPoint, iPointNormal; + unsigned short Boundary, Monitoring, iMarker, iMarker_Monitoring, iDim, jDim; + su2double Viscosity = 0.0, div_vel, WallDist[3] = {0.0}, Area, WallShearStress, TauNormal, RefTemp, RefVel2 = 0.0, + RefDensity = 0.0, GradTemperature, Density = 0.0, WallDistMod, FrictionVel, Mach2Vel, Mach_Motion, + UnitNormal[3] = {0.0}, TauElem[3] = {0.0}, TauTangent[3] = {0.0}, Tau[3][3] = {{0.0}}, Cp, + thermal_conductivity, MaxNorm = 8.0, Grad_Vel[3][3] = {{0.0}}, Grad_Temp[3] = {0.0}, + delta[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; + su2double AxiFactor; + const su2double *Coord = nullptr, *Coord_Normal = nullptr, *Normal = nullptr; + + string Marker_Tag, Monitoring_Tag; + + su2double Alpha = config->GetAoA() * PI_NUMBER / 180.0; + su2double Beta = config->GetAoS() * PI_NUMBER / 180.0; + su2double RefArea = config->GetRefArea(); + su2double RefLength = config->GetRefLength(); + su2double RefHeatFlux = config->GetHeat_Flux_Ref(); + su2double Gas_Constant = config->GetGas_ConstantND(); + auto Origin = config->GetRefOriginMoment(0); + + su2double Prandtl_Lam = config->GetPrandtl_Lam(); + bool energy = config->GetEnergy_Equation(); + bool QCR = config->GetQCR(); + bool axisymmetric = config->GetAxisymmetric(); + + /// TODO: Move these ifs to specialized functions. + + if (FlowRegime == COMPRESSIBLE) { + /*--- Evaluate reference values for non-dimensionalization. + For dynamic meshes, use the motion Mach number as a reference value + for computing the force coefficients. Otherwise, use the freestream values, + which is the standard convention. ---*/ + + RefTemp = Temperature_Inf; + RefDensity = Density_Inf; + if (dynamic_grid) { + Mach2Vel = sqrt(Gamma * Gas_Constant * RefTemp); + Mach_Motion = config->GetMach_Motion(); + RefVel2 = (Mach_Motion * Mach2Vel) * (Mach_Motion * Mach2Vel); + } else { + RefVel2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim]; + } + } + + if (FlowRegime == INCOMPRESSIBLE) { + /*--- Evaluate reference values for non-dimensionalization. + For dimensional or non-dim based on initial values, use + the far-field state (inf). For a custom non-dim based + on user-provided reference values, use the ref values + to compute the forces. ---*/ + + if ((config->GetRef_Inc_NonDim() == DIMENSIONAL) || (config->GetRef_Inc_NonDim() == INITIAL_VALUES)) { + RefDensity = Density_Inf; + RefVel2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim]; + } else if (config->GetRef_Inc_NonDim() == REFERENCE_VALUES) { + RefDensity = config->GetInc_Density_Ref(); + RefVel2 = config->GetInc_Velocity_Ref() * config->GetInc_Velocity_Ref(); + } + } + + const su2double factor = 1.0 / (0.5 * RefDensity * RefArea * RefVel2); + + /*--- Variables initialization ---*/ + + AllBoundViscCoeff.setZero(); + SurfaceViscCoeff.setZero(); + + AllBound_HF_Visc = 0.0; + AllBound_MaxHF_Visc = 0.0; + + for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { + Surface_HF_Visc[iMarker_Monitoring] = 0.0; + Surface_MaxHF_Visc[iMarker_Monitoring] = 0.0; + } + + /*--- Loop over the Navier-Stokes markers ---*/ + + for (iMarker = 0; iMarker < nMarker; iMarker++) { + Boundary = config->GetMarker_All_KindBC(iMarker); + Monitoring = config->GetMarker_All_Monitoring(iMarker); + + /*--- Obtain the origin for the moment computation for a particular marker ---*/ + + if (Monitoring == YES) { + 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); + if (Marker_Tag == Monitoring_Tag) Origin = config->GetRefOriginMoment(iMarker_Monitoring); + } + } + + if ((Boundary == HEAT_FLUX) || (Boundary == ISOTHERMAL) || (Boundary == CHT_WALL_INTERFACE)) { + /*--- Forces initialization at each Marker ---*/ + + ViscCoeff.setZero(iMarker); + + HF_Visc[iMarker] = 0.0; + MaxHF_Visc[iMarker] = 0.0; + + su2double ForceViscous[MAXNDIM] = {0.0}, MomentViscous[MAXNDIM] = {0.0}; + su2double MomentX_Force[MAXNDIM] = {0.0}, MomentY_Force[MAXNDIM] = {0.0}, MomentZ_Force[MAXNDIM] = {0.0}; + + /*--- Loop over the vertices to compute the forces ---*/ + + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + iPointNormal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); + + Coord = geometry->nodes->GetCoord(iPoint); + Coord_Normal = geometry->nodes->GetCoord(iPointNormal); + + Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); + + for (iDim = 0; iDim < nDim; iDim++) { + for (jDim = 0; jDim < nDim; jDim++) { + Grad_Vel[iDim][jDim] = nodes->GetGradient_Primitive(iPoint, iDim + 1, jDim); + } + + /// TODO: Move the temperature index logic to a function. + + if (FlowRegime == COMPRESSIBLE) Grad_Temp[iDim] = nodes->GetGradient_Primitive(iPoint, 0, iDim); + + if (FlowRegime == INCOMPRESSIBLE) Grad_Temp[iDim] = nodes->GetGradient_Primitive(iPoint, nDim + 1, iDim); + } + + Viscosity = nodes->GetLaminarViscosity(iPoint); + Density = nodes->GetDensity(iPoint); + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim] * Normal[iDim]; + Area = sqrt(Area); + + for (iDim = 0; iDim < nDim; iDim++) { + UnitNormal[iDim] = Normal[iDim] / Area; + } + + /*--- Evaluate Tau ---*/ + + div_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) div_vel += Grad_Vel[iDim][iDim]; + + for (iDim = 0; iDim < nDim; iDim++) { + for (jDim = 0; jDim < nDim; jDim++) { + Tau[iDim][jDim] = Viscosity * (Grad_Vel[jDim][iDim] + Grad_Vel[iDim][jDim]) - + TWO3 * Viscosity * div_vel * delta[iDim][jDim]; + } + } + + /*--- If necessary evaluate the QCR contribution to Tau ---*/ + + if (QCR) { + su2double den_aux, c_cr1 = 0.3, O_ik, O_jk; + unsigned short kDim; + + /*--- Denominator Antisymmetric normalized rotation tensor ---*/ + + den_aux = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + for (jDim = 0; jDim < nDim; jDim++) den_aux += Grad_Vel[iDim][jDim] * Grad_Vel[iDim][jDim]; + den_aux = sqrt(max(den_aux, 1E-10)); + + /*--- Adding the QCR contribution ---*/ + + su2double tauQCR[MAXNDIM][MAXNDIM] = {{0.0}}; + + for (iDim = 0; iDim < nDim; iDim++) { + for (jDim = 0; jDim < nDim; jDim++) { + for (kDim = 0; kDim < nDim; kDim++) { + O_ik = (Grad_Vel[iDim][kDim] - Grad_Vel[kDim][iDim]) / den_aux; + O_jk = (Grad_Vel[jDim][kDim] - Grad_Vel[kDim][jDim]) / den_aux; + tauQCR[iDim][jDim] += O_ik * Tau[jDim][kDim] + O_jk * Tau[iDim][kDim]; + } + } + } + + for (iDim = 0; iDim < nDim; iDim++) + for (jDim = 0; jDim < nDim; jDim++) Tau[iDim][jDim] -= c_cr1 * tauQCR[iDim][jDim]; + } + + /*--- Project Tau in each surface element ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + TauElem[iDim] = 0.0; + for (jDim = 0; jDim < nDim; jDim++) { + TauElem[iDim] += Tau[iDim][jDim] * UnitNormal[jDim]; + } + } + + /*--- Compute wall shear stress (using the stress tensor). Compute wall skin friction coefficient, and heat flux + * on the wall ---*/ + + TauNormal = 0.0; + for (iDim = 0; iDim < nDim; iDim++) TauNormal += TauElem[iDim] * UnitNormal[iDim]; + + WallShearStress = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + TauTangent[iDim] = TauElem[iDim] - TauNormal * UnitNormal[iDim]; + CSkinFriction[iMarker][iDim][iVertex] = TauTangent[iDim] / (0.5 * RefDensity * RefVel2); + WallShearStress += TauTangent[iDim] * TauTangent[iDim]; + } + WallShearStress = sqrt(WallShearStress); + + for (iDim = 0; iDim < nDim; iDim++) WallDist[iDim] = (Coord[iDim] - Coord_Normal[iDim]); + WallDistMod = 0.0; + for (iDim = 0; iDim < nDim; iDim++) WallDistMod += WallDist[iDim] * WallDist[iDim]; + WallDistMod = sqrt(WallDistMod); + + /*--- Compute y+ and non-dimensional velocity ---*/ + + FrictionVel = sqrt(fabs(WallShearStress) / Density); + YPlus[iMarker][iVertex] = WallDistMod * FrictionVel / (Viscosity / Density); + + /*--- Compute total and maximum heat flux on the wall ---*/ + + GradTemperature = 0.0; + + /// TODO: Move these ifs to specialized functions. + + if (FlowRegime == COMPRESSIBLE) { + for (iDim = 0; iDim < nDim; iDim++) GradTemperature -= Grad_Temp[iDim] * UnitNormal[iDim]; + + Cp = (Gamma / Gamma_Minus_One) * Gas_Constant; + thermal_conductivity = Cp * Viscosity / Prandtl_Lam; + } + + if (FlowRegime == INCOMPRESSIBLE) { + if (energy) + for (iDim = 0; iDim < nDim; iDim++) GradTemperature -= Grad_Temp[iDim] * UnitNormal[iDim]; + + thermal_conductivity = nodes->GetThermalConductivity(iPoint); + } + + HeatFlux[iMarker][iVertex] = -thermal_conductivity * GradTemperature * RefHeatFlux; + + /*--- Note that y+, and heat are computed at the + halo cells (for visualization purposes), but not the forces ---*/ + + if ((geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES)) { + /*--- Axisymmetric simulations ---*/ + + if (axisymmetric) + AxiFactor = 2.0 * PI_NUMBER * geometry->nodes->GetCoord(iPoint, 1); + else + AxiFactor = 1.0; + + /*--- Force computation ---*/ + + su2double Force[MAXNDIM] = {0.0}, MomentDist[MAXNDIM] = {0.0}; + for (iDim = 0; iDim < nDim; iDim++) { + Force[iDim] = TauElem[iDim] * Area * factor * AxiFactor; + ForceViscous[iDim] += Force[iDim]; + MomentDist[iDim] = Coord[iDim] - Origin[iDim]; + } + + /*--- Moment with respect to the reference axis ---*/ + + if (iDim == 3) { + MomentViscous[0] += (Force[2] * MomentDist[1] - Force[1] * MomentDist[2]) / RefLength; + MomentX_Force[1] += (-Force[1] * Coord[2]); + MomentX_Force[2] += (Force[2] * Coord[1]); + + MomentViscous[1] += (Force[0] * MomentDist[2] - Force[2] * MomentDist[0]) / RefLength; + MomentY_Force[2] += (-Force[2] * Coord[0]); + MomentY_Force[0] += (Force[0] * Coord[2]); + } + MomentViscous[2] += (Force[1] * MomentDist[0] - Force[0] * MomentDist[1]) / RefLength; + MomentZ_Force[0] += (-Force[0] * Coord[1]); + MomentZ_Force[1] += (Force[1] * Coord[0]); + + HF_Visc[iMarker] += HeatFlux[iMarker][iVertex] * Area; + MaxHF_Visc[iMarker] += pow(HeatFlux[iMarker][iVertex], MaxNorm); + } + } + + /*--- Project forces and store the non-dimensional coefficients ---*/ + + if (Monitoring == YES) { + if (nDim == 2) { + ViscCoeff.CD[iMarker] = ForceViscous[0] * cos(Alpha) + ForceViscous[1] * sin(Alpha); + ViscCoeff.CL[iMarker] = -ForceViscous[0] * sin(Alpha) + ForceViscous[1] * cos(Alpha); + ViscCoeff.CEff[iMarker] = ViscCoeff.CL[iMarker] / (ViscCoeff.CD[iMarker] + EPS); + ViscCoeff.CFx[iMarker] = ForceViscous[0]; + ViscCoeff.CFy[iMarker] = ForceViscous[1]; + ViscCoeff.CMz[iMarker] = MomentViscous[2]; + ViscCoeff.CoPx[iMarker] = MomentZ_Force[1]; + ViscCoeff.CoPy[iMarker] = -MomentZ_Force[0]; + ViscCoeff.CT[iMarker] = -ViscCoeff.CFx[iMarker]; + ViscCoeff.CQ[iMarker] = -ViscCoeff.CMz[iMarker]; + ViscCoeff.CMerit[iMarker] = ViscCoeff.CT[iMarker] / (ViscCoeff.CQ[iMarker] + EPS); + MaxHF_Visc[iMarker] = pow(MaxHF_Visc[iMarker], 1.0 / MaxNorm); + } + if (nDim == 3) { + ViscCoeff.CD[iMarker] = ForceViscous[0] * cos(Alpha) * cos(Beta) + ForceViscous[1] * sin(Beta) + + ForceViscous[2] * sin(Alpha) * cos(Beta); + ViscCoeff.CL[iMarker] = -ForceViscous[0] * sin(Alpha) + ForceViscous[2] * cos(Alpha); + ViscCoeff.CSF[iMarker] = -ForceViscous[0] * sin(Beta) * cos(Alpha) + ForceViscous[1] * cos(Beta) - + ForceViscous[2] * sin(Beta) * sin(Alpha); + ViscCoeff.CEff[iMarker] = ViscCoeff.CL[iMarker] / (ViscCoeff.CD[iMarker] + EPS); + ViscCoeff.CFx[iMarker] = ForceViscous[0]; + ViscCoeff.CFy[iMarker] = ForceViscous[1]; + ViscCoeff.CFz[iMarker] = ForceViscous[2]; + ViscCoeff.CMx[iMarker] = MomentViscous[0]; + ViscCoeff.CMy[iMarker] = MomentViscous[1]; + ViscCoeff.CMz[iMarker] = MomentViscous[2]; + ViscCoeff.CoPx[iMarker] = -MomentY_Force[0]; + ViscCoeff.CoPz[iMarker] = MomentY_Force[2]; + ViscCoeff.CT[iMarker] = -ViscCoeff.CFz[iMarker]; + ViscCoeff.CQ[iMarker] = -ViscCoeff.CMz[iMarker]; + ViscCoeff.CMerit[iMarker] = ViscCoeff.CT[iMarker] / (ViscCoeff.CQ[iMarker] + EPS); + MaxHF_Visc[iMarker] = pow(MaxHF_Visc[iMarker], 1.0 / MaxNorm); + } + + AllBoundViscCoeff.CD += ViscCoeff.CD[iMarker]; + AllBoundViscCoeff.CL += ViscCoeff.CL[iMarker]; + AllBoundViscCoeff.CSF += ViscCoeff.CSF[iMarker]; + AllBoundViscCoeff.CFx += ViscCoeff.CFx[iMarker]; + AllBoundViscCoeff.CFy += ViscCoeff.CFy[iMarker]; + AllBoundViscCoeff.CFz += ViscCoeff.CFz[iMarker]; + AllBoundViscCoeff.CMx += ViscCoeff.CMx[iMarker]; + AllBoundViscCoeff.CMy += ViscCoeff.CMy[iMarker]; + AllBoundViscCoeff.CMz += ViscCoeff.CMz[iMarker]; + AllBoundViscCoeff.CoPx += ViscCoeff.CoPx[iMarker]; + AllBoundViscCoeff.CoPy += ViscCoeff.CoPy[iMarker]; + AllBoundViscCoeff.CoPz += ViscCoeff.CoPz[iMarker]; + AllBoundViscCoeff.CT += ViscCoeff.CT[iMarker]; + AllBoundViscCoeff.CQ += ViscCoeff.CQ[iMarker]; + AllBound_HF_Visc += HF_Visc[iMarker]; + AllBound_MaxHF_Visc += pow(MaxHF_Visc[iMarker], MaxNorm); + + /*--- 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); + if (Marker_Tag == Monitoring_Tag) { + SurfaceViscCoeff.CL[iMarker_Monitoring] += ViscCoeff.CL[iMarker]; + SurfaceViscCoeff.CD[iMarker_Monitoring] += ViscCoeff.CD[iMarker]; + SurfaceViscCoeff.CSF[iMarker_Monitoring] += ViscCoeff.CSF[iMarker]; + SurfaceViscCoeff.CEff[iMarker_Monitoring] += ViscCoeff.CEff[iMarker]; + SurfaceViscCoeff.CFx[iMarker_Monitoring] += ViscCoeff.CFx[iMarker]; + SurfaceViscCoeff.CFy[iMarker_Monitoring] += ViscCoeff.CFy[iMarker]; + SurfaceViscCoeff.CFz[iMarker_Monitoring] += ViscCoeff.CFz[iMarker]; + SurfaceViscCoeff.CMx[iMarker_Monitoring] += ViscCoeff.CMx[iMarker]; + SurfaceViscCoeff.CMy[iMarker_Monitoring] += ViscCoeff.CMy[iMarker]; + SurfaceViscCoeff.CMz[iMarker_Monitoring] += ViscCoeff.CMz[iMarker]; + Surface_HF_Visc[iMarker_Monitoring] += HF_Visc[iMarker]; + Surface_MaxHF_Visc[iMarker_Monitoring] += pow(MaxHF_Visc[iMarker], MaxNorm); + } + } + } + } + } + + /*--- Update some global coeffients ---*/ + + AllBoundViscCoeff.CEff = AllBoundViscCoeff.CL / (AllBoundViscCoeff.CD + EPS); + AllBoundViscCoeff.CMerit = AllBoundViscCoeff.CT / (AllBoundViscCoeff.CQ + EPS); + AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0 / MaxNorm); + +#ifdef HAVE_MPI + + /*--- Add AllBound information using all the nodes ---*/ + + if (config->GetComm_Level() == COMM_FULL) { + auto Allreduce = [](su2double x) { + su2double tmp = x; + x = 0.0; + SU2_MPI::Allreduce(&tmp, &x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + return x; + }; + AllBoundViscCoeff.CD = Allreduce(AllBoundViscCoeff.CD); + AllBoundViscCoeff.CL = Allreduce(AllBoundViscCoeff.CL); + AllBoundViscCoeff.CSF = Allreduce(AllBoundViscCoeff.CSF); + AllBoundViscCoeff.CEff = AllBoundViscCoeff.CL / (AllBoundViscCoeff.CD + EPS); + + AllBoundViscCoeff.CMx = Allreduce(AllBoundViscCoeff.CMx); + AllBoundViscCoeff.CMy = Allreduce(AllBoundViscCoeff.CMy); + AllBoundViscCoeff.CMz = Allreduce(AllBoundViscCoeff.CMz); + + AllBoundViscCoeff.CFx = Allreduce(AllBoundViscCoeff.CFx); + AllBoundViscCoeff.CFy = Allreduce(AllBoundViscCoeff.CFy); + AllBoundViscCoeff.CFz = Allreduce(AllBoundViscCoeff.CFz); + + AllBoundViscCoeff.CoPx = Allreduce(AllBoundViscCoeff.CoPx); + AllBoundViscCoeff.CoPy = Allreduce(AllBoundViscCoeff.CoPy); + AllBoundViscCoeff.CoPz = Allreduce(AllBoundViscCoeff.CoPz); + + AllBoundViscCoeff.CT = Allreduce(AllBoundViscCoeff.CT); + AllBoundViscCoeff.CQ = Allreduce(AllBoundViscCoeff.CQ); + AllBoundViscCoeff.CMerit = AllBoundViscCoeff.CT / (AllBoundViscCoeff.CQ + EPS); + + AllBound_HF_Visc = Allreduce(AllBound_HF_Visc); + AllBound_MaxHF_Visc = pow(Allreduce(pow(AllBound_MaxHF_Visc, MaxNorm)), 1.0 / MaxNorm); + } + + /*--- Add the forces on the surfaces using all the nodes ---*/ + + if (config->GetComm_Level() == COMM_FULL) { + int nMarkerMon = config->GetnMarker_Monitoring(); + + /*--- Use the same buffer for all reductions. We could avoid the copy back into + * the original variable by swaping pointers, but it is safer this way... ---*/ + + su2double* buffer = new su2double[nMarkerMon]; + + auto Allreduce_inplace = [buffer](int size, su2double* x) { + SU2_MPI::Allreduce(x, buffer, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + for (int i = 0; i < size; ++i) x[i] = buffer[i]; + }; + + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CL); + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CD); + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CSF); + + for (iMarker_Monitoring = 0; iMarker_Monitoring < nMarkerMon; iMarker_Monitoring++) + SurfaceViscCoeff.CEff[iMarker_Monitoring] = + SurfaceViscCoeff.CL[iMarker_Monitoring] / (SurfaceViscCoeff.CD[iMarker_Monitoring] + EPS); + + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CFx); + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CFy); + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CFz); + + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CMx); + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CMy); + Allreduce_inplace(nMarkerMon, SurfaceViscCoeff.CMz); + + Allreduce_inplace(nMarkerMon, Surface_HF_Visc); + Allreduce_inplace(nMarkerMon, Surface_MaxHF_Visc); + + delete[] buffer; + } + +#endif + + /*--- Update the total coefficients (note that all the nodes have the same value)---*/ + + TotalCoeff.CD += AllBoundViscCoeff.CD; + TotalCoeff.CL += AllBoundViscCoeff.CL; + TotalCoeff.CSF += AllBoundViscCoeff.CSF; + TotalCoeff.CEff = TotalCoeff.CL / (TotalCoeff.CD + EPS); + TotalCoeff.CFx += AllBoundViscCoeff.CFx; + TotalCoeff.CFy += AllBoundViscCoeff.CFy; + TotalCoeff.CFz += AllBoundViscCoeff.CFz; + TotalCoeff.CMx += AllBoundViscCoeff.CMx; + TotalCoeff.CMy += AllBoundViscCoeff.CMy; + TotalCoeff.CMz += AllBoundViscCoeff.CMz; + TotalCoeff.CoPx += AllBoundViscCoeff.CoPx; + TotalCoeff.CoPy += AllBoundViscCoeff.CoPy; + TotalCoeff.CoPz += AllBoundViscCoeff.CoPz; + TotalCoeff.CT += AllBoundViscCoeff.CT; + TotalCoeff.CQ += AllBoundViscCoeff.CQ; + TotalCoeff.CMerit = AllBoundViscCoeff.CT / (AllBoundViscCoeff.CQ + EPS); + Total_Heat = AllBound_HF_Visc; + Total_MaxHeat = AllBound_MaxHF_Visc; + + /*--- Update the total coefficients per surface (note that all the nodes have the same value)---*/ + + for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { + SurfaceCoeff.CL[iMarker_Monitoring] += SurfaceViscCoeff.CL[iMarker_Monitoring]; + SurfaceCoeff.CD[iMarker_Monitoring] += SurfaceViscCoeff.CD[iMarker_Monitoring]; + SurfaceCoeff.CSF[iMarker_Monitoring] += SurfaceViscCoeff.CSF[iMarker_Monitoring]; + SurfaceCoeff.CEff[iMarker_Monitoring] = + SurfaceViscCoeff.CL[iMarker_Monitoring] / (SurfaceCoeff.CD[iMarker_Monitoring] + EPS); + SurfaceCoeff.CFx[iMarker_Monitoring] += SurfaceViscCoeff.CFx[iMarker_Monitoring]; + SurfaceCoeff.CFy[iMarker_Monitoring] += SurfaceViscCoeff.CFy[iMarker_Monitoring]; + SurfaceCoeff.CFz[iMarker_Monitoring] += SurfaceViscCoeff.CFz[iMarker_Monitoring]; + SurfaceCoeff.CMx[iMarker_Monitoring] += SurfaceViscCoeff.CMx[iMarker_Monitoring]; + SurfaceCoeff.CMy[iMarker_Monitoring] += SurfaceViscCoeff.CMy[iMarker_Monitoring]; + SurfaceCoeff.CMz[iMarker_Monitoring] += SurfaceViscCoeff.CMz[iMarker_Monitoring]; + } +} + +template +su2double CFVMFlowSolverBase::EvaluateCommonObjFunc(const CConfig& config) const { + + su2double objFun = 0.0; + + /*--- Loop over all monitored markers, add to the 'combo' objective ---*/ + + for (auto iMarker = 0u; iMarker < config.GetnMarker_Monitoring(); iMarker++) { + + const auto weight = config.GetWeight_ObjFunc(iMarker); + + switch (config.GetKind_ObjFunc(iMarker)) { + case DRAG_COEFFICIENT: + objFun += weight * SurfaceCoeff.CD[iMarker]; + break; + case LIFT_COEFFICIENT: + objFun += weight * SurfaceCoeff.CL[iMarker]; + break; + case SIDEFORCE_COEFFICIENT: + objFun += weight * SurfaceCoeff.CSF[iMarker]; + break; + case EFFICIENCY: + objFun += weight * SurfaceCoeff.CEff[iMarker]; + break; + case MOMENT_X_COEFFICIENT: + objFun += weight * SurfaceCoeff.CMx[iMarker]; + break; + case MOMENT_Y_COEFFICIENT: + objFun += weight * SurfaceCoeff.CMy[iMarker]; + break; + case MOMENT_Z_COEFFICIENT: + objFun += weight * SurfaceCoeff.CMz[iMarker]; + break; + case FORCE_X_COEFFICIENT: + objFun += weight * SurfaceCoeff.CFx[iMarker]; + break; + case FORCE_Y_COEFFICIENT: + objFun += weight * SurfaceCoeff.CFy[iMarker]; + break; + case FORCE_Z_COEFFICIENT: + objFun += weight * SurfaceCoeff.CFz[iMarker]; + break; + case TOTAL_HEATFLUX: + objFun += weight * Surface_HF_Visc[iMarker]; + break; + case MAXIMUM_HEATFLUX: + objFun += weight * Surface_MaxHF_Visc[iMarker]; + break; + default: + break; + } + } + + /*--- The following are not per-surface, and so to avoid that they are + double-counted when multiple surfaces are specified, they have been + placed outside of the loop above. In addition, multi-objective mode is + also disabled for these objective functions (error thrown at start). ---*/ + + const auto weight = config.GetWeight_ObjFunc(0); + + switch (config.GetKind_ObjFunc(0)) { + case INVERSE_DESIGN_PRESSURE: + objFun += weight * Total_CpDiff; + break; + case INVERSE_DESIGN_HEATFLUX: + objFun += weight * Total_HeatFluxDiff; + break; + case THRUST_COEFFICIENT: + objFun += weight * TotalCoeff.CT; + break; + case TORQUE_COEFFICIENT: + objFun += weight * TotalCoeff.CQ; + break; + case FIGURE_OF_MERIT: + objFun += weight * TotalCoeff.CMerit; + break; + case SURFACE_TOTAL_PRESSURE: + objFun += weight * config.GetSurface_TotalPressure(0); + break; + case SURFACE_STATIC_PRESSURE: + objFun += weight * config.GetSurface_Pressure(0); + break; + case SURFACE_MASSFLOW: + objFun += weight * config.GetSurface_MassFlow(0); + break; + case SURFACE_UNIFORMITY: + objFun += weight * config.GetSurface_Uniformity(0); + break; + case SURFACE_SECONDARY: + objFun += weight * config.GetSurface_SecondaryStrength(0); + break; + case SURFACE_MOM_DISTORTION: + objFun += weight * config.GetSurface_MomentumDistortion(0); + break; + case SURFACE_SECOND_OVER_UNIFORM: + objFun += weight * config.GetSurface_SecondOverUniform(0); + break; + case CUSTOM_OBJFUNC: + objFun += weight * Total_Custom_ObjFunc; + break; + default: + break; + } + + return objFun; +} diff --git a/SU2_CFD/include/solvers/CIncEulerSolver.hpp b/SU2_CFD/include/solvers/CIncEulerSolver.hpp index 763baf507e82..ce5c4fbd8c84 100644 --- a/SU2_CFD/include/solvers/CIncEulerSolver.hpp +++ b/SU2_CFD/include/solvers/CIncEulerSolver.hpp @@ -25,10 +25,9 @@ * License along with SU2. If not, see . */ - #pragma once -#include "CSolver.hpp" +#include "CFVMFlowSolverBase.hpp" #include "../variables/CIncEulerVariable.hpp" /*! @@ -37,201 +36,30 @@ * \ingroup Euler_Equations * \author F. Palacios, T. Economon, T. Albring */ -class CIncEulerSolver : public CSolver { +class CIncEulerSolver : public CFVMFlowSolverBase { protected: - - su2double - Density_Inf, /*!< \brief Density at the infinity. */ - Pressure_Inf, /*!< \brief Pressure at the infinity. */ - *Velocity_Inf, /*!< \brief Flow Velocity vector at the infinity. */ - Temperature_Inf; /*!< \brief Temperature at infinity. */ - su2double - *CD_Inv, /*!< \brief Drag coefficient (inviscid contribution) for each boundary. */ - *CL_Inv, /*!< \brief Lift coefficient (inviscid contribution) for each boundary. */ - *CSF_Inv, /*!< \brief Sideforce coefficient (inviscid contribution) for each boundary. */ - *CMx_Inv, /*!< \brief x Moment coefficient (inviscid contribution) for each boundary. */ - *CMy_Inv, /*!< \brief y Moment coefficient (inviscid contribution) for each boundary. */ - *CMz_Inv, /*!< \brief z Moment coefficient (inviscid contribution) for each boundary. */ - *CoPx_Inv, /*!< \brief x Moment coefficient (inviscid contribution) for each boundary. */ - *CoPy_Inv, /*!< \brief y Moment coefficient (inviscid contribution) for each boundary. */ - *CoPz_Inv, /*!< \brief z Moment coefficient (inviscid contribution) for each boundary. */ - *CFx_Inv, /*!< \brief x Force coefficient (inviscid contribution) for each boundary. */ - *CFy_Inv, /*!< \brief y Force coefficient (inviscid contribution) for each boundary. */ - *CFz_Inv, /*!< \brief z Force coefficient (inviscid contribution) for each boundary. */ - *Surface_CL_Inv, /*!< \brief Lift coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CD_Inv, /*!< \brief Drag coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CSF_Inv, /*!< \brief Side-force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CEff_Inv, /*!< \brief Side-force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CFx_Inv, /*!< \brief x Force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CFy_Inv, /*!< \brief y Force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CFz_Inv, /*!< \brief z Force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CMx_Inv, /*!< \brief x Moment coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CMy_Inv, /*!< \brief y Moment coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CMz_Inv, /*!< \brief z Moment coefficient (inviscid contribution) for each monitoring surface. */ - *CEff_Inv, /*!< \brief Efficiency (Cl/Cd) (inviscid contribution) for each boundary. */ - *CMerit_Inv, /*!< \brief Rotor Figure of Merit (inviscid contribution) for each boundary. */ - *CT_Inv, /*!< \brief Thrust coefficient (force in -x direction, inviscid contribution) for each boundary. */ - *CQ_Inv, /*!< \brief Torque coefficient (moment in -x direction, inviscid contribution) for each boundary. */ - *CD_Mnt, /*!< \brief Drag coefficient (inviscid contribution) for each boundary. */ - *CL_Mnt, /*!< \brief Lift coefficient (inviscid contribution) for each boundary. */ - *CSF_Mnt, /*!< \brief Sideforce coefficient (inviscid contribution) for each boundary. */ - *CMx_Mnt, /*!< \brief x Moment coefficient (inviscid contribution) for each boundary. */ - *CMy_Mnt, /*!< \brief y Moment coefficient (inviscid contribution) for each boundary. */ - *CMz_Mnt, /*!< \brief z Moment coefficient (inviscid contribution) for each boundary. */ - *CoPx_Mnt, /*!< \brief x Moment coefficient (inviscid contribution) for each boundary. */ - *CoPy_Mnt, /*!< \brief y Moment coefficient (inviscid contribution) for each boundary. */ - *CoPz_Mnt, /*!< \brief z Moment coefficient (inviscid contribution) for each boundary. */ - *CFx_Mnt, /*!< \brief x Force coefficient (inviscid contribution) for each boundary. */ - *CFy_Mnt, /*!< \brief y Force coefficient (inviscid contribution) for each boundary. */ - *CFz_Mnt, /*!< \brief z Force coefficient (inviscid contribution) for each boundary. */ - *Surface_CL_Mnt, /*!< \brief Lift coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CD_Mnt, /*!< \brief Drag coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CSF_Mnt, /*!< \brief Side-force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CEff_Mnt, /*!< \brief Side-force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CFx_Mnt, /*!< \brief x Force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CFy_Mnt, /*!< \brief y Force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CFz_Mnt, /*!< \brief z Force coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CMx_Mnt, /*!< \brief x Moment coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CMy_Mnt, /*!< \brief y Moment coefficient (inviscid contribution) for each monitoring surface. */ - *Surface_CMz_Mnt, /*!< \brief z Moment coefficient (inviscid contribution) for each monitoring surface. */ - *CEff_Mnt, /*!< \brief Efficiency (Cl/Cd) (inviscid contribution) for each boundary. */ - *CMerit_Mnt, /*!< \brief Rotor Figure of Merit (inviscid contribution) for each boundary. */ - *CT_Mnt, /*!< \brief Thrust coefficient (force in -x direction, inviscid contribution) for each boundary. */ - *CQ_Mnt, /*!< \brief Torque coefficient (moment in -x direction, inviscid contribution) for each boundary. */ - **CPressure, /*!< \brief Pressure coefficient for each boundary and vertex. */ - **CPressureTarget, /*!< \brief Target Pressure coefficient for each boundary and vertex. */ - **HeatFlux, /*!< \brief Heat transfer coefficient for each boundary and vertex. */ - **HeatFluxTarget, /*!< \brief Heat transfer coefficient for each boundary and vertex. */ - **YPlus, /*!< \brief Yplus for each boundary and vertex. */ - ***CharacPrimVar, /*!< \brief Value of the characteristic variables at each boundary. */ - *ForceInviscid, /*!< \brief Inviscid force for each boundary. */ - *MomentInviscid, /*!< \brief Inviscid moment for each boundary. */ - *ForceMomentum, /*!< \brief Inviscid force for each boundary. */ - *MomentMomentum, /*!< \brief Inviscid moment for each boundary. */ - InverseDesign; /*!< \brief Inverse design functional for each boundary. */ - su2double - **Inlet_Ptotal, /*!< \brief Value of the Total P. */ - **Inlet_Ttotal, /*!< \brief Value of the Total T. */ - ***Inlet_FlowDir; /*!< \brief Value of the Flow Direction. */ - - su2double - AllBound_CD_Inv, /*!< \brief Total drag coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CL_Inv, /*!< \brief Total lift coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CSF_Inv, /*!< \brief Total sideforce coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMx_Inv, /*!< \brief Total x moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMy_Inv, /*!< \brief Total y moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMz_Inv, /*!< \brief Total z moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CFx_Inv, /*!< \brief Total x force coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CFy_Inv, /*!< \brief Total y force coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CFz_Inv, /*!< \brief Total z force coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPx_Inv, /*!< \brief Total x moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPy_Inv, /*!< \brief Total y moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPz_Inv, /*!< \brief Total z moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CEff_Inv, /*!< \brief Efficient coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMerit_Inv, /*!< \brief Rotor Figure of Merit (inviscid contribution) for all the boundaries. */ - AllBound_CT_Inv, /*!< \brief Total thrust coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CQ_Inv; /*!< \brief Total torque coefficient (inviscid contribution) for all the boundaries. */ - - - su2double - AllBound_CD_Mnt, /*!< \brief Total drag coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CL_Mnt, /*!< \brief Total lift coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CSF_Mnt, /*!< \brief Total sideforce coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMx_Mnt, /*!< \brief Total x moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMy_Mnt, /*!< \brief Total y moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMz_Mnt, /*!< \brief Total z moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CFx_Mnt, /*!< \brief Total x force coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CFy_Mnt, /*!< \brief Total y force coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CFz_Mnt, /*!< \brief Total z force coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPx_Mnt, /*!< \brief Total x moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPy_Mnt, /*!< \brief Total y moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPz_Mnt, /*!< \brief Total z moment coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CEff_Mnt, /*!< \brief Efficient coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMerit_Mnt, /*!< \brief Rotor Figure of Merit (inviscid contribution) for all the boundaries. */ - AllBound_CT_Mnt, /*!< \brief Total thrust coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CQ_Mnt; /*!< \brief Total torque coefficient (inviscid contribution) for all the boundaries. */ - - su2double - Total_ComboObj, /*!< \brief Total 'combo' objective for all monitored boundaries */ - Total_CD, /*!< \brief Total drag coefficient for all the boundaries. */ - Total_CL, /*!< \brief Total lift coefficient for all the boundaries. */ - Total_CSF, /*!< \brief Total sideforce coefficient for all the boundaries. */ - Total_CMx, /*!< \brief Total x moment coefficient for all the boundaries. */ - Total_CMy, /*!< \brief Total y moment coefficient for all the boundaries. */ - Total_CMz, /*!< \brief Total z moment coefficient for all the boundaries. */ - Total_CoPx, /*!< \brief Total x moment coefficient for all the boundaries. */ - Total_CoPy, /*!< \brief Total y moment coefficient for all the boundaries. */ - Total_CoPz, /*!< \brief Total z moment coefficient for all the boundaries. */ - Total_CFx, /*!< \brief Total x force coefficient for all the boundaries. */ - Total_CFy, /*!< \brief Total y force coefficient for all the boundaries. */ - Total_CFz, /*!< \brief Total z force coefficient for all the boundaries. */ - Total_CEff, /*!< \brief Total efficiency coefficient for all the boundaries. */ - Total_CMerit, /*!< \brief Total rotor Figure of Merit for all the boundaries. */ - Total_CT, /*!< \brief Total thrust coefficient for all the boundaries. */ - Total_CQ, /*!< \brief Total torque coefficient for all the boundaries. */ - Total_Heat, /*!< \brief Total heat load for all the boundaries. */ - Total_MaxHeat, /*!< \brief Maximum heat flux on all boundaries. */ - Total_CpDiff, /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ - Total_HeatFluxDiff, /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ - Total_Custom_ObjFunc, /*!< \brief Total custom objective function for all the boundaries. */ - Total_MassFlowRate; /*!< \brief Total Mass Flow Rate on monitored boundaries. */ - su2double - *Surface_CL, /*!< \brief Lift coefficient for each monitoring surface. */ - *Surface_CD, /*!< \brief Drag coefficient for each monitoring surface. */ - *Surface_CSF, /*!< \brief Side-force coefficient for each monitoring surface. */ - *Surface_CEff, /*!< \brief Side-force coefficient for each monitoring surface. */ - *Surface_CFx, /*!< \brief x Force coefficient for each monitoring surface. */ - *Surface_CFy, /*!< \brief y Force coefficient for each monitoring surface. */ - *Surface_CFz, /*!< \brief z Force coefficient for each monitoring surface. */ - *Surface_CMx, /*!< \brief x Moment coefficient for each monitoring surface. */ - *Surface_CMy, /*!< \brief y Moment coefficient for each monitoring surface. */ - *Surface_CMz, /*!< \brief z Moment coefficient for each monitoring surface. */ - *Surface_HF_Visc, /*!< \brief Total (integrated) heat flux for each monitored surface. */ - *Surface_MaxHF_Visc; /*!< \brief Maximum heat flux for each monitored surface. */ - - su2double *SecondaryVar_i, /*!< \brief Auxiliary vector for storing the solution at point i. */ - *SecondaryVar_j; /*!< \brief Auxiliary vector for storing the solution at point j. */ - su2double *PrimVar_i, /*!< \brief Auxiliary vector for storing the solution at point i. */ - *PrimVar_j; /*!< \brief Auxiliary vector for storing the solution at point j. */ - bool space_centered, /*!< \brief True if space centered scheeme used. */ - euler_implicit, /*!< \brief True if euler implicit scheme used. */ - least_squares; /*!< \brief True if computing gradients by least squares. */ - su2double Gamma; /*!< \brief Fluid's Gamma constant (ratio of specific heats). */ - su2double Gamma_Minus_One; /*!< \brief Fluids's Gamma - 1.0 . */ - - su2double *Primitive, /*!< \brief Auxiliary nPrimVar vector. */ - *Primitive_i, /*!< \brief Auxiliary nPrimVar vector for storing the primitive at point i. */ - *Primitive_j; /*!< \brief Auxiliary nPrimVar vector for storing the primitive at point j. */ + *Primitive = nullptr, /*!< \brief Auxiliary nPrimVar vector. */ + *Primitive_i = nullptr, /*!< \brief Auxiliary nPrimVar vector for storing the primitive at point i. */ + *Primitive_j = nullptr; /*!< \brief Auxiliary nPrimVar vector for storing the primitive at point j. */ - CFluidModel *FluidModel; /*!< \brief fluid model used in the solver */ - su2double **Preconditioner; /*!< \brief Auxiliary matrix for storing the low speed preconditioner. */ - - /* Sliding meshes variables */ - - su2double ****SlidingState; - int **SlidingStateNodes; - - CIncEulerVariable* nodes = nullptr; /*!< \brief The highest level in the variable hierarchy this solver can safely use. */ - - /*! - * \brief Return nodes to allow CSolver::base_nodes to be set. - */ - inline CVariable* GetBaseClassPointerToNodes() final { return nodes; } + CFluidModel *FluidModel = nullptr; /*!< \brief fluid model used in the solver */ + su2double **Preconditioner = nullptr; /*!< \brief Auxiliary matrix for storing the low speed preconditioner. */ public: - /*! * \brief Constructor of the class. */ - CIncEulerSolver(void); + CIncEulerSolver() : CFVMFlowSolverBase() {} /*! * \overload * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Grid level. + * \param[in] navier_stokes - True when the constructor is called by the derived class CIncNSSolver. */ - CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh); + CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh, const bool navier_stokes = false); /*! * \brief Destructor of the class. @@ -251,65 +79,6 @@ class CIncEulerSolver : public CSolver { */ inline CFluidModel* GetFluidModel(void) const final { return FluidModel;} - /*! - * \brief Compute the density at the infinity. - * \return Value of the density at the infinity. - */ - inline su2double GetDensity_Inf(void) const final { return Density_Inf; } - - /*! - * \brief Compute 2-norm of the velocity at the infinity. - * \return Value of the 2-norm of the velocity at the infinity. - */ - inline su2double GetModVelocity_Inf(void) const final { - su2double Vel2 = 0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Vel2 += Velocity_Inf[iDim]*Velocity_Inf[iDim]; - return sqrt(Vel2); - } - - - /*! - * \brief Compute the pressure at the infinity. - * \return Value of the pressure at the infinity. - */ - inline su2double GetPressure_Inf(void) const final { return Pressure_Inf; } - - /*! - * \brief Get the temperature value at infinity. - * \return Value of the temperature at infinity. - */ - inline su2double GetTemperature_Inf(void) const { return Temperature_Inf; } - - /*! - * \brief Compute the density multiply by velocity at the infinity. - * \param[in] val_dim - Index of the velocity vector. - * \return Value of the density multiply by the velocity at the infinity. - */ - inline su2double GetDensity_Velocity_Inf(unsigned short val_dim) const final { return Density_Inf*Velocity_Inf[val_dim]; } - - /*! - * \brief Get the velocity at the infinity. - * \param[in] val_dim - Index of the velocity vector. - * \return Value of the velocity at the infinity. - */ - inline su2double GetVelocity_Inf(unsigned short val_dim) const final { return Velocity_Inf[val_dim]; } - - /*! - * \brief Get the velocity at the infinity. - * \return Value of the velocity at the infinity. - */ - inline su2double *GetVelocity_Inf(void) final { return Velocity_Inf; } - - /*! - * \brief Set the velocity at infinity. - * \param[in] val_dim - Index of the velocity vector. - * \param[in] val_velocity - Value of the velocity. - */ - inline void SetVelocity_Inf(unsigned short val_dim, su2double val_velocity) final { - Velocity_Inf[val_dim] = val_velocity; - } - /*! * \brief Compute the time step for solving the Euler equations. * \param[in] geometry - Geometrical definition of the problem. @@ -430,35 +199,6 @@ class CIncEulerSolver : public CSolver { */ void SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config); - /*! - * \brief Compute the gradient of the primitive variables using Green-Gauss method, - * and stores the result in the Gradient_Primitive variable. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] reconstruction - indicator that the gradient being computed is for upwind reconstruction. - */ - void SetPrimitive_Gradient_GG(CGeometry *geometry, - const CConfig *config, - bool reconstruction = false) final; - - /*! - * \brief Compute the gradient of the primitive variables using a Least-Squares method, - * and stores the result in the Gradient_Primitive variable. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] reconstruction - indicator that the gradient being computed is for upwind reconstruction. - */ - void SetPrimitive_Gradient_LS(CGeometry *geometry, - const CConfig *config, - bool reconstruction = false) final; - - /*! - * \brief Compute the limiter of the primitive variables. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void SetPrimitive_Limiter(CGeometry *geometry, const CConfig *config) final; - /*! * \brief Compute the undivided laplacian for the solution, except the energy equation. * \param[in] geometry - Geometrical definition of the problem. @@ -480,23 +220,6 @@ class CIncEulerSolver : public CSolver { */ void Evaluate_ObjFunc(CConfig *config) final; - /*! - * \author: T. Kattmann - * \brief Impose via the residual the Euler wall boundary condition. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Euler_Wall(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) override; - /*! * \brief Impose the far-field boundary condition using characteristics. * \param[in] geometry - Geometrical definition of the problem. @@ -513,22 +236,6 @@ class CIncEulerSolver : public CSolver { CConfig *config, unsigned short val_marker) final; - /*! - * \brief Impose the symmetry boundary condition using the residual. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Sym_Plane(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) final; - /*! * \brief Impose a subsonic inlet boundary condition. * \param[in] geometry - Geometrical definition of the problem. @@ -545,22 +252,6 @@ class CIncEulerSolver : public CSolver { CConfig *config, unsigned short val_marker) final; - /*! - * \brief Impose a custom or verification boundary condition. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the convective numerical method. - * \param[in] visc_numerics - Description of the viscous numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Custom(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) final; - /*! * \brief Impose the outlet boundary condition. * \param[in] geometry - Geometrical definition of the problem. @@ -577,32 +268,6 @@ class CIncEulerSolver : public CSolver { CConfig *config, unsigned short val_marker) final; - /*! - * \brief Impose the interface state across sliding meshes. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - */ - void BC_Fluid_Interface(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config) final; - - /*! - * \brief Impose a periodic boundary condition by summing contributions from the complete control volume. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - */ - void BC_Periodic(CGeometry *geometry, - CSolver **solver_container, - CNumerics *numerics, - CConfig *config) final; - /*! * \brief compare to values. * \param[in] a - value 1. @@ -632,20 +297,6 @@ class CIncEulerSolver : public CSolver { CSolver **solver_container, CConfig *config) final; - /*! - * \brief Compute the pressure forces and all the adimensional coefficients. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void Pressure_Forces(CGeometry *geometry, CConfig *config) final; - - /*! - * \brief Compute the pressure forces and all the adimensional coefficients. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void Momentum_Forces(CGeometry *geometry, CConfig *config) final; - /*! * \brief Update the solution using an implicit Euler scheme. * \param[in] geometry - Geometrical definition of the problem. @@ -656,642 +307,6 @@ class CIncEulerSolver : public CSolver { CSolver **solver_container, CConfig *config) final; - /*! - * \brief Compute a suitable under-relaxation parameter to limit the change in the solution variables over a nonlinear iteration for stability. - * \param[in] solver - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - */ - void ComputeUnderRelaxationFactor(CSolver **solver, CConfig *config) final; - - /*! - * \brief Provide the non dimensional lift coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient on the surface val_marker. - */ - inline su2double GetSurface_CL(unsigned short val_marker) const final { return Surface_CL[val_marker]; } - - /*! - * \brief Provide the non dimensional drag coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient on the surface val_marker. - */ - inline su2double GetSurface_CD(unsigned short val_marker) const final { return Surface_CD[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CSF(unsigned short val_marker) const final { return Surface_CSF[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CEff(unsigned short val_marker) const final { return Surface_CEff[val_marker]; } - - /*! - * \brief Provide the non dimensional x force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFx(unsigned short val_marker) const final { return Surface_CFx[val_marker]; } - - /*! - * \brief Provide the non dimensional y force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFy(unsigned short val_marker) const final { return Surface_CFy[val_marker]; } - - /*! - * \brief Provide the non dimensional z force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFz(unsigned short val_marker) const final { return Surface_CFz[val_marker]; } - - /*! - * \brief Provide the non dimensional x moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMx(unsigned short val_marker) const final { return Surface_CMx[val_marker]; } - - /*! - * \brief Provide the non dimensional y moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMy(unsigned short val_marker) const final { return Surface_CMy[val_marker]; } - - /*! - * \brief Provide the non dimensional z moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMz(unsigned short val_marker) const final { return Surface_CMz[val_marker]; } - - /*! - * \brief Provide the non dimensional lift coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient on the surface val_marker. - */ - inline su2double GetSurface_CL_Inv(unsigned short val_marker) const final { return Surface_CL_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional drag coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient on the surface val_marker. - */ - inline su2double GetSurface_CD_Inv(unsigned short val_marker) const final { return Surface_CD_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CSF_Inv(unsigned short val_marker) const final { return Surface_CSF_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CEff_Inv(unsigned short val_marker) const final { return Surface_CEff_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional x force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFx_Inv(unsigned short val_marker) const final { return Surface_CFx_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional y force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFy_Inv(unsigned short val_marker) const final { return Surface_CFy_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional z force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFz_Inv(unsigned short val_marker) const final { return Surface_CFz_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional x moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMx_Inv(unsigned short val_marker) const final { return Surface_CMx_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional y moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMy_Inv(unsigned short val_marker) const final { return Surface_CMy_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional z moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMz_Inv(unsigned short val_marker) const final { return Surface_CMz_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional lift coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient on the surface val_marker. - */ - inline su2double GetSurface_CL_Mnt(unsigned short val_marker) const final { return Surface_CL_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional drag coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient on the surface val_marker. - */ - inline su2double GetSurface_CD_Mnt(unsigned short val_marker) const final { return Surface_CD_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CSF_Mnt(unsigned short val_marker) const final { return Surface_CSF_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CEff_Mnt(unsigned short val_marker) const final { return Surface_CEff_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional x force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFx_Mnt(unsigned short val_marker) const final { return Surface_CFx_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional y force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFy_Mnt(unsigned short val_marker) const final { return Surface_CFy_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional z force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFz_Mnt(unsigned short val_marker) const final { return Surface_CFz_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional x moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMx_Mnt(unsigned short val_marker) const final { return Surface_CMx_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional y moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMy_Mnt(unsigned short val_marker) const final { return Surface_CMy_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional z moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMz_Mnt(unsigned short val_marker) const final { return Surface_CMz_Mnt[val_marker]; } - - /*! - * \brief Provide the non dimensional drag coefficient (inviscid contribution). - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the drag coefficient (inviscid contribution) on the surface val_marker. - */ - inline su2double GetCD_Inv(unsigned short val_marker) const final { return CD_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional sideforce coefficient (inviscid contribution). - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the sideforce coefficient (inviscid contribution) on the surface val_marker. - */ - inline su2double GetCSF_Inv(unsigned short val_marker) const final { return CSF_Inv[val_marker]; } - - /*! - * \brief Provide the non dimensional efficiency coefficient (inviscid contribution). - * \param val_marker Surface where the coeficient is going to be computed. - * \return Value of the efficiency coefficient (inviscid contribution) on the surface val_marker. - */ - inline su2double GetCEff_Inv(unsigned short val_marker) const final { return CEff_Inv[val_marker]; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional sideforce coefficient. - * \return Value of the sideforce coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CSF() const final { return Total_CSF; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CEff() const final { return Total_CEff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. - * \return Value of the Equivalent Area coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CpDiff() const final { return Total_CpDiff; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. - * \return Value of the Equivalent Area coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_HeatFluxDiff() const final { return Total_HeatFluxDiff; } - - /*! - * \brief Set the value of the Equivalent Area coefficient. - * \param[in] val_cequivarea - Value of the Equivalent Area coefficient. - */ - inline void SetTotal_CpDiff(su2double val_pressure) final { Total_CpDiff = val_pressure; } - - /*! - * \brief Set the value of the Equivalent Area coefficient. - * \param[in] val_cequivarea - Value of the Equivalent Area coefficient. - */ - inline void SetTotal_HeatFluxDiff(su2double val_heat) final { Total_HeatFluxDiff = val_heat; } - - /*! - * \brief Set the value of the custom objective function. - * \param[in] val_Total_Custom_ObjFunc - Value of the total custom objective function. - * \param[in] val_weight - Value of the weight for the custom objective function. - */ - inline void SetTotal_Custom_ObjFunc(su2double val_total_custom_objfunc, su2double val_weight) final { - Total_Custom_ObjFunc = val_total_custom_objfunc*val_weight; - } - - /*! - * \brief Add the value of the custom objective function. - * \param[in] val_Total_Custom_ObjFunc - Value of the total custom objective function. - * \param[in] val_weight - Value of the weight for the custom objective function. - */ - inline void AddTotal_Custom_ObjFunc(su2double val_total_custom_objfunc, su2double val_weight) final { - Total_Custom_ObjFunc += val_total_custom_objfunc*val_weight; - } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional lift coefficient. - * \return Value of the lift coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CL() const final { return Total_CL; } - - /*! - * \author H. Kline - * \brief Set the total "combo" objective (weighted sum of other values). - * \param[in] ComboObj - Value of the combined objective. - */ - inline void SetTotal_ComboObj(su2double ComboObj) final {Total_ComboObj = ComboObj; } - - /*! - * \author H. Kline - * \brief Provide the total "combo" objective (weighted sum of other values). - * \return Value of the "combo" objective values. - */ - inline su2double GetTotal_ComboObj() const final { return Total_ComboObj; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. - * \return Value of the drag coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CD() const final { return Total_CD; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional x moment coefficient. - * \return Value of the moment x coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CMx() const final { return Total_CMx; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional y moment coefficient. - * \return Value of the moment y coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CMy() const final { return Total_CMy; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional z moment coefficient. - * \return Value of the moment z coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CMz() const final { return Total_CMz; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional x moment coefficient. - * \return Value of the moment x coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CoPx() const final { return Total_CoPx; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional y moment coefficient. - * \return Value of the moment y coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CoPy() const final { return Total_CoPy; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional z moment coefficient. - * \return Value of the moment z coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CoPz() const final { return Total_CoPz; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional x force coefficient. - * \return Value of the force x coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CFx() const final { return Total_CFx; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional y force coefficient. - * \return Value of the force y coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CFy() const final { return Total_CFy; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional z force coefficient. - * \return Value of the force z coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CFz() const final { return Total_CFz; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional thrust coefficient. - * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CT() const final { return Total_CT; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional thrust coefficient. - * \param[in] val_Total_CT - Value of the total thrust coefficient. - */ - inline void SetTotal_CT(su2double val_Total_CT) final { Total_CT = val_Total_CT; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional torque coefficient. - * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CQ() const final { return Total_CQ; } - - /*! - * \brief Provide the total heat load. - * \return Value of the heat load (viscous contribution). - */ - inline su2double GetTotal_HeatFlux(void) const final { return Total_Heat; } - - /*! - * \brief Provide the total heat load. - * \return Value of the heat load (viscous contribution). - */ - inline su2double GetTotal_MaxHeatFlux() const final { return Total_MaxHeat; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional torque coefficient. - * \param[in] val_Total_CQ - Value of the total torque coefficient. - */ - inline void SetTotal_CQ(su2double val_Total_CQ) final { Total_CQ = val_Total_CQ; } - - /*! - * \brief Store the total heat load. - * \param[in] val_Total_Heat - Value of the heat load. - */ - inline void SetTotal_HeatFlux(su2double val_Total_Heat) final { Total_Heat = val_Total_Heat; } - - /*! - * \brief Store the total heat load. - * \param[in] val_Total_Heat - Value of the heat load. - */ - inline void SetTotal_MaxHeatFlux(su2double val_Total_MaxHeat) final { Total_MaxHeat = val_Total_MaxHeat; } - - /*! - * \brief Provide the total (inviscid + viscous) non dimensional rotor Figure of Merit. - * \return Value of the rotor efficiency coefficient (inviscid + viscous contribution). - */ - inline su2double GetTotal_CMerit() const final { return Total_CMerit; } - - /*! - * \brief Provide the total custom objective function. - * \return Value of the custom objective function. - */ - inline su2double GetTotal_Custom_ObjFunc() const final { return Total_Custom_ObjFunc; } - - /*! - * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. - * \param[in] val_Total_CDrag - Value of the total drag coefficient. - */ - inline void SetTotal_CD(su2double val_Total_CD) final { Total_CD = val_Total_CD; } - - /*! - * \brief Get the inviscid contribution to the lift coefficient. - * \return Value of the lift coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CL_Inv() const final { return AllBound_CL_Inv; } - - /*! - * \brief Get the inviscid contribution to the drag coefficient. - * \return Value of the drag coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CD_Inv() const final { return AllBound_CD_Inv; } - - /*! - * \brief Get the inviscid contribution to the sideforce coefficient. - * \return Value of the sideforce coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CSF_Inv() const final { return AllBound_CSF_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CEff_Inv() const final { return AllBound_CEff_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMx_Inv() const final { return AllBound_CMx_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMy_Inv() const final { return AllBound_CMy_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMz_Inv() const final { return AllBound_CMz_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPx_Inv() const final { return AllBound_CoPx_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPy_Inv() const final { return AllBound_CoPy_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPz_Inv() const final { return AllBound_CoPz_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFx_Inv() const final { return AllBound_CFx_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFy_Inv() const final { return AllBound_CFy_Inv; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFz_Inv() const final { return AllBound_CFz_Inv; } - - /*! - * \brief Get the inviscid contribution to the lift coefficient. - * \return Value of the lift coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CL_Mnt() const final { return AllBound_CL_Mnt; } - - /*! - * \brief Get the inviscid contribution to the drag coefficient. - * \return Value of the drag coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CD_Mnt() const final { return AllBound_CD_Mnt; } - - /*! - * \brief Get the inviscid contribution to the sideforce coefficient. - * \return Value of the sideforce coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CSF_Mnt() const final { return AllBound_CSF_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CEff_Mnt() const final { return AllBound_CEff_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMx_Mnt() const final { return AllBound_CMx_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMy_Mnt() const final { return AllBound_CMy_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMz_Mnt() const final { return AllBound_CMz_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPx_Mnt() const final { return AllBound_CoPx_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPy_Mnt() const final { return AllBound_CoPy_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPz_Mnt() const final { return AllBound_CoPz_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFx_Mnt() const final { return AllBound_CFx_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFy_Mnt() const final { return AllBound_CFy_Mnt; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFz_Mnt() const final { return AllBound_CFz_Mnt; } - - /*! - * \brief Provide the Pressure coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline su2double GetCPressure(unsigned short val_marker, unsigned long val_vertex) const final { - return CPressure[val_marker][val_vertex]; - } - - /*! - * \brief Provide the Target Pressure coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline su2double GetCPressureTarget(unsigned short val_marker, unsigned long val_vertex) const final { - return CPressureTarget[val_marker][val_vertex]; - } - - /*! - * \brief Set the value of the target Pressure coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline void SetCPressureTarget(unsigned short val_marker, - unsigned long val_vertex, - su2double val_pressure) final { - CPressureTarget[val_marker][val_vertex] = val_pressure; - } - - /*! - * \brief Value of the characteristic variables at the boundaries. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline su2double *GetCharacPrimVar(unsigned short val_marker, unsigned long val_vertex) const final { - return CharacPrimVar[val_marker][val_vertex]; - } - /*! * \brief Set the total residual adding the term that comes from the Dual Time Strategy. * \param[in] geometry - Geometrical definition of the problem. @@ -1333,25 +348,6 @@ class CIncEulerSolver : public CSolver { CSolver ***solver_container, CConfig *config, unsigned long TimeIter) final; - - /*! - * \brief Set the freestream pressure. - * \param[in] Value of freestream pressure. - */ - inline void SetPressure_Inf(su2double p_inf) final { Pressure_Inf = p_inf; } - - /*! - * \brief Set the freestream temperature. - * \param[in] Value of freestream temperature. - */ - inline void SetTemperature_Inf(su2double t_inf) final { Temperature_Inf = t_inf; } - - /*! - * \brief Set the freestream temperature. - * \param[in] Value of freestream temperature. - */ - inline void SetDensity_Inf(su2double rho_inf) final { Density_Inf = rho_inf; } - /*! * \brief Set the solution using the Freestream values. * \param[in] config - Definition of the particular problem. @@ -1377,92 +373,6 @@ class CIncEulerSolver : public CSolver { */ void SetPreconditioner(CConfig *config, unsigned long iPoint) final; - /*! - * \brief Value of the total temperature at an inlet boundary. - * \param[in] val_marker - Surface marker where the total temperature is evaluated. - * \param[in] val_vertex - Vertex of the marker val_marker where the total temperature is evaluated. - * \return Value of the total temperature - */ - inline su2double GetInlet_Ttotal(unsigned short val_marker, unsigned long val_vertex) const final { return Inlet_Ttotal[val_marker][val_vertex]; } - - /*! - * \brief Value of the total pressure at an inlet boundary. - * \param[in] val_marker - Surface marker where the total pressure is evaluated. - * \param[in] val_vertex - Vertex of the marker val_marker where the total pressure is evaluated. - * \return Value of the total pressure - */ - inline su2double GetInlet_Ptotal(unsigned short val_marker, unsigned long val_vertex) const final { return Inlet_Ptotal[val_marker][val_vertex]; } - - /*! - * \brief A component of the unit vector representing the flow direction at an inlet boundary. - * \param[in] val_marker - Surface marker where the flow direction is evaluated - * \param[in] val_vertex - Vertex of the marker val_marker where the flow direction is evaluated - * \param[in] val_dim - The component of the flow direction unit vector to be evaluated - * \return Component of a unit vector representing the flow direction. - */ - inline su2double GetInlet_FlowDir(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_dim) const final { - return Inlet_FlowDir[val_marker][val_vertex][val_dim]; - } - - /*! - * \brief Set a component of the unit vector representing the flow direction at an inlet boundary. - * \param[in] val_marker - Surface marker where the flow direction is set. - * \param[in] val_vertex - Vertex of the marker val_marker where the flow direction is set. - * \param[in] val_dim - The component of the flow direction unit vector to be set - * \param[in] val_flowdir - Component of a unit vector representing the flow direction. - */ - inline void SetInlet_FlowDir(unsigned short val_marker, unsigned long val_vertex, unsigned short val_dim, su2double val_flowdir) final { - /*--- Since this call can be accessed indirectly using python, do some error - * checking to prevent segmentation faults ---*/ - if (val_marker >= nMarker) - SU2_MPI::Error("Out-of-bounds marker index used on inlet.", CURRENT_FUNCTION); - else if (Inlet_FlowDir == nullptr || Inlet_FlowDir[val_marker] == nullptr) - SU2_MPI::Error("Tried to set custom inlet BC on an invalid marker.", CURRENT_FUNCTION); - else if (val_vertex >= nVertex[val_marker]) - SU2_MPI::Error("Out-of-bounds vertex index used on inlet.", CURRENT_FUNCTION); - else - Inlet_FlowDir[val_marker][val_vertex][val_dim] = val_flowdir; - } - - /*! - * \brief Set a uniform inlet profile - * - * The values at the inlet are set to match the values specified for - * inlets in the configuration file. - * - * \param[in] config - Definition of the particular problem. - * \param[in] iMarker - Surface marker where the coefficient is computed. - */ - void SetUniformInlet(CConfig* config, unsigned short iMarker) final; - - /*! - * \brief Store of a set of provided inlet profile values at a vertex. - * \param[in] val_inlet - vector containing the inlet values for the current vertex. - * \param[in] iMarker - Surface marker where the coefficient is computed. - * \param[in] iVertex - Vertex of the marker iMarker where the inlet is being set. - */ - void SetInletAtVertex(su2double *val_inlet, - unsigned short iMarker, - unsigned long iVertex) final; - - /*! - * \brief Get the set of value imposed at an inlet. - * \param[in] val_inlet - vector returning the inlet values for the current vertex. - * \param[in] val_inlet_point - Node index where the inlet is being set. - * \param[in] val_kind_marker - Enumerated type for the particular inlet type. - * \param[in] geometry - Geometrical definition of the problem. - * \param config - Definition of the particular problem. - * \return Value of the face area at the vertex. - */ - su2double GetInletAtVertex(su2double *val_inlet, - unsigned long val_inlet_point, - unsigned short val_kind_marker, - string val_marker, - CGeometry *geometry, - CConfig *config) const final; - /*! * \brief A virtual member. */ @@ -1472,80 +382,9 @@ class CIncEulerSolver : public CSolver { bool Output) final; /*! - * \brief Allocates the final pointer of SlidingState depending on how many donor vertex donate to it. That number is stored in SlidingStateNodes[val_marker][val_vertex]. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - */ - inline void SetSlidingStateStructure(unsigned short val_marker, unsigned long val_vertex) final { - int iVar; - - for( iVar = 0; iVar < nPrimVar+1; iVar++){ - if( SlidingState[val_marker][val_vertex][iVar] != nullptr ) - delete [] SlidingState[val_marker][val_vertex][iVar]; - } - - for( iVar = 0; iVar < nPrimVar+1; iVar++) - SlidingState[val_marker][val_vertex][iVar] = new su2double[ GetnSlidingStates(val_marker, val_vertex) ]; - } - - - - - /*! - * \brief Set the outer state for fluid interface nodes. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] val_state - requested state component - * \param[in] donor_index - index of the donor node to set - * \param[in] component - set value - */ - inline void SetSlidingState(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_state, - unsigned long donor_index, - su2double component) final { - SlidingState[val_marker][val_vertex][val_state][donor_index] = component; - } - - - /*! - * \brief Set the number of outer state for fluid interface nodes. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] value - number of outer states - */ - inline void SetnSlidingStates(unsigned short val_marker, - unsigned long val_vertex, - int value) final { SlidingStateNodes[val_marker][val_vertex] = value; } - - /*! - * \brief Get the number of outer state for fluid interface nodes. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - */ - inline int GetnSlidingStates(unsigned short val_marker, unsigned long val_vertex) const final{ - return SlidingStateNodes[val_marker][val_vertex]; - } - - /*! - * \brief Get the outer state for fluid interface nodes. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] val_state - requested state component - * \param[in] donor_index- index of the donor node to get - */ - inline su2double GetSlidingState(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_state, - unsigned long donor_index) const final { - return SlidingState[val_marker][val_vertex][val_state][donor_index]; - } - - /*! - * \brief Compute the global error measures (L2, Linf) for verification cases. - * \param[in] geometry - Geometrical definition. - * \param[in] config - Definition of the particular problem. + * \brief Print verification error to screen. + * \param[in] config - Definition of the particular problem. */ - void ComputeVerificationError(CGeometry *geometry, CConfig *config) final; + void PrintVerificationError(const CConfig* config) const final; }; diff --git a/SU2_CFD/include/solvers/CIncNSSolver.hpp b/SU2_CFD/include/solvers/CIncNSSolver.hpp index 4f68d57f0351..f858b585966a 100644 --- a/SU2_CFD/include/solvers/CIncNSSolver.hpp +++ b/SU2_CFD/include/solvers/CIncNSSolver.hpp @@ -36,72 +36,11 @@ * \author F. Palacios, T. Economon, T. Albring */ class CIncNSSolver final : public CIncEulerSolver { -private: - su2double Viscosity_Inf; /*!< \brief Viscosity at the infinity. */ - su2double Tke_Inf; /*!< \brief Turbulent kinetic energy at the infinity. */ - su2double - *CD_Visc, /*!< \brief Drag coefficient (viscous contribution) for each boundary. */ - *CL_Visc, /*!< \brief Lift coefficient (viscous contribution) for each boundary. */ - *CSF_Visc, /*!< \brief Side force coefficient (viscous contribution) for each boundary. */ - *CMx_Visc, /*!< \brief Moment x coefficient (viscous contribution) for each boundary. */ - *CMy_Visc, /*!< \brief Moment y coefficient (viscous contribution) for each boundary. */ - *CMz_Visc, /*!< \brief Moment z coefficient (viscous contribution) for each boundary. */ - *CoPx_Visc, /*!< \brief Moment x coefficient (viscous contribution) for each boundary. */ - *CoPy_Visc, /*!< \brief Moment y coefficient (viscous contribution) for each boundary. */ - *CoPz_Visc, /*!< \brief Moment z coefficient (viscous contribution) for each boundary. */ - *CFx_Visc, /*!< \brief Force x coefficient (viscous contribution) for each boundary. */ - *CFy_Visc, /*!< \brief Force y coefficient (viscous contribution) for each boundary. */ - *CFz_Visc, /*!< \brief Force z coefficient (viscous contribution) for each boundary. */ - *Surface_CL_Visc, /*!< \brief Lift coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CD_Visc, /*!< \brief Drag coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CSF_Visc, /*!< \brief Side-force coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CEff_Visc, /*!< \brief Side-force coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CFx_Visc, /*!< \brief Force x coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CFy_Visc, /*!< \brief Force y coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CFz_Visc, /*!< \brief Force z coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CMx_Visc, /*!< \brief Moment x coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CMy_Visc, /*!< \brief Moment y coefficient (viscous contribution) for each monitoring surface. */ - *Surface_CMz_Visc, /*!< \brief Moment z coefficient (viscous contribution) for each monitoring surface. */ - *CEff_Visc, /*!< \brief Efficiency (Cl/Cd) (Viscous contribution) for each boundary. */ - *CMerit_Visc, /*!< \brief Rotor Figure of Merit (Viscous contribution) for each boundary. */ - *CT_Visc, /*!< \brief Thrust coefficient (viscous contribution) for each boundary. */ - *CQ_Visc, /*!< \brief Torque coefficient (viscous contribution) for each boundary. */ - *HF_Visc, /*!< \brief Heat load (viscous contribution) for each boundary. */ - *MaxHF_Visc, /*!< \brief Maximum heat flux (viscous contribution) for each boundary. */ - ***HeatConjugateVar, /*!< \brief Conjugate heat transfer variables for each boundary and vertex. */ - ***CSkinFriction; /*!< \brief Skin friction coefficient for each boundary and vertex. */ - su2double - *ForceViscous, /*!< \brief Viscous force for each boundary. */ - *MomentViscous; /*!< \brief Inviscid moment for each boundary. */ - su2double - AllBound_CD_Visc, /*!< \brief Drag coefficient (viscous contribution) for all the boundaries. */ - AllBound_CL_Visc, /*!< \brief Lift coefficient (viscous contribution) for all the boundaries. */ - AllBound_CSF_Visc, /*!< \brief Sideforce coefficient (viscous contribution) for all the boundaries. */ - AllBound_CMx_Visc, /*!< \brief Moment x coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMy_Visc, /*!< \brief Moment y coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMz_Visc, /*!< \brief Moment z coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPx_Visc, /*!< \brief Moment x coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPy_Visc, /*!< \brief Moment y coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CoPz_Visc, /*!< \brief Moment z coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CEff_Visc, /*!< \brief Efficient coefficient (Viscous contribution) for all the boundaries. */ - AllBound_CFx_Visc, /*!< \brief Force x coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CFy_Visc, /*!< \brief Force y coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CFz_Visc, /*!< \brief Force z coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CMerit_Visc, /*!< \brief Rotor Figure of Merit coefficient (Viscous contribution) for all the boundaries. */ - AllBound_CT_Visc, /*!< \brief Thrust coefficient (viscous contribution) for all the boundaries. */ - AllBound_CQ_Visc, /*!< \brief Torque coefficient (viscous contribution) for all the boundaries. */ - AllBound_HF_Visc, /*!< \brief Heat load (viscous contribution) for all the boundaries. */ - AllBound_MaxHF_Visc; /*!< \brief Maximum heat flux (viscous contribution) for all boundaries. */ - su2double - StrainMag_Max, - Omega_Max; /*!< \brief Maximum Strain Rate magnitude and Omega. */ - public: - /*! * \brief Constructor of the class. */ - CIncNSSolver(void); + CIncNSSolver() : CIncEulerSolver() {} /*! * \overload @@ -110,171 +49,6 @@ class CIncNSSolver final : public CIncEulerSolver { */ CIncNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh); - /*! - * \brief Destructor of the class. - */ - ~CIncNSSolver(void) override; - - /*! - * \brief Provide the non dimensional lift coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient on the surface val_marker. - */ - inline su2double GetSurface_CL_Visc(unsigned short val_marker) const override { return Surface_CL_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional drag coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient on the surface val_marker. - */ - inline su2double GetSurface_CD_Visc(unsigned short val_marker) const override { return Surface_CD_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CSF_Visc(unsigned short val_marker) const override { return Surface_CSF_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CEff_Visc(unsigned short val_marker) const override { return Surface_CEff_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional x force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFx_Visc(unsigned short val_marker) const override { return Surface_CFx_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional y force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFy_Visc(unsigned short val_marker) const override { return Surface_CFy_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional z force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFz_Visc(unsigned short val_marker) const override { return Surface_CFz_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional x moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMx_Visc(unsigned short val_marker) const override { return Surface_CMx_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional y moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMy_Visc(unsigned short val_marker) const override { return Surface_CMy_Visc[val_marker]; } - - /*! - * \brief Provide the non dimensional z moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMz_Visc(unsigned short val_marker) const override { return Surface_CMz_Visc[val_marker]; } - - /*! - * \brief Get the inviscid contribution to the lift coefficient. - * \return Value of the lift coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CL_Visc() const override { return AllBound_CL_Visc; } - - /*! - * \brief Get the inviscid contribution to the drag coefficient. - * \return Value of the drag coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CD_Visc() const override { return AllBound_CD_Visc; } - - /*! - * \brief Get the inviscid contribution to the sideforce coefficient. - * \return Value of the sideforce coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CSF_Visc() const override { return AllBound_CSF_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CEff_Visc() const override { return AllBound_CEff_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMx_Visc() const override { return AllBound_CMx_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMy_Visc() const override { return AllBound_CMy_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMz_Visc() const override { return AllBound_CMz_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPx_Visc() const override { return AllBound_CoPx_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPy_Visc() const override { return AllBound_CoPy_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPz_Visc() const override { return AllBound_CoPz_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFx_Visc() const override { return AllBound_CFx_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFy_Visc() const override { return AllBound_CFy_Visc; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFz_Visc() const override { return AllBound_CFz_Visc; } - - /*! - * \brief Compute the viscosity at the infinity. - * \return Value of the viscosity at the infinity. - */ - inline su2double GetViscosity_Inf(void) const override { return Viscosity_Inf; } - - /*! - * \brief Get the turbulent kinetic energy at the infinity. - * \return Value of the turbulent kinetic energy at the infinity. - */ - inline su2double GetTke_Inf(void) const override { return Tke_Inf; } - /*! * \brief Compute the time step for solving the Navier-Stokes equations with turbulence model. * \param[in] geometry - Geometrical definition of the problem. @@ -363,76 +137,6 @@ class CIncNSSolver final : public CIncEulerSolver { CConfig *config, unsigned short val_marker) override; - /*! - * \brief Set the conjugate heat variables. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] pos_var - variable position (in vector of all conjugate heat variables) - * \param[in] relaxation factor - relaxation factor for the change of the variables - * \param[in] val_var - value of the variable - */ - inline void SetConjugateHeatVariable(unsigned short val_marker, - unsigned long val_vertex, - unsigned short pos_var, - su2double relaxation_factor, - su2double val_var) override { - HeatConjugateVar[val_marker][val_vertex][pos_var] = relaxation_factor*val_var + (1.0-relaxation_factor)*HeatConjugateVar[val_marker][val_vertex][pos_var]; - } - - /*! - * \brief Set the conjugate heat variables. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] pos_var - variable position (in vector of all conjugate heat variables) - */ - inline su2double GetConjugateHeatVariable(unsigned short val_marker, - unsigned long val_vertex, - unsigned short pos_var) const override { - return HeatConjugateVar[val_marker][val_vertex][pos_var]; - } - - /*! - * \brief Compute the viscous forces and all the addimensional coefficients. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void Friction_Forces(CGeometry *geometry, CConfig *config) override; - - /*! - * \brief Get the total heat flux. - * \param[in] val_marker - Surface marker where the heat flux is computed. - * \return Value of the integrated heat flux (viscous contribution) on the surface val_marker. - */ - inline su2double GetSurface_HF_Visc(unsigned short val_marker) const override { return Surface_HF_Visc[val_marker]; } - - /*! - * \brief Get the maximum (per surface) heat flux. - * \param[in] val_marker - Surface marker where the heat flux is computed. - * \return Value of the maximum heat flux (viscous contribution) on the surface val_marker. - */ - inline su2double GetSurface_MaxHF_Visc(unsigned short val_marker) const override { return Surface_MaxHF_Visc[val_marker]; } - - /*! - * \brief Get the non dimensional lift coefficient (viscous contribution). - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient (viscous contribution) on the surface val_marker. - */ - inline su2double GetCL_Visc(unsigned short val_marker) const override { return CL_Visc[val_marker]; } - - /*! - * \brief Get the non dimensional sideforce coefficient (viscous contribution). - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the sideforce coefficient (viscous contribution) on the surface val_marker. - */ - inline su2double GetCSF_Visc(unsigned short val_marker) const override { return CSF_Visc[val_marker]; } - - /*! - * \brief Get the non dimensional drag coefficient (viscous contribution). - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient (viscous contribution) on the surface val_marker. - */ - inline su2double GetCD_Visc(unsigned short val_marker) const override { return CD_Visc[val_marker]; } - /*! * \brief Compute the viscous residuals. * \param[in] geometry - Geometrical definition of the problem. @@ -449,68 +153,4 @@ class CIncNSSolver final : public CIncEulerSolver { unsigned short iMesh, unsigned short iRKStep) override; - /*! - * \brief Get the skin friction coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the skin friction coefficient. - */ - inline su2double GetCSkinFriction(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_dim) const override { - return CSkinFriction[val_marker][val_dim][val_vertex]; - } - - /*! - * \brief Get the skin friction coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the heat transfer coefficient. - */ - inline su2double GetHeatFlux(unsigned short val_marker, unsigned long val_vertex) const override { - return HeatFlux[val_marker][val_vertex]; - } - - /*! - * \brief Get the skin friction coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the heat transfer coefficient. - */ - inline su2double GetHeatFluxTarget(unsigned short val_marker, unsigned long val_vertex) const override { - return HeatFluxTarget[val_marker][val_vertex]; - } - - /*! - * \brief Set the value of the target Pressure coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline void SetHeatFluxTarget(unsigned short val_marker, - unsigned long val_vertex, - su2double val_heat) override { HeatFluxTarget[val_marker][val_vertex] = val_heat; } - - /*! - * \brief Get the y plus. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the y plus. - */ - inline su2double GetYPlus(unsigned short val_marker, unsigned long val_vertex) const override { - return YPlus[val_marker][val_vertex]; - } - - /*! - * \brief Get the max Omega. - * \return Value of the max Omega. - */ - inline su2double GetOmega_Max(void) const override { return Omega_Max; } - - /*! - * \brief Get the max Strain rate magnitude. - * \return Value of the max Strain rate magnitude. - */ - inline su2double GetStrainMag_Max(void) const override { return StrainMag_Max; } - }; diff --git a/SU2_CFD/include/solvers/CNSSolver.hpp b/SU2_CFD/include/solvers/CNSSolver.hpp index bbb00b0dddb7..2c60c9ee0f83 100644 --- a/SU2_CFD/include/solvers/CNSSolver.hpp +++ b/SU2_CFD/include/solvers/CNSSolver.hpp @@ -37,29 +37,11 @@ */ class CNSSolver final : public CEulerSolver { private: - su2double Viscosity_Inf; /*!< \brief Viscosity at the infinity. */ - su2double Tke_Inf; /*!< \brief Turbulent kinetic energy at the infinity. */ - - AeroCoeffsArray ViscCoeff; /*!< \brief Viscous contributions for each boundary. */ - AeroCoeffsArray SurfaceViscCoeff; /*!< \brief Viscous contributions for each monitoring boundary. */ - AeroCoeffs AllBoundViscCoeff; /*!< \brief Total pressure contribution for all the boundaries. */ - su2double *Surface_Buffet_Metric = nullptr, /*!< \brief Integrated separation sensor for each monitoring surface. */ *Buffet_Metric = nullptr, /*!< \brief Integrated separation sensor for each boundary. */ - *HF_Visc = nullptr, /*!< \brief Heat load (viscous contribution) for each boundary. */ - *MaxHF_Visc = nullptr, /*!< \brief Maximum heat flux (viscous contribution) for each boundary. */ - ***HeatConjugateVar = nullptr, /*!< \brief Conjugate heat transfer variables for each boundary and vertex. */ - ***CSkinFriction = nullptr, /*!< \brief Skin friction coefficient for each boundary and vertex. */ **Buffet_Sensor = nullptr, /*!< \brief Separation sensor for each boundary and vertex. */ - Total_Buffet_Metric; /*!< \brief Integrated separation sensor for all the boundaries. */ - - su2double - AllBound_HF_Visc, /*!< \brief Heat load (viscous contribution) for all the boundaries. */ - AllBound_MaxHF_Visc; /*!< \brief Maximum heat flux (viscous contribution) for all boundaries. */ - su2double - StrainMag_Max, - Omega_Max; /*!< \brief Maximum Strain Rate magnitude and Omega. */ + Total_Buffet_Metric = 0.0; /*!< \brief Integrated separation sensor for all the boundaries. */ /*! * \brief A virtual member. @@ -119,7 +101,7 @@ class CNSSolver final : public CEulerSolver { /*! * \brief Constructor of the class. */ - CNSSolver(void); + CNSSolver() = default; /*! * \overload @@ -133,76 +115,6 @@ class CNSSolver final : public CEulerSolver { */ ~CNSSolver(void) override; - /*! - * \brief Provide the non dimensional lift coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient on the surface val_marker. - */ - inline su2double GetSurface_CL_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CL[val_marker]; } - - /*! - * \brief Provide the non dimensional drag coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient on the surface val_marker. - */ - inline su2double GetSurface_CD_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CD[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CSF_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CSF[val_marker]; } - - /*! - * \brief Provide the non dimensional side-force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the side-force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CEff_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CEff[val_marker]; } - - /*! - * \brief Provide the non dimensional x force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFx_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CFx[val_marker]; } - - /*! - * \brief Provide the non dimensional y force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFy_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CFy[val_marker]; } - - /*! - * \brief Provide the non dimensional z force coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z force coefficient on the surface val_marker. - */ - inline su2double GetSurface_CFz_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CFz[val_marker]; } - - /*! - * \brief Provide the non dimensional x moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the x moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMx_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CMx[val_marker]; } - - /*! - * \brief Provide the non dimensional y moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the y moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMy_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CMy[val_marker]; } - - /*! - * \brief Provide the non dimensional z moment coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the z moment coefficient on the surface val_marker. - */ - inline su2double GetSurface_CMz_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CMz[val_marker]; } - /*! * \brief Provide the buffet metric. * \param[in] val_marker - Surface marker where the coefficient is computed. @@ -210,102 +122,12 @@ class CNSSolver final : public CEulerSolver { */ inline su2double GetSurface_Buffet_Metric(unsigned short val_marker) const override { return Surface_Buffet_Metric[val_marker]; } - /*! - * \brief Get the inviscid contribution to the lift coefficient. - * \return Value of the lift coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CL_Visc() const override { return AllBoundViscCoeff.CL; } - - /*! - * \brief Get the inviscid contribution to the drag coefficient. - * \return Value of the drag coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CD_Visc() const override { return AllBoundViscCoeff.CD; } - - /*! - * \brief Get the inviscid contribution to the sideforce coefficient. - * \return Value of the sideforce coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CSF_Visc() const override { return AllBoundViscCoeff.CSF; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CEff_Visc() const override { return AllBoundViscCoeff.CEff; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMx_Visc() const override { return AllBoundViscCoeff.CMx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMy_Visc() const override { return AllBoundViscCoeff.CMy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CMz_Visc() const override { return AllBoundViscCoeff.CMz; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPx_Visc() const override { return AllBoundViscCoeff.CoPx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPy_Visc() const override { return AllBoundViscCoeff.CoPy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CoPz_Visc() const override { return AllBoundViscCoeff.CoPz; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFx_Visc() const override { return AllBoundViscCoeff.CFx; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFy_Visc() const override { return AllBoundViscCoeff.CFy; } - - /*! - * \brief Get the inviscid contribution to the efficiency coefficient. - * \return Value of the efficiency coefficient (inviscid contribution). - */ - inline su2double GetAllBound_CFz_Visc() const override { return AllBoundViscCoeff.CFz; } - /*! * \brief Get the buffet metric. * \return Value of the buffet metric. */ inline su2double GetTotal_Buffet_Metric() const override { return Total_Buffet_Metric; } - /*! - * \brief Compute the viscosity at the infinity. - * \return Value of the viscosity at the infinity. - */ - inline su2double GetViscosity_Inf(void) const override { return Viscosity_Inf; } - - /*! - * \brief Get the turbulent kinetic energy at the infinity. - * \return Value of the turbulent kinetic energy at the infinity. - */ - inline su2double GetTke_Inf(void) const override { return Tke_Inf; } - /*! * \brief Restart residual and compute gradients. * \param[in] geometry - Geometrical definition of the problem. @@ -376,41 +198,6 @@ class CNSSolver final : public CEulerSolver { CConfig *config, unsigned short val_marker) override; - /*! - * \brief Set the conjugate heat variables. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] pos_var - variable position (in vector of all conjugate heat variables) - */ - inline su2double GetConjugateHeatVariable(unsigned short val_marker, - unsigned long val_vertex, - unsigned short pos_var) const override { - return HeatConjugateVar[val_marker][val_vertex][pos_var]; - } - - /*! - * \brief Set the conjugate heat variables. - * \param[in] val_marker - marker index - * \param[in] val_vertex - vertex index - * \param[in] pos_var - variable position (in vector of all conjugate heat variables) - * \param[in] relaxation factor - relaxation factor for the change of the variables - * \param[in] val_var - value of the variable - */ - inline void SetConjugateHeatVariable(unsigned short val_marker, - unsigned long val_vertex, - unsigned short pos_var, - su2double relaxation_factor, - su2double val_var) override { - HeatConjugateVar[val_marker][val_vertex][pos_var] = relaxation_factor*val_var + (1.0-relaxation_factor)*HeatConjugateVar[val_marker][val_vertex][pos_var]; - } - - /*! - * \brief Compute the viscous forces and all the addimensional coefficients. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void Friction_Forces(CGeometry *geometry, CConfig *config) override; - /*! * \brief Compute the buffet sensor. * \param[in] geometry - Geometrical definition of the problem. @@ -418,41 +205,6 @@ class CNSSolver final : public CEulerSolver { */ void Buffet_Monitoring(CGeometry *geometry, CConfig *config) override; - /*! - * \brief Get the total heat flux. - * \param[in] val_marker - Surface marker where the heat flux is computed. - * \return Value of the integrated heat flux (viscous contribution) on the surface val_marker. - */ - inline su2double GetSurface_HF_Visc(unsigned short val_marker) const override { return Surface_HF_Visc[val_marker]; } - - /*! - * \brief Get the maximum (per surface) heat flux. - * \param[in] val_marker - Surface marker where the heat flux is computed. - * \return Value of the maximum heat flux (viscous contribution) on the surface val_marker. - */ - inline su2double GetSurface_MaxHF_Visc(unsigned short val_marker) const override { return Surface_MaxHF_Visc[val_marker]; } - - /*! - * \brief Get the non dimensional lift coefficient (viscous contribution). - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the lift coefficient (viscous contribution) on the surface val_marker. - */ - inline su2double GetCL_Visc(unsigned short val_marker) const override { return ViscCoeff.CL[val_marker]; } - - /*! - * \brief Get the non dimensional sideforce coefficient (viscous contribution). - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the sideforce coefficient (viscous contribution) on the surface val_marker. - */ - inline su2double GetCSF_Visc(unsigned short val_marker) const override { return ViscCoeff.CSF[val_marker]; } - - /*! - * \brief Get the non dimensional drag coefficient (viscous contribution). - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \return Value of the drag coefficient (viscous contribution) on the surface val_marker. - */ - inline su2double GetCD_Visc(unsigned short val_marker) const override { return ViscCoeff.CD[val_marker]; } - /*! * \brief Compute the viscous contribution for a particular edge. * \param[in] iEdge - Edge for which the flux and Jacobians are to be computed. @@ -464,48 +216,6 @@ class CNSSolver final : public CEulerSolver { void Viscous_Residual(unsigned long iEdge, CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config) override; - /*! - * \brief Get the skin friction coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the skin friction coefficient. - */ - inline su2double GetCSkinFriction(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_dim) const override { - return CSkinFriction[val_marker][val_dim][val_vertex]; - } - - /*! - * \brief Get the skin friction coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the heat transfer coefficient. - */ - inline su2double GetHeatFlux(unsigned short val_marker, unsigned long val_vertex) const override { - return HeatFlux[val_marker][val_vertex]; - } - - /*! - * \brief Get the skin friction coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the heat transfer coefficient. - */ - inline su2double GetHeatFluxTarget(unsigned short val_marker, unsigned long val_vertex) const override { - return HeatFluxTarget[val_marker][val_vertex]; - } - - /*! - * \brief Set the value of the target Pressure coefficient. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline void SetHeatFluxTarget(unsigned short val_marker, - unsigned long val_vertex, - su2double val_heat) override { HeatFluxTarget[val_marker][val_vertex] = val_heat; } - /*! * \brief Get the value of the buffet sensor * \param[in] val_marker - Surface marker where the coefficient is computed. @@ -516,28 +226,6 @@ class CNSSolver final : public CEulerSolver { return Buffet_Sensor[val_marker][val_vertex]; } - /*! - * \brief Get the y plus. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the y plus. - */ - inline su2double GetYPlus(unsigned short val_marker, unsigned long val_vertex) const override { - return YPlus[val_marker][val_vertex]; - } - - /*! - * \brief Get the max Omega. - * \return Value of the max Omega. - */ - inline su2double GetOmega_Max(void) const override { return Omega_Max; } - - /*! - * \brief Get the max Strain rate magnitude. - * \return Value of the max Strain rate magnitude. - */ - inline su2double GetStrainMag_Max(void) const override { return StrainMag_Max; } - /*! * \brief Computes the wall shear stress (Tau_Wall) on the surface using a wall function. * \param[in] geometry - Geometrical definition of the problem. diff --git a/SU2_CFD/include/solvers/CSolver.hpp b/SU2_CFD/include/solvers/CSolver.hpp index c3bf7e379c04..d22af3f9c6cc 100644 --- a/SU2_CFD/include/solvers/CSolver.hpp +++ b/SU2_CFD/include/solvers/CSolver.hpp @@ -838,13 +838,6 @@ class CSolver { unsigned short RunTime_EqSystem, bool Output) { } - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - inline virtual void Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { } - /*! * \brief A virtual member. * \param[in] geometry - Geometrical definition of the problem. @@ -1531,7 +1524,7 @@ class CSolver { * \param[in] solver - Container vector with all the solutions. * \param[in] config - Definition of the particular problem. */ - inline virtual void ComputeUnderRelaxationFactor(CSolver **solver_container, CConfig *config) { } + inline virtual void ComputeUnderRelaxationFactor(CSolver **solver_container, const CConfig *config) { } /*! * \brief Adapt the CFL number based on the local under-relaxation parameters @@ -1617,21 +1610,21 @@ class CSolver { * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - inline virtual void Pressure_Forces(CGeometry *geometry, CConfig *config) { } + inline virtual void Pressure_Forces(const CGeometry* geometry, const CConfig* config) { } /*! * \brief A virtual member. * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - inline virtual void Momentum_Forces(CGeometry *geometry, CConfig *config) { } + inline virtual void Momentum_Forces(const CGeometry* geometry, const CConfig* config) { } /*! * \brief A virtual member. * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - inline virtual void Friction_Forces(CGeometry *geometry, CConfig *config) { } + inline virtual void Friction_Forces(const CGeometry* geometry, const CConfig* config) { } /*! * \brief A virtual member. @@ -2954,72 +2947,6 @@ class CSolver { unsigned short val_var, su2double val_value) { } - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline virtual su2double *GetDonorPrimVar(unsigned short val_marker, unsigned long val_vertex) const { return nullptr; } - - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline virtual void SetDonorPrimVar(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_var, - su2double val_value) { } - - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - - inline virtual void SetDonorAdjVar(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_var, - su2double val_value) { } - - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline virtual su2double GetDonorPrimVar(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_var) const { return 0; } - - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - - inline virtual su2double *GetDonorAdjVar(unsigned short val_marker, unsigned long val_vertex) const { - return nullptr; - } - - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - - inline virtual su2double GetDonorAdjVar(unsigned short val_marker, - unsigned long val_vertex, - unsigned short val_var) const { - return 0; - } - /*! * \brief A virtual member. * \param[in] val_marker - Surface marker where the coefficient is computed. @@ -3050,42 +2977,6 @@ class CSolver { inline virtual su2double *GetCharacPrimVar(unsigned short val_marker, unsigned long val_vertex) const { return nullptr; } - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline virtual su2double GetActDisk_DeltaP(unsigned short val_marker, unsigned long val_vertex) const { return 0; } - - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline virtual void SetActDisk_DeltaP(unsigned short val_marker, - unsigned long val_vertex, - su2double val_deltap) { } - - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline virtual su2double GetActDisk_DeltaT(unsigned short val_marker, unsigned long val_vertex) { return 0; } - - /*! - * \brief A virtual member. - * \param[in] val_marker - Surface marker where the coefficient is computed. - * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. - * \return Value of the pressure coefficient. - */ - inline virtual void SetActDisk_DeltaT(unsigned short val_marker, - unsigned long val_vertex, - su2double val_deltat) { } - /*! * \brief A virtual member * \param[in] val_marker - Surface marker where the total temperature is evaluated. @@ -3162,7 +3053,7 @@ class CSolver { * \param[in] config - Definition of the particular problem. * \param[in] iMarker - Surface marker where the coefficient is computed. */ - inline virtual void SetUniformInlet(CConfig* config, unsigned short iMarker) {}; + inline virtual void SetUniformInlet(const CConfig* config, unsigned short iMarker) {}; /*! * \brief A virtual member @@ -3170,7 +3061,7 @@ class CSolver { * \param[in] iMarker - Surface marker where the coefficient is computed. * \param[in] iVertex - Vertex of the marker iMarker where the inlet is being set. */ - inline virtual void SetInletAtVertex(su2double *val_inlet, + inline virtual void SetInletAtVertex(const su2double *val_inlet, unsigned short iMarker, unsigned long iVertex) { }; @@ -3187,8 +3078,8 @@ class CSolver { unsigned long val_inlet_point, unsigned short val_kind_marker, string val_marker, - CGeometry *geometry, - CConfig *config) const { return 0; } + const CGeometry *geometry, + const CConfig *config) const { return 0; } /*! * \brief Update the multi-grid structure for the customized boundary conditions @@ -3642,7 +3533,7 @@ class CSolver { * \param[in] val_filename - String name of the restart file. */ void Read_SU2_Restart_ASCII(CGeometry *geometry, - CConfig *config, + const CConfig *config, string val_filename); /*! @@ -3652,7 +3543,7 @@ class CSolver { * \param[in] val_filename - String name of the restart file. */ void Read_SU2_Restart_Binary(CGeometry *geometry, - CConfig *config, + const CConfig *config, string val_filename); /*! @@ -4550,18 +4441,16 @@ class CSolver { /*! * \brief Initialize the vertex traction containers at the vertices. - * \param[in] geometry - Geometrical definition. - * \param[in] config - Definition of the particular problem. */ - inline void InitVertexTractionContainer(CGeometry *geometry, CConfig *config){ + inline void InitVertexTractionContainer() { unsigned long iVertex; unsigned short iMarker; VertexTraction = new su2double** [nMarker]; for (iMarker = 0; iMarker < nMarker; iMarker++) { - VertexTraction[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { + VertexTraction[iMarker] = new su2double* [nVertex[iMarker]]; + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { VertexTraction[iMarker][iVertex] = new su2double [nDim](); } } @@ -4569,18 +4458,16 @@ class CSolver { /*! * \brief Initialize the adjoint vertex traction containers at the vertices. - * \param[in] geometry - Geometrical definition. - * \param[in] config - Definition of the particular problem. */ - inline void InitVertexTractionAdjointContainer(CGeometry *geometry, CConfig *config){ + inline void InitVertexTractionAdjointContainer() { unsigned long iVertex; unsigned short iMarker; VertexTractionAdjoint = new su2double** [nMarker]; for (iMarker = 0; iMarker < nMarker; iMarker++) { - VertexTractionAdjoint[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { + VertexTractionAdjoint[iMarker] = new su2double* [nVertex[iMarker]]; + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { VertexTractionAdjoint[iMarker][iVertex] = new su2double [nDim](); } } diff --git a/SU2_CFD/include/solvers/CTurbSASolver.hpp b/SU2_CFD/include/solvers/CTurbSASolver.hpp index df4b6f4df671..bb5f316c6e6a 100644 --- a/SU2_CFD/include/solvers/CTurbSASolver.hpp +++ b/SU2_CFD/include/solvers/CTurbSASolver.hpp @@ -363,7 +363,7 @@ class CTurbSASolver final : public CTurbSolver { * \param[in] iMarker - Surface marker where the coefficient is computed. * \param[in] iVertex - Vertex of the marker iMarker where the inlet is being set. */ - void SetInletAtVertex(su2double *val_inlet, + void SetInletAtVertex(const su2double *val_inlet, unsigned short iMarker, unsigned long iVertex) override; @@ -380,8 +380,8 @@ class CTurbSASolver final : public CTurbSolver { unsigned long val_inlet_point, unsigned short val_kind_marker, string val_marker, - CGeometry *geometry, - CConfig *config) const override; + const CGeometry *geometry, + const CConfig *config) const override; /*! * \brief Set a uniform inlet profile @@ -392,7 +392,7 @@ class CTurbSASolver final : public CTurbSolver { * \param[in] config - Definition of the particular problem. * \param[in] iMarker - Surface marker where the coefficient is computed. */ - void SetUniformInlet(CConfig* config, unsigned short iMarker) override; + void SetUniformInlet(const CConfig* config, unsigned short iMarker) override; /*! * \brief Get the value of nu tilde at the far-field. diff --git a/SU2_CFD/include/solvers/CTurbSSTSolver.hpp b/SU2_CFD/include/solvers/CTurbSSTSolver.hpp index 00df2213ea6d..943feaa5d0fa 100644 --- a/SU2_CFD/include/solvers/CTurbSSTSolver.hpp +++ b/SU2_CFD/include/solvers/CTurbSSTSolver.hpp @@ -252,7 +252,7 @@ class CTurbSSTSolver final : public CTurbSolver { * \param[in] iMarker - Surface marker where the coefficient is computed. * \param[in] iVertex - Vertex of the marker iMarker where the inlet is being set. */ - void SetInletAtVertex(su2double *val_inlet, + void SetInletAtVertex(const su2double *val_inlet, unsigned short iMarker, unsigned long iVertex) override; @@ -269,8 +269,8 @@ class CTurbSSTSolver final : public CTurbSolver { unsigned long val_inlet_point, unsigned short val_kind_marker, string val_marker, - CGeometry *geometry, - CConfig *config) const override; + const CGeometry *geometry, + const CConfig *config) const override; /*! * \brief Set a uniform inlet profile * @@ -280,7 +280,7 @@ class CTurbSSTSolver final : public CTurbSolver { * \param[in] config - Definition of the particular problem. * \param[in] iMarker - Surface marker where the coefficient is computed. */ - void SetUniformInlet(CConfig* config, unsigned short iMarker) override; + void SetUniformInlet(const CConfig* config, unsigned short iMarker) override; /*! * \brief Get the value of the turbulent kinetic energy. diff --git a/SU2_CFD/include/solvers/CTurbSolver.hpp b/SU2_CFD/include/solvers/CTurbSolver.hpp index 24a386af8abd..c0894f7b784f 100644 --- a/SU2_CFD/include/solvers/CTurbSolver.hpp +++ b/SU2_CFD/include/solvers/CTurbSolver.hpp @@ -271,7 +271,7 @@ class CTurbSolver : public CSolver { * \param[in] solver - Container vector with all the solutions. * \param[in] config - Definition of the particular problem. */ - void ComputeUnderRelaxationFactor(CSolver **solver, CConfig *config) final; + void ComputeUnderRelaxationFactor(CSolver **solver, const CConfig *config) final; /*! * \brief Load a solution from a restart file. diff --git a/SU2_CFD/src/drivers/CDriver.cpp b/SU2_CFD/src/drivers/CDriver.cpp index c4b6cf4eff67..ac4888b359c8 100644 --- a/SU2_CFD/src/drivers/CDriver.cpp +++ b/SU2_CFD/src/drivers/CDriver.cpp @@ -2924,7 +2924,7 @@ void CFluidDriver::Run() { /*--- Begin Unsteady pseudo-time stepping internal loop, if not unsteady it does only one step --*/ if (unsteady) - nIntIter = config_container[MESH_0]->GetUnst_nIntIter(); + nIntIter = config_container[MESH_0]->GetnInner_Iter(); else nIntIter = 1; diff --git a/SU2_CFD/src/output/output_structure_legacy.cpp b/SU2_CFD/src/output/output_structure_legacy.cpp index 136b3b3cd499..79b017e0e75e 100644 --- a/SU2_CFD/src/output/output_structure_legacy.cpp +++ b/SU2_CFD/src/output/output_structure_legacy.cpp @@ -8708,7 +8708,7 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, Force[3], ForceInviscid[3], MomentInviscid[3] = { 0.0, 0.0, 0.0 }, MomentDist[3] = { 0.0, 0.0, 0.0 }, RefDensity, RefPressure, RefArea, *Velocity_Inf, Gas_Constant, Mach2Vel, - Mach_Motion, Gamma, RefVel2 = 0.0, factor, NDPressure, *Origin, + Mach_Motion, Gamma, RefVel2 = 0.0, factor, NDPressure, RefLength, Alpha, CL_Inv, Xcoord_LeadingEdge = 0.0, Ycoord_LeadingEdge = 0.0, Zcoord_LeadingEdge = 0.0, Xcoord_TrailingEdge = 0.0, Ycoord_TrailingEdge = 0.0, Zcoord_TrailingEdge = 0.0, @@ -8745,7 +8745,7 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, RefArea = config->GetRefArea(); Velocity_Inf = solver->GetVelocity_Inf(); Gamma = config->GetGamma(); - Origin = config->GetRefOriginMoment(0); + const auto Origin = config->GetRefOriginMoment(0); RefLength = config->GetRefLength(); Alpha = config->GetAoA() * PI_NUMBER / 180.0; diff --git a/SU2_CFD/src/solvers/CAdjEulerSolver.cpp b/SU2_CFD/src/solvers/CAdjEulerSolver.cpp index 49855a15cf9a..5e581ff4b7ae 100644 --- a/SU2_CFD/src/solvers/CAdjEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CAdjEulerSolver.cpp @@ -1036,7 +1036,7 @@ void CAdjEulerSolver::SetForceProj_Vector(CGeometry *geometry, CSolver **solver_ su2double Alpha = (config->GetAoA()*PI_NUMBER)/180.0; su2double Beta = (config->GetAoS()*PI_NUMBER)/180.0; su2double RefLength = config->GetRefLength(); - su2double *RefOriginMoment = config->GetRefOriginMoment(0); + const auto RefOriginMoment = config->GetRefOriginMoment(0); su2double dCD_dCL = config->GetdCD_dCL(); su2double dCMx_dCL = config->GetdCMx_dCL(); su2double dCMy_dCL = config->GetdCMy_dCL(); diff --git a/SU2_CFD/src/solvers/CEulerSolver.cpp b/SU2_CFD/src/solvers/CEulerSolver.cpp index ce5b2eb59b3f..bf658cc059fc 100644 --- a/SU2_CFD/src/solvers/CEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CEulerSolver.cpp @@ -25,45 +25,18 @@ * License along with SU2. If not, see . */ - #include "../../include/solvers/CEulerSolver.hpp" #include "../../include/variables/CNSVariable.hpp" #include "../../../Common/include/toolboxes/geometry_toolbox.hpp" #include "../../../Common/include/toolboxes/printing_toolbox.hpp" -#include "../../include/gradients/computeGradientsGreenGauss.hpp" -#include "../../include/gradients/computeGradientsLeastSquares.hpp" -#include "../../include/limiters/computeLimiters.hpp" #include "../../include/fluid/CIdealGas.hpp" #include "../../include/fluid/CVanDerWaalsGas.hpp" #include "../../include/fluid/CPengRobinson.hpp" -void CEulerSolver::AeroCoeffsArray::allocate(int size) { - _size = size; - CD = new su2double[size]; CL = new su2double[size]; CSF = new su2double[size]; CEff = new su2double[size]; - CFx = new su2double[size]; CFy = new su2double[size]; CFz = new su2double[size]; CMx = new su2double[size]; - CMy = new su2double[size]; CMz = new su2double[size]; CoPx = new su2double[size]; CoPy = new su2double[size]; - CoPz = new su2double[size]; CT = new su2double[size]; CQ = new su2double[size]; CMerit = new su2double[size]; - setZero(); -} - -CEulerSolver::AeroCoeffsArray::~AeroCoeffsArray() { - delete [] CD; delete [] CL; delete [] CSF; delete [] CEff; - delete [] CFx; delete [] CFy; delete [] CFz; delete [] CMx; - delete [] CMy; delete [] CMz; delete [] CoPx; delete [] CoPy; - delete [] CoPz; delete [] CT; delete [] CQ; delete [] CMerit; -} - -void CEulerSolver::AeroCoeffsArray::setZero(int i) { - CD[i] = CL[i] = CSF[i] = CEff[i] = 0.0; - CFx[i] = CFy[i] = CFz[i] = CMx[i] = 0.0; - CMy[i] = CMz[i] = CoPx[i] = CoPy[i] = 0.0; - CoPz[i] = CT[i] = CQ[i] = CMerit[i] = 0.0; -} - -CEulerSolver::CEulerSolver(void) : CSolver() { } CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, - unsigned short iMesh, const bool navier_stokes) : CSolver() { + unsigned short iMesh, const bool navier_stokes) : + CFVMFlowSolverBase() { /*--- Based on the navier_stokes boolean, determine if this constructor is * being called by itself, or by its derived class CNSSolver. ---*/ @@ -79,7 +52,7 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, } unsigned long iPoint, counter_local = 0, counter_global = 0; - unsigned short iVar, iDim, iMarker, nLineLets; + unsigned short iDim, iMarker, nLineLets; su2double StaticEnergy, Density, Velocity2, Pressure, Temperature; unsigned short nZone = geometry->GetnZone(); bool restart = (config->GetRestart() || config->GetRestart_Flow()); @@ -171,83 +144,13 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, SetVerificationSolution(nDim, nVar, config); - /*--- Define some auxiliar vector related with the residual ---*/ - - Residual_RMS = new su2double[nVar](); - Residual_Max = new su2double[nVar](); - - /*--- Define some structures for locating max residuals ---*/ - - Point_Max = new unsigned long[nVar](); - Point_Max_Coord = new su2double*[nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - Point_Max_Coord[iVar] = new su2double[nDim](); - } - - /*--- Define some auxiliar vector related with the undivided lapalacian computation ---*/ - - if (config->GetKind_ConvNumScheme_Flow() == SPACE_CENTERED) { - iPoint_UndLapl = new su2double [nPoint]; - jPoint_UndLapl = new su2double [nPoint]; - } - - /*--- Initialize the solution and right hand side vectors for storing - the residuals and updating the solution (always needed even for - explicit schemes). ---*/ - - LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0); - LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0); + /*--- Allocate base class members. ---*/ -#ifdef HAVE_OMP - /*--- Get the edge coloring. If the expected parallel efficiency becomes too low setup the - * reducer strategy. Where one loop is performed over edges followed by a point loop to - * sum the fluxes for each cell and set the diagonal of the system matrix. ---*/ + Allocate(*config); - su2double parallelEff = 1.0; - const auto& coloring = geometry->GetEdgeColoring(¶llelEff); + /*--- MPI + OpenMP initialization. ---*/ - /*--- The decision to use the strategy is local to each rank. ---*/ - ReducerStrategy = parallelEff < COLORING_EFF_THRESH; - - /*--- When using the reducer force a single color to reduce the color loop overhead. ---*/ - if (ReducerStrategy && (coloring.getOuterSize()>1)) - geometry->SetNaturalEdgeColoring(); - - if (!coloring.empty()) { - /*--- If the reducer strategy is used we are not constrained by group - * size as we have no other edge loops in the Euler/NS solvers. ---*/ - auto groupSize = ReducerStrategy? 1ul : geometry->GetEdgeColorGroupSize(); - auto nColor = coloring.getOuterSize(); - EdgeColoring.reserve(nColor); - - for(auto iColor = 0ul; iColor < nColor; ++iColor) - EdgeColoring.emplace_back(coloring.innerIdx(iColor), coloring.getNumNonZeros(iColor), groupSize); - } - - /*--- If the reducer strategy is not being forced (by EDGE_COLORING_GROUP_SIZE=0) print some messages. ---*/ - if (config->GetEdgeColoringGroupSize() != 1<<30) { - - su2double minEff = 1.0; - SU2_MPI::Reduce(¶llelEff, &minEff, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, MPI_COMM_WORLD); - - int tmp = ReducerStrategy, numRanksUsingReducer = 0; - SU2_MPI::Reduce(&tmp, &numRanksUsingReducer, 1, MPI_INT, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD); - - if (minEff < COLORING_EFF_THRESH) { - cout << "WARNING: On " << numRanksUsingReducer << " MPI ranks the coloring efficiency was less than " - << COLORING_EFF_THRESH << " (min value was " << minEff << ").\n" - << " Those ranks will now use a fallback strategy, better performance may be possible\n" - << " with a different value of config option EDGE_COLORING_GROUP_SIZE (default 512)." << endl; - } - } - - if (ReducerStrategy) - EdgeFluxes.Initialize(geometry->GetnEdge(), geometry->GetnEdge(), nVar, nullptr); - - omp_chunk_size = computeStaticChunkSize(nPoint, omp_get_max_threads(), OMP_MAX_SIZE); -#else - EdgeColoring[0] = DummyGridColor<>(geometry->GetnEdge()); -#endif + HybridParallelInitialization(*config, *geometry); /*--- Jacobians and vector structures for implicit computations ---*/ @@ -263,9 +166,7 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, if (rank == MASTER_NODE) cout << "Compute linelet structure. " << nLineLets << " elements in each line (average)." << endl; } - } - else { if (rank == MASTER_NODE) cout << "Explicit scheme. No Jacobian structure (" << description << "). MG level: " << iMesh <<"." << endl; @@ -290,10 +191,6 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, } }; - /*--- Store the value of the characteristic primitive variables at the boundaries ---*/ - - Alloc3D(nMarker, nVertex, nPrimVar, CharacPrimVar); - /*--- Store the value of the primitive variables + 2 turb variables at the boundaries, used for IO with a donor cell ---*/ @@ -329,56 +226,30 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, Alloc2D(nMarker, nVertex, ActDisk_DeltaT); - /*--- Store the value of the Total Pressure at the inlet BC ---*/ - - Alloc2D(nMarker, nVertex, Inlet_Ttotal); - - /*--- Store the value of the Total Temperature at the inlet BC ---*/ - - Alloc2D(nMarker, nVertex, Inlet_Ptotal); - - /*--- Store the value of the Flow direction at the inlet BC ---*/ - - Alloc3D(nMarker, nVertex, nDim, Inlet_FlowDir); - - /*--- Force definition and coefficient arrays for all of the markers ---*/ - - Alloc2D(nMarker, nVertex, CPressure); - Alloc2D(nMarker, nVertex, CPressureTarget); - - /*--- Non dimensional aerodynamic coefficients ---*/ - - InvCoeff.allocate(nMarker); - MntCoeff.allocate(nMarker); - SurfaceInvCoeff.allocate(config->GetnMarker_Monitoring()); - SurfaceMntCoeff.allocate(config->GetnMarker_Monitoring()); - SurfaceCoeff.allocate(config->GetnMarker_Monitoring()); - /*--- Supersonic coefficients ---*/ - CEquivArea_Inv = new su2double[nMarker]; - CNearFieldOF_Inv = new su2double[nMarker]; + CEquivArea_Inv = new su2double[nMarker]; /*--- Engine simulation ---*/ - Inflow_MassFlow = new su2double[nMarker]; - Inflow_Pressure = new su2double[nMarker]; - Inflow_Mach = new su2double[nMarker]; - Inflow_Area = new su2double[nMarker]; + Inflow_MassFlow = new su2double[nMarker]; + Inflow_Pressure = new su2double[nMarker]; + Inflow_Mach = new su2double[nMarker]; + Inflow_Area = new su2double[nMarker]; - Exhaust_MassFlow = new su2double[nMarker]; - Exhaust_Pressure = new su2double[nMarker]; Exhaust_Temperature = new su2double[nMarker]; - Exhaust_Area = new su2double[nMarker]; + Exhaust_MassFlow = new su2double[nMarker]; + Exhaust_Pressure = new su2double[nMarker]; + Exhaust_Area = new su2double[nMarker]; /*--- Read farfield conditions from config ---*/ - Density_Inf = config->GetDensity_FreeStreamND(); - Pressure_Inf = config->GetPressure_FreeStreamND(); - Velocity_Inf = config->GetVelocity_FreeStreamND(); - Energy_Inf = config->GetEnergy_FreeStreamND(); Temperature_Inf = config->GetTemperature_FreeStreamND(); - Mach_Inf = config->GetMach(); + Velocity_Inf = config->GetVelocity_FreeStreamND(); + Pressure_Inf = config->GetPressure_FreeStreamND(); + Density_Inf = config->GetDensity_FreeStreamND(); + Energy_Inf = config->GetEnergy_FreeStreamND(); + Mach_Inf = config->GetMach(); /*--- Initialize the secondary values for direct derivative approxiations ---*/ @@ -418,34 +289,6 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, Exhaust_Area[iMarker] = 0.0; } - /*--- Initializate quantities for SlidingMesh Interface ---*/ - - SlidingState = new su2double*** [nMarker](); - SlidingStateNodes = new int* [nMarker](); - - for (iMarker = 0; iMarker < nMarker; iMarker++) { - - if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) { - - SlidingState[iMarker] = new su2double**[geometry->GetnVertex(iMarker)](); - SlidingStateNodes[iMarker] = new int [geometry->GetnVertex(iMarker)](); - - for (iPoint = 0; iPoint < geometry->GetnVertex(iMarker); iPoint++) - SlidingState[iMarker][iPoint] = new su2double*[nPrimVar+1](); - } - } - - /*--- Only initialize when there is a Marker_Fluid_Load defined - *--- (this avoids overhead in all other cases while a more permanent structure is being developed) ---*/ - if((config->GetnMarker_Fluid_Load() > 0) && (MGLevel == MESH_0)){ - - InitVertexTractionContainer(geometry, config); - - if (config->GetDiscrete_Adjoint()) - InitVertexTractionAdjointContainer(geometry, config); - - } - /*--- Initialize the solution to the far-field state everywhere. ---*/ if (navier_stokes) { @@ -498,52 +341,9 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, cout << "Warning. The original solution contains " << counter_global << " points that are not physical." << endl; } - /*--- Initialize the BGS residuals in FSI problems. ---*/ - if (config->GetMultizone_Residual()){ - Residual_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_BGS[iVar] = 1.0; - Residual_Max_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max_BGS[iVar] = 1.0; - - /*--- Define some structures for locating max residuals ---*/ - - Point_Max_BGS = new unsigned long[nVar](); - Point_Max_Coord_BGS = new su2double*[nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - Point_Max_Coord_BGS[iVar] = new su2double[nDim](); - } - } - - /*--- Define solver parameters needed for execution of destructor ---*/ - - space_centered = (config->GetKind_ConvNumScheme_Flow() == SPACE_CENTERED); - euler_implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - least_squares = (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES); - - /*--- Communicate and store volume and the number of neighbors for - any dual CVs that lie on on periodic markers. ---*/ - - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME); - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS); - } - SetImplicitPeriodic(euler_implicit); - if (iMesh == MESH_0) SetRotatePeriodic(true); - - /*--- Perform the MPI communication of the solution ---*/ - - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); - - /* Store the initial CFL number for all grid points. */ + /*--- Initial comms. ---*/ - const su2double CFL = config->GetCFL(MGLevel); - for (iPoint = 0; iPoint < nPoint; iPoint++) { - nodes->SetLocalCFL(iPoint, CFL); - } - Min_CFL_Local = CFL; - Max_CFL_Local = CFL; - Avg_CFL_Local = CFL; + CommunicateInitialState(geometry, config); /*--- Add the solver name (max 8 characters) ---*/ SolverName = "C.FLOW"; @@ -556,14 +356,12 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, CEulerSolver::~CEulerSolver(void) { - unsigned short iVar, iMarker, iSpan; - + unsigned short iMarker, iSpan; unsigned long iVertex; /*--- Array deallocation ---*/ delete [] CEquivArea_Inv; - delete [] CNearFieldOF_Inv; delete [] Inflow_MassFlow; delete [] Exhaust_MassFlow; @@ -575,50 +373,6 @@ CEulerSolver::~CEulerSolver(void) { delete [] Exhaust_Pressure; delete [] Exhaust_Temperature; - if (CPressure != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) - delete [] CPressure[iMarker]; - delete [] CPressure; - } - - if (CPressureTarget != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) - delete [] CPressureTarget[iMarker]; - delete [] CPressureTarget; - } - - if (CharacPrimVar != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) - delete [] CharacPrimVar[iMarker][iVertex]; - delete [] CharacPrimVar[iMarker]; - } - delete [] CharacPrimVar; - } - - if (SlidingState != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - if ( SlidingState[iMarker] != nullptr ) { - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) - if ( SlidingState[iMarker][iVertex] != nullptr ){ - for (iVar = 0; iVar < nPrimVar+1; iVar++) - delete [] SlidingState[iMarker][iVertex][iVar]; - delete [] SlidingState[iMarker][iVertex]; - } - delete [] SlidingState[iMarker]; - } - } - delete [] SlidingState; - } - - if ( SlidingStateNodes != nullptr ){ - for (iMarker = 0; iMarker < nMarker; iMarker++){ - if (SlidingStateNodes[iMarker] != nullptr) - delete [] SlidingStateNodes[iMarker]; - } - delete [] SlidingStateNodes; - } - if (DonorPrimVar != nullptr) { for (iMarker = 0; iMarker < nMarker; iMarker++) { for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) @@ -670,52 +424,6 @@ CEulerSolver::~CEulerSolver(void) { delete [] ActDisk_DeltaT; } - if (Inlet_Ttotal != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) - if (Inlet_Ttotal[iMarker] != nullptr) - delete [] Inlet_Ttotal[iMarker]; - delete [] Inlet_Ttotal; - } - - if (Inlet_Ptotal != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) - if (Inlet_Ptotal[iMarker] != nullptr) - delete [] Inlet_Ptotal[iMarker]; - delete [] Inlet_Ptotal; - } - - if (Inlet_FlowDir != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - if (Inlet_FlowDir[iMarker] != nullptr) { - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) - delete [] Inlet_FlowDir[iMarker][iVertex]; - delete [] Inlet_FlowDir[iMarker]; - } - } - delete [] Inlet_FlowDir; - } - - if (HeatFlux != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - delete [] HeatFlux[iMarker]; - } - delete [] HeatFlux; - } - - if (HeatFluxTarget != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - delete [] HeatFluxTarget[iMarker]; - } - delete [] HeatFluxTarget; - } - - if (YPlus != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - delete [] YPlus[iMarker]; - } - delete [] YPlus; - } - for(auto& model : FluidModel) delete model; if(AverageVelocity !=nullptr){ @@ -957,7 +665,6 @@ CEulerSolver::~CEulerSolver(void) { delete [] CkOutflow2; } - delete nodes; } void CEulerSolver::InitTurboContainers(CGeometry *geometry, CConfig *config){ @@ -1337,7 +1044,7 @@ void CEulerSolver::Set_MPI_ActDisk(CSolver **solver_container, CGeometry *geomet iMarker = Buffer_Receive_Data[iPoint*(3)+(2)]; for (iVar = 0; iVar < nPrimVar_; iVar++) - SetDonorPrimVar(iMarker, iVertex, iVar, iPrimVar[iVar]); + DonorPrimVar[iMarker][iVertex][iVar] = iPrimVar[iVar]; SetDonorGlobalIndex(iMarker, iVertex, iGlobal); @@ -1401,7 +1108,7 @@ void CEulerSolver::Set_MPI_ActDisk(CSolver **solver_container, CGeometry *geomet iPrimVar[iVar] = Buffer_Receive_PrimVar[iPoint*(nPrimVar_)+iVar]; for (iVar = 0; iVar < nPrimVar_; iVar++) { - SetDonorPrimVar(iMarker, iVertex, iVar, iPrimVar[iVar]); + DonorPrimVar[iMarker][iVertex][iVar] = iPrimVar[iVar]; } SetDonorGlobalIndex(iMarker, iVertex, iGlobal); @@ -1658,7 +1365,7 @@ void CEulerSolver::Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { if (iVertex > geometry->nVertex[iMarker]) cout << "ERROR" << endl; for (iVar = 0; iVar < nPrimVar; iVar++) - SetDonorPrimVar(iMarker, iVertex, iVar, iPrimVar[iVar]); + DonorPrimVar[iMarker][iVertex][iVar] = iPrimVar[iVar]; SetDonorGlobalIndex(iMarker, iVertex, iGlobal); @@ -1722,7 +1429,7 @@ void CEulerSolver::Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { if (iVertex > geometry->nVertex[iMarker]) cout << "ERROR" << endl; for (iVar = 0; iVar < nPrimVar; iVar++) - SetDonorPrimVar(iMarker, iVertex, iVar, iPrimVar[iVar]); + DonorPrimVar[iMarker][iVertex][iVar] = iPrimVar[iVar]; SetDonorGlobalIndex(iMarker, iVertex, iGlobal); @@ -2481,38 +2188,7 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c calculations with dual time-stepping (load additional restarts for 2nd-order). ---*/ if (dual_time && ((TimeIter == 0) || (restart && (TimeIter == config->GetRestart_Iter()))) ) { - - /*--- Push back the initial condition to previous solution containers - for a 1st-order restart or when simply intitializing to freestream. ---*/ - - for (unsigned short iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { - solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n(); - solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n1(); - if (rans) { - solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n(); - solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n1(); - } - } - - if (restart && (TimeIter == config->GetRestart_Iter()) && (config->GetTime_Marching() == DT_STEPPING_2ND)) { - - /*--- Load an additional restart file for a 2nd-order restart ---*/ - - solver_container[MESH_0][FLOW_SOL]->LoadRestart(geometry, solver_container, config, config->GetRestart_Iter()-1, true); - - /*--- Load an additional restart file for the turbulence model ---*/ - if (rans) - solver_container[MESH_0][TURB_SOL]->LoadRestart(geometry, solver_container, config, config->GetRestart_Iter()-1, false); - - /*--- Push back this new solution to time level N. ---*/ - - for (unsigned short iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { - solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n(); - if (rans) { - solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n(); - } - } - } + PushSolutionBackInTime(TimeIter, restart, rans, solver_container, geometry, config); } } // end SU2_OMP_PARALLEL @@ -3782,807 +3458,142 @@ void CEulerSolver::SetUpwind_Ducros_Sensor(CGeometry *geometry, CConfig *config) } -void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { - - unsigned long iVertex, iPoint; - unsigned short iDim, iMarker, Boundary, Monitoring, iMarker_Monitoring; - su2double Pressure = 0.0, factor, NFPressOF, RefVel2, - RefTemp, RefDensity, RefPressure, Mach2Vel, Mach_Motion; - const su2double *Normal = nullptr, *Coord = nullptr; - string Marker_Tag, Monitoring_Tag; - su2double AxiFactor; - - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - su2double RefArea = config->GetRefArea(); - su2double RefLength = config->GetRefLength(); - su2double Gas_Constant = config->GetGas_ConstantND(); - const su2double *Origin = nullptr; - if (config->GetnMarker_Monitoring() != 0){ - Origin = config->GetRefOriginMoment(0); - } - bool axisymmetric = config->GetAxisymmetric(); - - /*--- Evaluate reference values for non-dimensionalization. - For dynamic meshes, use the motion Mach number as a reference value - for computing the force coefficients. Otherwise, use the freestream - values, which is the standard convention. ---*/ +template +void CEulerSolver::Explicit_Iteration(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iRKStep) { - RefTemp = Temperature_Inf; - RefDensity = Density_Inf; - RefPressure = Pressure_Inf; - if (dynamic_grid) { - Mach2Vel = sqrt(Gamma*Gas_Constant*RefTemp); - Mach_Motion = config->GetMach_Motion(); - RefVel2 = (Mach_Motion*Mach2Vel)*(Mach_Motion*Mach2Vel); - } - else { - RefVel2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - RefVel2 += Velocity_Inf[iDim]*Velocity_Inf[iDim]; - } + static_assert(IntegrationType == CLASSICAL_RK4_EXPLICIT || + IntegrationType == RUNGE_KUTTA_EXPLICIT || + IntegrationType == EULER_EXPLICIT, ""); - factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2); + const bool adjoint = config->GetContinuous_Adjoint(); - /*-- Variables initialization ---*/ + const su2double RK_AlphaCoeff = config->Get_Alpha_RKStep(iRKStep); - TotalCoeff.setZero(); + /*--- Hard-coded classical RK4 coefficients. Will be added to config. ---*/ + const su2double RK_FuncCoeff[] = {1.0/6.0, 1.0/3.0, 1.0/3.0, 1.0/6.0}; + const su2double RK_TimeCoeff[] = {0.5, 0.5, 1.0, 1.0}; - Total_CNearFieldOF = 0.0; Total_Heat = 0.0; Total_MaxHeat = 0.0; + /*--- Set shared residual variables to 0 and declare + * local ones for current thread to work on. ---*/ - AllBoundInvCoeff.setZero(); + SU2_OMP_MASTER + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + SetRes_RMS(iVar, 0.0); + SetRes_Max(iVar, 0.0, 0); + } + SU2_OMP_BARRIER - AllBound_CNearFieldOF_Inv = 0.0; + su2double resMax[MAXNVAR] = {0.0}, resRMS[MAXNVAR] = {0.0}; + const su2double* coordMax[MAXNVAR] = {nullptr}; + unsigned long idxMax[MAXNVAR] = {0}; - SurfaceInvCoeff.setZero(); - SurfaceCoeff.setZero(); + /*--- Update the solution and residuals ---*/ - /*--- Loop over the Euler and Navier-Stokes markers ---*/ + SU2_OMP(for schedule(static,omp_chunk_size) nowait) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { + su2double Vol = geometry->nodes->GetVolume(iPoint) + geometry->nodes->GetPeriodicVolume(iPoint); + su2double Delta = nodes->GetDelta_Time(iPoint) / Vol; - Boundary = config->GetMarker_All_KindBC(iMarker); - Monitoring = config->GetMarker_All_Monitoring(iMarker); + const su2double* Res_TruncError = nodes->GetResTruncError(iPoint); + const su2double* Residual = LinSysRes.GetBlock(iPoint); - /*--- Obtain the origin for the moment computation for a particular marker ---*/ + if (!adjoint) { + for (unsigned short iVar = 0; iVar < nVar; iVar++) { - if (Monitoring == YES) { - 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); - if (Marker_Tag == Monitoring_Tag) - Origin = config->GetRefOriginMoment(iMarker_Monitoring); - } - } + su2double Res = Residual[iVar] + Res_TruncError[iVar]; - if ((Boundary == EULER_WALL) || (Boundary == HEAT_FLUX) || - (Boundary == ISOTHERMAL) || (Boundary == NEARFIELD_BOUNDARY) || - (Boundary == CHT_WALL_INTERFACE) || - (Boundary == INLET_FLOW) || (Boundary == OUTLET_FLOW) || - (Boundary == ACTDISK_INLET) || (Boundary == ACTDISK_OUTLET)|| - (Boundary == ENGINE_INFLOW) || (Boundary == ENGINE_EXHAUST)) { + /*--- "Static" switch which should be optimized at compile time. ---*/ + switch(IntegrationType) { - /*--- Forces initialization at each Marker ---*/ + case EULER_EXPLICIT: + nodes->AddSolution(iPoint,iVar, -Res*Delta); + break; - InvCoeff.setZero(iMarker); + case RUNGE_KUTTA_EXPLICIT: + nodes->AddSolution(iPoint, iVar, -Res*Delta*RK_AlphaCoeff); + break; - CNearFieldOF_Inv[iMarker] = 0.0; + case CLASSICAL_RK4_EXPLICIT: + { + su2double tmp_time = -1.0*RK_TimeCoeff[iRKStep]*Delta; + su2double tmp_func = -1.0*RK_FuncCoeff[iRKStep]*Delta; - su2double ForceInviscid[MAXNDIM] = {0.0}, MomentInviscid[MAXNDIM] = {0.0}; - su2double MomentX_Force[MAXNDIM] = {0.0}, MomentY_Force[MAXNDIM] = {0.0}, MomentZ_Force[MAXNDIM] = {0.0}; + if (iRKStep < 3) { + /* Base Solution Update */ + nodes->AddSolution(iPoint,iVar, tmp_time*Res); - NFPressOF = 0.0; + /* New Solution Update */ + nodes->AddSolution_New(iPoint,iVar, tmp_func*Res); + } else { + nodes->SetSolution(iPoint, iVar, nodes->GetSolution_New(iPoint, iVar) + tmp_func*Res); + } + } + break; + } - /*--- Loop over the vertices to compute the forces ---*/ + /*--- Update residual information for current thread. ---*/ + resRMS[iVar] += Res*Res; + if (fabs(Res) > resMax[iVar]) { + resMax[iVar] = fabs(Res); + idxMax[iVar] = iPoint; + coordMax[iVar] = geometry->nodes->GetCoord(iPoint); + } + } + } + } + if (!adjoint) { + /*--- Reduce residual information over all threads in this rank. ---*/ + SU2_OMP_CRITICAL + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + AddRes_RMS(iVar, resRMS[iVar]); + AddRes_Max(iVar, resMax[iVar], geometry->nodes->GetGlobalIndex(idxMax[iVar]), coordMax[iVar]); + } + } + SU2_OMP_BARRIER - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { + /*--- MPI solution ---*/ - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + InitiateComms(geometry, config, SOLUTION); + CompleteComms(geometry, config, SOLUTION); - Pressure = nodes->GetPressure(iPoint); + SU2_OMP_MASTER + { + /*--- Compute the root mean square residual ---*/ - CPressure[iMarker][iVertex] = (Pressure - RefPressure)*factor*RefArea; + SetResidual_RMS(geometry, config); - /*--- Note that the pressure coefficient is computed at the - halo cells (for visualization purposes), but not the forces ---*/ + /*--- For verification cases, compute the global error metrics. ---*/ - if ( (geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES) ) { + ComputeVerificationError(geometry, config); + } + SU2_OMP_BARRIER - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - Coord = geometry->nodes->GetCoord(iPoint); +} - /*--- Quadratic objective function for the near-field. - This uses the infinity pressure regardless of Mach number. ---*/ +void CEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iRKStep) { - NFPressOF += 0.5*(Pressure - Pressure_Inf)*(Pressure - Pressure_Inf)*Normal[nDim-1]; + Explicit_Iteration(geometry, solver_container, config, iRKStep); +} - su2double MomentDist[MAXNDIM] = {0.0}; - for (iDim = 0; iDim < nDim; iDim++) { - MomentDist[iDim] = Coord[iDim] - Origin[iDim]; - } +void CEulerSolver::ClassicalRK4_Iteration(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iRKStep) { - /*--- Axisymmetric simulations ---*/ + Explicit_Iteration(geometry, solver_container, config, iRKStep); +} - if (axisymmetric) AxiFactor = 2.0*PI_NUMBER*geometry->nodes->GetCoord(iPoint, 1); - else AxiFactor = 1.0; +void CEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - /*--- Force computation, note the minus sign due to the - orientation of the normal (outward) ---*/ + Explicit_Iteration(geometry, solver_container, config, 0); +} - su2double Force[MAXNDIM] = {0.0}; - for (iDim = 0; iDim < nDim; iDim++) { - Force[iDim] = -(Pressure - Pressure_Inf) * Normal[iDim] * factor * AxiFactor; - ForceInviscid[iDim] += Force[iDim]; - } +void CEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - /*--- Moment with respect to the reference axis ---*/ - - if (nDim == 3) { - MomentInviscid[0] += (Force[2]*MomentDist[1]-Force[1]*MomentDist[2])/RefLength; - MomentX_Force[1] += (-Force[1]*Coord[2]); - MomentX_Force[2] += (Force[2]*Coord[1]); - - MomentInviscid[1] += (Force[0]*MomentDist[2]-Force[2]*MomentDist[0])/RefLength; - MomentY_Force[2] += (-Force[2]*Coord[0]); - MomentY_Force[0] += (Force[0]*Coord[2]); - } - MomentInviscid[2] += (Force[1]*MomentDist[0]-Force[0]*MomentDist[1])/RefLength; - MomentZ_Force[0] += (-Force[0]*Coord[1]); - MomentZ_Force[1] += (Force[1]*Coord[0]); - } - - } - - /*--- Project forces and store the non-dimensional coefficients ---*/ - - if (Monitoring == YES) { - - if (Boundary != NEARFIELD_BOUNDARY) { - if (nDim == 2) { - InvCoeff.CD[iMarker] = ForceInviscid[0]*cos(Alpha) + ForceInviscid[1]*sin(Alpha); - InvCoeff.CL[iMarker] = -ForceInviscid[0]*sin(Alpha) + ForceInviscid[1]*cos(Alpha); - InvCoeff.CEff[iMarker] = InvCoeff.CL[iMarker] / (InvCoeff.CD[iMarker]+EPS); - InvCoeff.CMz[iMarker] = MomentInviscid[2]; - InvCoeff.CoPx[iMarker] = MomentZ_Force[1]; - InvCoeff.CoPy[iMarker] = -MomentZ_Force[0]; - InvCoeff.CFx[iMarker] = ForceInviscid[0]; - InvCoeff.CFy[iMarker] = ForceInviscid[1]; - InvCoeff.CT[iMarker] = -InvCoeff.CFx[iMarker]; - InvCoeff.CQ[iMarker] = -InvCoeff.CMz[iMarker]; - InvCoeff.CMerit[iMarker] = InvCoeff.CT[iMarker] / (InvCoeff.CQ[iMarker] + EPS); - } - if (nDim == 3) { - InvCoeff.CD[iMarker] = ForceInviscid[0]*cos(Alpha)*cos(Beta) + ForceInviscid[1]*sin(Beta) + ForceInviscid[2]*sin(Alpha)*cos(Beta); - InvCoeff.CL[iMarker] = -ForceInviscid[0]*sin(Alpha) + ForceInviscid[2]*cos(Alpha); - InvCoeff.CSF[iMarker] = -ForceInviscid[0]*sin(Beta)*cos(Alpha) + ForceInviscid[1]*cos(Beta) - ForceInviscid[2]*sin(Beta)*sin(Alpha); - InvCoeff.CEff[iMarker] = InvCoeff.CL[iMarker] / (InvCoeff.CD[iMarker] + EPS); - InvCoeff.CMx[iMarker] = MomentInviscid[0]; - InvCoeff.CMy[iMarker] = MomentInviscid[1]; - InvCoeff.CMz[iMarker] = MomentInviscid[2]; - InvCoeff.CoPx[iMarker] = -MomentY_Force[0]; - InvCoeff.CoPz[iMarker] = MomentY_Force[2]; - InvCoeff.CFx[iMarker] = ForceInviscid[0]; - InvCoeff.CFy[iMarker] = ForceInviscid[1]; - InvCoeff.CFz[iMarker] = ForceInviscid[2]; - InvCoeff.CT[iMarker] = -InvCoeff.CFz[iMarker]; - InvCoeff.CQ[iMarker] = -InvCoeff.CMz[iMarker]; - InvCoeff.CMerit[iMarker] = InvCoeff.CT[iMarker] / (InvCoeff.CQ[iMarker] + EPS); - } - - AllBoundInvCoeff.CD += InvCoeff.CD[iMarker]; - AllBoundInvCoeff.CL += InvCoeff.CL[iMarker]; - AllBoundInvCoeff.CSF += InvCoeff.CSF[iMarker]; - AllBoundInvCoeff.CEff = AllBoundInvCoeff.CL / (AllBoundInvCoeff.CD + EPS); - AllBoundInvCoeff.CMx += InvCoeff.CMx[iMarker]; - AllBoundInvCoeff.CMy += InvCoeff.CMy[iMarker]; - AllBoundInvCoeff.CMz += InvCoeff.CMz[iMarker]; - AllBoundInvCoeff.CoPx += InvCoeff.CoPx[iMarker]; - AllBoundInvCoeff.CoPy += InvCoeff.CoPy[iMarker]; - AllBoundInvCoeff.CoPz += InvCoeff.CoPz[iMarker]; - AllBoundInvCoeff.CFx += InvCoeff.CFx[iMarker]; - AllBoundInvCoeff.CFy += InvCoeff.CFy[iMarker]; - AllBoundInvCoeff.CFz += InvCoeff.CFz[iMarker]; - AllBoundInvCoeff.CT += InvCoeff.CT[iMarker]; - AllBoundInvCoeff.CQ += InvCoeff.CQ[iMarker]; - AllBoundInvCoeff.CMerit = AllBoundInvCoeff.CT / (AllBoundInvCoeff.CQ + EPS); - - /*--- 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); - if (Marker_Tag == Monitoring_Tag) { - SurfaceInvCoeff.CL[iMarker_Monitoring] += InvCoeff.CL[iMarker]; - SurfaceInvCoeff.CD[iMarker_Monitoring] += InvCoeff.CD[iMarker]; - SurfaceInvCoeff.CSF[iMarker_Monitoring] += InvCoeff.CSF[iMarker]; - SurfaceInvCoeff.CEff[iMarker_Monitoring] = InvCoeff.CL[iMarker] / (InvCoeff.CD[iMarker] + EPS); - SurfaceInvCoeff.CFx[iMarker_Monitoring] += InvCoeff.CFx[iMarker]; - SurfaceInvCoeff.CFy[iMarker_Monitoring] += InvCoeff.CFy[iMarker]; - SurfaceInvCoeff.CFz[iMarker_Monitoring] += InvCoeff.CFz[iMarker]; - SurfaceInvCoeff.CMx[iMarker_Monitoring] += InvCoeff.CMx[iMarker]; - SurfaceInvCoeff.CMy[iMarker_Monitoring] += InvCoeff.CMy[iMarker]; - SurfaceInvCoeff.CMz[iMarker_Monitoring] += InvCoeff.CMz[iMarker]; - } - } - - } - - /*--- At the Nearfield SU2 only cares about the pressure coeffient ---*/ - - else { - CNearFieldOF_Inv[iMarker] = NFPressOF; - AllBound_CNearFieldOF_Inv += CNearFieldOF_Inv[iMarker]; - } - - } - - } - } - -#ifdef HAVE_MPI - - /*--- Add AllBound information using all the nodes ---*/ - - if (config->GetComm_Level() == COMM_FULL) { - - auto Allreduce = [](su2double x) { - su2double tmp = x; x = 0.0; - SU2_MPI::Allreduce(&tmp, &x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - return x; - }; - AllBoundInvCoeff.CD = Allreduce(AllBoundInvCoeff.CD); - AllBoundInvCoeff.CL = Allreduce(AllBoundInvCoeff.CL); - AllBoundInvCoeff.CSF = Allreduce(AllBoundInvCoeff.CSF); - AllBoundInvCoeff.CEff = AllBoundInvCoeff.CL / (AllBoundInvCoeff.CD + EPS); - - AllBoundInvCoeff.CMx = Allreduce(AllBoundInvCoeff.CMx); - AllBoundInvCoeff.CMy = Allreduce(AllBoundInvCoeff.CMy); - AllBoundInvCoeff.CMz = Allreduce(AllBoundInvCoeff.CMz); - - AllBoundInvCoeff.CoPx = Allreduce(AllBoundInvCoeff.CoPx); - AllBoundInvCoeff.CoPy = Allreduce(AllBoundInvCoeff.CoPy); - AllBoundInvCoeff.CoPz = Allreduce(AllBoundInvCoeff.CoPz); - - AllBoundInvCoeff.CFx = Allreduce(AllBoundInvCoeff.CFx); - AllBoundInvCoeff.CFy = Allreduce(AllBoundInvCoeff.CFy); - AllBoundInvCoeff.CFz = Allreduce(AllBoundInvCoeff.CFz); - - AllBoundInvCoeff.CT = Allreduce(AllBoundInvCoeff.CT); - AllBoundInvCoeff.CQ = Allreduce(AllBoundInvCoeff.CQ); - AllBoundInvCoeff.CMerit = AllBoundInvCoeff.CT / (AllBoundInvCoeff.CQ + EPS); - AllBound_CNearFieldOF_Inv = Allreduce(AllBound_CNearFieldOF_Inv); - - } - - /*--- Add the forces on the surfaces using all the nodes ---*/ - - if (config->GetComm_Level() == COMM_FULL) { - - int nMarkerMon = config->GetnMarker_Monitoring(); - - /*--- Use the same buffer for all reductions. We could avoid the copy back into - * the original variable by swaping pointers, but it is safer this way... ---*/ - - su2double* buffer = new su2double [nMarkerMon]; - - auto Allreduce_inplace = [buffer](int size, su2double* x) { - SU2_MPI::Allreduce(x, buffer, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - for(int i=0; iGetnMarker_Monitoring(); iMarker_Monitoring++) { - SurfaceCoeff.CL[iMarker_Monitoring] = SurfaceInvCoeff.CL[iMarker_Monitoring]; - SurfaceCoeff.CD[iMarker_Monitoring] = SurfaceInvCoeff.CD[iMarker_Monitoring]; - SurfaceCoeff.CSF[iMarker_Monitoring] = SurfaceInvCoeff.CSF[iMarker_Monitoring]; - SurfaceCoeff.CEff[iMarker_Monitoring] = SurfaceInvCoeff.CL[iMarker_Monitoring] / (SurfaceInvCoeff.CD[iMarker_Monitoring] + EPS); - SurfaceCoeff.CFx[iMarker_Monitoring] = SurfaceInvCoeff.CFx[iMarker_Monitoring]; - SurfaceCoeff.CFy[iMarker_Monitoring] = SurfaceInvCoeff.CFy[iMarker_Monitoring]; - SurfaceCoeff.CFz[iMarker_Monitoring] = SurfaceInvCoeff.CFz[iMarker_Monitoring]; - SurfaceCoeff.CMx[iMarker_Monitoring] = SurfaceInvCoeff.CMx[iMarker_Monitoring]; - SurfaceCoeff.CMy[iMarker_Monitoring] = SurfaceInvCoeff.CMy[iMarker_Monitoring]; - SurfaceCoeff.CMz[iMarker_Monitoring] = SurfaceInvCoeff.CMz[iMarker_Monitoring]; - } - -} - -void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { - - unsigned long iVertex, iPoint; - unsigned short iDim, iMarker, Boundary, Monitoring, iMarker_Monitoring; - su2double Area, factor, RefVel2, RefTemp, RefDensity, Mach2Vel, Mach_Motion, MassFlow, Density; - const su2double *Normal = nullptr, *Coord = nullptr; - string Marker_Tag, Monitoring_Tag; - su2double AxiFactor; - - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - su2double RefArea = config->GetRefArea(); - su2double RefLength = config->GetRefLength(); - su2double Gas_Constant = config->GetGas_ConstantND(); - const su2double *Origin = nullptr; - if (config->GetnMarker_Monitoring() != 0){ - Origin = config->GetRefOriginMoment(0); - } - bool axisymmetric = config->GetAxisymmetric(); - - /*--- Evaluate reference values for non-dimensionalization. - For dynamic meshes, use the motion Mach number as a reference value - for computing the force coefficients. Otherwise, use the freestream values, - which is the standard convention. ---*/ - - RefTemp = Temperature_Inf; - RefDensity = Density_Inf; - if (dynamic_grid) { - Mach2Vel = sqrt(Gamma*Gas_Constant*RefTemp); - Mach_Motion = config->GetMach_Motion(); - RefVel2 = (Mach_Motion*Mach2Vel)*(Mach_Motion*Mach2Vel); - } - else { - RefVel2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - RefVel2 += Velocity_Inf[iDim]*Velocity_Inf[iDim]; - } - - factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2); - - /*-- Variables initialization ---*/ - - AllBoundMntCoeff.setZero(); - SurfaceMntCoeff.setZero(); - - /*--- Loop over the Inlet -Outlet Markers ---*/ - - for (iMarker = 0; iMarker < nMarker; iMarker++) { - - Boundary = config->GetMarker_All_KindBC(iMarker); - Monitoring = config->GetMarker_All_Monitoring(iMarker); - - /*--- Obtain the origin for the moment computation for a particular marker ---*/ - - if (Monitoring == YES) { - 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); - if (Marker_Tag == Monitoring_Tag) - Origin = config->GetRefOriginMoment(iMarker_Monitoring); - } - } - - if ((Boundary == INLET_FLOW) || (Boundary == OUTLET_FLOW) || - (Boundary == ACTDISK_INLET) || (Boundary == ACTDISK_OUTLET)|| - (Boundary == ENGINE_INFLOW) || (Boundary == ENGINE_EXHAUST)) { - - /*--- Forces initialization at each Marker ---*/ - - MntCoeff.setZero(iMarker); - - su2double ForceMomentum[MAXNDIM] = {0.0}, MomentMomentum[MAXNDIM] = {0.0}; - su2double MomentX_Force[3] = {0.0}, MomentY_Force[3] = {0.0}, MomentZ_Force[3] = {0.0}; - - /*--- Loop over the vertices to compute the forces ---*/ - - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - - /*--- Note that the pressure coefficient is computed at the - halo cells (for visualization purposes), but not the forces ---*/ - - if ( (geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES) ) { - - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - Coord = geometry->nodes->GetCoord(iPoint); - Density = nodes->GetDensity(iPoint); - - /*--- Quadratic objective function for the near-field. - This uses the infinity pressure regardless of Mach number. ---*/ - - Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); - - MassFlow = 0.0; - su2double Velocity[MAXNDIM] = {0.0}, MomentDist[MAXNDIM] = {0.0}; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity[iDim] = nodes->GetVelocity(iPoint,iDim); - MomentDist[iDim] = Coord[iDim] - Origin[iDim]; - MassFlow -= Normal[iDim]*Velocity[iDim]*Density; - } - - /*--- Axisymmetric simulations ---*/ - - if (axisymmetric) AxiFactor = 2.0*PI_NUMBER*geometry->nodes->GetCoord(iPoint, 1); - else AxiFactor = 1.0; - - /*--- Force computation, note the minus sign due to the - orientation of the normal (outward) ---*/ - - su2double Force[MAXNDIM] = {0.0}; - for (iDim = 0; iDim < nDim; iDim++) { - Force[iDim] = MassFlow * Velocity[iDim] * factor * AxiFactor; - ForceMomentum[iDim] += Force[iDim]; - } - - /*--- Moment with respect to the reference axis ---*/ - - if (iDim == 3) { - MomentMomentum[0] += (Force[2]*MomentDist[1]-Force[1]*MomentDist[2])/RefLength; - MomentX_Force[1] += (-Force[1]*Coord[2]); - MomentX_Force[2] += (Force[2]*Coord[1]); - - MomentMomentum[1] += (Force[0]*MomentDist[2]-Force[2]*MomentDist[0])/RefLength; - MomentY_Force[2] += (-Force[2]*Coord[0]); - MomentY_Force[0] += (Force[0]*Coord[2]); - } - MomentMomentum[2] += (Force[1]*MomentDist[0]-Force[0]*MomentDist[1])/RefLength; - MomentZ_Force[0] += (-Force[0]*Coord[1]); - MomentZ_Force[1] += (Force[1]*Coord[0]); - - } - - } - - /*--- Project forces and store the non-dimensional coefficients ---*/ - - if (Monitoring == YES) { - - if (nDim == 2) { - MntCoeff.CD[iMarker] = ForceMomentum[0]*cos(Alpha) + ForceMomentum[1]*sin(Alpha); - MntCoeff.CL[iMarker] = -ForceMomentum[0]*sin(Alpha) + ForceMomentum[1]*cos(Alpha); - MntCoeff.CEff[iMarker] = MntCoeff.CL[iMarker] / (MntCoeff.CD[iMarker]+EPS); - MntCoeff.CFx[iMarker] = ForceMomentum[0]; - MntCoeff.CFy[iMarker] = ForceMomentum[1]; - MntCoeff.CMz[iMarker] = MomentMomentum[2]; - MntCoeff.CoPx[iMarker] = MomentZ_Force[1]; - MntCoeff.CoPy[iMarker] = -MomentZ_Force[0]; - MntCoeff.CT[iMarker] = -MntCoeff.CFx[iMarker]; - MntCoeff.CQ[iMarker] = -MntCoeff.CMz[iMarker]; - MntCoeff.CMerit[iMarker] = MntCoeff.CT[iMarker] / (MntCoeff.CQ[iMarker] + EPS); - } - if (nDim == 3) { - MntCoeff.CD[iMarker] = ForceMomentum[0]*cos(Alpha)*cos(Beta) + ForceMomentum[1]*sin(Beta) + ForceMomentum[2]*sin(Alpha)*cos(Beta); - MntCoeff.CL[iMarker] = -ForceMomentum[0]*sin(Alpha) + ForceMomentum[2]*cos(Alpha); - MntCoeff.CSF[iMarker] = -ForceMomentum[0]*sin(Beta)*cos(Alpha) + ForceMomentum[1]*cos(Beta) - ForceMomentum[2]*sin(Beta)*sin(Alpha); - MntCoeff.CEff[iMarker] = MntCoeff.CL[iMarker] / (MntCoeff.CD[iMarker] + EPS); - MntCoeff.CFx[iMarker] = ForceMomentum[0]; - MntCoeff.CFy[iMarker] = ForceMomentum[1]; - MntCoeff.CFz[iMarker] = ForceMomentum[2]; - MntCoeff.CMx[iMarker] = MomentMomentum[0]; - MntCoeff.CMy[iMarker] = MomentMomentum[1]; - MntCoeff.CMz[iMarker] = MomentMomentum[2]; - MntCoeff.CoPx[iMarker] = -MomentY_Force[0]; - MntCoeff.CoPz[iMarker] = MomentY_Force[2]; - MntCoeff.CT[iMarker] = -MntCoeff.CFz[iMarker]; - MntCoeff.CQ[iMarker] = -MntCoeff.CMz[iMarker]; - MntCoeff.CMerit[iMarker] = MntCoeff.CT[iMarker] / (MntCoeff.CQ[iMarker] + EPS); - } - - AllBoundMntCoeff.CD += MntCoeff.CD[iMarker]; - AllBoundMntCoeff.CL += MntCoeff.CL[iMarker]; - AllBoundMntCoeff.CSF += MntCoeff.CSF[iMarker]; - AllBoundMntCoeff.CEff = AllBoundMntCoeff.CL / (AllBoundMntCoeff.CD + EPS); - AllBoundMntCoeff.CFx += MntCoeff.CFx[iMarker]; - AllBoundMntCoeff.CFy += MntCoeff.CFy[iMarker]; - AllBoundMntCoeff.CFz += MntCoeff.CFz[iMarker]; - AllBoundMntCoeff.CMx += MntCoeff.CMx[iMarker]; - AllBoundMntCoeff.CMy += MntCoeff.CMy[iMarker]; - AllBoundMntCoeff.CMx += MntCoeff.CMz[iMarker]; - AllBoundMntCoeff.CoPx += MntCoeff.CoPx[iMarker]; - AllBoundMntCoeff.CoPy += MntCoeff.CoPy[iMarker]; - AllBoundMntCoeff.CoPz += MntCoeff.CoPz[iMarker]; - AllBoundMntCoeff.CT += MntCoeff.CT[iMarker]; - AllBoundMntCoeff.CQ += MntCoeff.CQ[iMarker]; - AllBoundMntCoeff.CMerit += AllBoundMntCoeff.CT / (AllBoundMntCoeff.CQ + EPS); - - /*--- 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); - if (Marker_Tag == Monitoring_Tag) { - SurfaceMntCoeff.CL[iMarker_Monitoring] += MntCoeff.CL[iMarker]; - SurfaceMntCoeff.CD[iMarker_Monitoring] += MntCoeff.CD[iMarker]; - SurfaceMntCoeff.CSF[iMarker_Monitoring] += MntCoeff.CSF[iMarker]; - SurfaceMntCoeff.CEff[iMarker_Monitoring] = MntCoeff.CL[iMarker] / (MntCoeff.CD[iMarker] + EPS); - SurfaceMntCoeff.CFx[iMarker_Monitoring] += MntCoeff.CFx[iMarker]; - SurfaceMntCoeff.CFy[iMarker_Monitoring] += MntCoeff.CFy[iMarker]; - SurfaceMntCoeff.CFz[iMarker_Monitoring] += MntCoeff.CFz[iMarker]; - SurfaceMntCoeff.CMx[iMarker_Monitoring] += MntCoeff.CMx[iMarker]; - SurfaceMntCoeff.CMy[iMarker_Monitoring] += MntCoeff.CMy[iMarker]; - SurfaceMntCoeff.CMz[iMarker_Monitoring] += MntCoeff.CMz[iMarker]; - } - } - - } - - } - } - -#ifdef HAVE_MPI - - /*--- Add AllBound information using all the nodes ---*/ - - if (config->GetComm_Level() == COMM_FULL) { - - auto Allreduce = [](su2double x) { - su2double tmp = x; x = 0.0; - SU2_MPI::Allreduce(&tmp, &x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - return x; - }; - - AllBoundMntCoeff.CD = Allreduce(AllBoundMntCoeff.CD); - AllBoundMntCoeff.CL = Allreduce(AllBoundMntCoeff.CL); - AllBoundMntCoeff.CSF = Allreduce(AllBoundMntCoeff.CSF); - AllBoundMntCoeff.CEff = AllBoundMntCoeff.CL / (AllBoundMntCoeff.CD + EPS); - - AllBoundMntCoeff.CFx = Allreduce(AllBoundMntCoeff.CFx); - AllBoundMntCoeff.CFy = Allreduce(AllBoundMntCoeff.CFy); - AllBoundMntCoeff.CFz = Allreduce(AllBoundMntCoeff.CFz); - - AllBoundMntCoeff.CMx = Allreduce(AllBoundMntCoeff.CMx); - AllBoundMntCoeff.CMy = Allreduce(AllBoundMntCoeff.CMy); - AllBoundMntCoeff.CMz = Allreduce(AllBoundMntCoeff.CMz); - - AllBoundMntCoeff.CoPx = Allreduce(AllBoundMntCoeff.CoPx); - AllBoundMntCoeff.CoPy = Allreduce(AllBoundMntCoeff.CoPy); - AllBoundMntCoeff.CoPz = Allreduce(AllBoundMntCoeff.CoPz); - - AllBoundMntCoeff.CT = Allreduce(AllBoundMntCoeff.CT); - AllBoundMntCoeff.CQ = Allreduce(AllBoundMntCoeff.CQ); - AllBoundMntCoeff.CMerit = AllBoundMntCoeff.CT / (AllBoundMntCoeff.CQ + EPS); - - } - - /*--- Add the forces on the surfaces using all the nodes ---*/ - - if (config->GetComm_Level() == COMM_FULL) { - - int nMarkerMon = config->GetnMarker_Monitoring(); - - /*--- Use the same buffer for all reductions. We could avoid the copy back into - * the original variable by swaping pointers, but it is safer this way... ---*/ - - su2double* buffer = new su2double [nMarkerMon]; - - auto Allreduce_inplace = [buffer](int size, su2double* x) { - SU2_MPI::Allreduce(x, buffer, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - for(int i=0; iGetnMarker_Monitoring(); iMarker_Monitoring++) { - SurfaceCoeff.CL[iMarker_Monitoring] += SurfaceMntCoeff.CL[iMarker_Monitoring]; - SurfaceCoeff.CD[iMarker_Monitoring] += SurfaceMntCoeff.CD[iMarker_Monitoring]; - SurfaceCoeff.CSF[iMarker_Monitoring] += SurfaceMntCoeff.CSF[iMarker_Monitoring]; - SurfaceCoeff.CEff[iMarker_Monitoring] += SurfaceMntCoeff.CL[iMarker_Monitoring] / (SurfaceMntCoeff.CD[iMarker_Monitoring] + EPS); - SurfaceCoeff.CFx[iMarker_Monitoring] += SurfaceMntCoeff.CFx[iMarker_Monitoring]; - SurfaceCoeff.CFy[iMarker_Monitoring] += SurfaceMntCoeff.CFy[iMarker_Monitoring]; - SurfaceCoeff.CFz[iMarker_Monitoring] += SurfaceMntCoeff.CFz[iMarker_Monitoring]; - SurfaceCoeff.CMx[iMarker_Monitoring] += SurfaceMntCoeff.CMx[iMarker_Monitoring]; - SurfaceCoeff.CMy[iMarker_Monitoring] += SurfaceMntCoeff.CMy[iMarker_Monitoring]; - SurfaceCoeff.CMz[iMarker_Monitoring] += SurfaceMntCoeff.CMz[iMarker_Monitoring]; - } - -} - -template -void CEulerSolver::Explicit_Iteration(CGeometry *geometry, CSolver **solver_container, - CConfig *config, unsigned short iRKStep) { - - static_assert(IntegrationType == CLASSICAL_RK4_EXPLICIT || - IntegrationType == RUNGE_KUTTA_EXPLICIT || - IntegrationType == EULER_EXPLICIT, ""); - - const bool adjoint = config->GetContinuous_Adjoint(); - - const su2double RK_AlphaCoeff = config->Get_Alpha_RKStep(iRKStep); - - /*--- Hard-coded classical RK4 coefficients. Will be added to config. ---*/ - const su2double RK_FuncCoeff[] = {1.0/6.0, 1.0/3.0, 1.0/3.0, 1.0/6.0}; - const su2double RK_TimeCoeff[] = {0.5, 0.5, 1.0, 1.0}; - - /*--- Set shared residual variables to 0 and declare - * local ones for current thread to work on. ---*/ - - SU2_OMP_MASTER - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - SetRes_RMS(iVar, 0.0); - SetRes_Max(iVar, 0.0, 0); - } - SU2_OMP_BARRIER - - su2double resMax[MAXNVAR] = {0.0}, resRMS[MAXNVAR] = {0.0}; - const su2double* coordMax[MAXNVAR] = {nullptr}; - unsigned long idxMax[MAXNVAR] = {0}; - - /*--- Update the solution and residuals ---*/ - - SU2_OMP(for schedule(static,omp_chunk_size) nowait) - for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - - su2double Vol = geometry->nodes->GetVolume(iPoint) + geometry->nodes->GetPeriodicVolume(iPoint); - su2double Delta = nodes->GetDelta_Time(iPoint) / Vol; - - const su2double* Res_TruncError = nodes->GetResTruncError(iPoint); - const su2double* Residual = LinSysRes.GetBlock(iPoint); - - if (!adjoint) { - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - - su2double Res = Residual[iVar] + Res_TruncError[iVar]; - - /*--- "Static" switch which should be optimized at compile time. ---*/ - switch(IntegrationType) { - - case EULER_EXPLICIT: - nodes->AddSolution(iPoint,iVar, -Res*Delta); - break; - - case RUNGE_KUTTA_EXPLICIT: - nodes->AddSolution(iPoint, iVar, -Res*Delta*RK_AlphaCoeff); - break; - - case CLASSICAL_RK4_EXPLICIT: - { - su2double tmp_time = -1.0*RK_TimeCoeff[iRKStep]*Delta; - su2double tmp_func = -1.0*RK_FuncCoeff[iRKStep]*Delta; - - if (iRKStep < 3) { - /* Base Solution Update */ - nodes->AddSolution(iPoint,iVar, tmp_time*Res); - - /* New Solution Update */ - nodes->AddSolution_New(iPoint,iVar, tmp_func*Res); - } else { - nodes->SetSolution(iPoint, iVar, nodes->GetSolution_New(iPoint, iVar) + tmp_func*Res); - } - } - break; - } - - /*--- Update residual information for current thread. ---*/ - resRMS[iVar] += Res*Res; - if (fabs(Res) > resMax[iVar]) { - resMax[iVar] = fabs(Res); - idxMax[iVar] = iPoint; - coordMax[iVar] = geometry->nodes->GetCoord(iPoint); - } - } - } - } - if (!adjoint) { - /*--- Reduce residual information over all threads in this rank. ---*/ - SU2_OMP_CRITICAL - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - AddRes_RMS(iVar, resRMS[iVar]); - AddRes_Max(iVar, resMax[iVar], geometry->nodes->GetGlobalIndex(idxMax[iVar]), coordMax[iVar]); - } - } - SU2_OMP_BARRIER - - /*--- MPI solution ---*/ - - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); - - SU2_OMP_MASTER - { - /*--- Compute the root mean square residual ---*/ - - SetResidual_RMS(geometry, config); - - /*--- For verification cases, compute the global error metrics. ---*/ - - ComputeVerificationError(geometry, config); - } - SU2_OMP_BARRIER - -} - -void CEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver_container, - CConfig *config, unsigned short iRKStep) { - - Explicit_Iteration(geometry, solver_container, config, iRKStep); -} - -void CEulerSolver::ClassicalRK4_Iteration(CGeometry *geometry, CSolver **solver_container, - CConfig *config, unsigned short iRKStep) { - - Explicit_Iteration(geometry, solver_container, config, iRKStep); -} - -void CEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - - Explicit_Iteration(geometry, solver_container, config, 0); -} - -void CEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - - const bool adjoint = config->GetContinuous_Adjoint(); - const bool roe_turkel = config->GetKind_Upwind_Flow() == TURKEL; - const bool low_mach_prec = config->Low_Mach_Preconditioning(); + const bool adjoint = config->GetContinuous_Adjoint(); + const bool roe_turkel = config->GetKind_Upwind_Flow() == TURKEL; + const bool low_mach_prec = config->Low_Mach_Preconditioning(); /*--- Local matrix for preconditioning. ---*/ su2double** LowMachPrec = nullptr; @@ -4731,93 +3742,6 @@ void CEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver } -void CEulerSolver::ComputeUnderRelaxationFactor(CSolver **solver_container, CConfig *config) { - - /* Loop over the solution update given by relaxing the linear - system for this nonlinear iteration. */ - - const su2double allowableRatio = 0.2; - - SU2_OMP_FOR_STAT(omp_chunk_size) - for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - - su2double localUnderRelaxation = 1.0; - - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - - /* We impose a limit on the maximum percentage that the - density and energy can change over a nonlinear iteration. */ - - if ((iVar == 0) || (iVar == nVar-1)) { - const unsigned long index = iPoint*nVar + iVar; - su2double ratio = fabs(LinSysSol[index])/(nodes->GetSolution(iPoint, iVar)+EPS); - if (ratio > allowableRatio) { - localUnderRelaxation = min(allowableRatio/ratio, localUnderRelaxation); - } - } - } - - /* In case of turbulence, take the min of the under-relaxation factor - between the mean flow and the turb model. */ - - if (config->GetKind_Turb_Model() != NONE) - localUnderRelaxation = min(localUnderRelaxation, solver_container[TURB_SOL]->GetNodes()->GetUnderRelaxation(iPoint)); - - /* Threshold the relaxation factor in the event that there is - a very small value. This helps avoid catastrophic crashes due - to non-realizable states by canceling the update. */ - - if (localUnderRelaxation < 1e-10) localUnderRelaxation = 0.0; - - /* Store the under-relaxation factor for this point. */ - - nodes->SetUnderRelaxation(iPoint, localUnderRelaxation); - - } - -} - -void CEulerSolver::SetPrimitive_Gradient_GG(CGeometry *geometry, const CConfig *config, bool reconstruction) { - - const auto& primitives = nodes->GetPrimitive(); - auto& gradient = reconstruction? nodes->GetGradient_Reconstruction() : nodes->GetGradient_Primitive(); - - computeGradientsGreenGauss(this, PRIMITIVE_GRADIENT, PERIODIC_PRIM_GG, *geometry, - *config, primitives, 0, nPrimVarGrad, gradient); -} - -void CEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, const CConfig *config, bool reconstruction) { - - /*--- Set a flag for unweighted or weighted least-squares. ---*/ - bool weighted; - - if (reconstruction) - weighted = (config->GetKind_Gradient_Method_Recon() == WEIGHTED_LEAST_SQUARES); - else - weighted = (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES); - - const auto& primitives = nodes->GetPrimitive(); - auto& rmatrix = nodes->GetRmatrix(); - auto& gradient = reconstruction? nodes->GetGradient_Reconstruction() : nodes->GetGradient_Primitive(); - PERIODIC_QUANTITIES kindPeriodicComm = weighted? PERIODIC_PRIM_LS : PERIODIC_PRIM_ULS; - - computeGradientsLeastSquares(this, PRIMITIVE_GRADIENT, kindPeriodicComm, *geometry, *config, - weighted, primitives, 0, nPrimVarGrad, gradient, rmatrix); -} - -void CEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, const CConfig *config) { - - auto kindLimiter = static_cast(config->GetKind_SlopeLimit_Flow()); - const auto& primitives = nodes->GetPrimitive(); - const auto& gradient = nodes->GetGradient_Reconstruction(); - auto& primMin = nodes->GetSolution_Min(); - auto& primMax = nodes->GetSolution_Max(); - auto& limiter = nodes->GetLimiter_Primitive(); - - computeLimiters(kindLimiter, this, PRIMITIVE_LIMITER, PERIODIC_LIM_PRIM_1, PERIODIC_LIM_PRIM_2, - *geometry, *config, 0, nPrimVarGrad, primitives, gradient, primMin, primMax, limiter); -} - void CEulerSolver::SetPreconditioner(const CConfig *config, unsigned long iPoint, su2double delta, su2double** preconditioner) const { @@ -5811,8 +4735,8 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con } /*--- Delta P and delta T are inputs ---*/ - else { - if (Kind_ActDisk == VARIABLES_JUMP) { + else if (Kind_ActDisk == VARIABLES_JUMP) { + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if ((config->GetMarker_All_KindBC(iMarker) == ACTDISK_INLET) || @@ -5845,10 +4769,9 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - SetActDisk_DeltaP(iMarker, iVertex, DeltaP); - SetActDisk_DeltaT(iMarker, iVertex, DeltaT); + ActDisk_DeltaP[iMarker][iVertex] = DeltaP; + ActDisk_DeltaT[iMarker][iVertex] = DeltaT; } - } } } @@ -6073,7 +4996,6 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con } } } - } /*--- Evaluate the pressure jump at each node using the total thrust ---*/ @@ -6115,7 +5037,7 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con if (config->GetMarker_All_KindBC(iMarker) == ACTDISK_INLET) V_inlet = nodes->GetPrimitive(iPoint); if (config->GetMarker_All_KindBC(iMarker) == ACTDISK_OUTLET) - V_inlet = GetDonorPrimVar(iMarker, iVertex); + V_inlet = DonorPrimVar[iMarker][iVertex]; Density = V_inlet[nDim+2]; Pressure = V_inlet[nDim+1]; @@ -6179,26 +5101,23 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con La = min(La, sqrt(6.0)); La = max(La, 0.0); To_Ti = max(1.0, T0_Ti*(1.0-CTerm_*La*La)); - SetActDisk_DeltaT(iMarker, iVertex, To_Ti); + ActDisk_DeltaT[iMarker][iVertex] = To_Ti; Po_Pi = max(1.0, pow(To_Ti, PolyCoeff*DTerm_)); - SetActDisk_DeltaP(iMarker, iVertex, Po_Pi); + ActDisk_DeltaP[iMarker][iVertex] = Po_Pi; } else { - SetActDisk_DeltaT(iMarker, iVertex, 1.0); - SetActDisk_DeltaP(iMarker, iVertex, 1.0); + ActDisk_DeltaT[iMarker][iVertex] = 1.0; + ActDisk_DeltaP[iMarker][iVertex] = 1.0; } - } - } } - } } } -} + /*--- Broadcast some information to the master node ---*/ ActDisk_Info = false; @@ -6252,169 +5171,168 @@ void CEulerSolver::ReadActDisk_InputFile(CGeometry *geometry, CSolver **solver_c /*--- Error message if the propeller data input file fails to open. ---*/ if (ActDisk_file.fail()) SU2_MPI::Error("Unable to open Actuator Disk Input File", CURRENT_FUNCTION); - string text_line, text_line_appo, name[2]; - string::size_type position; - - while (getline (ActDisk_file, text_line)) { - /*--- Check if there is the "MARKER_ACTDISK=" string in the current line. If not keep on reading. ---*/ - position = text_line.find ("MARKER_ACTDISK="); - if(position == string::npos){continue;} - text_line.erase (0,15); - /*--- Read the names of the two faces of the actuator disk and assign them to the name[] array. ---*/ - istringstream NameID(text_line); - for (int i = 0; i < 2; i++){ - NameID >> name[i]; + string text_line, text_line_appo, name[2]; + string::size_type position; + + while (getline (ActDisk_file, text_line)) { + /*--- Check if there is the "MARKER_ACTDISK=" string in the current line. If not keep on reading. ---*/ + position = text_line.find ("MARKER_ACTDISK="); + if(position == string::npos){continue;} + text_line.erase (0,15); + /*--- Read the names of the two faces of the actuator disk and assign them to the name[] array. ---*/ + istringstream NameID(text_line); + for (int i = 0; i < 2; i++){ + NameID >> name[i]; + } + + /*--- Check if the propeller data correspond to the actual BC marker. ---*/ + if (Marker_Tag == name[0] || Marker_Tag == name[1]){ + /*--- Read and assign the coordinates of the actuator disk center. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,7); + istringstream C_value(text_line_appo); + for (iDim = 0; iDim < nDim; iDim++){ + C_value >> AD_Center[iDim]; + } + + /*--- Read and assign the components of the actuator disk axis versor pointing backward. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,5); + istringstream axis_value(text_line_appo); + for (iDim = 0; iDim < nDim; iDim++){ + axis_value >> AD_Axis[iDim]; + } + + /*--- Read and assign the value of the actuator disk radius. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,7); + istringstream R_value(text_line_appo); + R_value >> AD_Radius; + + /*--- Read and assign the value of the actuator disk advance ratio. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,10); + istringstream J_value(text_line_appo); + J_value >> AD_J; + + /*--- Read and assign the number of radial stations contained in the propeller data file. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,5); + istringstream row_value(text_line_appo); + row_value >> nRow; + + /*--- Assign the vectors dimension. ---*/ + rad_v.resize(nRow); + dCt_v.resize(nRow); + dCp_v.resize(nRow); + dCr_v.resize(nRow); + + Fa.resize(nRow); + Ft.resize(nRow); + Fr.resize(nRow); + + /*--- Read and assign the values of the non-dimensional radius, thrust coefficient, power coefficient + and radial force coefficient. ---*/ + getline (ActDisk_file, text_line_appo); + for (iRow = 0; iRow < nRow; iRow++){ + getline (ActDisk_file, text_line_appo); + istringstream row_val_value(text_line_appo); + row_val_value >> rad_v[iRow] >> dCt_v[iRow] >> dCp_v[iRow] >> dCr_v[iRow]; + } + + /*--- Set the actuator disk radius value, center coordiantes values and axis coordinates values. ---*/ + ActDisk_R(iMarker) = AD_Radius; + for (iDim = 0; iDim < nDim; iDim++){ + ActDisk_C(iMarker, iDim) = AD_Center[iDim]; + ActDisk_Axis(iMarker, iDim) = AD_Axis[iDim]; + } + + /*--- If the first radial station corresponds to the actuator disk center, the radial and tangential forces + per unit area (Fr and Ft) are equal to zero, while the axial force per unit area (Fa) is computed using + a linear interpolation in order to avoid a mathematical singularity at actuator disk center. ---*/ + if (rad_v[0] == 0.0){ + Fa[0] = (((2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER))*((dCt_v[1] - dCt_v[0])/rad_v[1])) / config->GetPressure_Ref(); + Ft[0] = 0.0; + Fr[0] = 0.0; + } + else { + Fa[0] = (dCt_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER*rad_v[0])) / config->GetPressure_Ref(); + Ft[0] = (dCp_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + ((AD_J*PI_NUMBER*rad_v[0])*(AD_J*PI_NUMBER*rad_v[0]))) / config->GetPressure_Ref(); + Fr[0] = (dCr_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER*rad_v[0])) / config->GetPressure_Ref(); + } + + /*--- Loop over the radial stations. Computation of Fa (axial force per unit area), Ft (tangential force per unit area) + and Fr (radial force per unit area). + These equations are not valid if the freestream velocity is equal to zero (hovering condition not enabled yet). ---*/ + for (iEl = 1; iEl < nRow; iEl++){ + Fa[iEl] = (dCt_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER*rad_v[iEl])) / config->GetPressure_Ref(); + Ft[iEl] = (dCp_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + ((AD_J*PI_NUMBER*rad_v[iEl])*(AD_J*PI_NUMBER*rad_v[iEl]))) / config->GetPressure_Ref(); + Fr[iEl] = (dCr_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER*rad_v[iEl])) / config->GetPressure_Ref(); } - /*--- Check if the propeller data correspond to the actual BC marker. ---*/ - if (Marker_Tag == name[0] || Marker_Tag == name[1]){ - /*--- Read and assign the coordinates of the actuator disk center. ---*/ - getline (ActDisk_file, text_line_appo); - text_line_appo.erase (0,7); - istringstream C_value(text_line_appo); - for (iDim = 0; iDim < nDim; iDim++){ - C_value >> AD_Center[iDim]; - } + /*--- Loop over the marker nodes. ---*/ + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { + /*--- Get the coordinates of the current node. ---*/ + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + P = geometry->nodes->GetCoord(iPoint); + + /*--- Computation of the radius coordinates for the current node. ---*/ + GeometryToolbox::Distance(nDim, P, AD_Center, r); + + /*--- Computation of the non-dimensional radius for the current node. ---*/ + r_ = GeometryToolbox::Norm(nDim, r) / AD_Radius; + + /*--- Loop over the actuator disk radial stations. ---*/ + for (iEl = 0; iEl < nRow; iEl++){ + /*--- Check if the current node is located between rad_v[iEl] and rad_v[iEl-1]. ---*/ + if (r_ <= rad_v[iEl]){ + /*--- h is the dinstance of the current node from the previous radial element (iEl-1) + divided by the length of the radial element in which the node is contained. ---*/ + h = (r_-rad_v[iEl-1])/(rad_v[iEl]-rad_v[iEl-1]); + /*--- Fx, Fy and Fz are the x, y and z components of the tangential and radial forces + per unit area resultant. ---*/ + if(r_ == 0.0){ + Fx = 0.0; + Fy = 0.0; + Fz = 0.0; + } + /*--- _inf is the value of the previous radial element. _sup is the value of the + following radial element. ---*/ + else{ + Fx_inf = (Ft[iEl-1]+Fr[iEl-1])*(r[0]/(r_*AD_Radius)); + Fy_inf = (Ft[iEl-1]+Fr[iEl-1])*(r[2]/(r_*AD_Radius)); + Fz_inf = -(Ft[iEl-1]+Fr[iEl-1])*(r[1]/(r_*AD_Radius)); + Fx_sup = (Ft[iEl]+Fr[iEl])*(r[0]/(r_*AD_Radius)); + Fy_sup = (Ft[iEl]+Fr[iEl])*(r[2]/(r_*AD_Radius)); + Fz_sup = -(Ft[iEl]+Fr[iEl])*(r[1]/(r_*AD_Radius)); + + /*--- Fx, Fy and Fz at the current node are evaluated using a linear interpolation between + the end vaues of the radial element in which the current node is contained. ---*/ + Fx = Fx_inf + (Fx_sup - Fx_inf)*h; + Fy = Fy_inf + (Fy_sup - Fy_inf)*h; + Fz = Fz_inf + (Fz_sup - Fz_inf)*h; + } + /*--- Set the values of Fa, Fx, Fy and Fz. Fa is evaluated using a linear interpolation. ---*/ + ActDisk_Fa[iMarker][iVertex] = Fa[iEl-1] + (Fa[iEl]-Fa[iEl-1])*h; + ActDisk_Fx[iMarker][iVertex] = Fx; + ActDisk_Fy[iMarker][iVertex] = Fy; + ActDisk_Fz[iMarker][iVertex] = Fz; - /*--- Read and assign the components of the actuator disk axis versor pointing backward. ---*/ - getline (ActDisk_file, text_line_appo); - text_line_appo.erase (0,5); - istringstream axis_value(text_line_appo); - for (iDim = 0; iDim < nDim; iDim++){ - axis_value >> AD_Axis[iDim]; + break; + } } - - /*--- Read and assign the value of the actuator disk radius. ---*/ - getline (ActDisk_file, text_line_appo); - text_line_appo.erase (0,7); - istringstream R_value(text_line_appo); - R_value >> AD_Radius; - - /*--- Read and assign the value of the actuator disk advance ratio. ---*/ - getline (ActDisk_file, text_line_appo); - text_line_appo.erase (0,10); - istringstream J_value(text_line_appo); - J_value >> AD_J; - - /*--- Read and assign the number of radial stations contained in the propeller data file. ---*/ - getline (ActDisk_file, text_line_appo); - text_line_appo.erase (0,5); - istringstream row_value(text_line_appo); - row_value >> nRow; - - /*--- Assign the vectors dimension. ---*/ - rad_v.resize(nRow); - dCt_v.resize(nRow); - dCp_v.resize(nRow); - dCr_v.resize(nRow); - - Fa.resize(nRow); - Ft.resize(nRow); - Fr.resize(nRow); - - /*--- Read and assign the values of the non-dimensional radius, thrust coefficient, power coefficient - and radial force coefficient. ---*/ - getline (ActDisk_file, text_line_appo); - for (iRow = 0; iRow < nRow; iRow++){ - getline (ActDisk_file, text_line_appo); - istringstream row_val_value(text_line_appo); - row_val_value >> rad_v[iRow] >> dCt_v[iRow] >> dCp_v[iRow] >> dCr_v[iRow]; - } - - /*--- Set the actuator disk radius value, center coordiantes values and axis coordinates values. ---*/ - ActDisk_R(iMarker) = AD_Radius; - for (iDim = 0; iDim < nDim; iDim++){ - ActDisk_C(iMarker, iDim) = AD_Center[iDim]; - ActDisk_Axis(iMarker, iDim) = AD_Axis[iDim]; - } - - /*--- If the first radial station corresponds to the actuator disk center, the radial and tangential forces - per unit area (Fr and Ft) are equal to zero, while the axial force per unit area (Fa) is computed using - a linear interpolation in order to avoid a mathematical singularity at actuator disk center. ---*/ - if (rad_v[0] == 0.0){ - Fa[0] = (((2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ - (pow(AD_J,2)*PI_NUMBER))*((dCt_v[1] - dCt_v[0])/rad_v[1])) / config->GetPressure_Ref(); - Ft[0] = 0.0; - Fr[0] = 0.0; - } - else { - Fa[0] = (dCt_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ - (pow(AD_J,2)*PI_NUMBER*rad_v[0])) / config->GetPressure_Ref(); - Ft[0] = (dCp_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ - ((AD_J*PI_NUMBER*rad_v[0])*(AD_J*PI_NUMBER*rad_v[0]))) / config->GetPressure_Ref(); - Fr[0] = (dCr_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ - (pow(AD_J,2)*PI_NUMBER*rad_v[0])) / config->GetPressure_Ref(); - } - - /*--- Loop over the radial stations. Computation of Fa (axial force per unit area), Ft (tangential force per unit area) - and Fr (radial force per unit area). - These equations are not valid if the freestream velocity is equal to zero (hovering condition not enabled yet). ---*/ - for (iEl = 1; iEl < nRow; iEl++){ - Fa[iEl] = (dCt_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ - (pow(AD_J,2)*PI_NUMBER*rad_v[iEl])) / config->GetPressure_Ref(); - Ft[iEl] = (dCp_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ - ((AD_J*PI_NUMBER*rad_v[iEl])*(AD_J*PI_NUMBER*rad_v[iEl]))) / config->GetPressure_Ref(); - Fr[iEl] = (dCr_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ - (pow(AD_J,2)*PI_NUMBER*rad_v[iEl])) / config->GetPressure_Ref(); - } - - /*--- Loop over the marker nodes. ---*/ - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - /*--- Get the coordinates of the current node. ---*/ - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - P = geometry->nodes->GetCoord(iPoint); - - /*--- Computation of the radius coordinates for the current node. ---*/ - GeometryToolbox::Distance(nDim, P, AD_Center, r); - - /*--- Computation of the non-dimensional radius for the current node. ---*/ - r_ = GeometryToolbox::Norm(nDim, r) / AD_Radius; - - /*--- Loop over the actuator disk radial stations. ---*/ - for (iEl = 0; iEl < nRow; iEl++){ - /*--- Check if the current node is located between rad_v[iEl] and rad_v[iEl-1]. ---*/ - if (r_ <= rad_v[iEl]){ - /*--- h is the dinstance of the current node from the previous radial element (iEl-1) - divided by the length of the radial element in which the node is contained. ---*/ - h = (r_-rad_v[iEl-1])/(rad_v[iEl]-rad_v[iEl-1]); - /*--- Fx, Fy and Fz are the x, y and z components of the tangential and radial forces - per unit area resultant. ---*/ - if(r_ == 0.0){ - Fx = 0.0; - Fy = 0.0; - Fz = 0.0; - } - /*--- _inf is the value of the previous radial element. _sup is the value of the - following radial element. ---*/ - else{ - Fx_inf = (Ft[iEl-1]+Fr[iEl-1])*(r[0]/(r_*AD_Radius)); - Fy_inf = (Ft[iEl-1]+Fr[iEl-1])*(r[2]/(r_*AD_Radius)); - Fz_inf = -(Ft[iEl-1]+Fr[iEl-1])*(r[1]/(r_*AD_Radius)); - Fx_sup = (Ft[iEl]+Fr[iEl])*(r[0]/(r_*AD_Radius)); - Fy_sup = (Ft[iEl]+Fr[iEl])*(r[2]/(r_*AD_Radius)); - Fz_sup = -(Ft[iEl]+Fr[iEl])*(r[1]/(r_*AD_Radius)); - - /*--- Fx, Fy and Fz at the current node are evaluated using a linear interpolation between - the end vaues of the radial element in which the current node is contained. ---*/ - Fx = Fx_inf + (Fx_sup - Fx_inf)*h; - Fy = Fy_inf + (Fy_sup - Fy_inf)*h; - Fz = Fz_inf + (Fz_sup - Fz_inf)*h; - } - /*--- Set the values of Fa, Fx, Fy and Fz. Fa is evaluated using a linear interpolation. ---*/ - SetActDisk_Fa(iMarker, iVertex, Fa[iEl-1] + (Fa[iEl]-Fa[iEl-1])*h); - SetActDisk_Fx(iMarker, iVertex, Fx); - SetActDisk_Fy(iMarker, iVertex, Fy); - SetActDisk_Fz(iMarker, iVertex, Fz); - - break; - } - } - } - } - } - ActDisk_file.close(); - } - } + } + } + } + } + } } void CEulerSolver::SetFarfield_AoA(CGeometry *geometry, CSolver **solver_container, @@ -6634,149 +5552,6 @@ void CEulerSolver::SetCoefficient_Gradients(CConfig *config) const{ } } -void CEulerSolver::SetInletAtVertex(su2double *val_inlet, - unsigned short iMarker, - unsigned long iVertex) { - - /*--- Alias positions within inlet file for readability ---*/ - - unsigned short T_position = nDim; - unsigned short P_position = nDim+1; - unsigned short FlowDir_position = nDim+2; - - /*--- Check that the norm of the flow unit vector is actually 1 ---*/ - - su2double norm = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - norm += pow(val_inlet[FlowDir_position + iDim], 2); - } - norm = sqrt(norm); - - /*--- The tolerance here needs to be loose. When adding a very - * small number (1e-10 or smaller) to a number close to 1.0, floating - * point roundoff errors can occur. ---*/ - - if (abs(norm - 1.0) > 1e-6) { - ostringstream error_msg; - error_msg << "ERROR: Found these values in columns "; - error_msg << FlowDir_position << " - "; - error_msg << FlowDir_position + nDim - 1 << endl; - error_msg << std::scientific; - error_msg << " [" << val_inlet[FlowDir_position]; - error_msg << ", " << val_inlet[FlowDir_position + 1]; - if (nDim == 3) error_msg << ", " << val_inlet[FlowDir_position + 2]; - error_msg << "]" << endl; - error_msg << " These values should be components of a unit vector for direction," << endl; - error_msg << " but their magnitude is: " << norm << endl; - SU2_MPI::Error(error_msg.str(), CURRENT_FUNCTION); - } - - /*--- Store the values in our inlet data structures. ---*/ - - Inlet_Ttotal[iMarker][iVertex] = val_inlet[T_position]; - Inlet_Ptotal[iMarker][iVertex] = val_inlet[P_position]; - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - Inlet_FlowDir[iMarker][iVertex][iDim] = val_inlet[FlowDir_position + iDim]; - } - -} - -su2double CEulerSolver::GetInletAtVertex(su2double *val_inlet, - unsigned long val_inlet_point, - unsigned short val_kind_marker, - string val_marker, - CGeometry *geometry, - CConfig *config) const { - - /*--- Local variables ---*/ - - unsigned short iMarker, iDim; - unsigned long iPoint, iVertex; - su2double Area = 0.0; - su2double Normal[3] = {0.0,0.0,0.0}; - - /*--- Alias positions within inlet file for readability ---*/ - - unsigned short T_position = nDim; - unsigned short P_position = nDim+1; - unsigned short FlowDir_position = nDim+2; - - if (val_kind_marker == INLET_FLOW) { - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - if ((config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) && - (config->GetMarker_All_TagBound(iMarker) == val_marker)) { - - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++){ - - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - - if (iPoint == val_inlet_point) { - - /*-- Compute boundary face area for this vertex. ---*/ - - geometry->vertex[iMarker][iVertex]->GetNormal(Normal); - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); - - /*--- Access and store the inlet variables for this vertex. ---*/ - - val_inlet[T_position] = Inlet_Ttotal[iMarker][iVertex]; - val_inlet[P_position] = Inlet_Ptotal[iMarker][iVertex]; - for (iDim = 0; iDim < nDim; iDim++) { - val_inlet[FlowDir_position + iDim] = Inlet_FlowDir[iMarker][iVertex][iDim]; - } - - /*--- Exit once we find the point. ---*/ - - return Area; - - } - } - } - } - } - - /*--- If we don't find a match, then the child point is not on the - current inlet boundary marker. Return zero area so this point does - not contribute to the restriction operator and continue. ---*/ - - return Area; - -} - -void CEulerSolver::SetUniformInlet(CConfig* config, unsigned short iMarker) { - - if (config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) { - - string Marker_Tag = config->GetMarker_All_TagBound(iMarker); - su2double p_total = config->GetInlet_Ptotal(Marker_Tag); - su2double t_total = config->GetInlet_Ttotal(Marker_Tag); - su2double* flow_dir = config->GetInlet_FlowDir(Marker_Tag); - - for (unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ - Inlet_Ttotal[iMarker][iVertex] = t_total; - Inlet_Ptotal[iMarker][iVertex] = p_total; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Inlet_FlowDir[iMarker][iVertex][iDim] = flow_dir[iDim]; - } - - } else { - - /*--- For now, non-inlets just get set to zero. In the future, we - can do more customization for other boundary types here. ---*/ - - for (unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ - Inlet_Ttotal[iMarker][iVertex] = 0.0; - Inlet_Ptotal[iMarker][iVertex] = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Inlet_FlowDir[iMarker][iVertex][iDim] = 0.0; - } - } - -} - void CEulerSolver::UpdateCustomBoundaryConditions(CGeometry **geometry_container, CConfig *config){ unsigned short nMGlevel, iMarker; @@ -6798,416 +5573,59 @@ void CEulerSolver::Evaluate_ObjFunc(CConfig *config) { unsigned short iMarker_Monitoring, Kind_ObjFunc; su2double Weight_ObjFunc; - Total_ComboObj = 0.0; + Total_ComboObj = EvaluateCommonObjFunc(*config); /*--- Loop over all monitored markers, add to the 'combo' objective ---*/ for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Weight_ObjFunc = config->GetWeight_ObjFunc(iMarker_Monitoring); - Kind_ObjFunc = config->GetKind_ObjFunc(iMarker_Monitoring); - - switch(Kind_ObjFunc) { - case DRAG_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CD[iMarker_Monitoring]); - if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCD_dCL()*(SurfaceCoeff.CL[iMarker_Monitoring]); - if (config->GetFixed_CM_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCD_dCMy()*(SurfaceCoeff.CMy[iMarker_Monitoring]); - break; - case LIFT_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CL[iMarker_Monitoring]); - break; - case SIDEFORCE_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CSF[iMarker_Monitoring]); - break; - case EFFICIENCY: - Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CEff[iMarker_Monitoring]); - break; - case MOMENT_X_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CMx[iMarker_Monitoring]); - if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMx_dCL()*(SurfaceCoeff.CL[iMarker_Monitoring]); - break; - case MOMENT_Y_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CMy[iMarker_Monitoring]); - if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMy_dCL()*(SurfaceCoeff.CL[iMarker_Monitoring]); - break; - case MOMENT_Z_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CMz[iMarker_Monitoring]); - if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMz_dCL()*(SurfaceCoeff.CL[iMarker_Monitoring]); - break; - case FORCE_X_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*SurfaceCoeff.CFx[iMarker_Monitoring]; - break; - case FORCE_Y_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*SurfaceCoeff.CFy[iMarker_Monitoring]; - break; - case FORCE_Z_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*SurfaceCoeff.CFz[iMarker_Monitoring]; - break; - case TOTAL_HEATFLUX: - Total_ComboObj+=Weight_ObjFunc*Surface_HF_Visc[iMarker_Monitoring]; - break; - case MAXIMUM_HEATFLUX: - Total_ComboObj+=Weight_ObjFunc*Surface_MaxHF_Visc[iMarker_Monitoring]; - break; - default: - break; - } - } - - /*--- The following are not per-surface, and so to avoid that they are - double-counted when multiple surfaces are specified, they have been - placed outside of the loop above. In addition, multi-objective mode is - also disabled for these objective functions (error thrown at start). ---*/ - - Weight_ObjFunc = config->GetWeight_ObjFunc(0); - Kind_ObjFunc = config->GetKind_ObjFunc(0); - - switch(Kind_ObjFunc) { - case EQUIVALENT_AREA: - Total_ComboObj+=Weight_ObjFunc*Total_CEquivArea; - break; - case NEARFIELD_PRESSURE: - Total_ComboObj+=Weight_ObjFunc*Total_CNearFieldOF; - break; - case INVERSE_DESIGN_PRESSURE: - Total_ComboObj+=Weight_ObjFunc*Total_CpDiff; - break; - case INVERSE_DESIGN_HEATFLUX: - Total_ComboObj+=Weight_ObjFunc*Total_HeatFluxDiff; - break; - case THRUST_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*TotalCoeff.CT; - break; - case TORQUE_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*TotalCoeff.CQ; - break; - case FIGURE_OF_MERIT: - Total_ComboObj+=Weight_ObjFunc*TotalCoeff.CMerit; - break; - case SURFACE_TOTAL_PRESSURE: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_TotalPressure(0); - break; - case SURFACE_STATIC_PRESSURE: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_Pressure(0); - break; - case SURFACE_MASSFLOW: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_MassFlow(0); - break; - case SURFACE_MACH: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_Mach(0); - break; - case SURFACE_UNIFORMITY: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_Uniformity(0); - break; - case SURFACE_SECONDARY: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_SecondaryStrength(0); - break; - case SURFACE_MOM_DISTORTION: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_MomentumDistortion(0); - break; - case SURFACE_SECOND_OVER_UNIFORM: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_SecondOverUniform(0); - break; - case TOTAL_AVG_TEMPERATURE: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_Temperature(0); - break; - case CUSTOM_OBJFUNC: - Total_ComboObj+=Weight_ObjFunc*Total_Custom_ObjFunc; - break; - default: - break; - } - -} - - -void CEulerSolver::BC_Euler_Wall(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) { - - /*--- Call the equivalent symmetry plane boundary condition. ---*/ - BC_Sym_Plane(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker); - -} - - -void CEulerSolver::BC_Sym_Plane(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) { - - unsigned short iDim, iVar; - unsigned long iVertex, iPoint; - - bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); - bool viscous = config->GetViscous(); - bool preprocessed = false; - - /*--- Allocation of variables necessary for convective fluxes. ---*/ - su2double Area, ProjVelocity_i, *V_reflected, *V_domain, - Normal[MAXNDIM] = {0.0}, UnitNormal[MAXNDIM] = {0.0}; - - /*--- Allocation of variables necessary for viscous fluxes. ---*/ - su2double ProjGradient, ProjNormVelGrad, ProjTangVelGrad, TangentialNorm, - Tangential[MAXNDIM] = {0.0}, GradNormVel[MAXNDIM] = {0.0}, - GradTangVel[MAXNDIM] = {0.0}; - - /*--- Allocation of primitive gradient arrays for viscous fluxes. ---*/ - su2double **Grad_Reflected = new su2double*[nPrimVarGrad]; - for (iVar = 0; iVar < nPrimVarGrad; iVar++) - Grad_Reflected[iVar] = new su2double[nDim]; - - /*--- Loop over all the vertices on this boundary marker. ---*/ - - SU2_OMP_FOR_DYN(OMP_MIN_SIZE) - for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { - - if (!preprocessed || - geometry->bound_is_straight[val_marker] != true) { - - /*----------------------------------------------------------------------------------------------*/ - /*--- Preprocessing: ---*/ - /*--- Compute the unit normal and (in case of viscous flow) a corresponding unit tangential ---*/ - /*--- to that normal. On a straight(2D)/plane(3D) boundary these two vectors are constant. ---*/ - /*--- This circumstance is checked in gemoetry->ComputeSurf_Straightness(...) and stored ---*/ - /*--- such that the recomputation does not occur for each node. On true symmetry planes, the ---*/ - /*--- normal is constant but this routines is used for Symmetry, Euler-Wall in inviscid flow ---*/ - /*--- and Euler Wall in viscous flow as well. In the latter curvy boundaries are likely to ---*/ - /*--- happen. In doubt, the conditional above which checks straightness can be thrown out ---*/ - /*--- such that the recomputation is done for each node (which comes with a tiny performance ---*/ - /*--- penalty). ---*/ - /*----------------------------------------------------------------------------------------------*/ - - preprocessed = true; - - /*--- Normal vector for a random vertex (zero) on this marker (negate for outward convention). ---*/ - geometry->vertex[val_marker][iVertex]->GetNormal(Normal); - for (iDim = 0; iDim < nDim; iDim++) - Normal[iDim] = -Normal[iDim]; - - /*--- Compute unit normal, to be used for unit tangential, projected velocity and velocity - component gradients. ---*/ - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt (Area); - - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = -Normal[iDim]/Area; - - /*--- Preprocessing: Compute unit tangential, the direction is arbitrary as long as - t*n=0 && |t|_2 = 1 ---*/ - if (viscous) { - switch( nDim ) { - case 2: { - Tangential[0] = -UnitNormal[1]; - Tangential[1] = UnitNormal[0]; - break; - } - case 3: { - /*--- n = ai + bj + ck, if |b| > |c| ---*/ - if( abs(UnitNormal[1]) > abs(UnitNormal[2])) { - /*--- t = bi + (c-a)j - bk ---*/ - Tangential[0] = UnitNormal[1]; - Tangential[1] = UnitNormal[2] - UnitNormal[0]; - Tangential[2] = -UnitNormal[1]; - } else { - /*--- t = ci - cj + (b-a)k ---*/ - Tangential[0] = UnitNormal[2]; - Tangential[1] = -UnitNormal[2]; - Tangential[2] = UnitNormal[1] - UnitNormal[0]; - } - /*--- Make it a unit vector. ---*/ - TangentialNorm = sqrt(pow(Tangential[0],2) + pow(Tangential[1],2) + pow(Tangential[2],2)); - Tangential[0] = Tangential[0] / TangentialNorm; - Tangential[1] = Tangential[1] / TangentialNorm; - Tangential[2] = Tangential[2] / TangentialNorm; - break; - } - }// switch - }//if viscous - }//if bound_is_straight - - iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); - - /*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/ - if (geometry->nodes->GetDomain(iPoint)) { - - /*-------------------------------------------------------------------------------*/ - /*--- Step 1: For the convective fluxes, create a reflected state of the ---*/ - /*--- Primitive variables by copying all interior values to the ---*/ - /*--- reflected. Only the velocity is mirrored along the symmetry ---*/ - /*--- axis. Based on the Upwind_Residual routine. ---*/ - /*-------------------------------------------------------------------------------*/ - - /*--- Allocate the reflected state at the symmetry boundary. ---*/ - V_reflected = GetCharacPrimVar(val_marker, iVertex); - - /*--- Grid movement ---*/ - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), - geometry->nodes->GetGridVel(iPoint)); - - /*--- Normal vector for this vertex (negate for outward convention). ---*/ - geometry->vertex[val_marker][iVertex]->GetNormal(Normal); - for (iDim = 0; iDim < nDim; iDim++) - Normal[iDim] = -Normal[iDim]; - conv_numerics->SetNormal(Normal); - - /*--- Get current solution at this boundary node ---*/ - V_domain = nodes->GetPrimitive(iPoint); - - /*--- Set the reflected state based on the boundary node. Scalars are copied and - the velocity is mirrored along the symmetry boundary, i.e. the velocity in - normal direction is substracted twice. ---*/ - for(iVar = 0; iVar < nPrimVar; iVar++) - V_reflected[iVar] = nodes->GetPrimitive(iPoint,iVar); - - /*--- Compute velocity in normal direction (ProjVelcity_i=(v*n)) und substract twice from - velocity in normal direction: v_r = v - 2 (v*n)n ---*/ - ProjVelocity_i = nodes->GetProjVel(iPoint,UnitNormal); - - /*--- Adjustment to v.n due to grid movement. ---*/ - if (dynamic_grid) { - ProjVelocity_i -= GeometryToolbox::DotProduct(nDim, geometry->nodes->GetGridVel(iPoint), UnitNormal); - } - - for (iDim = 0; iDim < nDim; iDim++) - V_reflected[iDim+1] = nodes->GetVelocity(iPoint,iDim) - 2.0 * ProjVelocity_i*UnitNormal[iDim]; - - /*--- Set Primitive and Secondary for numerics class. ---*/ - conv_numerics->SetPrimitive(V_domain, V_reflected); - conv_numerics->SetSecondary(nodes->GetSecondary(iPoint), - nodes->GetSecondary(iPoint)); - - /*--- Compute the residual using an upwind scheme. ---*/ - - auto residual = conv_numerics->ComputeResidual(config); - - /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, residual); - - /*--- Jacobian contribution for implicit integration. ---*/ - if (implicit) { - Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); - } - - if (viscous) { - - /*-------------------------------------------------------------------------------*/ - /*--- Step 2: The viscous fluxes of the Navier-Stokes equations depend on the ---*/ - /*--- Primitive variables and their gradients. The viscous numerics ---*/ - /*--- container is filled just as the convective numerics container, ---*/ - /*--- but the primitive gradients of the reflected state have to be ---*/ - /*--- determined additionally such that symmetry at the boundary is ---*/ - /*--- enforced. Based on the Viscous_Residual routine. ---*/ - /*-------------------------------------------------------------------------------*/ - - /*--- Set the normal vector and the coordinates. ---*/ - visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), - geometry->nodes->GetCoord(iPoint)); - visc_numerics->SetNormal(Normal); - - /*--- Set the primitive and Secondary variables. ---*/ - visc_numerics->SetPrimitive(V_domain, V_reflected); - visc_numerics->SetSecondary(nodes->GetSecondary(iPoint), - nodes->GetSecondary(iPoint)); - - /*--- For viscous Fluxes also the gradients of the primitives need to be determined. - 1. The gradients of scalars are mirrored along the sym plane just as velocity for the primitives - 2. The gradients of the velocity components need more attention, i.e. the gradient of the - normal velocity in tangential direction is mirrored and the gradient of the tangential velocity in - normal direction is mirrored. ---*/ - - /*--- Get gradients of primitives of boundary cell ---*/ - for (iVar = 0; iVar < nPrimVarGrad; iVar++) - for (iDim = 0; iDim < nDim; iDim++) - Grad_Reflected[iVar][iDim] = nodes->GetGradient_Primitive(iPoint, iVar, iDim); - - /*--- Reflect the gradients for all scalars including the velocity components. - The gradients of the velocity components are set later with the - correct values: grad(V)_r = grad(V) - 2 [grad(V)*n]n, V beeing any primitive ---*/ - for (iVar = 0; iVar < nPrimVarGrad; iVar++) { - if(iVar == 0 || iVar > nDim) { // Exclude velocity component gradients - - /*--- Compute projected part of the gradient in a dot product ---*/ - ProjGradient = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGradient += Grad_Reflected[iVar][iDim]*UnitNormal[iDim]; - - for (iDim = 0; iDim < nDim; iDim++) - Grad_Reflected[iVar][iDim] = Grad_Reflected[iVar][iDim] - 2.0 * ProjGradient*UnitNormal[iDim]; - } - } - - /*--- Compute gradients of normal and tangential velocity: - grad(v*n) = grad(v_x) n_x + grad(v_y) n_y (+ grad(v_z) n_z) - grad(v*t) = grad(v_x) t_x + grad(v_y) t_y (+ grad(v_z) t_z) ---*/ - for (iVar = 0; iVar < nDim; iVar++) { // counts gradient components - GradNormVel[iVar] = 0.0; - GradTangVel[iVar] = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { // counts sum with unit normal/tangential - GradNormVel[iVar] += Grad_Reflected[iDim+1][iVar] * UnitNormal[iDim]; - GradTangVel[iVar] += Grad_Reflected[iDim+1][iVar] * Tangential[iDim]; - } - } - - /*--- Refelect gradients in tangential and normal direction by substracting the normal/tangential - component twice, just as done with velocity above. - grad(v*n)_r = grad(v*n) - 2 {grad([v*n])*t}t - grad(v*t)_r = grad(v*t) - 2 {grad([v*t])*n}n ---*/ - ProjNormVelGrad = 0.0; - ProjTangVelGrad = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjNormVelGrad += GradNormVel[iDim]*Tangential[iDim]; //grad([v*n])*t - ProjTangVelGrad += GradTangVel[iDim]*UnitNormal[iDim]; //grad([v*t])*n - } - - for (iDim = 0; iDim < nDim; iDim++) { - GradNormVel[iDim] = GradNormVel[iDim] - 2.0 * ProjNormVelGrad * Tangential[iDim]; - GradTangVel[iDim] = GradTangVel[iDim] - 2.0 * ProjTangVelGrad * UnitNormal[iDim]; - } - - /*--- Transfer reflected gradients back into the Cartesian Coordinate system: - grad(v_x)_r = grad(v*n)_r n_x + grad(v*t)_r t_x - grad(v_y)_r = grad(v*n)_r n_y + grad(v*t)_r t_y - ( grad(v_z)_r = grad(v*n)_r n_z + grad(v*t)_r t_z ) ---*/ - for (iVar = 0; iVar < nDim; iVar++) // loops over the velocity component gradients - for (iDim = 0; iDim < nDim; iDim++) // loops over the entries of the above - Grad_Reflected[iVar+1][iDim] = GradNormVel[iDim]*UnitNormal[iVar] + GradTangVel[iDim]*Tangential[iVar]; - - /*--- Set the primitive gradients of the boundary and reflected state. ---*/ - visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), Grad_Reflected); - - /*--- Turbulent kinetic energy. ---*/ - if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) - visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), - solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0)); - - /*--- Compute and update residual. Note that the viscous shear stress tensor is computed in the - following routine based upon the velocity-component gradients. ---*/ - auto residual = visc_numerics->ComputeResidual(config); + Weight_ObjFunc = config->GetWeight_ObjFunc(iMarker_Monitoring); + Kind_ObjFunc = config->GetKind_ObjFunc(iMarker_Monitoring); - LinSysRes.SubtractBlock(iPoint, residual); + switch(Kind_ObjFunc) { + case DRAG_COEFFICIENT: + if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCD_dCL()*(SurfaceCoeff.CL[iMarker_Monitoring]); + if (config->GetFixed_CM_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCD_dCMy()*(SurfaceCoeff.CMy[iMarker_Monitoring]); + break; + case MOMENT_X_COEFFICIENT: + if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMx_dCL()*(SurfaceCoeff.CL[iMarker_Monitoring]); + break; + case MOMENT_Y_COEFFICIENT: + if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMy_dCL()*(SurfaceCoeff.CL[iMarker_Monitoring]); + break; + case MOMENT_Z_COEFFICIENT: + if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMz_dCL()*(SurfaceCoeff.CL[iMarker_Monitoring]); + break; + default: + break; + } + } - /*--- Jacobian contribution for implicit integration. ---*/ - if (implicit) - Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); - }//if viscous - }//if GetDomain - }//for iVertex + /*--- The following are not per-surface, and so to avoid that they are + double-counted when multiple surfaces are specified, they have been + placed outside of the loop above. In addition, multi-objective mode is + also disabled for these objective functions (error thrown at start). ---*/ - /*--- Free locally allocated memory ---*/ - for (iVar = 0; iVar < nPrimVarGrad; iVar++) - delete [] Grad_Reflected[iVar]; - delete [] Grad_Reflected; -} + Weight_ObjFunc = config->GetWeight_ObjFunc(0); + Kind_ObjFunc = config->GetKind_ObjFunc(0); + switch(Kind_ObjFunc) { + case EQUIVALENT_AREA: + Total_ComboObj+=Weight_ObjFunc*Total_CEquivArea; + break; + case NEARFIELD_PRESSURE: + Total_ComboObj+=Weight_ObjFunc*Total_CNearFieldOF; + break; + case SURFACE_MACH: + Total_ComboObj+=Weight_ObjFunc*config->GetSurface_Mach(0); + break; + case TOTAL_AVG_TEMPERATURE: + Total_ComboObj+=Weight_ObjFunc*config->GetSurface_Temperature(0); + break; + default: + break; + } +} void CEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { @@ -10614,182 +9032,6 @@ void CEulerSolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_conta } -void CEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, - CNumerics *visc_numerics, CConfig *config) { - - unsigned long iVertex, jVertex, iPoint, Point_Normal = 0; - unsigned short iDim, iVar, jVar, iMarker, nDonorVertex; - - bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); - bool viscous = config->GetViscous(); - - su2double Normal[MAXNDIM] = {0.0}; - su2double PrimVar_i[MAXNVAR] = {0.0}; - su2double PrimVar_j[MAXNVAR] = {0.0}; - su2double Secondary_j[MAXNVAR] = {0.0}; - su2double Residual[MAXNVAR] = {0.0}; - su2double **Jacobian_i = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar++) - Jacobian_i[iVar] = new su2double [nVar]; - - su2double weight; - su2double P_static, rho_static; - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - - if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) { - - SU2_OMP_FOR_DYN(OMP_MIN_SIZE) - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - - if (geometry->nodes->GetDomain(iPoint)) { - - nDonorVertex = GetnSlidingStates(iMarker, iVertex); - - /*--- Initialize Residual, this will serve to accumulate the average ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] = 0.0; - for (jVar = 0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] = 0.0; - } - - /*--- Loop over the nDonorVertexes and compute the averaged flux ---*/ - - for (jVertex = 0; jVertex < nDonorVertex; jVertex++) { - - Point_Normal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); - - for (iVar = 0; iVar < nPrimVar; iVar++) { - PrimVar_i[iVar] = nodes->GetPrimitive(iPoint,iVar); - PrimVar_j[iVar] = GetSlidingState(iMarker, iVertex, iVar, jVertex); - } - - /*--- Get the weight computed in the interpolator class for the j-th donor vertex ---*/ - - weight = GetSlidingState(iMarker, iVertex, nPrimVar, jVertex); - - /*--- Set primitive variables ---*/ - - conv_numerics->SetPrimitive( PrimVar_i, PrimVar_j ); - - if( !( config->GetKind_FluidModel() == STANDARD_AIR || config->GetKind_FluidModel() == IDEAL_GAS ) ) { - auto Secondary_i = nodes->GetSecondary(iPoint); - - P_static = PrimVar_j[nDim+1]; - rho_static = PrimVar_j[nDim+2]; - GetFluidModel()->SetTDState_Prho(P_static, rho_static); - - Secondary_j[0] = GetFluidModel()->GetdPdrho_e(); - Secondary_j[1] = GetFluidModel()->GetdPde_rho(); - - conv_numerics->SetSecondary(Secondary_i, Secondary_j); - } - - /*--- Set the normal vector ---*/ - - geometry->vertex[iMarker][iVertex]->GetNormal(Normal); - for (iDim = 0; iDim < nDim; iDim++) - Normal[iDim] = -Normal[iDim]; - - conv_numerics->SetNormal(Normal); - - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint)); - - /*--- Compute the convective residual using an upwind scheme ---*/ - - auto residual = conv_numerics->ComputeResidual(config); - - /*--- Accumulate the residuals to compute the average ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] += weight*residual.residual[iVar]; - for (jVar = 0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] += weight*residual.jacobian_i[iVar][jVar]; - } - } - - /*--- Add Residuals and Jacobians ---*/ - - LinSysRes.AddBlock(iPoint, Residual); - - if (implicit) - Jacobian.AddBlock2Diag(iPoint, Jacobian_i); - - if (viscous) { - - /*--- Initialize Residual, this will serve to accumulate the average ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] = 0.0; - for (jVar = 0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] = 0.0; - } - - /*--- Loop over the nDonorVertexes and compute the averaged flux ---*/ - - for (jVertex = 0; jVertex < nDonorVertex; jVertex++) { - PrimVar_j[nDim+5] = GetSlidingState(iMarker, iVertex, nDim+5, jVertex); - PrimVar_j[nDim+6] = GetSlidingState(iMarker, iVertex, nDim+6, jVertex); - - /*--- Get the weight computed in the interpolator class for the j-th donor vertex ---*/ - - weight = GetSlidingState(iMarker, iVertex, nPrimVar, jVertex); - - /*--- Set the normal vector and the coordinates ---*/ - - visc_numerics->SetNormal(Normal); - visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), geometry->nodes->GetCoord(Point_Normal)); - - /*--- Primitive variables, and gradient ---*/ - - visc_numerics->SetPrimitive(PrimVar_i, PrimVar_j); - visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), nodes->GetGradient_Primitive(iPoint)); - - /*--- Turbulent kinetic energy ---*/ - - if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) - visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), - solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0)); - - /*--- Set the wall shear stress values (wall functions) to -1 (no evaluation using wall functions) ---*/ - - visc_numerics->SetTauWall(-1.0, -1.0); - - /*--- Compute and update residual ---*/ - - auto residual = visc_numerics->ComputeResidual(config); - - /*--- Accumulate the residuals to compute the average ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] += weight*residual.residual[iVar]; - for (jVar = 0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] += weight*residual.jacobian_i[iVar][jVar]; - } - } - - LinSysRes.SubtractBlock(iPoint, Residual); - - /*--- Jacobian contribution for implicit integration ---*/ - - if (implicit) - Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); - - } - } - } - } - } - - for (iVar = 0; iVar < nVar; iVar++) - delete [] Jacobian_i[iVar]; - delete [] Jacobian_i; - -} - void CEulerSolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short val_marker) { @@ -10818,7 +9060,7 @@ void CEulerSolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solver_c for (iVar = 0; iVar < nPrimVar; iVar++) { PrimVar_i[iVar] = nodes->GetPrimitive(iPoint,iVar); - PrimVar_j[iVar] = GetDonorPrimVar(val_marker, iVertex, iVar); + PrimVar_j[iVar] = DonorPrimVar[val_marker][iVertex][iVar]; } /*--- Set Conservative Variables ---*/ @@ -10881,7 +9123,7 @@ void CEulerSolver::BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_c for (iVar = 0; iVar < nPrimVar; iVar++) { PrimVar_i[iVar] = nodes->GetPrimitive(iPoint,iVar); - PrimVar_j[iVar] = GetDonorPrimVar(val_marker, iVertex, iVar); + PrimVar_j[iVar] = DonorPrimVar[val_marker][iVertex][iVar]; } /*--- Set Conservative Variables ---*/ @@ -11002,12 +9244,12 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C /*--- Current solution at this boundary node and jumps values ---*/ V_domain = nodes->GetPrimitive(iPoint); - Target_Press_Jump = GetActDisk_DeltaP(val_marker, iVertex); - Target_Temp_Jump = GetActDisk_DeltaT(val_marker, iVertex); + Target_Press_Jump = ActDisk_DeltaP[val_marker][iVertex]; + Target_Temp_Jump = ActDisk_DeltaT[val_marker][iVertex]; if (val_inlet_surface) { V_inlet = nodes->GetPrimitive(iPoint); - V_outlet = GetDonorPrimVar(val_marker, iVertex); + V_outlet = DonorPrimVar[val_marker][iVertex]; Pressure_out = V_outlet[nDim+1]; Density_out = V_outlet[nDim+2]; @@ -11044,7 +9286,7 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C } else { V_outlet = nodes->GetPrimitive(iPoint); - V_inlet = GetDonorPrimVar(val_marker, iVertex); + V_inlet = DonorPrimVar[val_marker][iVertex]; Pressure_out = V_outlet[nDim+1]; Density_out = V_outlet[nDim+2]; @@ -11385,30 +9627,23 @@ void CEulerSolver::BC_ActDisk_VariableLoad(CGeometry *geometry, CSolver **solver su2double Pressure_out, Density_out, Pressure_in, Density_in; - su2double C[MAXNDIM], Prop_Axis[MAXNDIM], R, r[MAXNDIM], r_; + su2double Prop_Axis[MAXNDIM]; su2double Fa, Fx, Fy, Fz; su2double u_in, v_in, w_in, u_out, v_out, w_out, uJ, vJ, wJ; su2double Temperature_out, H_in, H_out; su2double FQ, Q_out, Density_Disk; su2double SoSextr, Vnextr[MAXNDIM], Vnextr_, RiemannExtr, QdMnorm[MAXNDIM], QdMnorm2, appo2, SoS_out; - const su2double *P = nullptr; - - bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); - su2double Gas_Constant = config->GetGas_ConstantND(); - bool tkeNeeded = (config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST); - bool ratio = (config->GetActDisk_Jump() == RATIO); - su2double Normal[MAXNDIM]; + const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + const auto Gas_Constant = config->GetGas_ConstantND(); + const bool tkeNeeded = (config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST); + /*--- Get the actuator disk center and axis coordinates for the current marker. ---*/ for (iDim = 0; iDim < nDim; iDim++){ - C[iDim] = ActDisk_C(val_marker, iDim); Prop_Axis[iDim] = ActDisk_Axis(val_marker, iDim); } - /*--- Get the actuator disk radius for the current marker. ---*/ - R = ActDisk_R(val_marker); - /*--- Loop over all the vertices on this boundary marker. ---*/ SU2_OMP_FOR_DYN(OMP_MIN_SIZE) for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { @@ -11438,18 +9673,18 @@ void CEulerSolver::BC_ActDisk_VariableLoad(CGeometry *geometry, CSolver **solver /*--- Get the values of Fa (axial force per unit area), Fx, Fy and Fz (x, y and z components of the tangential and radial forces per unit area resultant). ---*/ - Fa = GetActDisk_Fa(val_marker, iVertex); - Fx = GetActDisk_Fx(val_marker, iVertex); - Fy = GetActDisk_Fy(val_marker, iVertex); - Fz = GetActDisk_Fz(val_marker, iVertex); + Fa = ActDisk_Fa[val_marker][iVertex]; + Fx = ActDisk_Fx[val_marker][iVertex]; + Fy = ActDisk_Fy[val_marker][iVertex]; + Fz = ActDisk_Fz[val_marker][iVertex]; /*--- Get the primitive variables and the extrapolated variables. ---*/ if (val_inlet_surface){ V_inlet = nodes->GetPrimitive(iPoint); - V_outlet = GetDonorPrimVar(val_marker, iVertex);} + V_outlet = DonorPrimVar[val_marker][iVertex];} else{ - V_outlet = nodes->GetPrimitive(iPoint); - V_inlet = GetDonorPrimVar(val_marker, iVertex);} + V_outlet = nodes->GetPrimitive(iPoint); + V_inlet = DonorPrimVar[val_marker][iVertex];} /*--- u, v and w are the three momentum components. ---*/ Pressure_out = V_outlet[nDim+1]; @@ -11518,173 +9753,83 @@ void CEulerSolver::BC_ActDisk_VariableLoad(CGeometry *geometry, CSolver **solver /*--- Conservative variables, using the derived quantities ---*/ V_inlet[0] = Pressure / ( Gas_Constant * Density); - for (iDim = 0; iDim < nDim; iDim++) - V_inlet[iDim+1] = Velocity[iDim]; - V_inlet[nDim+1] = Pressure; - V_inlet[nDim+2] = Density; - V_inlet[nDim+3] = Energy + Pressure/Density; - V_inlet[nDim+4] = SoundSpeed; - conv_numerics->SetPrimitive(V_domain, V_inlet); - }else{ - /*--- Acoustic Riemann invariant extrapolation form the interior domain. ---*/ - SoSextr = V_domain[nDim+4]; - - Vnextr_ = 0.0; - for (iDim = 0; iDim < nDim; iDim++){ - Vnextr[iDim] = V_domain[iDim+1]*Prop_Axis[iDim]; - Vnextr_ += Vnextr[iDim]*Vnextr[iDim]; - } - Vnextr_ = sqrt(max(0.0,Vnextr_)); - RiemannExtr = Vnextr_ - ((2*SoSextr)/(Gamma_Minus_One)); - - /*--- Assigning the momentum in tangential direction jump and the pressure jump. ---*/ - Velocity[0] = u_in + uJ; - Velocity[1] = v_in + vJ; - Velocity[2] = w_in + wJ; - Pressure_out = Pressure_in + Fa; - - /*--- Computation of the momentum normal to the disk plane. ---*/ - QdMnorm[0] = u_in*Prop_Axis[0]; - QdMnorm[1] = v_in*Prop_Axis[1]; - QdMnorm[2] = w_in*Prop_Axis[2]; - - QdMnorm2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) QdMnorm2 += QdMnorm[iDim]*QdMnorm[iDim]; - - /*--- Resolving the second grade equation for the density. ---*/ - appo2 = -((2*sqrt(QdMnorm2)*RiemannExtr)+((4*Gamma*Pressure_out)/(pow(Gamma_Minus_One,2)))); - Density_out = (-appo2+sqrt(max(0.0,pow(appo2,2)-4*QdMnorm2*pow(RiemannExtr,2))))/(2*pow(RiemannExtr,2)); - - Velocity2 = 0; - for (iDim = 0; iDim < nDim; iDim++) Velocity2 += (Velocity[iDim]*Velocity[iDim]); - - /*--- Computation of the enthalpy, total energy, temperature and speed of sound. ---*/ - H_out = H_in/Density_in + Fa/Density_out; - Energy = H_out - Pressure_out/Density_out; - if (tkeNeeded) Energy += GetTke_Inf(); - Temperature_out = (Energy-0.5*Velocity2/(pow(Density_out,2)))*(Gamma_Minus_One/Gas_Constant); - - SoS_out = sqrt(Gamma*Gas_Constant*Temperature_out); - - /*--- Set the primitive variables. ---*/ - V_outlet[0] = Temperature_out; - for (iDim = 0; iDim < nDim; iDim++) - V_outlet[iDim+1] = Velocity[iDim]/Density_out; - V_outlet[nDim+1] = Pressure_out; - V_outlet[nDim+2] = Density_out; - V_outlet[nDim+3] = H_out; - V_outlet[nDim+4] = SoS_out; - conv_numerics->SetPrimitive(V_domain, V_outlet); - } - - /*--- Grid Movement (NOT TESTED!)---*/ - - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint)); - - /*--- Compute the residual using an upwind scheme ---*/ - - auto residual = conv_numerics->ComputeResidual(config); - - /*--- Update residual value ---*/ - - LinSysRes.AddBlock(iPoint, residual); - - /*--- Jacobian contribution for implicit integration ---*/ - - if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); - - } - } -} - -void CEulerSolver::BC_Periodic(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, CConfig *config) { - - /*--- Complete residuals for periodic boundary conditions. We loop over - the periodic BCs in matching pairs so that, in the event that there are - adjacent periodic markers, the repeated points will have their residuals - accumulated correctly during the communications. For implicit calculations, - the Jacobians and linear system are also correctly adjusted here. ---*/ - - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL); - } - -} - -void CEulerSolver::BC_Custom(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) { - - /* Check for a verification solution. */ - - if (VerificationSolution) { - - unsigned short iVar; - unsigned long iVertex, iPoint, total_index; - - bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + for (iDim = 0; iDim < nDim; iDim++) V_inlet[iDim+1] = Velocity[iDim]; + V_inlet[nDim+1] = Pressure; + V_inlet[nDim+2] = Density; + V_inlet[nDim+3] = Energy + Pressure/Density; + V_inlet[nDim+4] = SoundSpeed; + conv_numerics->SetPrimitive(V_domain, V_inlet); + } + else { + /*--- Acoustic Riemann invariant extrapolation form the interior domain. ---*/ + SoSextr = V_domain[nDim+4]; - /*--- Get the physical time. ---*/ + Vnextr_ = 0.0; + for (iDim = 0; iDim < nDim; iDim++){ + Vnextr[iDim] = V_domain[iDim+1]*Prop_Axis[iDim]; + Vnextr_ += Vnextr[iDim]*Vnextr[iDim]; + } + Vnextr_ = sqrt(max(0.0,Vnextr_)); + RiemannExtr = Vnextr_ - ((2*SoSextr)/(Gamma_Minus_One)); - su2double time = 0.0; - if (config->GetTime_Marching()) time = config->GetPhysicalTime(); + /*--- Assigning the momentum in tangential direction jump and the pressure jump. ---*/ + Velocity[0] = u_in + uJ; + Velocity[1] = v_in + vJ; + Velocity[2] = w_in + wJ; + Pressure_out = Pressure_in + Fa; - /*--- Loop over all the vertices on this boundary marker ---*/ + /*--- Computation of the momentum normal to the disk plane. ---*/ + QdMnorm[0] = u_in*Prop_Axis[0]; + QdMnorm[1] = v_in*Prop_Axis[1]; + QdMnorm[2] = w_in*Prop_Axis[2]; - SU2_OMP_FOR_STAT(OMP_MIN_SIZE) - for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { + QdMnorm2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) QdMnorm2 += QdMnorm[iDim]*QdMnorm[iDim]; - /*--- Get the point index for the current node. ---*/ + /*--- Resolving the second grade equation for the density. ---*/ + appo2 = -((2*sqrt(QdMnorm2)*RiemannExtr)+((4*Gamma*Pressure_out)/(pow(Gamma_Minus_One,2)))); + Density_out = (-appo2+sqrt(max(0.0,pow(appo2,2)-4*QdMnorm2*pow(RiemannExtr,2))))/(2*pow(RiemannExtr,2)); - iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); + Velocity2 = 0; + for (iDim = 0; iDim < nDim; iDim++) Velocity2 += (Velocity[iDim]*Velocity[iDim]); - /*--- Check if the node belongs to the domain (i.e, not a halo node) ---*/ + /*--- Computation of the enthalpy, total energy, temperature and speed of sound. ---*/ + H_out = H_in/Density_in + Fa/Density_out; + Energy = H_out - Pressure_out/Density_out; + if (tkeNeeded) Energy += GetTke_Inf(); + Temperature_out = (Energy-0.5*Velocity2/(pow(Density_out,2)))*(Gamma_Minus_One/Gas_Constant); - if (geometry->nodes->GetDomain(iPoint)) { + SoS_out = sqrt(Gamma*Gas_Constant*Temperature_out); - /*--- Get the coordinates for the current node. ---*/ + /*--- Set the primitive variables. ---*/ + V_outlet[0] = Temperature_out; + for (iDim = 0; iDim < nDim; iDim++) + V_outlet[iDim+1] = Velocity[iDim]/Density_out; + V_outlet[nDim+1] = Pressure_out; + V_outlet[nDim+2] = Density_out; + V_outlet[nDim+3] = H_out; + V_outlet[nDim+4] = SoS_out; + conv_numerics->SetPrimitive(V_domain, V_outlet); + } - const su2double *coor = geometry->nodes->GetCoord(iPoint); + /*--- Grid Movement (NOT TESTED!)---*/ - /*--- Get the conservative state from the verification solution. ---*/ + if (dynamic_grid) + conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint)); - su2double Solution[MAXNVAR] = {0.0}; - VerificationSolution->GetBCState(coor, time, Solution); + /*--- Compute the residual using an upwind scheme ---*/ - /*--- For verification cases, we will apply a strong Dirichlet - condition by setting the solution values at the boundary nodes - directly and setting the residual to zero at those nodes. ---*/ + auto residual = conv_numerics->ComputeResidual(config); - nodes->SetSolution_Old(iPoint,Solution); - nodes->SetSolution(iPoint,Solution); - nodes->SetRes_TruncErrorZero(iPoint); - LinSysRes.SetBlock_Zero(iPoint); + /*--- Update residual value ---*/ - /*--- Adjust rows of the Jacobian (includes 1 in the diagonal) ---*/ + LinSysRes.AddBlock(iPoint, residual); - if (implicit){ - for (iVar = 0; iVar < nVar; iVar++) { - total_index = iPoint*nVar+iVar; - Jacobian.DeleteValsRowi(total_index); - } - } + /*--- Jacobian contribution for implicit integration ---*/ - } + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } - - } else { - - /* The user must specify the custom BC's here. */ - SU2_MPI::Error("Implement customized boundary conditions here.", CURRENT_FUNCTION); - } - } void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_container, CConfig *config, @@ -11863,103 +10008,42 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co } -void CEulerSolver::ComputeVerificationError(CGeometry *geometry, - CConfig *config) { +void CEulerSolver::PrintVerificationError(const CConfig *config) const { - /*--- The errors only need to be computed on the finest grid. ---*/ - if(MGLevel != MESH_0) return; + if ((rank != MASTER_NODE) || (MGLevel != MESH_0)) return; - /*--- If this is a verification case, we can compute the global - error metrics by using the difference between the local error - and the known solution at each DOF. This is then collected into - RMS (L2) and maximum (Linf) global error norms. From these - global measures, one can compute the order of accuracy. ---*/ + if (config && !config->GetDiscrete_Adjoint()) { - bool write_heads = ((((config->GetInnerIter() % (config->GetWrt_Con_Freq()*40)) == 0) - && (config->GetInnerIter()!= 0)) - || (config->GetInnerIter() == 1)); - if( !write_heads ) return; + cout.precision(5); + cout.setf(ios::scientific, ios::floatfield); - /*--- Check if there actually is an exact solution for this - verification case, if computed at all. ---*/ - if (VerificationSolution) { - if (VerificationSolution->ExactSolutionKnown()) { + cout << endl << "------------------------ Global Error Analysis --------------------------" << endl; - /*--- Get the physical time if necessary. ---*/ - su2double time = 0.0; - if (config->GetTime_Marching()) time = config->GetPhysicalTime(); - - /*--- Reset the global error measures to zero. ---*/ - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - VerificationSolution->SetError_RMS(iVar, 0.0); - VerificationSolution->SetError_Max(iVar, 0.0, 0); - } - - /*--- Loop over all owned points. ---*/ - for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - - /* Set the pointers to the coordinates and solution of this DOF. */ - const su2double *coor = geometry->nodes->GetCoord(iPoint); - su2double *solDOF = nodes->GetSolution(iPoint); - - /* Get local error from the verification solution class. */ - vector error(nVar,0.0); - VerificationSolution->GetLocalError(coor, time, solDOF, error.data()); - - /* Increment the global error measures */ - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - VerificationSolution->AddError_RMS(iVar, error[iVar]*error[iVar]); - VerificationSolution->AddError_Max(iVar, fabs(error[iVar]), - geometry->nodes->GetGlobalIndex(iPoint), - geometry->nodes->GetCoord(iPoint)); - } - } - - /* Finalize the calculation of the global error measures. */ - VerificationSolution->SetVerificationError(geometry->GetGlobal_nPointDomain(), config); - - /*--- Screen output of the error metrics. This can be improved - once the new output classes are in place. ---*/ - - if ((rank == MASTER_NODE) && (geometry->GetMGLevel() == MESH_0)) { - - cout.precision(5); - cout.setf(ios::scientific, ios::floatfield); - - if (!config->GetDiscrete_Adjoint()) { - - cout << endl << "------------------------ Global Error Analysis --------------------------" << endl; - - cout << setw(20) << "RMS Error [Rho]: " << setw(12) << VerificationSolution->GetError_RMS(0) << " | "; - cout << setw(20) << "Max Error [Rho]: " << setw(12) << VerificationSolution->GetError_Max(0); - cout << endl; - - cout << setw(20) << "RMS Error [RhoU]: " << setw(12) << VerificationSolution->GetError_RMS(1) << " | "; - cout << setw(20) << "Max Error [RhoU]: " << setw(12) << VerificationSolution->GetError_Max(1); - cout << endl; + cout << setw(20) << "RMS Error [Rho]: " << setw(12) << VerificationSolution->GetError_RMS(0) << " | "; + cout << setw(20) << "Max Error [Rho]: " << setw(12) << VerificationSolution->GetError_Max(0); + cout << endl; - cout << setw(20) << "RMS Error [RhoV]: " << setw(12) << VerificationSolution->GetError_RMS(2) << " | "; - cout << setw(20) << "Max Error [RhoV]: " << setw(12) << VerificationSolution->GetError_Max(2); - cout << endl; + cout << setw(20) << "RMS Error [RhoU]: " << setw(12) << VerificationSolution->GetError_RMS(1) << " | "; + cout << setw(20) << "Max Error [RhoU]: " << setw(12) << VerificationSolution->GetError_Max(1); + cout << endl; - if (nDim == 3) { - cout << setw(20) << "RMS Error [RhoW]: " << setw(12) << VerificationSolution->GetError_RMS(3) << " | "; - cout << setw(20) << "Max Error [RhoW]: " << setw(12) << VerificationSolution->GetError_Max(3); - cout << endl; - } + cout << setw(20) << "RMS Error [RhoV]: " << setw(12) << VerificationSolution->GetError_RMS(2) << " | "; + cout << setw(20) << "Max Error [RhoV]: " << setw(12) << VerificationSolution->GetError_Max(2); + cout << endl; - cout << setw(20) << "RMS Error [RhoE]: " << setw(12) << VerificationSolution->GetError_RMS(nDim+1) << " | "; - cout << setw(20) << "Max Error [RhoE]: " << setw(12) << VerificationSolution->GetError_Max(nDim+1); - cout << endl; + if (nDim == 3) { + cout << setw(20) << "RMS Error [RhoW]: " << setw(12) << VerificationSolution->GetError_RMS(3) << " | "; + cout << setw(20) << "Max Error [RhoW]: " << setw(12) << VerificationSolution->GetError_Max(3); + cout << endl; + } - cout << "-------------------------------------------------------------------------" << endl << endl; - cout.unsetf(ios_base::floatfield); + cout << setw(20) << "RMS Error [RhoE]: " << setw(12) << VerificationSolution->GetError_RMS(nDim+1) << " | "; + cout << setw(20) << "Max Error [RhoE]: " << setw(12) << VerificationSolution->GetError_Max(nDim+1); + cout << endl; - } - } - } + cout << "-------------------------------------------------------------------------" << endl << endl; + cout.unsetf(ios_base::floatfield); } - } void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *config, int val_iter, bool val_update_geo) { diff --git a/SU2_CFD/src/solvers/CFEM_DG_EulerSolver.cpp b/SU2_CFD/src/solvers/CFEM_DG_EulerSolver.cpp index 46eaae00c80a..1c3f32e5bf9a 100644 --- a/SU2_CFD/src/solvers/CFEM_DG_EulerSolver.cpp +++ b/SU2_CFD/src/solvers/CFEM_DG_EulerSolver.cpp @@ -6708,7 +6708,7 @@ void CFEM_DG_EulerSolver::MultiplyResidualByInverseMassMatrix( } } -void CFEM_DG_EulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { +void CFEM_DG_EulerSolver::Pressure_Forces(const CGeometry* geometry, const CConfig* config) { /* Allocate the memory for the work array and initialize it to zero to avoid warnings in debug mode about uninitialized memory when padding is applied. */ @@ -6733,7 +6733,7 @@ void CFEM_DG_EulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) const su2double RefArea = config->GetRefArea(); const su2double RefLength = config->GetRefLength(); const su2double Gas_Constant = config->GetGas_ConstantND(); - const su2double *Origin = config->GetRefOriginMoment(0); + auto Origin = config->GetRefOriginMoment(0); const bool grid_movement = config->GetGrid_Movement(); /*--- Evaluate reference values for non-dimensionalization. @@ -7518,7 +7518,7 @@ void CFEM_DG_EulerSolver::BoundaryStates_Inlet(CConfig *config, su2double P_Total = config->GetInlet_Ptotal(Marker_Tag); su2double T_Total = config->GetInlet_Ttotal(Marker_Tag); - su2double *Flow_Dir = config->GetInlet_FlowDir(Marker_Tag); + auto Flow_Dir = config->GetInlet_FlowDir(Marker_Tag); /*--- Non-dim. the inputs if necessary, and compute the total enthalpy. ---*/ P_Total /= config->GetPressure_Ref(); diff --git a/SU2_CFD/src/solvers/CFEM_DG_NSSolver.cpp b/SU2_CFD/src/solvers/CFEM_DG_NSSolver.cpp index ed4520ce54cf..c943633ddaa0 100644 --- a/SU2_CFD/src/solvers/CFEM_DG_NSSolver.cpp +++ b/SU2_CFD/src/solvers/CFEM_DG_NSSolver.cpp @@ -180,7 +180,7 @@ CFEM_DG_NSSolver::~CFEM_DG_NSSolver(void) { delete SGSModel; } -void CFEM_DG_NSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { +void CFEM_DG_NSSolver::Friction_Forces(const CGeometry* geometry, const CConfig* config) { /* Allocate the memory for the work array and initialize it to zero to avoid warnings in debug mode about uninitialized memory when padding is applied. */ @@ -215,7 +215,7 @@ void CFEM_DG_NSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { const su2double RefArea = config->GetRefArea(); const su2double RefLength = config->GetRefLength(); const su2double Gas_Constant = config->GetGas_ConstantND(); - const su2double *Origin = config->GetRefOriginMoment(0); + auto Origin = config->GetRefOriginMoment(0); const bool grid_movement = config->GetGrid_Movement(); /*--- Evaluate reference values for non-dimensionalization. diff --git a/SU2_CFD/src/solvers/CHeatSolver.cpp b/SU2_CFD/src/solvers/CHeatSolver.cpp index 709d622acf1a..fc8954e0f0fd 100644 --- a/SU2_CFD/src/solvers/CHeatSolver.cpp +++ b/SU2_CFD/src/solvers/CHeatSolver.cpp @@ -891,8 +891,7 @@ void CHeatSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, unsigned short iDim; unsigned long iVertex, iPoint, Point_Normal; - su2double *Flow_Dir, Vel_Mag; - su2double *V_inlet, *V_domain; + su2double Vel_Mag, *V_inlet, *V_domain; bool flow = ((config->GetKind_Solver() == INC_NAVIER_STOKES) || (config->GetKind_Solver() == INC_RANS) @@ -936,7 +935,7 @@ void CHeatSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, /*--- Retrieve the specified velocity for the inlet. ---*/ Vel_Mag = config->GetInlet_Ptotal(Marker_Tag)/config->GetVelocity_Ref(); - Flow_Dir = config->GetInlet_FlowDir(Marker_Tag); + auto Flow_Dir = config->GetInlet_FlowDir(Marker_Tag); V_inlet = solver_container[FLOW_SOL]->GetCharacPrimVar(val_marker, iVertex); diff --git a/SU2_CFD/src/solvers/CIncEulerSolver.cpp b/SU2_CFD/src/solvers/CIncEulerSolver.cpp index 38cd704360e3..a6c81c41a49c 100644 --- a/SU2_CFD/src/solvers/CIncEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CIncEulerSolver.cpp @@ -1,5 +1,5 @@ /*! - * \file solution_direct_mean_inc.cpp + * \file CIncEulerSolver.cpp * \brief Main subroutines for solving incompressible flow (Euler, Navier-Stokes, etc.). * \author F. Palacios, T. Economon * \version 7.0.6 "Blackbird" @@ -25,90 +25,36 @@ * License along with SU2. If not, see . */ - #include "../../include/solvers/CIncEulerSolver.hpp" #include "../../../Common/include/toolboxes/printing_toolbox.hpp" -#include "../../include/gradients/computeGradientsGreenGauss.hpp" -#include "../../include/gradients/computeGradientsLeastSquares.hpp" -#include "../../include/limiters/computeLimiters.hpp" #include "../../include/fluid/CConstantDensity.hpp" #include "../../include/fluid/CIncIdealGas.hpp" #include "../../include/fluid/CIncIdealGasPolynomial.hpp" +#include "../../include/variables/CIncNSVariable.hpp" -CIncEulerSolver::CIncEulerSolver(void) : CSolver() { - /*--- Basic array initialization ---*/ - - CD_Inv = nullptr; CL_Inv = nullptr; CSF_Inv = nullptr; CEff_Inv = nullptr; - CMx_Inv = nullptr; CMy_Inv = nullptr; CMz_Inv = nullptr; - CFx_Inv = nullptr; CFy_Inv = nullptr; CFz_Inv = nullptr; - CoPx_Inv = nullptr; CoPy_Inv = nullptr; CoPz_Inv = nullptr; - - CD_Mnt = nullptr; CL_Mnt = nullptr; CSF_Mnt = nullptr; CEff_Mnt = nullptr; - CMx_Mnt = nullptr; CMy_Mnt = nullptr; CMz_Mnt = nullptr; - CFx_Mnt = nullptr; CFy_Mnt = nullptr; CFz_Mnt = nullptr; - CoPx_Mnt = nullptr; CoPy_Mnt = nullptr; CoPz_Mnt = nullptr; - - CPressure = nullptr; CPressureTarget = nullptr; HeatFlux = nullptr; HeatFluxTarget = nullptr; YPlus = nullptr; - ForceInviscid = nullptr; MomentInviscid = nullptr; - ForceMomentum = nullptr; MomentMomentum = nullptr; - - /*--- Surface based array initialization ---*/ - - Surface_CL_Inv = nullptr; Surface_CD_Inv = nullptr; Surface_CSF_Inv = nullptr; Surface_CEff_Inv = nullptr; - Surface_CFx_Inv = nullptr; Surface_CFy_Inv = nullptr; Surface_CFz_Inv = nullptr; - Surface_CMx_Inv = nullptr; Surface_CMy_Inv = nullptr; Surface_CMz_Inv = nullptr; - - Surface_CL_Mnt = nullptr; Surface_CD_Mnt = nullptr; Surface_CSF_Mnt = nullptr; Surface_CEff_Mnt = nullptr; - Surface_CFx_Mnt = nullptr; Surface_CFy_Mnt = nullptr; Surface_CFz_Mnt = nullptr; - Surface_CMx_Mnt = nullptr; Surface_CMy_Mnt = nullptr; Surface_CMz_Mnt = nullptr; - - Surface_CL = nullptr; Surface_CD = nullptr; Surface_CSF = nullptr; Surface_CEff = nullptr; - Surface_CFx = nullptr; Surface_CFy = nullptr; Surface_CFz = nullptr; - Surface_CMx = nullptr; Surface_CMy = nullptr; Surface_CMz = nullptr; - /*--- Rotorcraft simulation array initialization ---*/ +CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh, + const bool navier_stokes) : + CFVMFlowSolverBase() { - CMerit_Inv = nullptr; CT_Inv = nullptr; CQ_Inv = nullptr; + /*--- Based on the navier_stokes boolean, determine if this constructor is + * being called by itself, or by its derived class CIncNSSolver. ---*/ + const string description = navier_stokes? "Navier-Stokes" : "Euler"; - /*--- Numerical methods array initialization ---*/ - - iPoint_UndLapl = nullptr; - jPoint_UndLapl = nullptr; - Primitive = nullptr; Primitive_i = nullptr; Primitive_j = nullptr; - CharacPrimVar = nullptr; - Preconditioner = nullptr; - - FluidModel = nullptr; - - SlidingState = nullptr; - SlidingStateNodes = nullptr; - - nodes = nullptr; -} - -CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : CSolver() { - - unsigned long iPoint, iVertex; - unsigned short iVar, iDim, iMarker, nLineLets; + unsigned short iVar, iMarker, nLineLets; ifstream restart_file; unsigned short nZone = geometry->GetnZone(); - bool restart = (config->GetRestart() || config->GetRestart_Flow()); - string filename = config->GetSolution_FileName(); + bool restart = (config->GetRestart() || config->GetRestart_Flow()); int Unst_RestartIter; unsigned short iZone = config->GetiZone(); bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || (config->GetTime_Marching() == DT_STEPPING_2ND)); bool time_stepping = config->GetTime_Marching() == TIME_STEPPING; bool adjoint = (config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint()); - bool fsi = config->GetFSI_Simulation(); - bool multizone = config->GetMultizone_Problem(); - string filename_ = config->GetSolution_FileName(); /* A grid is defined as dynamic if there's rigid grid movement or grid deformation AND the problem is time domain */ dynamic_grid = config->GetDynamic_Grid(); - unsigned short direct_diff = config->GetDirectDiff(); - /*--- Store the multigrid level. ---*/ MGLevel = iMesh; @@ -119,6 +65,8 @@ CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned /*--- Multizone problems require the number of the zone to be appended. ---*/ + auto filename_ = config->GetSolution_FileName(); + if (nZone > 1) filename_ = config->GetMultizone_FileName(filename_, iZone, ".dat"); /*--- Modify file name for a dual-time unsteady restart ---*/ @@ -145,51 +93,6 @@ CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned } - /*--- Basic array initialization ---*/ - - CD_Inv = nullptr; CL_Inv = nullptr; CSF_Inv = nullptr; CEff_Inv = nullptr; - CMx_Inv = nullptr; CMy_Inv = nullptr; CMz_Inv = nullptr; - CFx_Inv = nullptr; CFy_Inv = nullptr; CFz_Inv = nullptr; - CoPx_Inv = nullptr; CoPy_Inv = nullptr; CoPz_Inv = nullptr; - - CD_Mnt = nullptr; CL_Mnt = nullptr; CSF_Mnt = nullptr; CEff_Mnt = nullptr; - CMx_Mnt = nullptr; CMy_Mnt = nullptr; CMz_Mnt = nullptr; - CFx_Mnt = nullptr; CFy_Mnt = nullptr; CFz_Mnt = nullptr; - CoPx_Mnt= nullptr; CoPy_Mnt= nullptr; CoPz_Mnt= nullptr; - - CPressure = nullptr; CPressureTarget = nullptr; HeatFlux = nullptr; HeatFluxTarget = nullptr; YPlus = nullptr; - ForceInviscid = nullptr; MomentInviscid = nullptr; - ForceMomentum = nullptr; MomentMomentum = nullptr; - - /*--- Surface based array initialization ---*/ - - Surface_CL_Inv = nullptr; Surface_CD_Inv = nullptr; Surface_CSF_Inv = nullptr; Surface_CEff_Inv = nullptr; - Surface_CFx_Inv = nullptr; Surface_CFy_Inv = nullptr; Surface_CFz_Inv = nullptr; - Surface_CMx_Inv = nullptr; Surface_CMy_Inv = nullptr; Surface_CMz_Inv = nullptr; - - Surface_CL_Mnt = nullptr; Surface_CD_Mnt = nullptr; Surface_CSF_Mnt = nullptr; Surface_CEff_Mnt= nullptr; - Surface_CFx_Mnt = nullptr; Surface_CFy_Mnt = nullptr; Surface_CFz_Mnt = nullptr; - Surface_CMx_Mnt = nullptr; Surface_CMy_Mnt = nullptr; Surface_CMz_Mnt = nullptr; - - Surface_CL = nullptr; Surface_CD = nullptr; Surface_CSF = nullptr; Surface_CEff = nullptr; - Surface_CMx = nullptr; Surface_CMy = nullptr; Surface_CMz = nullptr; - - /*--- Rotorcraft simulation array initialization ---*/ - - CMerit_Inv = nullptr; CT_Inv = nullptr; CQ_Inv = nullptr; - - /*--- Numerical methods array initialization ---*/ - - iPoint_UndLapl = nullptr; - jPoint_UndLapl = nullptr; - Primitive = nullptr; Primitive_i = nullptr; Primitive_j = nullptr; - CharacPrimVar = nullptr; - Preconditioner = nullptr; - - /*--- Fluid model pointer initialization ---*/ - - FluidModel = nullptr; - /*--- Set the gamma value ---*/ Gamma = config->GetGamma(); @@ -229,234 +132,45 @@ CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned SetVerificationSolution(nDim, nVar, config); - /*--- Define some auxiliary vectors related to the residual ---*/ - - Residual = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual[iVar] = 0.0; - Residual_RMS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_RMS[iVar] = 0.0; - Residual_Max = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max[iVar] = 0.0; - Res_Conv = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Res_Conv[iVar] = 0.0; - Res_Visc = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Res_Visc[iVar] = 0.0; - Res_Sour = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Res_Sour[iVar] = 0.0; + /// TODO: This type of variables will be replaced. - /*--- Define some structures for locating max residuals ---*/ - - Point_Max = new unsigned long[nVar]; - for (iVar = 0; iVar < nVar; iVar++) Point_Max[iVar] = 0; - - Point_Max_Coord = new su2double*[nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - Point_Max_Coord[iVar] = new su2double[nDim]; - for (iDim = 0; iDim < nDim; iDim++) Point_Max_Coord[iVar][iDim] = 0.0; - } - - /*--- Define some auxiliary vectors related to the solution ---*/ - - Solution = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 0.0; - Solution_i = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Solution_i[iVar] = 0.0; - Solution_j = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Solution_j[iVar] = 0.0; - - /*--- Define some auxiliary vectors related to the geometry ---*/ - - Vector = new su2double[nDim]; for (iDim = 0; iDim < nDim; iDim++) Vector[iDim] = 0.0; - Vector_i = new su2double[nDim]; for (iDim = 0; iDim < nDim; iDim++) Vector_i[iDim] = 0.0; - Vector_j = new su2double[nDim]; for (iDim = 0; iDim < nDim; iDim++) Vector_j[iDim] = 0.0; + AllocateTerribleLegacyTemporaryVariables(); /*--- Define some auxiliary vectors related to the primitive solution ---*/ - Primitive = new su2double[nPrimVar]; for (iVar = 0; iVar < nPrimVar; iVar++) Primitive[iVar] = 0.0; - Primitive_i = new su2double[nPrimVar]; for (iVar = 0; iVar < nPrimVar; iVar++) Primitive_i[iVar] = 0.0; - Primitive_j = new su2double[nPrimVar]; for (iVar = 0; iVar < nPrimVar; iVar++) Primitive_j[iVar] = 0.0; + Primitive = new su2double[nPrimVar] (); + Primitive_i = new su2double[nPrimVar] (); + Primitive_j = new su2double[nPrimVar] (); - /*--- Define some auxiliary vectors related to the undivided lapalacian ---*/ - - if (config->GetKind_ConvNumScheme_Flow() == SPACE_CENTERED) { - iPoint_UndLapl = new su2double [nPoint]; - jPoint_UndLapl = new su2double [nPoint]; - } + /*--- Allocate preconditioning matrix. ---*/ Preconditioner = new su2double* [nVar]; for (iVar = 0; iVar < nVar; iVar ++) Preconditioner[iVar] = new su2double[nVar]; - /*--- Initialize the solution and right-hand side vectors for storing - the residuals and updating the solution (always needed even for - explicit schemes). ---*/ + /*--- Allocate base class members. ---*/ - LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0); - LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0); + Allocate(*config); /*--- Jacobians and vector structures for implicit computations ---*/ if (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT) { - Jacobian_i = new su2double* [nVar]; - Jacobian_j = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - Jacobian_i[iVar] = new su2double [nVar]; - Jacobian_j[iVar] = new su2double [nVar]; - } + if (rank == MASTER_NODE) + cout << "Initialize Jacobian structure (" << description << "). MG level: " << iMesh <<"." << endl; - if (rank == MASTER_NODE) cout << "Initialize Jacobian structure (Euler). MG level: " << iMesh <<"." << endl; Jacobian.Initialize(nPoint, nPointDomain, nVar, nVar, true, geometry, config); if (config->GetKind_Linear_Solver_Prec() == LINELET) { nLineLets = Jacobian.BuildLineletPreconditioner(geometry, config); if (rank == MASTER_NODE) cout << "Compute linelet structure. " << nLineLets << " elements in each line (average)." << endl; } - } - else { - if (rank == MASTER_NODE) cout << "Explicit scheme. No Jacobian structure (Euler). MG level: " << iMesh <<"." << endl; - } - - /*--- Store the value of the characteristic primitive variables at the boundaries ---*/ - - CharacPrimVar = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - CharacPrimVar[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - CharacPrimVar[iMarker][iVertex] = new su2double [nPrimVar]; - for (iVar = 0; iVar < nPrimVar; iVar++) { - CharacPrimVar[iMarker][iVertex][iVar] = 0.0; - } - } - } - - /*--- Force definition and coefficient arrays for all of the markers ---*/ - - CPressure = new su2double* [nMarker]; - CPressureTarget = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - CPressure[iMarker] = new su2double [geometry->nVertex[iMarker]]; - CPressureTarget[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - CPressure[iMarker][iVertex] = 0.0; - CPressureTarget[iMarker][iVertex] = 0.0; - } - } - - /*--- Store the value of the Total Pressure at the inlet BC ---*/ - - Inlet_Ttotal = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_Ttotal[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - Inlet_Ttotal[iMarker][iVertex] = 0; - } - } - - /*--- Store the value of the Total Temperature at the inlet BC ---*/ - - Inlet_Ptotal = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_Ptotal[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - Inlet_Ptotal[iMarker][iVertex] = 0; - } - } - - /*--- Store the value of the Flow direction at the inlet BC ---*/ - - Inlet_FlowDir = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_FlowDir[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - Inlet_FlowDir[iMarker][iVertex] = new su2double [nDim]; - for (iDim = 0; iDim < nDim; iDim++) { - Inlet_FlowDir[iMarker][iVertex][iDim] = 0; - } - } + if (rank == MASTER_NODE) + cout << "Explicit scheme. No Jacobian structure (" << description << "). MG level: " << iMesh <<"." << endl; } - /*--- Non-dimensional coefficients ---*/ - - ForceInviscid = new su2double[nDim]; - MomentInviscid = new su2double[3]; - CD_Inv = new su2double[nMarker]; - CL_Inv = new su2double[nMarker]; - CSF_Inv = new su2double[nMarker]; - CMx_Inv = new su2double[nMarker]; - CMy_Inv = new su2double[nMarker]; - CMz_Inv = new su2double[nMarker]; - CEff_Inv = new su2double[nMarker]; - CFx_Inv = new su2double[nMarker]; - CFy_Inv = new su2double[nMarker]; - CFz_Inv = new su2double[nMarker]; - CoPx_Inv = new su2double[nMarker]; - CoPy_Inv = new su2double[nMarker]; - CoPz_Inv = new su2double[nMarker]; - - ForceMomentum = new su2double[nDim]; - MomentMomentum = new su2double[3]; - CD_Mnt = new su2double[nMarker]; - CL_Mnt = new su2double[nMarker]; - CSF_Mnt = new su2double[nMarker]; - CMx_Mnt = new su2double[nMarker]; - CMy_Mnt = new su2double[nMarker]; - CMz_Mnt = new su2double[nMarker]; - CEff_Mnt = new su2double[nMarker]; - CFx_Mnt = new su2double[nMarker]; - CFy_Mnt = new su2double[nMarker]; - CFz_Mnt = new su2double[nMarker]; - CoPx_Mnt = new su2double[nMarker]; - CoPy_Mnt = new su2double[nMarker]; - CoPz_Mnt = new su2double[nMarker]; - - Surface_CL_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CD_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CSF_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CEff_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFx_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFy_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFz_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMx_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMy_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMz_Inv = new su2double[config->GetnMarker_Monitoring()]; - - Surface_CL_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CD_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CSF_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CEff_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFx_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFy_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFz_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMx_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMy_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMz_Mnt = new su2double[config->GetnMarker_Monitoring()]; - - Surface_CL = new su2double[config->GetnMarker_Monitoring()]; - Surface_CD = new su2double[config->GetnMarker_Monitoring()]; - Surface_CSF = new su2double[config->GetnMarker_Monitoring()]; - Surface_CEff = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFx = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFy = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFz = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMx = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMy = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMz = new su2double[config->GetnMarker_Monitoring()]; - - /*--- Rotorcraft coefficients ---*/ - - CT_Inv = new su2double[nMarker]; - CQ_Inv = new su2double[nMarker]; - CMerit_Inv = new su2double[nMarker]; - - CT_Mnt = new su2double[nMarker]; - CQ_Mnt = new su2double[nMarker]; - CMerit_Mnt = new su2double[nMarker]; - - /*--- Init total coefficients ---*/ - - Total_CD = 0.0; Total_CL = 0.0; Total_CSF = 0.0; - Total_CMx = 0.0; Total_CMy = 0.0; Total_CMz = 0.0; - Total_CoPx = 0.0; Total_CoPy = 0.0; Total_CoPz = 0.0; - Total_CEff = 0.0; - Total_CFx = 0.0; Total_CFy = 0.0; Total_CFz = 0.0; - Total_CT = 0.0; Total_CQ = 0.0; Total_CMerit = 0.0; - Total_MaxHeat = 0.0; Total_Heat = 0.0; Total_ComboObj = 0.0; - Total_CpDiff = 0.0; Total_HeatFluxDiff = 0.0; Total_Custom_ObjFunc = 0.0; - /*--- Read farfield conditions ---*/ Density_Inf = config->GetDensity_FreeStreamND(); @@ -466,7 +180,7 @@ CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned /*--- Initialize the secondary values for direct derivative approxiations ---*/ - switch(direct_diff){ + switch (config->GetDirectDiff()) { case NO_DERIVATIVE: /*--- Default ---*/ break; @@ -488,185 +202,31 @@ CIncEulerSolver::CIncEulerSolver(CGeometry *geometry, CConfig *config, unsigned break; } - /*--- Initializate quantities for SlidingMesh Interface ---*/ - - SlidingState = new su2double*** [nMarker]; - SlidingStateNodes = new int* [nMarker]; - - for (iMarker = 0; iMarker < nMarker; iMarker++){ - SlidingState[iMarker] = nullptr; - SlidingStateNodes[iMarker] = nullptr; - - if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE){ - - SlidingState[iMarker] = new su2double**[geometry->GetnVertex(iMarker)]; - SlidingStateNodes[iMarker] = new int [geometry->GetnVertex(iMarker)]; - - for (iPoint = 0; iPoint < geometry->GetnVertex(iMarker); iPoint++){ - SlidingState[iMarker][iPoint] = new su2double*[nPrimVar+1]; - - SlidingStateNodes[iMarker][iPoint] = 0; - for (iVar = 0; iVar < nPrimVar+1; iVar++) - SlidingState[iMarker][iPoint][iVar] = nullptr; - } - - } - } - - /*--- Only initialize when there is a Marker_Fluid_Load defined - *--- (this avoids overhead in all other cases while a more permanent structure is being developed) ---*/ - if((config->GetnMarker_Fluid_Load() > 0) && (MGLevel == MESH_0)){ - - InitVertexTractionContainer(geometry, config); - - if (config->GetDiscrete_Adjoint()) - InitVertexTractionAdjointContainer(geometry, config); - - } - /*--- Initialize the solution to the far-field state everywhere. ---*/ - nodes = new CIncEulerVariable(Pressure_Inf, Velocity_Inf, Temperature_Inf, nPoint, nDim, nVar, config); - SetBaseClassPointerToNodes(); - - /*--- Initialize the BGS residuals in FSI problems. ---*/ - if (fsi || multizone){ - Residual_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_RMS[iVar] = 1.0; - Residual_Max_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max_BGS[iVar] = 1.0; - - /*--- Define some structures for locating max residuals ---*/ - - Point_Max_BGS = new unsigned long[nVar]; for (iVar = 0; iVar < nVar; iVar++) Point_Max_BGS[iVar] = 0; - Point_Max_Coord_BGS = new su2double*[nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - Point_Max_Coord_BGS[iVar] = new su2double[nDim]; - for (iDim = 0; iDim < nDim; iDim++) Point_Max_Coord_BGS[iVar][iDim] = 0.0; - } - } - - /*--- Define solver parameters needed for execution of destructor ---*/ - - if (config->GetKind_ConvNumScheme_Flow() == SPACE_CENTERED ) space_centered = true; - else space_centered = false; - - if (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT) euler_implicit = true; - else euler_implicit = false; - - if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) least_squares = true; - else least_squares = false; - - /*--- Communicate and store volume and the number of neighbors for - any dual CVs that lie on on periodic markers. ---*/ - - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME); - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS); + if (navier_stokes) { + nodes = new CIncNSVariable(Pressure_Inf, Velocity_Inf, Temperature_Inf, nPoint, nDim, nVar, config); + } else { + nodes = new CIncEulerVariable(Pressure_Inf, Velocity_Inf, Temperature_Inf, nPoint, nDim, nVar, config); } - SetImplicitPeriodic(euler_implicit); - if (iMesh == MESH_0) SetRotatePeriodic(true); - - /*--- Perform the MPI communication of the solution ---*/ - - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); + SetBaseClassPointerToNodes(); - /* Store the initial CFL number for all grid points. */ + /*--- Initial comms. ---*/ - const su2double CFL = config->GetCFL(MGLevel); - for (iPoint = 0; iPoint < nPoint; iPoint++) { - nodes->SetLocalCFL(iPoint, CFL); - } - Min_CFL_Local = CFL; - Max_CFL_Local = CFL; - Avg_CFL_Local = CFL; + CommunicateInitialState(geometry, config); /*--- Add the solver name (max 8 characters) ---*/ SolverName = "INC.FLOW"; + /*--- Finally, check that the static arrays will be large enough (keep this + * check at the bottom to make sure we consider the "final" values). ---*/ + if((nDim > MAXNDIM) || (nPrimVar > MAXNVAR)) + SU2_MPI::Error("Oops! The CIncEulerSolver static array sizes are not large enough.", CURRENT_FUNCTION); } CIncEulerSolver::~CIncEulerSolver(void) { - unsigned short iMarker, iVar; - unsigned long iVertex; - - /*--- Array deallocation ---*/ - - delete [] CD_Inv; - delete [] CL_Inv; - delete [] CSF_Inv; - delete [] CMx_Inv; - delete [] CMy_Inv; - delete [] CMz_Inv; - delete [] CFx_Inv; - delete [] CFy_Inv; - delete [] CFz_Inv; - delete [] CoPx_Inv; - delete [] CoPy_Inv; - delete [] CoPz_Inv; - - delete [] Surface_CL_Inv; - delete [] Surface_CD_Inv; - delete [] Surface_CSF_Inv; - delete [] Surface_CEff_Inv; - delete [] Surface_CFx_Inv; - delete [] Surface_CFy_Inv; - delete [] Surface_CFz_Inv; - delete [] Surface_CMx_Inv; - delete [] Surface_CMy_Inv; - delete [] Surface_CMz_Inv; - - delete [] CD_Mnt; - delete [] CL_Mnt; - delete [] CSF_Mnt; - delete [] CMx_Mnt; - delete [] CMy_Mnt; - delete [] CMz_Mnt; - delete [] CFx_Mnt; - delete [] CFy_Mnt; - delete [] CFz_Mnt; - delete [] CoPx_Mnt; - delete [] CoPy_Mnt; - delete [] CoPz_Mnt; - - delete [] Surface_CL_Mnt; - delete [] Surface_CD_Mnt; - delete [] Surface_CSF_Mnt; - delete [] Surface_CEff_Mnt; - delete [] Surface_CFx_Mnt; - delete [] Surface_CFy_Mnt; - delete [] Surface_CFz_Mnt; - delete [] Surface_CMx_Mnt; - delete [] Surface_CMy_Mnt; - delete [] Surface_CMz_Mnt; - - delete [] Surface_CL; - delete [] Surface_CD; - delete [] Surface_CSF; - delete [] Surface_CEff; - delete [] Surface_CFx; - delete [] Surface_CFy; - delete [] Surface_CFz; - delete [] Surface_CMx; - delete [] Surface_CMy; - delete [] Surface_CMz; - - delete [] CEff_Inv; - delete [] CMerit_Inv; - delete [] CT_Inv; - delete [] CQ_Inv; - - delete [] CEff_Mnt; - delete [] CMerit_Mnt; - delete [] CT_Mnt; - delete [] CQ_Mnt; - - delete [] ForceInviscid; - delete [] MomentInviscid; - delete [] ForceMomentum; - delete [] MomentMomentum; + unsigned short iVar; delete [] Primitive; delete [] Primitive_i; @@ -678,99 +238,7 @@ CIncEulerSolver::~CIncEulerSolver(void) { delete [] Preconditioner; } - if (CPressure != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) - delete [] CPressure[iMarker]; - delete [] CPressure; - } - - if (CPressureTarget != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) - delete [] CPressureTarget[iMarker]; - delete [] CPressureTarget; - } - - if (CharacPrimVar != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - for (iVertex = 0; iVertexGetRestart() || config->GetRestart_Flow()); - bool rans = ((config->GetKind_Solver() == INC_RANS) || - (config->GetKind_Solver() == DISC_ADJ_INC_RANS)); - bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || - (config->GetTime_Marching() == DT_STEPPING_2ND)); + const bool restart = (config->GetRestart() || config->GetRestart_Flow()); + const bool rans = (config->GetKind_Turb_Model() != NONE); + const bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || + (config->GetTime_Marching() == DT_STEPPING_2ND)); /*--- Check if a verification solution is to be computed. ---*/ if ((VerificationSolution) && (TimeIter == 0) && !restart) { @@ -1447,40 +914,8 @@ void CIncEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solve /*--- The value of the solution for the first iteration of the dual time ---*/ - if (dual_time && (TimeIter == 0 || (restart && (long)TimeIter == (long)config->GetRestart_Iter()))) { - - /*--- Push back the initial condition to previous solution containers - for a 1st-order restart or when simply intitializing to freestream. ---*/ - - for (iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { - solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n(); - solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n1(); - if (rans) { - solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n(); - solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n1(); - } - } - - if ((restart && (long)TimeIter == (long)config->GetRestart_Iter()) && - (config->GetTime_Marching() == DT_STEPPING_2ND)) { - - /*--- Load an additional restart file for a 2nd-order restart ---*/ - - solver_container[MESH_0][FLOW_SOL]->LoadRestart(geometry, solver_container, config, SU2_TYPE::Int(config->GetRestart_Iter()-1), true); - - /*--- Load an additional restart file for the turbulence model ---*/ - if (rans) - solver_container[MESH_0][TURB_SOL]->LoadRestart(geometry, solver_container, config, SU2_TYPE::Int(config->GetRestart_Iter()-1), false); - - /*--- Push back this new solution to time level N. ---*/ - - for (iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { - solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n(); - if (rans) { - solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n(); - } - } - } + if (dual_time && (TimeIter == 0 || (restart && TimeIter == config->GetRestart_Iter()))) { + PushSolutionBackInTime(TimeIter, restart, rans, solver_container, geometry, config); } } @@ -2545,902 +1980,133 @@ void CIncEulerSolver::SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfi } -void CIncEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { +void CIncEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iRKStep) { - unsigned long iVertex, iPoint; - unsigned short iDim, iMarker, Boundary, Monitoring, iMarker_Monitoring; - su2double Pressure = 0.0, *Normal = nullptr, MomentDist[3] = {0.0,0.0,0.0}, *Coord, - factor, RefVel2 = 0.0, RefDensity = 0.0, RefPressure, - Force[3] = {0.0,0.0,0.0}; - su2double MomentX_Force[3] = {0.0,0.0,0.0}, MomentY_Force[3] = {0.0,0.0,0.0}, MomentZ_Force[3] = {0.0,0.0,0.0}; - su2double AxiFactor; + su2double *Residual, *Res_TruncError, Vol, Delta, Res; + unsigned short iVar, jVar; + unsigned long iPoint; - bool axisymmetric = config->GetAxisymmetric(); + su2double RK_AlphaCoeff = config->Get_Alpha_RKStep(iRKStep); + bool adjoint = config->GetContinuous_Adjoint(); + + for (iVar = 0; iVar < nVar; iVar++) { + SetRes_RMS(iVar, 0.0); + SetRes_Max(iVar, 0.0, 0); + } - string Marker_Tag, Monitoring_Tag; + /*--- Update the solution ---*/ -#ifdef HAVE_MPI - su2double MyAllBound_CD_Inv, MyAllBound_CL_Inv, MyAllBound_CSF_Inv, MyAllBound_CMx_Inv, MyAllBound_CMy_Inv, MyAllBound_CMz_Inv, MyAllBound_CoPx_Inv, MyAllBound_CoPy_Inv, MyAllBound_CoPz_Inv, MyAllBound_CFx_Inv, MyAllBound_CFy_Inv, MyAllBound_CFz_Inv, MyAllBound_CT_Inv, MyAllBound_CQ_Inv, *MySurface_CL_Inv = NULL, *MySurface_CD_Inv = NULL, *MySurface_CSF_Inv = NULL, *MySurface_CEff_Inv = NULL, *MySurface_CFx_Inv = NULL, *MySurface_CFy_Inv = NULL, *MySurface_CFz_Inv = NULL, *MySurface_CMx_Inv = NULL, *MySurface_CMy_Inv = NULL, *MySurface_CMz_Inv = NULL; -#endif + for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + Vol = (geometry->nodes->GetVolume(iPoint) + + geometry->nodes->GetPeriodicVolume(iPoint)); + Delta = nodes->GetDelta_Time(iPoint) / Vol; - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - su2double RefArea = config->GetRefArea(); - su2double RefLength = config->GetRefLength(); + Res_TruncError = nodes->GetResTruncError(iPoint); + Residual = LinSysRes.GetBlock(iPoint); - su2double *Origin = nullptr; - if (config->GetnMarker_Monitoring() != 0){ - Origin = config->GetRefOriginMoment(0); + if (!adjoint) { + SetPreconditioner(config, iPoint); + for (iVar = 0; iVar < nVar; iVar ++ ) { + Res = 0.0; + for (jVar = 0; jVar < nVar; jVar ++ ) + Res += Preconditioner[iVar][jVar]*(Residual[jVar] + Res_TruncError[jVar]); + nodes->AddSolution(iPoint,iVar, -Res*Delta*RK_AlphaCoeff); + AddRes_RMS(iVar, Res*Res); + AddRes_Max(iVar, fabs(Res), geometry->nodes->GetGlobalIndex(iPoint), geometry->nodes->GetCoord(iPoint)); + } + } } - /*--- Evaluate reference values for non-dimensionalization. - For dimensional or non-dim based on initial values, use - the far-field state (inf). For a custom non-dim based - on user-provided reference values, use the ref values - to compute the forces. ---*/ + /*--- MPI solution ---*/ - if ((config->GetRef_Inc_NonDim() == DIMENSIONAL) || - (config->GetRef_Inc_NonDim() == INITIAL_VALUES)) { - RefDensity = Density_Inf; - RefVel2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - RefVel2 += Velocity_Inf[iDim]*Velocity_Inf[iDim]; - } - else if (config->GetRef_Inc_NonDim() == REFERENCE_VALUES) { - RefDensity = config->GetInc_Density_Ref(); - RefVel2 = config->GetInc_Velocity_Ref()*config->GetInc_Velocity_Ref(); - } + InitiateComms(geometry, config, SOLUTION); + CompleteComms(geometry, config, SOLUTION); - /*--- Reference pressure is always the far-field value. ---*/ + /*--- Compute the root mean square residual ---*/ - RefPressure = Pressure_Inf; + SetResidual_RMS(geometry, config); - /*--- Compute factor for force coefficients. ---*/ + /*--- For verification cases, compute the global error metrics. ---*/ - factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2); + ComputeVerificationError(geometry, config); - /*-- Variables initialization ---*/ +} - Total_CD = 0.0; Total_CL = 0.0; Total_CSF = 0.0; Total_CEff = 0.0; - Total_CMx = 0.0; Total_CMy = 0.0; Total_CMz = 0.0; - Total_CoPx = 0.0; Total_CoPy = 0.0; Total_CoPz = 0.0; - Total_CFx = 0.0; Total_CFy = 0.0; Total_CFz = 0.0; - Total_CT = 0.0; Total_CQ = 0.0; Total_CMerit = 0.0; - Total_Heat = 0.0; Total_MaxHeat = 0.0; +void CIncEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - AllBound_CD_Inv = 0.0; AllBound_CL_Inv = 0.0; AllBound_CSF_Inv = 0.0; - AllBound_CMx_Inv = 0.0; AllBound_CMy_Inv = 0.0; AllBound_CMz_Inv = 0.0; - AllBound_CoPx_Inv = 0.0; AllBound_CoPy_Inv = 0.0; AllBound_CoPz_Inv = 0.0; - AllBound_CFx_Inv = 0.0; AllBound_CFy_Inv = 0.0; AllBound_CFz_Inv = 0.0; - AllBound_CT_Inv = 0.0; AllBound_CQ_Inv = 0.0; AllBound_CMerit_Inv = 0.0; - AllBound_CEff_Inv = 0.0; + su2double *local_Residual, *local_Res_TruncError, Vol, Delta, Res; + unsigned short iVar, jVar; + unsigned long iPoint; - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Surface_CL_Inv[iMarker_Monitoring] = 0.0; Surface_CD_Inv[iMarker_Monitoring] = 0.0; - Surface_CSF_Inv[iMarker_Monitoring] = 0.0; Surface_CEff_Inv[iMarker_Monitoring] = 0.0; - Surface_CFx_Inv[iMarker_Monitoring] = 0.0; Surface_CFy_Inv[iMarker_Monitoring] = 0.0; - Surface_CFz_Inv[iMarker_Monitoring] = 0.0; Surface_CMx_Inv[iMarker_Monitoring] = 0.0; - Surface_CMy_Inv[iMarker_Monitoring] = 0.0; Surface_CMz_Inv[iMarker_Monitoring] = 0.0; + bool adjoint = config->GetContinuous_Adjoint(); - Surface_CL[iMarker_Monitoring] = 0.0; Surface_CD[iMarker_Monitoring] = 0.0; - Surface_CSF[iMarker_Monitoring] = 0.0; Surface_CEff[iMarker_Monitoring] = 0.0; - Surface_CFx[iMarker_Monitoring] = 0.0; Surface_CFy[iMarker_Monitoring] = 0.0; - Surface_CFz[iMarker_Monitoring] = 0.0; Surface_CMx[iMarker_Monitoring] = 0.0; - Surface_CMy[iMarker_Monitoring] = 0.0; Surface_CMz[iMarker_Monitoring] = 0.0; + for (iVar = 0; iVar < nVar; iVar++) { + SetRes_RMS(iVar, 0.0); + SetRes_Max(iVar, 0.0, 0); } - /*--- Loop over the Euler and Navier-Stokes markers ---*/ + /*--- Update the solution ---*/ - for (iMarker = 0; iMarker < nMarker; iMarker++) { + for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + Vol = (geometry->nodes->GetVolume(iPoint) + + geometry->nodes->GetPeriodicVolume(iPoint)); + Delta = nodes->GetDelta_Time(iPoint) / Vol; - Boundary = config->GetMarker_All_KindBC(iMarker); - Monitoring = config->GetMarker_All_Monitoring(iMarker); + local_Res_TruncError = nodes->GetResTruncError(iPoint); + local_Residual = LinSysRes.GetBlock(iPoint); - /*--- Obtain the origin for the moment computation for a particular marker ---*/ - if (Monitoring == YES) { - 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); - if (Marker_Tag == Monitoring_Tag) - Origin = config->GetRefOriginMoment(iMarker_Monitoring); + if (!adjoint) { + SetPreconditioner(config, iPoint); + for (iVar = 0; iVar < nVar; iVar ++ ) { + Res = 0.0; + for (jVar = 0; jVar < nVar; jVar ++ ) + Res += Preconditioner[iVar][jVar]*(local_Residual[jVar] + local_Res_TruncError[jVar]); + nodes->AddSolution(iPoint,iVar, -Res*Delta); + AddRes_RMS(iVar, Res*Res); + AddRes_Max(iVar, fabs(Res), geometry->nodes->GetGlobalIndex(iPoint), geometry->nodes->GetCoord(iPoint)); } } + } - if ((Boundary == EULER_WALL) || (Boundary == HEAT_FLUX) || - (Boundary == ISOTHERMAL) || (Boundary == NEARFIELD_BOUNDARY) || - (Boundary == CHT_WALL_INTERFACE) || - (Boundary == INLET_FLOW) || (Boundary == OUTLET_FLOW) || - (Boundary == ACTDISK_INLET) || (Boundary == ACTDISK_OUTLET)|| - (Boundary == ENGINE_INFLOW) || (Boundary == ENGINE_EXHAUST)) { + /*--- MPI solution ---*/ - /*--- Forces initialization at each Marker ---*/ + InitiateComms(geometry, config, SOLUTION); + CompleteComms(geometry, config, SOLUTION); - CD_Inv[iMarker] = 0.0; CL_Inv[iMarker] = 0.0; CSF_Inv[iMarker] = 0.0; - CMx_Inv[iMarker] = 0.0; CMy_Inv[iMarker] = 0.0; CMz_Inv[iMarker] = 0.0; - CoPx_Inv[iMarker] = 0.0; CoPy_Inv[iMarker] = 0.0; CoPz_Inv[iMarker] = 0.0; - CFx_Inv[iMarker] = 0.0; CFy_Inv[iMarker] = 0.0; CFz_Inv[iMarker] = 0.0; - CT_Inv[iMarker] = 0.0; CQ_Inv[iMarker] = 0.0; CMerit_Inv[iMarker] = 0.0; - CEff_Inv[iMarker] = 0.0; + /*--- Compute the root mean square residual ---*/ - for (iDim = 0; iDim < nDim; iDim++) ForceInviscid[iDim] = 0.0; - MomentInviscid[0] = 0.0; MomentInviscid[1] = 0.0; MomentInviscid[2] = 0.0; - MomentX_Force[0] = 0.0; MomentX_Force[1] = 0.0; MomentX_Force[2] = 0.0; - MomentY_Force[0] = 0.0; MomentY_Force[1] = 0.0; MomentY_Force[2] = 0.0; - MomentZ_Force[0] = 0.0; MomentZ_Force[1] = 0.0; MomentZ_Force[2] = 0.0; + SetResidual_RMS(geometry, config); - /*--- Loop over the vertices to compute the forces ---*/ + /*--- For verification cases, compute the global error metrics. ---*/ - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { + ComputeVerificationError(geometry, config); - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); +} - Pressure = nodes->GetPressure(iPoint); +void CIncEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - CPressure[iMarker][iVertex] = (Pressure - RefPressure)*factor*RefArea; + unsigned short iVar, jVar; + unsigned long iPoint, total_index, IterLinSol = 0; + su2double Delta, *local_Res_TruncError, Vol; - /*--- Note that the pressure coefficient is computed at the - halo cells (for visualization purposes), but not the forces ---*/ + bool adjoint = config->GetContinuous_Adjoint(); - if ( (geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES) ) { + /*--- Set maximum residual to zero ---*/ - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - Coord = geometry->nodes->GetCoord(iPoint); + for (iVar = 0; iVar < nVar; iVar++) { + SetRes_RMS(iVar, 0.0); + SetRes_Max(iVar, 0.0, 0); + } - for (iDim = 0; iDim < nDim; iDim++) { - MomentDist[iDim] = Coord[iDim] - Origin[iDim]; - } + /*--- Build implicit system ---*/ - /*--- Axisymmetric simulations ---*/ + for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - if (axisymmetric) AxiFactor = 2.0*PI_NUMBER*geometry->nodes->GetCoord(iPoint, 1); - else AxiFactor = 1.0; + /*--- Read the residual ---*/ - /*--- Force computation, note the minus sign due to the - orientation of the normal (outward) ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Force[iDim] = -(Pressure - Pressure_Inf) * Normal[iDim] * factor * AxiFactor; - ForceInviscid[iDim] += Force[iDim]; - } - - /*--- Moment with respect to the reference axis ---*/ - - if (nDim == 3) { - MomentInviscid[0] += (Force[2]*MomentDist[1]-Force[1]*MomentDist[2])/RefLength; - MomentX_Force[1] += (-Force[1]*Coord[2]); - MomentX_Force[2] += (Force[2]*Coord[1]); - - MomentInviscid[1] += (Force[0]*MomentDist[2]-Force[2]*MomentDist[0])/RefLength; - MomentY_Force[2] += (-Force[2]*Coord[0]); - MomentY_Force[0] += (Force[0]*Coord[2]); - } - MomentInviscid[2] += (Force[1]*MomentDist[0]-Force[0]*MomentDist[1])/RefLength; - MomentZ_Force[0] += (-Force[0]*Coord[1]); - MomentZ_Force[1] += (Force[1]*Coord[0]); - } - - } - - /*--- Project forces and store the non-dimensional coefficients ---*/ - - if (Monitoring == YES) { - - if (Boundary != NEARFIELD_BOUNDARY) { - if (nDim == 2) { - CD_Inv[iMarker] = ForceInviscid[0]*cos(Alpha) + ForceInviscid[1]*sin(Alpha); - CL_Inv[iMarker] = -ForceInviscid[0]*sin(Alpha) + ForceInviscid[1]*cos(Alpha); - CEff_Inv[iMarker] = CL_Inv[iMarker] / (CD_Inv[iMarker]+EPS); - CMz_Inv[iMarker] = MomentInviscid[2]; - CoPx_Inv[iMarker] = MomentZ_Force[1]; - CoPy_Inv[iMarker] = -MomentZ_Force[0]; - CFx_Inv[iMarker] = ForceInviscid[0]; - CFy_Inv[iMarker] = ForceInviscid[1]; - CT_Inv[iMarker] = -CFx_Inv[iMarker]; - CQ_Inv[iMarker] = -CMz_Inv[iMarker]; - CMerit_Inv[iMarker] = CT_Inv[iMarker] / (CQ_Inv[iMarker] + EPS); - } - if (nDim == 3) { - CD_Inv[iMarker] = ForceInviscid[0]*cos(Alpha)*cos(Beta) + ForceInviscid[1]*sin(Beta) + ForceInviscid[2]*sin(Alpha)*cos(Beta); - CL_Inv[iMarker] = -ForceInviscid[0]*sin(Alpha) + ForceInviscid[2]*cos(Alpha); - CSF_Inv[iMarker] = -ForceInviscid[0]*sin(Beta)*cos(Alpha) + ForceInviscid[1]*cos(Beta) - ForceInviscid[2]*sin(Beta)*sin(Alpha); - CEff_Inv[iMarker] = CL_Inv[iMarker] / (CD_Inv[iMarker] + EPS); - CMx_Inv[iMarker] = MomentInviscid[0]; - CMy_Inv[iMarker] = MomentInviscid[1]; - CMz_Inv[iMarker] = MomentInviscid[2]; - CoPx_Inv[iMarker] = -MomentY_Force[0]; - CoPz_Inv[iMarker] = MomentY_Force[2]; - CFx_Inv[iMarker] = ForceInviscid[0]; - CFy_Inv[iMarker] = ForceInviscid[1]; - CFz_Inv[iMarker] = ForceInviscid[2]; - CT_Inv[iMarker] = -CFz_Inv[iMarker]; - CQ_Inv[iMarker] = -CMz_Inv[iMarker]; - CMerit_Inv[iMarker] = CT_Inv[iMarker] / (CQ_Inv[iMarker] + EPS); - } - - AllBound_CD_Inv += CD_Inv[iMarker]; - AllBound_CL_Inv += CL_Inv[iMarker]; - AllBound_CSF_Inv += CSF_Inv[iMarker]; - AllBound_CEff_Inv = AllBound_CL_Inv / (AllBound_CD_Inv + EPS); - AllBound_CMx_Inv += CMx_Inv[iMarker]; - AllBound_CMy_Inv += CMy_Inv[iMarker]; - AllBound_CMz_Inv += CMz_Inv[iMarker]; - AllBound_CoPx_Inv += CoPx_Inv[iMarker]; - AllBound_CoPy_Inv += CoPy_Inv[iMarker]; - AllBound_CoPz_Inv += CoPz_Inv[iMarker]; - AllBound_CFx_Inv += CFx_Inv[iMarker]; - AllBound_CFy_Inv += CFy_Inv[iMarker]; - AllBound_CFz_Inv += CFz_Inv[iMarker]; - AllBound_CT_Inv += CT_Inv[iMarker]; - AllBound_CQ_Inv += CQ_Inv[iMarker]; - AllBound_CMerit_Inv = AllBound_CT_Inv / (AllBound_CQ_Inv + EPS); - - /*--- 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); - if (Marker_Tag == Monitoring_Tag) { - Surface_CL_Inv[iMarker_Monitoring] += CL_Inv[iMarker]; - Surface_CD_Inv[iMarker_Monitoring] += CD_Inv[iMarker]; - Surface_CSF_Inv[iMarker_Monitoring] += CSF_Inv[iMarker]; - Surface_CEff_Inv[iMarker_Monitoring] = CL_Inv[iMarker] / (CD_Inv[iMarker] + EPS); - Surface_CFx_Inv[iMarker_Monitoring] += CFx_Inv[iMarker]; - Surface_CFy_Inv[iMarker_Monitoring] += CFy_Inv[iMarker]; - Surface_CFz_Inv[iMarker_Monitoring] += CFz_Inv[iMarker]; - Surface_CMx_Inv[iMarker_Monitoring] += CMx_Inv[iMarker]; - Surface_CMy_Inv[iMarker_Monitoring] += CMy_Inv[iMarker]; - Surface_CMz_Inv[iMarker_Monitoring] += CMz_Inv[iMarker]; - } - } - - } - - } - - } - } - -#ifdef HAVE_MPI - - /*--- Add AllBound information using all the nodes ---*/ - - MyAllBound_CD_Inv = AllBound_CD_Inv; AllBound_CD_Inv = 0.0; - MyAllBound_CL_Inv = AllBound_CL_Inv; AllBound_CL_Inv = 0.0; - MyAllBound_CSF_Inv = AllBound_CSF_Inv; AllBound_CSF_Inv = 0.0; - AllBound_CEff_Inv = 0.0; - MyAllBound_CMx_Inv = AllBound_CMx_Inv; AllBound_CMx_Inv = 0.0; - MyAllBound_CMy_Inv = AllBound_CMy_Inv; AllBound_CMy_Inv = 0.0; - MyAllBound_CMz_Inv = AllBound_CMz_Inv; AllBound_CMz_Inv = 0.0; - MyAllBound_CoPx_Inv = AllBound_CoPx_Inv; AllBound_CoPx_Inv = 0.0; - MyAllBound_CoPy_Inv = AllBound_CoPy_Inv; AllBound_CoPy_Inv = 0.0; - MyAllBound_CoPz_Inv = AllBound_CoPz_Inv; AllBound_CoPz_Inv = 0.0; - MyAllBound_CFx_Inv = AllBound_CFx_Inv; AllBound_CFx_Inv = 0.0; - MyAllBound_CFy_Inv = AllBound_CFy_Inv; AllBound_CFy_Inv = 0.0; - MyAllBound_CFz_Inv = AllBound_CFz_Inv; AllBound_CFz_Inv = 0.0; - MyAllBound_CT_Inv = AllBound_CT_Inv; AllBound_CT_Inv = 0.0; - MyAllBound_CQ_Inv = AllBound_CQ_Inv; AllBound_CQ_Inv = 0.0; - AllBound_CMerit_Inv = 0.0; - - if (config->GetComm_Level() == COMM_FULL) { - SU2_MPI::Allreduce(&MyAllBound_CD_Inv, &AllBound_CD_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CL_Inv, &AllBound_CL_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CSF_Inv, &AllBound_CSF_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - AllBound_CEff_Inv = AllBound_CL_Inv / (AllBound_CD_Inv + EPS); - SU2_MPI::Allreduce(&MyAllBound_CMx_Inv, &AllBound_CMx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CMy_Inv, &AllBound_CMy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CMz_Inv, &AllBound_CMz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPx_Inv, &AllBound_CoPx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPy_Inv, &AllBound_CoPy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPz_Inv, &AllBound_CoPz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFx_Inv, &AllBound_CFx_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFy_Inv, &AllBound_CFy_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFz_Inv, &AllBound_CFz_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CT_Inv, &AllBound_CT_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CQ_Inv, &AllBound_CQ_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - AllBound_CMerit_Inv = AllBound_CT_Inv / (AllBound_CQ_Inv + EPS); - } - - /*--- Add the forces on the surfaces using all the nodes ---*/ - - MySurface_CL_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CD_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CSF_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CEff_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFx_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFy_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFz_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMx_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMy_Inv = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMz_Inv = new su2double[config->GetnMarker_Monitoring()]; - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - MySurface_CL_Inv[iMarker_Monitoring] = Surface_CL_Inv[iMarker_Monitoring]; - MySurface_CD_Inv[iMarker_Monitoring] = Surface_CD_Inv[iMarker_Monitoring]; - MySurface_CSF_Inv[iMarker_Monitoring] = Surface_CSF_Inv[iMarker_Monitoring]; - MySurface_CEff_Inv[iMarker_Monitoring] = Surface_CEff_Inv[iMarker_Monitoring]; - MySurface_CFx_Inv[iMarker_Monitoring] = Surface_CFx_Inv[iMarker_Monitoring]; - MySurface_CFy_Inv[iMarker_Monitoring] = Surface_CFy_Inv[iMarker_Monitoring]; - MySurface_CFz_Inv[iMarker_Monitoring] = Surface_CFz_Inv[iMarker_Monitoring]; - MySurface_CMx_Inv[iMarker_Monitoring] = Surface_CMx_Inv[iMarker_Monitoring]; - MySurface_CMy_Inv[iMarker_Monitoring] = Surface_CMy_Inv[iMarker_Monitoring]; - MySurface_CMz_Inv[iMarker_Monitoring] = Surface_CMz_Inv[iMarker_Monitoring]; - - Surface_CL_Inv[iMarker_Monitoring] = 0.0; - Surface_CD_Inv[iMarker_Monitoring] = 0.0; - Surface_CSF_Inv[iMarker_Monitoring] = 0.0; - Surface_CEff_Inv[iMarker_Monitoring] = 0.0; - Surface_CFx_Inv[iMarker_Monitoring] = 0.0; - Surface_CFy_Inv[iMarker_Monitoring] = 0.0; - Surface_CFz_Inv[iMarker_Monitoring] = 0.0; - Surface_CMx_Inv[iMarker_Monitoring] = 0.0; - Surface_CMy_Inv[iMarker_Monitoring] = 0.0; - Surface_CMz_Inv[iMarker_Monitoring] = 0.0; - } - - if (config->GetComm_Level() == COMM_FULL) { - SU2_MPI::Allreduce(MySurface_CL_Inv, Surface_CL_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CD_Inv, Surface_CD_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CSF_Inv, Surface_CSF_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) - Surface_CEff_Inv[iMarker_Monitoring] = Surface_CL_Inv[iMarker_Monitoring] / (Surface_CD_Inv[iMarker_Monitoring] + EPS); - SU2_MPI::Allreduce(MySurface_CFx_Inv, Surface_CFx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CFy_Inv, Surface_CFy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CFz_Inv, Surface_CFz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMx_Inv, Surface_CMx_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMy_Inv, Surface_CMy_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMz_Inv, Surface_CMz_Inv, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - } - - delete [] MySurface_CL_Inv; delete [] MySurface_CD_Inv; delete [] MySurface_CSF_Inv; - delete [] MySurface_CEff_Inv; delete [] MySurface_CFx_Inv; delete [] MySurface_CFy_Inv; - delete [] MySurface_CFz_Inv; delete [] MySurface_CMx_Inv; delete [] MySurface_CMy_Inv; - delete [] MySurface_CMz_Inv; - -#endif - - /*--- Update the total coefficients (note that all the nodes have the same value) ---*/ - - Total_CD = AllBound_CD_Inv; - Total_CL = AllBound_CL_Inv; - Total_CSF = AllBound_CSF_Inv; - Total_CEff = Total_CL / (Total_CD + EPS); - Total_CMx = AllBound_CMx_Inv; - Total_CMy = AllBound_CMy_Inv; - Total_CMz = AllBound_CMz_Inv; - Total_CoPx = AllBound_CoPx_Inv; - Total_CoPy = AllBound_CoPy_Inv; - Total_CoPz = AllBound_CoPz_Inv; - Total_CFx = AllBound_CFx_Inv; - Total_CFy = AllBound_CFy_Inv; - Total_CFz = AllBound_CFz_Inv; - Total_CT = AllBound_CT_Inv; - Total_CQ = AllBound_CQ_Inv; - Total_CMerit = Total_CT / (Total_CQ + EPS); - - /*--- Update the total coefficients per surface (note that all the nodes have the same value)---*/ - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Surface_CL[iMarker_Monitoring] = Surface_CL_Inv[iMarker_Monitoring]; - Surface_CD[iMarker_Monitoring] = Surface_CD_Inv[iMarker_Monitoring]; - Surface_CSF[iMarker_Monitoring] = Surface_CSF_Inv[iMarker_Monitoring]; - Surface_CEff[iMarker_Monitoring] = Surface_CL_Inv[iMarker_Monitoring] / (Surface_CD_Inv[iMarker_Monitoring] + EPS); - Surface_CFx[iMarker_Monitoring] = Surface_CFx_Inv[iMarker_Monitoring]; - Surface_CFy[iMarker_Monitoring] = Surface_CFy_Inv[iMarker_Monitoring]; - Surface_CFz[iMarker_Monitoring] = Surface_CFz_Inv[iMarker_Monitoring]; - Surface_CMx[iMarker_Monitoring] = Surface_CMx_Inv[iMarker_Monitoring]; - Surface_CMy[iMarker_Monitoring] = Surface_CMy_Inv[iMarker_Monitoring]; - Surface_CMz[iMarker_Monitoring] = Surface_CMz_Inv[iMarker_Monitoring]; - } - -} - -void CIncEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { - - unsigned long iVertex, iPoint; - unsigned short iDim, iMarker, Boundary, Monitoring, iMarker_Monitoring; - su2double *Normal = nullptr, MomentDist[3] = {0.0,0.0,0.0}, *Coord, Area, - factor, RefVel2 = 0.0, RefDensity = 0.0, - Force[3] = {0.0,0.0,0.0}, Velocity[3], MassFlow, Density; - string Marker_Tag, Monitoring_Tag; - su2double MomentX_Force[3] = {0.0,0.0,0.0}, MomentY_Force[3] = {0.0,0.0,0.0}, MomentZ_Force[3] = {0.0,0.0,0.0}; - su2double AxiFactor; - -#ifdef HAVE_MPI - su2double MyAllBound_CD_Mnt, MyAllBound_CL_Mnt, MyAllBound_CSF_Mnt, - MyAllBound_CMx_Mnt, MyAllBound_CMy_Mnt, MyAllBound_CMz_Mnt, - MyAllBound_CoPx_Mnt, MyAllBound_CoPy_Mnt, MyAllBound_CoPz_Mnt, - MyAllBound_CFx_Mnt, MyAllBound_CFy_Mnt, MyAllBound_CFz_Mnt, MyAllBound_CT_Mnt, - MyAllBound_CQ_Mnt, - *MySurface_CL_Mnt = NULL, *MySurface_CD_Mnt = NULL, *MySurface_CSF_Mnt = NULL, - *MySurface_CEff_Mnt = NULL, *MySurface_CFx_Mnt = NULL, *MySurface_CFy_Mnt = NULL, - *MySurface_CFz_Mnt = NULL, - *MySurface_CMx_Mnt = NULL, *MySurface_CMy_Mnt = NULL, *MySurface_CMz_Mnt = NULL; -#endif - - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - su2double RefArea = config->GetRefArea(); - su2double RefLength = config->GetRefLength(); - su2double *Origin = nullptr; - if (config->GetnMarker_Monitoring() != 0){ - Origin = config->GetRefOriginMoment(0); - } - bool axisymmetric = config->GetAxisymmetric(); - - /*--- Evaluate reference values for non-dimensionalization. - For dimensional or non-dim based on initial values, use - the far-field state (inf). For a custom non-dim based - on user-provided reference values, use the ref values - to compute the forces. ---*/ - - if ((config->GetRef_Inc_NonDim() == DIMENSIONAL) || - (config->GetRef_Inc_NonDim() == INITIAL_VALUES)) { - RefDensity = Density_Inf; - RefVel2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - RefVel2 += Velocity_Inf[iDim]*Velocity_Inf[iDim]; - } - else if (config->GetRef_Inc_NonDim() == REFERENCE_VALUES) { - RefDensity = config->GetInc_Density_Ref(); - RefVel2 = config->GetInc_Velocity_Ref()*config->GetInc_Velocity_Ref(); - } - - /*--- Compute factor for force coefficients. ---*/ - - factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2); - - /*-- Variables initialization ---*/ - - AllBound_CD_Mnt = 0.0; AllBound_CL_Mnt = 0.0; AllBound_CSF_Mnt = 0.0; - AllBound_CMx_Mnt = 0.0; AllBound_CMy_Mnt = 0.0; AllBound_CMz_Mnt = 0.0; - AllBound_CoPx_Mnt = 0.0; AllBound_CoPy_Mnt = 0.0; AllBound_CoPz_Mnt = 0.0; - AllBound_CFx_Mnt = 0.0; AllBound_CFy_Mnt = 0.0; AllBound_CFz_Mnt = 0.0; - AllBound_CT_Mnt = 0.0; AllBound_CQ_Mnt = 0.0; AllBound_CMerit_Mnt = 0.0; - AllBound_CEff_Mnt = 0.0; - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Surface_CL_Mnt[iMarker_Monitoring] = 0.0; Surface_CD_Mnt[iMarker_Monitoring] = 0.0; - Surface_CSF_Mnt[iMarker_Monitoring] = 0.0; Surface_CEff_Mnt[iMarker_Monitoring] = 0.0; - Surface_CFx_Mnt[iMarker_Monitoring] = 0.0; Surface_CFy_Mnt[iMarker_Monitoring] = 0.0; - Surface_CFz_Mnt[iMarker_Monitoring] = 0.0; - Surface_CMx_Mnt[iMarker_Monitoring] = 0.0; Surface_CMy_Mnt[iMarker_Monitoring] = 0.0; Surface_CMz_Mnt[iMarker_Monitoring] = 0.0; - } - - /*--- Loop over the Inlet / Outlet Markers ---*/ - - for (iMarker = 0; iMarker < nMarker; iMarker++) { - - Boundary = config->GetMarker_All_KindBC(iMarker); - Monitoring = config->GetMarker_All_Monitoring(iMarker); - - /*--- Obtain the origin for the moment computation for a particular marker ---*/ - - if (Monitoring == YES) { - 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); - if (Marker_Tag == Monitoring_Tag) - Origin = config->GetRefOriginMoment(iMarker_Monitoring); - } - } - - if ((Boundary == INLET_FLOW) || (Boundary == OUTLET_FLOW) || - (Boundary == ACTDISK_INLET) || (Boundary == ACTDISK_OUTLET)|| - (Boundary == ENGINE_INFLOW) || (Boundary == ENGINE_EXHAUST)) { - - /*--- Forces initialization at each Marker ---*/ - - CD_Mnt[iMarker] = 0.0; CL_Mnt[iMarker] = 0.0; CSF_Mnt[iMarker] = 0.0; - CMx_Mnt[iMarker] = 0.0; CMy_Mnt[iMarker] = 0.0; CMz_Mnt[iMarker] = 0.0; - CFx_Mnt[iMarker] = 0.0; CFy_Mnt[iMarker] = 0.0; CFz_Mnt[iMarker] = 0.0; - CoPx_Mnt[iMarker] = 0.0; CoPy_Mnt[iMarker] = 0.0; CoPz_Mnt[iMarker] = 0.0; - CT_Mnt[iMarker] = 0.0; CQ_Mnt[iMarker] = 0.0; CMerit_Mnt[iMarker] = 0.0; - CEff_Mnt[iMarker] = 0.0; - - for (iDim = 0; iDim < nDim; iDim++) ForceMomentum[iDim] = 0.0; - MomentMomentum[0] = 0.0; MomentMomentum[1] = 0.0; MomentMomentum[2] = 0.0; - MomentX_Force[0] = 0.0; MomentX_Force[1] = 0.0; MomentX_Force[2] = 0.0; - MomentY_Force[0] = 0.0; MomentY_Force[1] = 0.0; MomentY_Force[2] = 0.0; - MomentZ_Force[0] = 0.0; MomentZ_Force[1] = 0.0; MomentZ_Force[2] = 0.0; - - /*--- Loop over the vertices to compute the forces ---*/ - - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - - /*--- Note that the pressure coefficient is computed at the - halo cells (for visualization purposes), but not the forces ---*/ - - if ( (geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES) ) { - - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - Coord = geometry->nodes->GetCoord(iPoint); - Density = nodes->GetDensity(iPoint); - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); - - MassFlow = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity[iDim] = nodes->GetVelocity(iPoint,iDim); - MomentDist[iDim] = Coord[iDim] - Origin[iDim]; - MassFlow -= Normal[iDim]*Velocity[iDim]*Density; - } - - /*--- Axisymmetric simulations ---*/ - - if (axisymmetric) AxiFactor = 2.0*PI_NUMBER*geometry->nodes->GetCoord(iPoint, 1); - else AxiFactor = 1.0; - - /*--- Force computation, note the minus sign due to the - orientation of the normal (outward) ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Force[iDim] = MassFlow * Velocity[iDim] * factor * AxiFactor; - ForceMomentum[iDim] += Force[iDim]; - } - - /*--- Moment with respect to the reference axis ---*/ - - if (iDim == 3) { - MomentMomentum[0] += (Force[2]*MomentDist[1]-Force[1]*MomentDist[2])/RefLength; - MomentX_Force[1] += (-Force[1]*Coord[2]); - MomentX_Force[2] += (Force[2]*Coord[1]); - - MomentMomentum[1] += (Force[0]*MomentDist[2]-Force[2]*MomentDist[0])/RefLength; - MomentY_Force[2] += (-Force[2]*Coord[0]); - MomentY_Force[0] += (Force[0]*Coord[2]); - } - MomentMomentum[2] += (Force[1]*MomentDist[0]-Force[0]*MomentDist[1])/RefLength; - MomentZ_Force[0] += (-Force[0]*Coord[1]); - MomentZ_Force[1] += (Force[1]*Coord[0]); - - } - - } - - /*--- Project forces and store the non-dimensional coefficients ---*/ - - if (Monitoring == YES) { - - if (nDim == 2) { - CD_Mnt[iMarker] = ForceMomentum[0]*cos(Alpha) + ForceMomentum[1]*sin(Alpha); - CL_Mnt[iMarker] = -ForceMomentum[0]*sin(Alpha) + ForceMomentum[1]*cos(Alpha); - CEff_Mnt[iMarker] = CL_Mnt[iMarker] / (CD_Mnt[iMarker]+EPS); - CMz_Mnt[iMarker] = MomentInviscid[2]; - CFx_Mnt[iMarker] = ForceMomentum[0]; - CFy_Mnt[iMarker] = ForceMomentum[1]; - CoPx_Mnt[iMarker] = MomentZ_Force[1]; - CoPy_Mnt[iMarker] = -MomentZ_Force[0]; - CT_Mnt[iMarker] = -CFx_Mnt[iMarker]; - CQ_Mnt[iMarker] = -CMz_Mnt[iMarker]; - CMerit_Mnt[iMarker] = CT_Mnt[iMarker] / (CQ_Mnt[iMarker] + EPS); - } - if (nDim == 3) { - CD_Mnt[iMarker] = ForceMomentum[0]*cos(Alpha)*cos(Beta) + ForceMomentum[1]*sin(Beta) + ForceMomentum[2]*sin(Alpha)*cos(Beta); - CL_Mnt[iMarker] = -ForceMomentum[0]*sin(Alpha) + ForceMomentum[2]*cos(Alpha); - CSF_Mnt[iMarker] = -ForceMomentum[0]*sin(Beta)*cos(Alpha) + ForceMomentum[1]*cos(Beta) - ForceMomentum[2]*sin(Beta)*sin(Alpha); - CEff_Mnt[iMarker] = CL_Mnt[iMarker] / (CD_Mnt[iMarker] + EPS); - CMx_Mnt[iMarker] = MomentInviscid[0]; - CMy_Mnt[iMarker] = MomentInviscid[1]; - CMz_Mnt[iMarker] = MomentInviscid[2]; - CFx_Mnt[iMarker] = ForceMomentum[0]; - CFy_Mnt[iMarker] = ForceMomentum[1]; - CFz_Mnt[iMarker] = ForceMomentum[2]; - CoPx_Mnt[iMarker] = -MomentY_Force[0]; - CoPz_Mnt[iMarker] = MomentY_Force[2]; - CT_Mnt[iMarker] = -CFz_Mnt[iMarker]; - CQ_Mnt[iMarker] = -CMz_Mnt[iMarker]; - CMerit_Mnt[iMarker] = CT_Mnt[iMarker] / (CQ_Mnt[iMarker] + EPS); - } - - AllBound_CD_Mnt += CD_Mnt[iMarker]; - AllBound_CL_Mnt += CL_Mnt[iMarker]; - AllBound_CSF_Mnt += CSF_Mnt[iMarker]; - AllBound_CEff_Mnt = AllBound_CL_Mnt / (AllBound_CD_Mnt + EPS); - AllBound_CMx_Mnt += CMx_Mnt[iMarker]; - AllBound_CMy_Mnt += CMy_Mnt[iMarker]; - AllBound_CMz_Mnt += CMz_Mnt[iMarker]; - AllBound_CFx_Mnt += CFx_Mnt[iMarker]; - AllBound_CFy_Mnt += CFy_Mnt[iMarker]; - AllBound_CFz_Mnt += CFz_Mnt[iMarker]; - AllBound_CoPx_Mnt += CoPx_Mnt[iMarker]; - AllBound_CoPy_Mnt += CoPy_Mnt[iMarker]; - AllBound_CoPz_Mnt += CoPz_Mnt[iMarker]; - AllBound_CT_Mnt += CT_Mnt[iMarker]; - AllBound_CQ_Mnt += CQ_Mnt[iMarker]; - AllBound_CMerit_Mnt += AllBound_CT_Mnt / (AllBound_CQ_Mnt + EPS); - - /*--- 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); - if (Marker_Tag == Monitoring_Tag) { - Surface_CL_Mnt[iMarker_Monitoring] += CL_Mnt[iMarker]; - Surface_CD_Mnt[iMarker_Monitoring] += CD_Mnt[iMarker]; - Surface_CSF_Mnt[iMarker_Monitoring] += CSF_Mnt[iMarker]; - Surface_CEff_Mnt[iMarker_Monitoring] = CL_Mnt[iMarker] / (CD_Mnt[iMarker] + EPS); - Surface_CFx_Mnt[iMarker_Monitoring] += CFx_Mnt[iMarker]; - Surface_CFy_Mnt[iMarker_Monitoring] += CFy_Mnt[iMarker]; - Surface_CFz_Mnt[iMarker_Monitoring] += CFz_Mnt[iMarker]; - Surface_CMx_Mnt[iMarker_Monitoring] += CMx_Mnt[iMarker]; - Surface_CMy_Mnt[iMarker_Monitoring] += CMy_Mnt[iMarker]; - Surface_CMz_Mnt[iMarker_Monitoring] += CMz_Mnt[iMarker]; - } - } - - } - - - } - } - -#ifdef HAVE_MPI - - /*--- Add AllBound information using all the nodes ---*/ - - MyAllBound_CD_Mnt = AllBound_CD_Mnt; AllBound_CD_Mnt = 0.0; - MyAllBound_CL_Mnt = AllBound_CL_Mnt; AllBound_CL_Mnt = 0.0; - MyAllBound_CSF_Mnt = AllBound_CSF_Mnt; AllBound_CSF_Mnt = 0.0; - AllBound_CEff_Mnt = 0.0; - MyAllBound_CMx_Mnt = AllBound_CMx_Mnt; AllBound_CMx_Mnt = 0.0; - MyAllBound_CMy_Mnt = AllBound_CMy_Mnt; AllBound_CMy_Mnt = 0.0; - MyAllBound_CMz_Mnt = AllBound_CMz_Mnt; AllBound_CMz_Mnt = 0.0; - MyAllBound_CFx_Mnt = AllBound_CFx_Mnt; AllBound_CFx_Mnt = 0.0; - MyAllBound_CFy_Mnt = AllBound_CFy_Mnt; AllBound_CFy_Mnt = 0.0; - MyAllBound_CFz_Mnt = AllBound_CFz_Mnt; AllBound_CFz_Mnt = 0.0; - MyAllBound_CoPx_Mnt = AllBound_CoPx_Mnt; AllBound_CoPx_Mnt = 0.0; - MyAllBound_CoPy_Mnt = AllBound_CoPy_Mnt; AllBound_CoPy_Mnt = 0.0; - MyAllBound_CoPz_Mnt = AllBound_CoPz_Mnt; AllBound_CoPz_Mnt = 0.0; - MyAllBound_CT_Mnt = AllBound_CT_Mnt; AllBound_CT_Mnt = 0.0; - MyAllBound_CQ_Mnt = AllBound_CQ_Mnt; AllBound_CQ_Mnt = 0.0; - AllBound_CMerit_Mnt = 0.0; - - if (config->GetComm_Level() == COMM_FULL) { - SU2_MPI::Allreduce(&MyAllBound_CD_Mnt, &AllBound_CD_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CL_Mnt, &AllBound_CL_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CSF_Mnt, &AllBound_CSF_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - AllBound_CEff_Mnt = AllBound_CL_Mnt / (AllBound_CD_Mnt + EPS); - SU2_MPI::Allreduce(&MyAllBound_CMx_Mnt, &AllBound_CMx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CMy_Mnt, &AllBound_CMy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CMz_Mnt, &AllBound_CMz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFx_Mnt, &AllBound_CFx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFy_Mnt, &AllBound_CFy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFz_Mnt, &AllBound_CFz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPx_Mnt, &AllBound_CoPx_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPy_Mnt, &AllBound_CoPy_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPz_Mnt, &AllBound_CoPz_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CT_Mnt, &AllBound_CT_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CQ_Mnt, &AllBound_CQ_Mnt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - AllBound_CMerit_Mnt = AllBound_CT_Mnt / (AllBound_CQ_Mnt + EPS); - } - - /*--- Add the forces on the surfaces using all the nodes ---*/ - - MySurface_CL_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CD_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CSF_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CEff_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFx_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFy_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFz_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMx_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMy_Mnt = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMz_Mnt = new su2double[config->GetnMarker_Monitoring()]; - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - MySurface_CL_Mnt[iMarker_Monitoring] = Surface_CL_Mnt[iMarker_Monitoring]; - MySurface_CD_Mnt[iMarker_Monitoring] = Surface_CD_Mnt[iMarker_Monitoring]; - MySurface_CSF_Mnt[iMarker_Monitoring] = Surface_CSF_Mnt[iMarker_Monitoring]; - MySurface_CEff_Mnt[iMarker_Monitoring] = Surface_CEff_Mnt[iMarker_Monitoring]; - MySurface_CFx_Mnt[iMarker_Monitoring] = Surface_CFx_Mnt[iMarker_Monitoring]; - MySurface_CFy_Mnt[iMarker_Monitoring] = Surface_CFy_Mnt[iMarker_Monitoring]; - MySurface_CFz_Mnt[iMarker_Monitoring] = Surface_CFz_Mnt[iMarker_Monitoring]; - MySurface_CMx_Mnt[iMarker_Monitoring] = Surface_CMx_Mnt[iMarker_Monitoring]; - MySurface_CMy_Mnt[iMarker_Monitoring] = Surface_CMy_Mnt[iMarker_Monitoring]; - MySurface_CMz_Mnt[iMarker_Monitoring] = Surface_CMz_Mnt[iMarker_Monitoring]; - - Surface_CL_Mnt[iMarker_Monitoring] = 0.0; - Surface_CD_Mnt[iMarker_Monitoring] = 0.0; - Surface_CSF_Mnt[iMarker_Monitoring] = 0.0; - Surface_CEff_Mnt[iMarker_Monitoring] = 0.0; - Surface_CFx_Mnt[iMarker_Monitoring] = 0.0; - Surface_CFy_Mnt[iMarker_Monitoring] = 0.0; - Surface_CFz_Mnt[iMarker_Monitoring] = 0.0; - Surface_CMx_Mnt[iMarker_Monitoring] = 0.0; - Surface_CMy_Mnt[iMarker_Monitoring] = 0.0; - Surface_CMz_Mnt[iMarker_Monitoring] = 0.0; - } - - if (config->GetComm_Level() == COMM_FULL) { - SU2_MPI::Allreduce(MySurface_CL_Mnt, Surface_CL_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CD_Mnt, Surface_CD_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CSF_Mnt, Surface_CSF_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) - Surface_CEff_Mnt[iMarker_Monitoring] = Surface_CL_Mnt[iMarker_Monitoring] / (Surface_CD_Mnt[iMarker_Monitoring] + EPS); - SU2_MPI::Allreduce(MySurface_CFx_Mnt, Surface_CFx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CFy_Mnt, Surface_CFy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CFz_Mnt, Surface_CFz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMx_Mnt, Surface_CMx_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMy_Mnt, Surface_CMy_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMz_Mnt, Surface_CMz_Mnt, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - } - - delete [] MySurface_CL_Mnt; delete [] MySurface_CD_Mnt; delete [] MySurface_CSF_Mnt; - delete [] MySurface_CEff_Mnt; delete [] MySurface_CFx_Mnt; delete [] MySurface_CFy_Mnt; - delete [] MySurface_CFz_Mnt; - delete [] MySurface_CMx_Mnt; delete [] MySurface_CMy_Mnt; delete [] MySurface_CMz_Mnt; - -#endif - - /*--- Update the total coefficients (note that all the nodes have the same value) ---*/ - - Total_CD += AllBound_CD_Mnt; - Total_CL += AllBound_CL_Mnt; - Total_CSF += AllBound_CSF_Mnt; - Total_CEff = Total_CL / (Total_CD + EPS); - Total_CMx += AllBound_CMx_Mnt; - Total_CMy += AllBound_CMy_Mnt; - Total_CMz += AllBound_CMz_Mnt; - Total_CFx += AllBound_CFx_Mnt; - Total_CFy += AllBound_CFy_Mnt; - Total_CFz += AllBound_CFz_Mnt; - Total_CoPx += AllBound_CoPx_Mnt; - Total_CoPy += AllBound_CoPy_Mnt; - Total_CoPz += AllBound_CoPz_Mnt; - Total_CT += AllBound_CT_Mnt; - Total_CQ += AllBound_CQ_Mnt; - Total_CMerit = Total_CT / (Total_CQ + EPS); - - /*--- Update the total coefficients per surface (note that all the nodes have the same value)---*/ - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Surface_CL[iMarker_Monitoring] += Surface_CL_Mnt[iMarker_Monitoring]; - Surface_CD[iMarker_Monitoring] += Surface_CD_Mnt[iMarker_Monitoring]; - Surface_CSF[iMarker_Monitoring] += Surface_CSF_Mnt[iMarker_Monitoring]; - Surface_CEff[iMarker_Monitoring] += Surface_CL_Mnt[iMarker_Monitoring] / (Surface_CD_Mnt[iMarker_Monitoring] + EPS); - Surface_CFx[iMarker_Monitoring] += Surface_CFx_Mnt[iMarker_Monitoring]; - Surface_CFy[iMarker_Monitoring] += Surface_CFy_Mnt[iMarker_Monitoring]; - Surface_CFz[iMarker_Monitoring] += Surface_CFz_Mnt[iMarker_Monitoring]; - Surface_CMx[iMarker_Monitoring] += Surface_CMx_Mnt[iMarker_Monitoring]; - Surface_CMy[iMarker_Monitoring] += Surface_CMy_Mnt[iMarker_Monitoring]; - Surface_CMz[iMarker_Monitoring] += Surface_CMz_Mnt[iMarker_Monitoring]; - } - -} - -void CIncEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver_container, - CConfig *config, unsigned short iRKStep) { - - su2double *Residual, *Res_TruncError, Vol, Delta, Res; - unsigned short iVar, jVar; - unsigned long iPoint; - - su2double RK_AlphaCoeff = config->Get_Alpha_RKStep(iRKStep); - bool adjoint = config->GetContinuous_Adjoint(); - - for (iVar = 0; iVar < nVar; iVar++) { - SetRes_RMS(iVar, 0.0); - SetRes_Max(iVar, 0.0, 0); - } - - /*--- Update the solution ---*/ - - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - Vol = (geometry->nodes->GetVolume(iPoint) + - geometry->nodes->GetPeriodicVolume(iPoint)); - Delta = nodes->GetDelta_Time(iPoint) / Vol; - - Res_TruncError = nodes->GetResTruncError(iPoint); - Residual = LinSysRes.GetBlock(iPoint); - - if (!adjoint) { - SetPreconditioner(config, iPoint); - for (iVar = 0; iVar < nVar; iVar ++ ) { - Res = 0.0; - for (jVar = 0; jVar < nVar; jVar ++ ) - Res += Preconditioner[iVar][jVar]*(Residual[jVar] + Res_TruncError[jVar]); - nodes->AddSolution(iPoint,iVar, -Res*Delta*RK_AlphaCoeff); - AddRes_RMS(iVar, Res*Res); - AddRes_Max(iVar, fabs(Res), geometry->nodes->GetGlobalIndex(iPoint), geometry->nodes->GetCoord(iPoint)); - } - } - } - - /*--- MPI solution ---*/ - - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); - - /*--- Compute the root mean square residual ---*/ - - SetResidual_RMS(geometry, config); - - /*--- For verification cases, compute the global error metrics. ---*/ - - ComputeVerificationError(geometry, config); - -} - -void CIncEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - - su2double *local_Residual, *local_Res_TruncError, Vol, Delta, Res; - unsigned short iVar, jVar; - unsigned long iPoint; - - bool adjoint = config->GetContinuous_Adjoint(); - - for (iVar = 0; iVar < nVar; iVar++) { - SetRes_RMS(iVar, 0.0); - SetRes_Max(iVar, 0.0, 0); - } - - /*--- Update the solution ---*/ - - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - Vol = (geometry->nodes->GetVolume(iPoint) + - geometry->nodes->GetPeriodicVolume(iPoint)); - Delta = nodes->GetDelta_Time(iPoint) / Vol; - - local_Res_TruncError = nodes->GetResTruncError(iPoint); - local_Residual = LinSysRes.GetBlock(iPoint); - - - if (!adjoint) { - SetPreconditioner(config, iPoint); - for (iVar = 0; iVar < nVar; iVar ++ ) { - Res = 0.0; - for (jVar = 0; jVar < nVar; jVar ++ ) - Res += Preconditioner[iVar][jVar]*(local_Residual[jVar] + local_Res_TruncError[jVar]); - nodes->AddSolution(iPoint,iVar, -Res*Delta); - AddRes_RMS(iVar, Res*Res); - AddRes_Max(iVar, fabs(Res), geometry->nodes->GetGlobalIndex(iPoint), geometry->nodes->GetCoord(iPoint)); - } - } - } - - /*--- MPI solution ---*/ - - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); - - /*--- Compute the root mean square residual ---*/ - - SetResidual_RMS(geometry, config); - - /*--- For verification cases, compute the global error metrics. ---*/ - - ComputeVerificationError(geometry, config); - -} - -void CIncEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - - unsigned short iVar, jVar; - unsigned long iPoint, total_index, IterLinSol = 0; - su2double Delta, *local_Res_TruncError, Vol; - - bool adjoint = config->GetContinuous_Adjoint(); - - /*--- Set maximum residual to zero ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - SetRes_RMS(iVar, 0.0); - SetRes_Max(iVar, 0.0, 0); - } - - /*--- Build implicit system ---*/ - - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - - /*--- Read the residual ---*/ - - local_Res_TruncError = nodes->GetResTruncError(iPoint); + local_Res_TruncError = nodes->GetResTruncError(iPoint); /*--- Read the volume ---*/ @@ -3531,346 +2197,25 @@ void CIncEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **sol } -void CIncEulerSolver::ComputeUnderRelaxationFactor(CSolver **solver_container, CConfig *config) { - - /* Loop over the solution update given by relaxing the linear - system for this nonlinear iteration. */ - - su2double localUnderRelaxation = 1.0; - const su2double allowableRatio = 0.2; - for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - - localUnderRelaxation = 1.0; - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - - /* We impose a limit on the maximum percentage that the - temperature can change over a nonlinear iteration. */ - - if ((config->GetEnergy_Equation() && (iVar == nVar-1))) { - const unsigned long index = iPoint*nVar + iVar; - su2double ratio = fabs(LinSysSol[index])/(nodes->GetSolution(iPoint, iVar)+EPS); - if (ratio > allowableRatio) { - localUnderRelaxation = min(allowableRatio/ratio, localUnderRelaxation); - } - } - } - - /* In case of turbulence, take the min of the under-relaxation factor - between the mean flow and the turb model. */ - - if (config->GetKind_Turb_Model() != NONE) - localUnderRelaxation = min(localUnderRelaxation, solver_container[TURB_SOL]->GetNodes()->GetUnderRelaxation(iPoint)); - - /* Threshold the relaxation factor in the event that there is - a very small value. This helps avoid catastrophic crashes due - to non-realizable states by canceling the update. */ - - if (localUnderRelaxation < 1e-10) localUnderRelaxation = 0.0; - - /* Store the under-relaxation factor for this point. */ - - nodes->SetUnderRelaxation(iPoint, localUnderRelaxation); - - } - -} - -void CIncEulerSolver::SetPrimitive_Gradient_GG(CGeometry *geometry, const CConfig *config, bool reconstruction) { - - const auto& primitives = nodes->GetPrimitive(); - auto& gradient = reconstruction? nodes->GetGradient_Reconstruction() : nodes->GetGradient_Primitive(); - - computeGradientsGreenGauss(this, PRIMITIVE_GRADIENT, PERIODIC_PRIM_GG, *geometry, - *config, primitives, 0, nPrimVarGrad, gradient); -} - -void CIncEulerSolver::SetPrimitive_Gradient_LS(CGeometry *geometry, const CConfig *config, bool reconstruction) { - - /*--- Set a flag for unweighted or weighted least-squares. ---*/ - bool weighted; - - if (reconstruction) - weighted = (config->GetKind_Gradient_Method_Recon() == WEIGHTED_LEAST_SQUARES); - else - weighted = (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES); - - const auto& primitives = nodes->GetPrimitive(); - auto& rmatrix = nodes->GetRmatrix(); - auto& gradient = reconstruction? nodes->GetGradient_Reconstruction() : nodes->GetGradient_Primitive(); - PERIODIC_QUANTITIES kindPeriodicComm = weighted? PERIODIC_PRIM_LS : PERIODIC_PRIM_ULS; - - computeGradientsLeastSquares(this, PRIMITIVE_GRADIENT, kindPeriodicComm, *geometry, *config, - weighted, primitives, 0, nPrimVarGrad, gradient, rmatrix); -} - -void CIncEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, const CConfig *config) { - - auto kindLimiter = static_cast(config->GetKind_SlopeLimit_Flow()); - const auto& primitives = nodes->GetPrimitive(); - const auto& gradient = nodes->GetGradient_Reconstruction(); - auto& primMin = nodes->GetSolution_Min(); - auto& primMax = nodes->GetSolution_Max(); - auto& limiter = nodes->GetLimiter_Primitive(); - - computeLimiters(kindLimiter, this, PRIMITIVE_LIMITER, PERIODIC_LIM_PRIM_1, PERIODIC_LIM_PRIM_2, - *geometry, *config, 0, nPrimVarGrad, primitives, gradient, primMin, primMax, limiter); -} - -void CIncEulerSolver::SetInletAtVertex(su2double *val_inlet, - unsigned short iMarker, - unsigned long iVertex) { - - /*--- Alias positions within inlet file for readability ---*/ - - unsigned short T_position = nDim; - unsigned short P_position = nDim+1; - unsigned short FlowDir_position = nDim+2; - - /*--- Check that the norm of the flow unit vector is actually 1 ---*/ - - su2double norm = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - norm += pow(val_inlet[FlowDir_position + iDim], 2); - } - norm = sqrt(norm); - - /*--- The tolerance here needs to be loose. When adding a very - * small number (1e-10 or smaller) to a number close to 1.0, floating - * point roundoff errors can occur. ---*/ - - if (abs(norm - 1.0) > 1e-6) { - ostringstream error_msg; - error_msg << "ERROR: Found these values in columns "; - error_msg << FlowDir_position << " - "; - error_msg << FlowDir_position + nDim - 1 << endl; - error_msg << std::scientific; - error_msg << " [" << val_inlet[FlowDir_position]; - error_msg << ", " << val_inlet[FlowDir_position + 1]; - if (nDim == 3) error_msg << ", " << val_inlet[FlowDir_position + 2]; - error_msg << "]" << endl; - error_msg << " These values should be components of a unit vector for direction," << endl; - error_msg << " but their magnitude is: " << norm << endl; - SU2_MPI::Error(error_msg.str(), CURRENT_FUNCTION); - } - - /*--- Store the values in our inlet data structures. ---*/ - - Inlet_Ttotal[iMarker][iVertex] = val_inlet[T_position]; - Inlet_Ptotal[iMarker][iVertex] = val_inlet[P_position]; - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - Inlet_FlowDir[iMarker][iVertex][iDim] = val_inlet[FlowDir_position + iDim]; - } - -} - -su2double CIncEulerSolver::GetInletAtVertex(su2double *val_inlet, - unsigned long val_inlet_point, - unsigned short val_kind_marker, - string val_marker, - CGeometry *geometry, - CConfig *config) const { - - /*--- Local variables ---*/ - - unsigned short iMarker, iDim; - unsigned long iPoint, iVertex; - su2double Area = 0.0; - su2double Normal[3] = {0.0,0.0,0.0}; - - /*--- Alias positions within inlet file for readability ---*/ - - unsigned short T_position = nDim; - unsigned short P_position = nDim+1; - unsigned short FlowDir_position = nDim+2; - - if (val_kind_marker == INLET_FLOW) { - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - if ((config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) && - (config->GetMarker_All_TagBound(iMarker) == val_marker)) { - - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++){ - - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - - if (iPoint == val_inlet_point) { - - /*-- Compute boundary face area for this vertex. ---*/ - - geometry->vertex[iMarker][iVertex]->GetNormal(Normal); - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); - - /*--- Access and store the inlet variables for this vertex. ---*/ - - val_inlet[T_position] = Inlet_Ttotal[iMarker][iVertex]; - val_inlet[P_position] = Inlet_Ptotal[iMarker][iVertex]; - for (iDim = 0; iDim < nDim; iDim++) { - val_inlet[FlowDir_position + iDim] = Inlet_FlowDir[iMarker][iVertex][iDim]; - } - - /*--- Exit once we find the point. ---*/ - - return Area; - - } - } - } - } - } - - /*--- If we don't find a match, then the child point is not on the - current inlet boundary marker. Return zero area so this point does - not contribute to the restriction operator and continue. ---*/ - - return Area; - -} - -void CIncEulerSolver::SetUniformInlet(CConfig* config, unsigned short iMarker) { - - if (config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) { - - string Marker_Tag = config->GetMarker_All_TagBound(iMarker); - su2double p_total = config->GetInlet_Ptotal(Marker_Tag); - su2double t_total = config->GetInlet_Ttotal(Marker_Tag); - su2double* flow_dir = config->GetInlet_FlowDir(Marker_Tag); - - for(unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ - Inlet_Ttotal[iMarker][iVertex] = t_total; - Inlet_Ptotal[iMarker][iVertex] = p_total; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Inlet_FlowDir[iMarker][iVertex][iDim] = flow_dir[iDim]; - } - - } else { - - /*--- For now, non-inlets just get set to zero. In the future, we - can do more customization for other boundary types here. ---*/ - - for(unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ - Inlet_Ttotal[iMarker][iVertex] = 0.0; - Inlet_Ptotal[iMarker][iVertex] = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Inlet_FlowDir[iMarker][iVertex][iDim] = 0.0; - } - } - -} - void CIncEulerSolver::Evaluate_ObjFunc(CConfig *config) { - unsigned short iMarker_Monitoring, Kind_ObjFunc; - su2double Weight_ObjFunc; - - Total_ComboObj = 0.0; - - /*--- Loop over all monitored markers, add to the 'combo' objective ---*/ - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - - Weight_ObjFunc = config->GetWeight_ObjFunc(iMarker_Monitoring); - Kind_ObjFunc = config->GetKind_ObjFunc(iMarker_Monitoring); - - switch(Kind_ObjFunc) { - case DRAG_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CD[iMarker_Monitoring]); - break; - case LIFT_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CL[iMarker_Monitoring]); - break; - case SIDEFORCE_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CSF[iMarker_Monitoring]); - break; - case EFFICIENCY: - Total_ComboObj+=Weight_ObjFunc*(Surface_CEff[iMarker_Monitoring]); - break; - case MOMENT_X_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CMx[iMarker_Monitoring]); - break; - case MOMENT_Y_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CMy[iMarker_Monitoring]); - break; - case MOMENT_Z_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CMz[iMarker_Monitoring]); - break; - case FORCE_X_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Surface_CFx[iMarker_Monitoring]; - break; - case FORCE_Y_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Surface_CFy[iMarker_Monitoring]; - break; - case FORCE_Z_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Surface_CFz[iMarker_Monitoring]; - break; - case TOTAL_HEATFLUX: - Total_ComboObj+=Weight_ObjFunc*Surface_HF_Visc[iMarker_Monitoring]; - break; - case MAXIMUM_HEATFLUX: - Total_ComboObj+=Weight_ObjFunc*Surface_MaxHF_Visc[iMarker_Monitoring]; - break; - default: - break; - - } - } + Total_ComboObj = EvaluateCommonObjFunc(*config); /*--- The following are not per-surface, and so to avoid that they are double-counted when multiple surfaces are specified, they have been placed outside of the loop above. In addition, multi-objective mode is also disabled for these objective functions (error thrown at start). ---*/ - Weight_ObjFunc = config->GetWeight_ObjFunc(0); - Kind_ObjFunc = config->GetKind_ObjFunc(0); - - switch(Kind_ObjFunc) { - case INVERSE_DESIGN_PRESSURE: - Total_ComboObj+=Weight_ObjFunc*Total_CpDiff; - break; - case INVERSE_DESIGN_HEATFLUX: - Total_ComboObj+=Weight_ObjFunc*Total_HeatFluxDiff; - break; - case THRUST_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Total_CT; - break; - case TORQUE_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Total_CQ; - break; - case FIGURE_OF_MERIT: - Total_ComboObj+=Weight_ObjFunc*Total_CMerit; - break; - case SURFACE_TOTAL_PRESSURE: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_TotalPressure(0); - break; - case SURFACE_STATIC_PRESSURE: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_Pressure(0); - break; - case SURFACE_MASSFLOW: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_MassFlow(0); - break; - case SURFACE_UNIFORMITY: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_Uniformity(0); - break; - case SURFACE_SECONDARY: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_SecondaryStrength(0); - break; - case SURFACE_MOM_DISTORTION: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_MomentumDistortion(0); - break; - case SURFACE_SECOND_OVER_UNIFORM: - Total_ComboObj+=Weight_ObjFunc*config->GetSurface_SecondOverUniform(0); - break; + const auto Weight_ObjFunc = config->GetWeight_ObjFunc(0); + const auto Kind_ObjFunc = config->GetKind_ObjFunc(0); + + switch(Kind_ObjFunc) { case SURFACE_PRESSURE_DROP: Total_ComboObj+=Weight_ObjFunc*config->GetSurface_PressureDrop(0); break; - case CUSTOM_OBJFUNC: - Total_ComboObj+=Weight_ObjFunc*Total_Custom_ObjFunc; - break; default: break; } - } void CIncEulerSolver::SetBeta_Parameter(CGeometry *geometry, CSolver **solver_container, @@ -4119,259 +2464,7 @@ void CIncEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_contain /*--- Primitive variables, and gradient ---*/ - visc_numerics->SetPrimitive(V_domain, V_infty); - visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), - nodes->GetGradient_Primitive(iPoint)); - - /*--- Turbulent kinetic energy ---*/ - - if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) - visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), - solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0)); - - /*--- Compute and update viscous residual ---*/ - - auto residual = visc_numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, residual); - - /*--- Viscous Jacobian contribution for implicit integration ---*/ - - if (implicit) - Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); - - } - - } - } - - /*--- Free locally allocated memory ---*/ - - delete [] Normal; - -} - -void CIncEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { - unsigned short iDim; - unsigned long iVertex, iPoint; - unsigned long Point_Normal; - su2double *Flow_Dir, Flow_Dir_Mag, Vel_Mag, Area, P_total, P_domain, Vn; - su2double *V_inlet, *V_domain; - su2double UnitFlowDir[3] = {0.0,0.0,0.0}; - su2double dV[3] = {0.0,0.0,0.0}; - su2double Damping = config->GetInc_Inlet_Damping(); - - bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); - bool viscous = config->GetViscous(); - - string Marker_Tag = config->GetMarker_All_TagBound(val_marker); - - unsigned short Kind_Inlet = config->GetKind_Inc_Inlet(Marker_Tag); - - su2double *Normal = new su2double[nDim]; - - /*--- Loop over all the vertices on this boundary marker ---*/ - - for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { - - /*--- Allocate the value at the inlet ---*/ - - V_inlet = GetCharacPrimVar(val_marker, iVertex); - - iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); - - /*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/ - - if (geometry->nodes->GetDomain(iPoint)) { - - /*--- Index of the closest interior node ---*/ - - Point_Normal = geometry->vertex[val_marker][iVertex]->GetNormal_Neighbor(); - - /*--- Normal vector for this vertex (negate for outward convention) ---*/ - - geometry->vertex[val_marker][iVertex]->GetNormal(Normal); - for (iDim = 0; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim]; - conv_numerics->SetNormal(Normal); - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; - Area = sqrt (Area); - - /*--- Both types of inlets may use the prescribed flow direction. - Ensure that the flow direction is a unit vector. ---*/ - - Flow_Dir = Inlet_FlowDir[val_marker][iVertex]; - Flow_Dir_Mag = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Flow_Dir_Mag += Flow_Dir[iDim]*Flow_Dir[iDim]; - Flow_Dir_Mag = sqrt(Flow_Dir_Mag); - - /*--- Store the unit flow direction vector. ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - UnitFlowDir[iDim] = Flow_Dir[iDim]/Flow_Dir_Mag; - - /*--- Retrieve solution at this boundary node. ---*/ - - V_domain = nodes->GetPrimitive(iPoint); - - /*--- Neumann condition for dynamic pressure ---*/ - - V_inlet[0] = nodes->GetPressure(iPoint); - - /*--- The velocity is either prescribed or computed from total pressure. ---*/ - - switch (Kind_Inlet) { - - /*--- Velocity and temperature (if required) been specified at the inlet. ---*/ - - case VELOCITY_INLET: - - /*--- Retrieve the specified velocity and temperature for the inlet. ---*/ - - Vel_Mag = Inlet_Ptotal[val_marker][iVertex]/config->GetVelocity_Ref(); - - /*--- Store the velocity in the primitive variable vector. ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - V_inlet[iDim+1] = Vel_Mag*UnitFlowDir[iDim]; - - /*--- Dirichlet condition for temperature (if energy is active) ---*/ - - V_inlet[nDim+1] = Inlet_Ttotal[val_marker][iVertex]/config->GetTemperature_Ref(); - - break; - - /*--- Stagnation pressure has been specified at the inlet. ---*/ - - case PRESSURE_INLET: - - /*--- Retrieve the specified total pressure for the inlet. ---*/ - - P_total = Inlet_Ptotal[val_marker][iVertex]/config->GetPressure_Ref(); - - /*--- Store the current static pressure for clarity. ---*/ - - P_domain = nodes->GetPressure(iPoint); - - /*--- Check for back flow through the inlet. ---*/ - - Vn = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Vn += V_domain[iDim+1]*(-1.0*Normal[iDim]/Area); - } - - /*--- If the local static pressure is larger than the specified - total pressure or the velocity is directed upstream, we have a - back flow situation. The specified total pressure should be used - as a static pressure condition and the velocity from the domain - is used for the BC. ---*/ - - if ((P_domain > P_total) || (Vn < 0.0)) { - - /*--- Back flow: use the prescribed P_total as static pressure. ---*/ - - V_inlet[0] = Inlet_Ptotal[val_marker][iVertex]/config->GetPressure_Ref(); - - /*--- Neumann condition for velocity. ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - V_inlet[iDim+1] = V_domain[iDim+1]; - - /*--- Neumann condition for the temperature. ---*/ - - V_inlet[nDim+1] = nodes->GetTemperature(iPoint); - - } else { - - /*--- Update the velocity magnitude using the total pressure. ---*/ - - Vel_Mag = sqrt((P_total - P_domain)/(0.5*nodes->GetDensity(iPoint))); - - /*--- If requested, use the local boundary normal (negative), - instead of the prescribed flow direction in the config. ---*/ - - if (config->GetInc_Inlet_UseNormal()) { - for (iDim = 0; iDim < nDim; iDim++) - UnitFlowDir[iDim] = -Normal[iDim]/Area; - } - - /*--- Compute the delta change in velocity in each direction. ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - dV[iDim] = Vel_Mag*UnitFlowDir[iDim] - V_domain[iDim+1]; - - /*--- Update the velocity in the primitive variable vector. - Note we use damping here to improve stability/convergence. ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - V_inlet[iDim+1] = V_domain[iDim+1] + Damping*dV[iDim]; - - /*--- Dirichlet condition for temperature (if energy is active) ---*/ - - V_inlet[nDim+1] = Inlet_Ttotal[val_marker][iVertex]/config->GetTemperature_Ref(); - - } - - break; - - } - - /*--- Access density at the node. This is either constant by - construction, or will be set fixed implicitly by the temperature - and equation of state. ---*/ - - V_inlet[nDim+2] = nodes->GetDensity(iPoint); - - /*--- Beta coefficient from the config file ---*/ - - V_inlet[nDim+3] = nodes->GetBetaInc2(iPoint); - - /*--- Cp is needed for Temperature equation. ---*/ - - V_inlet[nDim+7] = nodes->GetSpecificHeatCp(iPoint); - - /*--- Set various quantities in the solver class ---*/ - - conv_numerics->SetPrimitive(V_domain, V_inlet); - - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), - geometry->nodes->GetGridVel(iPoint)); - - /*--- Compute the residual using an upwind scheme ---*/ - - auto residual = conv_numerics->ComputeResidual(config); - - /*--- Update residual value ---*/ - - LinSysRes.AddBlock(iPoint, residual); - - /*--- Jacobian contribution for implicit integration ---*/ - - if (implicit) - Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); - - /*--- Viscous contribution, commented out because serious convergence problems ---*/ - - if (viscous) { - - /*--- Set transport properties at the inlet ---*/ - - V_inlet[nDim+4] = nodes->GetLaminarViscosity(iPoint); - V_inlet[nDim+5] = nodes->GetEddyViscosity(iPoint); - V_inlet[nDim+6] = nodes->GetThermalConductivity(iPoint); - - /*--- Set the normal vector and the coordinates ---*/ - - visc_numerics->SetNormal(Normal); - visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), - geometry->nodes->GetCoord(Point_Normal)); - - /*--- Primitive variables, and gradient ---*/ - - visc_numerics->SetPrimitive(V_domain, V_inlet); + visc_numerics->SetPrimitive(V_domain, V_infty); visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), nodes->GetGradient_Primitive(iPoint)); @@ -4381,13 +2474,12 @@ void CIncEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0)); - /*--- Compute and update residual ---*/ + /*--- Compute and update viscous residual ---*/ auto residual = visc_numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, residual); - /*--- Jacobian contribution for implicit integration ---*/ + /*--- Viscous Jacobian contribution for implicit integration ---*/ if (implicit) Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); @@ -4403,30 +2495,33 @@ void CIncEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, } -void CIncEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CIncEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, + CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iDim; - unsigned long iVertex, iPoint, Point_Normal; - su2double Area; - su2double *V_outlet, *V_domain, P_Outlet = 0.0, P_domain; - su2double mDot_Target, mDot_Old, dP, Density_Avg, Area_Outlet; - su2double Damping = config->GetInc_Outlet_Damping(); + unsigned long iVertex, iPoint; + unsigned long Point_Normal; + su2double *Flow_Dir, Flow_Dir_Mag, Vel_Mag, Area, P_total, P_domain, Vn; + su2double *V_inlet, *V_domain; + su2double UnitFlowDir[3] = {0.0,0.0,0.0}; + su2double dV[3] = {0.0,0.0,0.0}; + su2double Damping = config->GetInc_Inlet_Damping(); bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); bool viscous = config->GetViscous(); + string Marker_Tag = config->GetMarker_All_TagBound(val_marker); - su2double *Normal = new su2double[nDim]; + unsigned short Kind_Inlet = config->GetKind_Inc_Inlet(Marker_Tag); - unsigned short Kind_Outlet = config->GetKind_Inc_Outlet(Marker_Tag); + su2double *Normal = new su2double[nDim]; /*--- Loop over all the vertices on this boundary marker ---*/ for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { - /*--- Allocate the value at the outlet ---*/ + /*--- Allocate the value at the inlet ---*/ - V_outlet = GetCharacPrimVar(val_marker, iVertex); + V_inlet = GetCharacPrimVar(val_marker, iVertex); iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); @@ -4448,697 +2543,416 @@ void CIncEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt (Area); - /*--- Current solution at this boundary node ---*/ - - V_domain = nodes->GetPrimitive(iPoint); - - /*--- Store the current static pressure for clarity. ---*/ + /*--- Both types of inlets may use the prescribed flow direction. + Ensure that the flow direction is a unit vector. ---*/ - P_domain = nodes->GetPressure(iPoint); + Flow_Dir = Inlet_FlowDir[val_marker][iVertex]; + Flow_Dir_Mag = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Flow_Dir_Mag += Flow_Dir[iDim]*Flow_Dir[iDim]; + Flow_Dir_Mag = sqrt(Flow_Dir_Mag); - /*--- Compute a boundary value for the pressure depending on whether - we are prescribing a back pressure or a mass flow target. ---*/ + /*--- Store the unit flow direction vector. ---*/ - switch (Kind_Outlet) { + for (iDim = 0; iDim < nDim; iDim++) + UnitFlowDir[iDim] = Flow_Dir[iDim]/Flow_Dir_Mag; - /*--- Velocity and temperature (if required) been specified at the inlet. ---*/ + /*--- Retrieve solution at this boundary node. ---*/ - case PRESSURE_OUTLET: + V_domain = nodes->GetPrimitive(iPoint); - /*--- Retrieve the specified back pressure for this outlet. ---*/ + /*--- Neumann condition for dynamic pressure ---*/ - P_Outlet = config->GetOutlet_Pressure(Marker_Tag)/config->GetPressure_Ref(); + V_inlet[0] = nodes->GetPressure(iPoint); - /*--- The pressure is prescribed at the outlet. ---*/ + /*--- The velocity is either prescribed or computed from total pressure. ---*/ - V_outlet[0] = P_Outlet; + switch (Kind_Inlet) { - /*--- Neumann condition for the velocity. ---*/ + /*--- Velocity and temperature (if required) been specified at the inlet. ---*/ - for (iDim = 0; iDim < nDim; iDim++) { - V_outlet[iDim+1] = nodes->GetVelocity(iPoint,iDim); - } + case VELOCITY_INLET: - break; + /*--- Retrieve the specified velocity and temperature for the inlet. ---*/ - /*--- A mass flow target has been specified for the outlet. ---*/ + Vel_Mag = Inlet_Ptotal[val_marker][iVertex]/config->GetVelocity_Ref(); - case MASS_FLOW_OUTLET: + /*--- Store the velocity in the primitive variable vector. ---*/ - /*--- Retrieve the specified target mass flow at the outlet. ---*/ + for (iDim = 0; iDim < nDim; iDim++) + V_inlet[iDim+1] = Vel_Mag*UnitFlowDir[iDim]; - mDot_Target = config->GetOutlet_Pressure(Marker_Tag)/(config->GetDensity_Ref() * config->GetVelocity_Ref()); + /*--- Dirichlet condition for temperature (if energy is active) ---*/ - /*--- Retrieve the old mass flow, density, and area of the outlet, - which has been computed in a preprocessing step. These values - were stored in non-dim. form in the config container. ---*/ + V_inlet[nDim+1] = Inlet_Ttotal[val_marker][iVertex]/config->GetTemperature_Ref(); - mDot_Old = config->GetOutlet_MassFlow(Marker_Tag); - Density_Avg = config->GetOutlet_Density(Marker_Tag); - Area_Outlet = config->GetOutlet_Area(Marker_Tag); + break; - /*--- Compute the pressure increment based on the difference - between the current and target mass flow. Note that increasing - pressure decreases flow speed. ---*/ + /*--- Stagnation pressure has been specified at the inlet. ---*/ - dP = 0.5*Density_Avg*(mDot_Old*mDot_Old - mDot_Target*mDot_Target)/((Density_Avg*Area_Outlet)*(Density_Avg*Area_Outlet)); + case PRESSURE_INLET: - /*--- Update the new outlet pressure. Note that we use damping - here to improve stability/convergence. ---*/ + /*--- Retrieve the specified total pressure for the inlet. ---*/ - P_Outlet = P_domain + Damping*dP; + P_total = Inlet_Ptotal[val_marker][iVertex]/config->GetPressure_Ref(); - /*--- The pressure is prescribed at the outlet. ---*/ + /*--- Store the current static pressure for clarity. ---*/ - V_outlet[0] = P_Outlet; + P_domain = nodes->GetPressure(iPoint); - /*--- Neumann condition for the velocity ---*/ + /*--- Check for back flow through the inlet. ---*/ + Vn = 0.0; for (iDim = 0; iDim < nDim; iDim++) { - V_outlet[iDim+1] = nodes->GetVelocity(iPoint,iDim); + Vn += V_domain[iDim+1]*(-1.0*Normal[iDim]/Area); } - break; - - } - - /*--- Neumann condition for the temperature. ---*/ - - V_outlet[nDim+1] = nodes->GetTemperature(iPoint); - - /*--- Access density at the interior node. This is either constant by - construction, or will be set fixed implicitly by the temperature - and equation of state. ---*/ - - V_outlet[nDim+2] = nodes->GetDensity(iPoint); - - /*--- Beta coefficient from the config file ---*/ - - V_outlet[nDim+3] = nodes->GetBetaInc2(iPoint); - - /*--- Cp is needed for Temperature equation. ---*/ - - V_outlet[nDim+7] = nodes->GetSpecificHeatCp(iPoint); - - /*--- Set various quantities in the solver class ---*/ - - conv_numerics->SetPrimitive(V_domain, V_outlet); - - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), - geometry->nodes->GetGridVel(iPoint)); - - /*--- Compute the residual using an upwind scheme ---*/ - - auto residual = conv_numerics->ComputeResidual(config); - - /*--- Update residual value ---*/ - - LinSysRes.AddBlock(iPoint, residual); - - /*--- Jacobian contribution for implicit integration ---*/ - - if (implicit) { - Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); - } - - /*--- Viscous contribution, commented out because serious convergence problems ---*/ - - if (viscous) { - - /*--- Set transport properties at the outlet. ---*/ - - V_outlet[nDim+4] = nodes->GetLaminarViscosity(iPoint); - V_outlet[nDim+5] = nodes->GetEddyViscosity(iPoint); - V_outlet[nDim+6] = nodes->GetThermalConductivity(iPoint); - - /*--- Set the normal vector and the coordinates ---*/ - - visc_numerics->SetNormal(Normal); - visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), - geometry->nodes->GetCoord(Point_Normal)); - - /*--- Primitive variables, and gradient ---*/ - - visc_numerics->SetPrimitive(V_domain, V_outlet); - visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), - nodes->GetGradient_Primitive(iPoint)); - - /*--- Turbulent kinetic energy ---*/ - - if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) - visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), - solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0)); - - /*--- Compute and update residual ---*/ - - auto residual = visc_numerics->ComputeResidual(config); - - LinSysRes.SubtractBlock(iPoint, residual); - - /*--- Jacobian contribution for implicit integration ---*/ - if (implicit) - Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); - - } + /*--- If the local static pressure is larger than the specified + total pressure or the velocity is directed upstream, we have a + back flow situation. The specified total pressure should be used + as a static pressure condition and the velocity from the domain + is used for the BC. ---*/ - } - } + if ((P_domain > P_total) || (Vn < 0.0)) { - /*--- Free locally allocated memory ---*/ - delete [] Normal; + /*--- Back flow: use the prescribed P_total as static pressure. ---*/ -} + V_inlet[0] = Inlet_Ptotal[val_marker][iVertex]/config->GetPressure_Ref(); + /*--- Neumann condition for velocity. ---*/ -void CIncEulerSolver::BC_Euler_Wall(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) { + for (iDim = 0; iDim < nDim; iDim++) + V_inlet[iDim+1] = V_domain[iDim+1]; - /*--- Call the equivalent symmetry plane boundary condition. ---*/ - BC_Sym_Plane(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker); + /*--- Neumann condition for the temperature. ---*/ -} + V_inlet[nDim+1] = nodes->GetTemperature(iPoint); + } else { -void CIncEulerSolver::BC_Sym_Plane(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) { + /*--- Update the velocity magnitude using the total pressure. ---*/ - unsigned short iDim, iVar; - unsigned long iVertex, iPoint; + Vel_Mag = sqrt((P_total - P_domain)/(0.5*nodes->GetDensity(iPoint))); - bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT), - viscous = config->GetViscous(); + /*--- If requested, use the local boundary normal (negative), + instead of the prescribed flow direction in the config. ---*/ - /*--- Allocation of variables necessary for convective fluxes. ---*/ - su2double Area, ProjVelocity_i, - *V_reflected, - *V_domain, - *Normal = new su2double[nDim], - *UnitNormal = new su2double[nDim]; + if (config->GetInc_Inlet_UseNormal()) { + for (iDim = 0; iDim < nDim; iDim++) + UnitFlowDir[iDim] = -Normal[iDim]/Area; + } - /*--- Allocation of variables necessary for viscous fluxes. ---*/ - su2double ProjGradient, ProjNormVelGrad, ProjTangVelGrad, TangentialNorm, - *Tangential = new su2double[nDim], - *GradNormVel = new su2double[nDim], - *GradTangVel = new su2double[nDim]; + /*--- Compute the delta change in velocity in each direction. ---*/ - /*--- Allocation of primitive gradient arrays for viscous fluxes. ---*/ - su2double **Grad_Reflected = new su2double*[nPrimVarGrad]; - for (iVar = 0; iVar < nPrimVarGrad; iVar++) - Grad_Reflected[iVar] = new su2double[nDim]; + for (iDim = 0; iDim < nDim; iDim++) + dV[iDim] = Vel_Mag*UnitFlowDir[iDim] - V_domain[iDim+1]; - /*--- Loop over all the vertices on this boundary marker. ---*/ - for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { + /*--- Update the velocity in the primitive variable vector. + Note we use damping here to improve stability/convergence. ---*/ - if (iVertex == 0 || - geometry->bound_is_straight[val_marker] != true) { - - /*----------------------------------------------------------------------------------------------*/ - /*--- Preprocessing: ---*/ - /*--- Compute the unit normal and (in case of viscous flow) a corresponding unit tangential ---*/ - /*--- to that normal. On a straight(2D)/plane(3D) boundary these two vectors are constant. ---*/ - /*--- This circumstance is checked in gemoetry->ComputeSurf_Straightness(...) and stored ---*/ - /*--- such that the recomputation does not occur for each node. On true symmetry planes, the ---*/ - /*--- normal is constant but this routines is used for Symmetry, Euler-Wall in inviscid flow ---*/ - /*--- and Euler Wall in viscous flow as well. In the latter curvy boundaries are likely to ---*/ - /*--- happen. In doubt, the conditional above which checks straightness can be thrown out ---*/ - /*--- such that the recomputation is done for each node (which comes with a tiny performance ---*/ - /*--- penalty). ---*/ - /*----------------------------------------------------------------------------------------------*/ - - /*--- Normal vector for a random vertex (zero) on this marker (negate for outward convention). ---*/ - geometry->vertex[val_marker][iVertex]->GetNormal(Normal); - for (iDim = 0; iDim < nDim; iDim++) - Normal[iDim] = -Normal[iDim]; + for (iDim = 0; iDim < nDim; iDim++) + V_inlet[iDim+1] = V_domain[iDim+1] + Damping*dV[iDim]; - /*--- Compute unit normal, to be used for unit tangential, projected velocity and velocity - component gradients. ---*/ - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt (Area); + /*--- Dirichlet condition for temperature (if energy is active) ---*/ - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = -Normal[iDim]/Area; + V_inlet[nDim+1] = Inlet_Ttotal[val_marker][iVertex]/config->GetTemperature_Ref(); - /*--- Preprocessing: Compute unit tangential, the direction is arbitrary as long as - t*n=0 && |t|_2 = 1 ---*/ - if (viscous) { - switch( nDim ) { - case 2: { - Tangential[0] = -UnitNormal[1]; - Tangential[1] = UnitNormal[0]; - break; - } - case 3: { - /*--- n = ai + bj + ck, if |b| > |c| ---*/ - if( abs(UnitNormal[1]) > abs(UnitNormal[2])) { - /*--- t = bi + (c-a)j - bk ---*/ - Tangential[0] = UnitNormal[1]; - Tangential[1] = UnitNormal[2] - UnitNormal[0]; - Tangential[2] = -UnitNormal[1]; - } else { - /*--- t = ci - cj + (b-a)k ---*/ - Tangential[0] = UnitNormal[2]; - Tangential[1] = -UnitNormal[2]; - Tangential[2] = UnitNormal[1] - UnitNormal[0]; - } - /*--- Make it a unit vector. ---*/ - TangentialNorm = sqrt(pow(Tangential[0],2) + pow(Tangential[1],2) + pow(Tangential[2],2)); - Tangential[0] = Tangential[0] / TangentialNorm; - Tangential[1] = Tangential[1] / TangentialNorm; - Tangential[2] = Tangential[2] / TangentialNorm; - break; } - }// switch - }//if viscous - }//if bound_is_straight - - iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); - - /*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/ - if (geometry->nodes->GetDomain(iPoint)) { - /*-------------------------------------------------------------------------------*/ - /*--- Step 1: For the convective fluxes, create a reflected state of the ---*/ - /*--- Primitive variables by copying all interior values to the ---*/ - /*--- reflected. Only the velocity is mirrored along the symmetry ---*/ - /*--- axis. Based on the Upwind_Residual routine. ---*/ - /*-------------------------------------------------------------------------------*/ + break; - /*--- Allocate the reflected state at the symmetry boundary. ---*/ - V_reflected = GetCharacPrimVar(val_marker, iVertex); + } - /*--- Grid movement ---*/ - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint)); + /*--- Access density at the node. This is either constant by + construction, or will be set fixed implicitly by the temperature + and equation of state. ---*/ - /*--- Normal vector for this vertex (negate for outward convention). ---*/ - geometry->vertex[val_marker][iVertex]->GetNormal(Normal); - for (iDim = 0; iDim < nDim; iDim++) - Normal[iDim] = -Normal[iDim]; - conv_numerics->SetNormal(Normal); + V_inlet[nDim+2] = nodes->GetDensity(iPoint); - /*--- Get current solution at this boundary node ---*/ - V_domain = nodes->GetPrimitive(iPoint); + /*--- Beta coefficient from the config file ---*/ - /*--- Set the reflected state based on the boundary node. Scalars are copied and - the velocity is mirrored along the symmetry boundary, i.e. the velocity in - normal direction is substracted twice. ---*/ - for(iVar = 0; iVar < nPrimVar; iVar++) - V_reflected[iVar] = nodes->GetPrimitive(iPoint,iVar); + V_inlet[nDim+3] = nodes->GetBetaInc2(iPoint); - /*--- Compute velocity in normal direction (ProjVelcity_i=(v*n)) und substract twice from - velocity in normal direction: v_r = v - 2 (v*n)n ---*/ - ProjVelocity_i = nodes->GetProjVel(iPoint,UnitNormal); + /*--- Cp is needed for Temperature equation. ---*/ - for (iDim = 0; iDim < nDim; iDim++) - V_reflected[iDim+1] = nodes->GetVelocity(iPoint,iDim) - 2.0 * ProjVelocity_i*UnitNormal[iDim]; + V_inlet[nDim+7] = nodes->GetSpecificHeatCp(iPoint); - /*--- Set Primitive and Secondary for numerics class. ---*/ - conv_numerics->SetPrimitive(V_domain, V_reflected); - conv_numerics->SetSecondary(nodes->GetSecondary(iPoint), nodes->GetSecondary(iPoint)); + /*--- Set various quantities in the solver class ---*/ - /*--- Compute the residual using an upwind scheme. ---*/ - auto residual = conv_numerics->ComputeResidual(config); + conv_numerics->SetPrimitive(V_domain, V_inlet); - /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, residual); + if (dynamic_grid) + conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), + geometry->nodes->GetGridVel(iPoint)); - /*--- Jacobian contribution for implicit integration. ---*/ - if (implicit) { - Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); - } + /*--- Compute the residual using an upwind scheme ---*/ - if (viscous) { + auto residual = conv_numerics->ComputeResidual(config); - /*-------------------------------------------------------------------------------*/ - /*--- Step 2: The viscous fluxes of the Navier-Stokes equations depend on the ---*/ - /*--- Primitive variables and their gradients. The viscous numerics ---*/ - /*--- container is filled just as the convective numerics container, ---*/ - /*--- but the primitive gradients of the reflected state have to be ---*/ - /*--- determined additionally such that symmetry at the boundary is ---*/ - /*--- enforced. Based on the Viscous_Residual routine. ---*/ - /*-------------------------------------------------------------------------------*/ + /*--- Update residual value ---*/ - /*--- Set the normal vector and the coordinates. ---*/ - visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), - geometry->nodes->GetCoord(iPoint)); - visc_numerics->SetNormal(Normal); + LinSysRes.AddBlock(iPoint, residual); - /*--- Set the primitive and Secondary variables. ---*/ - visc_numerics->SetPrimitive(V_domain, V_reflected); - visc_numerics->SetSecondary(nodes->GetSecondary(iPoint), nodes->GetSecondary(iPoint)); + /*--- Jacobian contribution for implicit integration ---*/ - /*--- For viscous Fluxes also the gradients of the primitives need to be determined. - 1. The gradients of scalars are mirrored along the sym plane just as velocity for the primitives - 2. The gradients of the velocity components need more attention, i.e. the gradient of the - normal velocity in tangential direction is mirrored and the gradient of the tangential velocity in - normal direction is mirrored. ---*/ + if (implicit) + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); - /*--- Get gradients of primitives of boundary cell ---*/ - for (iVar = 0; iVar < nPrimVarGrad; iVar++) - for (iDim = 0; iDim < nDim; iDim++) - Grad_Reflected[iVar][iDim] = nodes->GetGradient_Primitive(iPoint,iVar, iDim); + /*--- Viscous contribution, commented out because serious convergence problems ---*/ - /*--- Reflect the gradients for all scalars including the velocity components. - The gradients of the velocity components are set later with the - correct values: grad(V)_r = grad(V) - 2 [grad(V)*n]n, V beeing any primitive ---*/ - for (iVar = 0; iVar < nPrimVarGrad; iVar++) { - if(iVar == 0 || iVar > nDim) { // Exclude velocity component gradients + if (viscous) { - /*--- Compute projected part of the gradient in a dot product ---*/ - ProjGradient = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGradient += Grad_Reflected[iVar][iDim]*UnitNormal[iDim]; + /*--- Set transport properties at the inlet ---*/ - for (iDim = 0; iDim < nDim; iDim++) - Grad_Reflected[iVar][iDim] = Grad_Reflected[iVar][iDim] - 2.0 * ProjGradient*UnitNormal[iDim]; - } - } + V_inlet[nDim+4] = nodes->GetLaminarViscosity(iPoint); + V_inlet[nDim+5] = nodes->GetEddyViscosity(iPoint); + V_inlet[nDim+6] = nodes->GetThermalConductivity(iPoint); - /*--- Compute gradients of normal and tangential velocity: - grad(v*n) = grad(v_x) n_x + grad(v_y) n_y (+ grad(v_z) n_z) - grad(v*t) = grad(v_x) t_x + grad(v_y) t_y (+ grad(v_z) t_z) ---*/ - for (iVar = 0; iVar < nDim; iVar++) { // counts gradient components - GradNormVel[iVar] = 0.0; - GradTangVel[iVar] = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { // counts sum with unit normal/tangential - GradNormVel[iVar] += Grad_Reflected[iDim+1][iVar] * UnitNormal[iDim]; - GradTangVel[iVar] += Grad_Reflected[iDim+1][iVar] * Tangential[iDim]; - } - } + /*--- Set the normal vector and the coordinates ---*/ - /*--- Refelect gradients in tangential and normal direction by substracting the normal/tangential - component twice, just as done with velocity above. - grad(v*n)_r = grad(v*n) - 2 {grad([v*n])*t}t - grad(v*t)_r = grad(v*t) - 2 {grad([v*t])*n}n ---*/ - ProjNormVelGrad = 0.0; - ProjTangVelGrad = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjNormVelGrad += GradNormVel[iDim]*Tangential[iDim]; //grad([v*n])*t - ProjTangVelGrad += GradTangVel[iDim]*UnitNormal[iDim]; //grad([v*t])*n - } + visc_numerics->SetNormal(Normal); + visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), + geometry->nodes->GetCoord(Point_Normal)); - for (iDim = 0; iDim < nDim; iDim++) { - GradNormVel[iDim] = GradNormVel[iDim] - 2.0 * ProjNormVelGrad * Tangential[iDim]; - GradTangVel[iDim] = GradTangVel[iDim] - 2.0 * ProjTangVelGrad * UnitNormal[iDim]; - } + /*--- Primitive variables, and gradient ---*/ - /*--- Transfer reflected gradients back into the Cartesian Coordinate system: - grad(v_x)_r = grad(v*n)_r n_x + grad(v*t)_r t_x - grad(v_y)_r = grad(v*n)_r n_y + grad(v*t)_r t_y - ( grad(v_z)_r = grad(v*n)_r n_z + grad(v*t)_r t_z ) ---*/ - for (iVar = 0; iVar < nDim; iVar++) // loops over the velocity component gradients - for (iDim = 0; iDim < nDim; iDim++) // loops over the entries of the above - Grad_Reflected[iVar+1][iDim] = GradNormVel[iDim]*UnitNormal[iVar] + GradTangVel[iDim]*Tangential[iVar]; + visc_numerics->SetPrimitive(V_domain, V_inlet); + visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), + nodes->GetGradient_Primitive(iPoint)); - /*--- Set the primitive gradients of the boundary and reflected state. ---*/ - visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), Grad_Reflected); + /*--- Turbulent kinetic energy ---*/ - /*--- Turbulent kinetic energy. ---*/ if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0)); - /*--- Compute and update residual. Note that the viscous shear stress tensor is computed in the - following routine based upon the velocity-component gradients. ---*/ + /*--- Compute and update residual ---*/ + auto residual = visc_numerics->ComputeResidual(config); LinSysRes.SubtractBlock(iPoint, residual); - /*--- Jacobian contribution for implicit integration. ---*/ + /*--- Jacobian contribution for implicit integration ---*/ + if (implicit) Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); - }//if viscous - }//if GetDomain - }//for iVertex - - /*--- Free locally allocated memory ---*/ - delete [] Normal; - delete [] UnitNormal; - delete [] Tangential; - delete [] GradNormVel; - delete [] GradTangVel; - - for (iVar = 0; iVar < nPrimVarGrad; iVar++) - delete [] Grad_Reflected[iVar]; - delete [] Grad_Reflected; -} + } -void CIncEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, - CNumerics *visc_numerics, CConfig *config) { + } + } - unsigned long iVertex, jVertex, iPoint, Point_Normal = 0; - unsigned short iDim, iVar, jVar, iMarker, nDonorVertex; + /*--- Free locally allocated memory ---*/ - bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); - bool viscous = config->GetViscous(); + delete [] Normal; - su2double *Normal = new su2double[nDim]; - su2double *PrimVar_i = new su2double[nPrimVar]; - su2double *PrimVar_j = new su2double[nPrimVar]; - su2double *tmp_residual = new su2double[nVar]; +} - su2double weight; +void CIncEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, + CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + unsigned short iDim; + unsigned long iVertex, iPoint, Point_Normal; + su2double Area; + su2double *V_outlet, *V_domain, P_Outlet = 0.0, P_domain; + su2double mDot_Target, mDot_Old, dP, Density_Avg, Area_Outlet; + su2double Damping = config->GetInc_Outlet_Damping(); - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + bool viscous = config->GetViscous(); + string Marker_Tag = config->GetMarker_All_TagBound(val_marker); - if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) { + su2double *Normal = new su2double[nDim]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + unsigned short Kind_Outlet = config->GetKind_Inc_Outlet(Marker_Tag); - if (geometry->nodes->GetDomain(iPoint)) { + /*--- Loop over all the vertices on this boundary marker ---*/ - nDonorVertex = GetnSlidingStates(iMarker, iVertex); + for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { - /*--- Initialize Residual, this will serve to accumulate the average ---*/ + /*--- Allocate the value at the outlet ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] = 0.0; - for (jVar = 0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] = 0.0; - } + V_outlet = GetCharacPrimVar(val_marker, iVertex); - /*--- Loop over the nDonorVertexes and compute the averaged flux ---*/ + iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); - for (jVertex = 0; jVertex < nDonorVertex; jVertex++) { + /*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/ - Point_Normal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); + if (geometry->nodes->GetDomain(iPoint)) { - for (iVar = 0; iVar < nPrimVar; iVar++) { - PrimVar_i[iVar] = nodes->GetPrimitive(iPoint,iVar); - PrimVar_j[iVar] = GetSlidingState(iMarker, iVertex, iVar, jVertex); - } + /*--- Index of the closest interior node ---*/ - /*--- Get the weight computed in the interpolator class for the j-th donor vertex ---*/ + Point_Normal = geometry->vertex[val_marker][iVertex]->GetNormal_Neighbor(); - weight = GetSlidingState(iMarker, iVertex, nPrimVar, jVertex); + /*--- Normal vector for this vertex (negate for outward convention) ---*/ - /*--- Set primitive variables ---*/ + geometry->vertex[val_marker][iVertex]->GetNormal(Normal); + for (iDim = 0; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim]; + conv_numerics->SetNormal(Normal); - conv_numerics->SetPrimitive( PrimVar_i, PrimVar_j ); + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; + Area = sqrt (Area); - /*--- Set the normal vector ---*/ + /*--- Current solution at this boundary node ---*/ - geometry->vertex[iMarker][iVertex]->GetNormal(Normal); - for (iDim = 0; iDim < nDim; iDim++) - Normal[iDim] = -Normal[iDim]; + V_domain = nodes->GetPrimitive(iPoint); - conv_numerics->SetNormal(Normal); + /*--- Store the current static pressure for clarity. ---*/ - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint)); + P_domain = nodes->GetPressure(iPoint); - /*--- Compute the convective residual using an upwind scheme ---*/ + /*--- Compute a boundary value for the pressure depending on whether + we are prescribing a back pressure or a mass flow target. ---*/ - auto residual = conv_numerics->ComputeResidual(config); + switch (Kind_Outlet) { - /*--- Accumulate the residuals to compute the average ---*/ + /*--- Velocity and temperature (if required) been specified at the inlet. ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] += weight*residual.residual[iVar]; - for (jVar = 0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] += weight*residual.jacobian_i[iVar][jVar]; - } + case PRESSURE_OUTLET: - } + /*--- Retrieve the specified back pressure for this outlet. ---*/ - /*--- Add Residuals and Jacobians ---*/ + P_Outlet = config->GetOutlet_Pressure(Marker_Tag)/config->GetPressure_Ref(); - LinSysRes.AddBlock(iPoint, Residual); - if (implicit) - Jacobian.AddBlock2Diag(iPoint, Jacobian_i); + /*--- The pressure is prescribed at the outlet. ---*/ - if (viscous) { + V_outlet[0] = P_Outlet; - /*--- Initialize Residual, this will serve to accumulate the average ---*/ + /*--- Neumann condition for the velocity. ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] = 0.0; - for (jVar = 0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] = 0.0; - } + for (iDim = 0; iDim < nDim; iDim++) { + V_outlet[iDim+1] = nodes->GetVelocity(iPoint,iDim); + } - /*--- Loop over the nDonorVertexes and compute the averaged flux ---*/ + break; - for (jVertex = 0; jVertex < nDonorVertex; jVertex++){ - PrimVar_j[nDim+5] = GetSlidingState(iMarker, iVertex, nDim+5, jVertex); - PrimVar_j[nDim+6] = GetSlidingState(iMarker, iVertex, nDim+6, jVertex); + /*--- A mass flow target has been specified for the outlet. ---*/ - /*--- Get the weight computed in the interpolator class for the j-th donor vertex ---*/ + case MASS_FLOW_OUTLET: - weight = GetSlidingState(iMarker, iVertex, nPrimVar, jVertex); + /*--- Retrieve the specified target mass flow at the outlet. ---*/ - /*--- Set the normal vector and the coordinates ---*/ + mDot_Target = config->GetOutlet_Pressure(Marker_Tag)/(config->GetDensity_Ref() * config->GetVelocity_Ref()); - visc_numerics->SetNormal(Normal); - visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), geometry->nodes->GetCoord(Point_Normal)); + /*--- Retrieve the old mass flow, density, and area of the outlet, + which has been computed in a preprocessing step. These values + were stored in non-dim. form in the config container. ---*/ - /*--- Primitive variables, and gradient ---*/ + mDot_Old = config->GetOutlet_MassFlow(Marker_Tag); + Density_Avg = config->GetOutlet_Density(Marker_Tag); + Area_Outlet = config->GetOutlet_Area(Marker_Tag); - visc_numerics->SetPrimitive(PrimVar_i, PrimVar_j); - visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), nodes->GetGradient_Primitive(iPoint)); + /*--- Compute the pressure increment based on the difference + between the current and target mass flow. Note that increasing + pressure decreases flow speed. ---*/ - /*--- Turbulent kinetic energy ---*/ + dP = 0.5*Density_Avg*(mDot_Old*mDot_Old - mDot_Target*mDot_Target)/((Density_Avg*Area_Outlet)*(Density_Avg*Area_Outlet)); - if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) - visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0)); + /*--- Update the new outlet pressure. Note that we use damping + here to improve stability/convergence. ---*/ - /*--- Set the wall shear stress values (wall functions) to -1 (no evaluation using wall functions) ---*/ + P_Outlet = P_domain + Damping*dP; - visc_numerics->SetTauWall(-1.0, -1.0); + /*--- The pressure is prescribed at the outlet. ---*/ - /*--- Compute and update residual ---*/ + V_outlet[0] = P_Outlet; - auto residual = visc_numerics->ComputeResidual(config); + /*--- Neumann condition for the velocity ---*/ - /*--- Accumulate the residuals to compute the average ---*/ + for (iDim = 0; iDim < nDim; iDim++) { + V_outlet[iDim+1] = nodes->GetVelocity(iPoint,iDim); + } - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] += weight*residual.residual[iVar]; - for (jVar = 0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] += weight*residual.jacobian_i[iVar][jVar]; - } - } + break; - LinSysRes.SubtractBlock(iPoint, Residual); + } - /*--- Jacobian contribution for implicit integration ---*/ + /*--- Neumann condition for the temperature. ---*/ - if (implicit) - Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); + V_outlet[nDim+1] = nodes->GetTemperature(iPoint); - } - } - } - } - } + /*--- Access density at the interior node. This is either constant by + construction, or will be set fixed implicitly by the temperature + and equation of state. ---*/ - /*--- Free locally allocated memory ---*/ + V_outlet[nDim+2] = nodes->GetDensity(iPoint); - delete [] tmp_residual; - delete [] Normal; - delete [] PrimVar_i; - delete [] PrimVar_j; + /*--- Beta coefficient from the config file ---*/ -} + V_outlet[nDim+3] = nodes->GetBetaInc2(iPoint); -void CIncEulerSolver::BC_Periodic(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, CConfig *config) { + /*--- Cp is needed for Temperature equation. ---*/ - /*--- Complete residuals for periodic boundary conditions. We loop over - the periodic BCs in matching pairs so that, in the event that there are - adjacent periodic markers, the repeated points will have their residuals - accumulated correctly during the communications. For implicit calculations, - the Jacobians and linear system are also correctly adjusted here. ---*/ + V_outlet[nDim+7] = nodes->GetSpecificHeatCp(iPoint); - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL); - } + /*--- Set various quantities in the solver class ---*/ -} + conv_numerics->SetPrimitive(V_domain, V_outlet); -void CIncEulerSolver::BC_Custom(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) { + if (dynamic_grid) + conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), + geometry->nodes->GetGridVel(iPoint)); - /* Check for a verification solution. */ + /*--- Compute the residual using an upwind scheme ---*/ - if (VerificationSolution) { + auto residual = conv_numerics->ComputeResidual(config); - unsigned short iVar; - unsigned long iVertex, iPoint, total_index; + /*--- Update residual value ---*/ - bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + LinSysRes.AddBlock(iPoint, residual); - /*--- Get the physical time. ---*/ + /*--- Jacobian contribution for implicit integration ---*/ - su2double time = 0.0; - if (config->GetTime_Marching()) time = config->GetPhysicalTime(); + if (implicit) { + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); + } - /*--- Loop over all the vertices on this boundary marker ---*/ + /*--- Viscous contribution, commented out because serious convergence problems ---*/ - for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { + if (viscous) { - /*--- Get the point index for the current node. ---*/ + /*--- Set transport properties at the outlet. ---*/ - iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); + V_outlet[nDim+4] = nodes->GetLaminarViscosity(iPoint); + V_outlet[nDim+5] = nodes->GetEddyViscosity(iPoint); + V_outlet[nDim+6] = nodes->GetThermalConductivity(iPoint); - /*--- Check if the node belongs to the domain (i.e, not a halo node) ---*/ + /*--- Set the normal vector and the coordinates ---*/ - if (geometry->nodes->GetDomain(iPoint)) { + visc_numerics->SetNormal(Normal); + visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), + geometry->nodes->GetCoord(Point_Normal)); - /*--- Get the coordinates for the current node. ---*/ + /*--- Primitive variables, and gradient ---*/ - const su2double *coor = geometry->nodes->GetCoord(iPoint); + visc_numerics->SetPrimitive(V_domain, V_outlet); + visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), + nodes->GetGradient_Primitive(iPoint)); - /*--- Get the conservative state from the verification solution. ---*/ + /*--- Turbulent kinetic energy ---*/ - VerificationSolution->GetBCState(coor, time, Solution); + if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) + visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), + solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0)); - /*--- For verification cases, we will apply a strong Dirichlet - condition by setting the solution values at the boundary nodes - directly and setting the residual to zero at those nodes. ---*/ + /*--- Compute and update residual ---*/ - nodes->SetSolution_Old(iPoint,Solution); - nodes->SetSolution(iPoint,Solution); - nodes->SetRes_TruncErrorZero(iPoint); - LinSysRes.SetBlock_Zero(iPoint); + auto residual = visc_numerics->ComputeResidual(config); - /*--- Adjust rows of the Jacobian (includes 1 in the diagonal) ---*/ + LinSysRes.SubtractBlock(iPoint, residual); - if (implicit){ - for (iVar = 0; iVar < nVar; iVar++) { - total_index = iPoint*nVar+iVar; - Jacobian.DeleteValsRowi(total_index); - } - } + /*--- Jacobian contribution for implicit integration ---*/ + if (implicit) + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } - } - - } else { - - /* The user must specify the custom BC's here. */ - SU2_MPI::Error("Implement customized boundary conditions here.", CURRENT_FUNCTION); + } } + /*--- Free locally allocated memory ---*/ + delete [] Normal; + } void CIncEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_container, CConfig *config, @@ -5706,105 +3520,44 @@ void CIncEulerSolver::GetOutlet_Properties(CGeometry *geometry, CConfig *config, } -void CIncEulerSolver::ComputeVerificationError(CGeometry *geometry, - CConfig *config) { +void CIncEulerSolver::PrintVerificationError(const CConfig *config) const { - /*--- The errors only need to be computed on the finest grid. ---*/ - if(MGLevel != MESH_0) return; + if ((rank != MASTER_NODE) || (MGLevel != MESH_0)) return; - /*--- If this is a verification case, we can compute the global - error metrics by using the difference between the local error - and the known solution at each DOF. This is then collected into - RMS (L2) and maximum (Linf) global error norms. From these - global measures, one can compute the order of accuracy. ---*/ + if (config && !config->GetDiscrete_Adjoint()) { - bool write_heads = ((((config->GetInnerIter() % (config->GetWrt_Con_Freq()*40)) == 0) - && (config->GetInnerIter()!= 0)) - || (config->GetInnerIter() == 1)); - if( !write_heads ) return; - - /*--- Check if there actually is an exact solution for this - verification case, if computed at all. ---*/ - if (VerificationSolution) { - if (VerificationSolution->ExactSolutionKnown()) { - - /*--- Get the physical time if necessary. ---*/ - su2double time = 0.0; - if (config->GetTime_Marching()) time = config->GetPhysicalTime(); - - /*--- Reset the global error measures to zero. ---*/ - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - VerificationSolution->SetError_RMS(iVar, 0.0); - VerificationSolution->SetError_Max(iVar, 0.0, 0); - } - - /*--- Loop over all owned points. ---*/ - for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - - /* Set the pointers to the coordinates and solution of this DOF. */ - const su2double *coor = geometry->nodes->GetCoord(iPoint); - su2double *solDOF = nodes->GetSolution(iPoint); - - /* Get local error from the verification solution class. */ - vector error(nVar,0.0); - VerificationSolution->GetLocalError(coor, time, solDOF, error.data()); - - /* Increment the global error measures */ - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - VerificationSolution->AddError_RMS(iVar, error[iVar]*error[iVar]); - VerificationSolution->AddError_Max(iVar, fabs(error[iVar]), - geometry->nodes->GetGlobalIndex(iPoint), - geometry->nodes->GetCoord(iPoint)); - } - } - - /* Finalize the calculation of the global error measures. */ - VerificationSolution->SetVerificationError(geometry->GetGlobal_nPointDomain(), config); - - /*--- Screen output of the error metrics. This can be improved - once the new output classes are in place. ---*/ - - if ((rank == MASTER_NODE) && (geometry->GetMGLevel() == MESH_0)) { - - cout.precision(6); - cout.setf(ios::scientific, ios::floatfield); - - if (!config->GetDiscrete_Adjoint()) { - - cout << endl << "------------------------ Global Error Analysis --------------------------" << endl; + cout.precision(6); + cout.setf(ios::scientific, ios::floatfield); - cout << setw(20) << "RMS Error [P]: " << setw(12) << VerificationSolution->GetError_RMS(0) << " | "; - cout << setw(20) << "Max Error [P]: " << setw(12) << VerificationSolution->GetError_Max(0); - cout << endl; + cout << endl << "------------------------ Global Error Analysis --------------------------" << endl; - cout << setw(20) << "RMS Error [U]: " << setw(12) << VerificationSolution->GetError_RMS(1) << " | "; - cout << setw(20) << "Max Error [U]: " << setw(12) << VerificationSolution->GetError_Max(1); - cout << endl; + cout << setw(20) << "RMS Error [P]: " << setw(12) << VerificationSolution->GetError_RMS(0) << " | "; + cout << setw(20) << "Max Error [P]: " << setw(12) << VerificationSolution->GetError_Max(0); + cout << endl; - cout << setw(20) << "RMS Error [V]: " << setw(12) << VerificationSolution->GetError_RMS(2) << " | "; - cout << setw(20) << "Max Error [V]: " << setw(12) << VerificationSolution->GetError_Max(2); - cout << endl; + cout << setw(20) << "RMS Error [U]: " << setw(12) << VerificationSolution->GetError_RMS(1) << " | "; + cout << setw(20) << "Max Error [U]: " << setw(12) << VerificationSolution->GetError_Max(1); + cout << endl; - if (nDim == 3) { - cout << setw(20) << "RMS Error [W]: " << setw(12) << VerificationSolution->GetError_RMS(3) << " | "; - cout << setw(20) << "Max Error [W]: " << setw(12) << VerificationSolution->GetError_Max(3); - cout << endl; - } + cout << setw(20) << "RMS Error [V]: " << setw(12) << VerificationSolution->GetError_RMS(2) << " | "; + cout << setw(20) << "Max Error [V]: " << setw(12) << VerificationSolution->GetError_Max(2); + cout << endl; - if (config->GetEnergy_Equation()) { - cout << setw(20) << "RMS Error [T]: " << setw(12) << VerificationSolution->GetError_RMS(nDim+1) << " | "; - cout << setw(20) << "Max Error [T]: " << setw(12) << VerificationSolution->GetError_Max(nDim+1); - cout << endl; - } + if (nDim == 3) { + cout << setw(20) << "RMS Error [W]: " << setw(12) << VerificationSolution->GetError_RMS(3) << " | "; + cout << setw(20) << "Max Error [W]: " << setw(12) << VerificationSolution->GetError_Max(3); + cout << endl; + } - cout << "-------------------------------------------------------------------------" << endl << endl; - cout.unsetf(ios_base::floatfield); - } - } + if (config->GetEnergy_Equation()) { + cout << setw(20) << "RMS Error [T]: " << setw(12) << VerificationSolution->GetError_RMS(nDim+1) << " | "; + cout << setw(20) << "Max Error [T]: " << setw(12) << VerificationSolution->GetError_Max(nDim+1); + cout << endl; } + cout << "-------------------------------------------------------------------------" << endl << endl; + cout.unsetf(ios_base::floatfield); } - } void CIncEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *config, int val_iter, bool val_update_geo) { diff --git a/SU2_CFD/src/solvers/CIncNSSolver.cpp b/SU2_CFD/src/solvers/CIncNSSolver.cpp index 2bb16a6c08d9..4ff45ef0f5b8 100644 --- a/SU2_CFD/src/solvers/CIncNSSolver.cpp +++ b/SU2_CFD/src/solvers/CIncNSSolver.cpp @@ -25,666 +25,33 @@ * License along with SU2. If not, see . */ - #include "../../include/solvers/CIncNSSolver.hpp" #include "../../include/variables/CIncNSVariable.hpp" #include "../../../Common/include/toolboxes/printing_toolbox.hpp" +#include "../../include/solvers/CFVMFlowSolverBase.inl" -CIncNSSolver::CIncNSSolver(void) : CIncEulerSolver() { - - /*--- Basic array initialization ---*/ - - CD_Visc = nullptr; CL_Visc = nullptr; CSF_Visc = nullptr; CEff_Visc = nullptr; - CMx_Visc = nullptr; CMy_Visc = nullptr; CMz_Visc = nullptr; - CFx_Visc = nullptr; CFy_Visc = nullptr; CFz_Visc = nullptr; - CoPx_Visc = nullptr; CoPy_Visc = nullptr; CoPz_Visc = nullptr; - - ForceViscous = nullptr; MomentViscous = nullptr; CSkinFriction = nullptr; - - /*--- Surface based array initialization ---*/ - - Surface_CL_Visc = nullptr; Surface_CD_Visc = nullptr; Surface_CSF_Visc = nullptr; Surface_CEff_Visc = nullptr; - Surface_CFx_Visc = nullptr; Surface_CFy_Visc = nullptr; Surface_CFz_Visc = nullptr; - Surface_CMx_Visc = nullptr; Surface_CMy_Visc = nullptr; Surface_CMz_Visc = nullptr; - Surface_HF_Visc = nullptr; Surface_MaxHF_Visc = nullptr; - - /*--- Rotorcraft simulation array initialization ---*/ - - CMerit_Visc = nullptr; CT_Visc = nullptr; CQ_Visc = nullptr; - - SlidingState = nullptr; - SlidingStateNodes = nullptr; - -} - -CIncNSSolver::CIncNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : CIncEulerSolver() { - - unsigned long iPoint, iVertex; - unsigned short iVar, iDim, iMarker, nLineLets; - ifstream restart_file; - unsigned short nZone = geometry->GetnZone(); - bool restart = (config->GetRestart() || config->GetRestart_Flow()); - int Unst_RestartIter; - unsigned short iZone = config->GetiZone(); - bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || - (config->GetTime_Marching() == DT_STEPPING_2ND)); - bool time_stepping = config->GetTime_Marching() == TIME_STEPPING; - bool adjoint = (config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint()); - string filename_ = config->GetSolution_FileName(); - - /* A grid is defined as dynamic if there's rigid grid movement or grid deformation AND the problem is time domain */ - dynamic_grid = config->GetDynamic_Grid(); - - unsigned short direct_diff = config->GetDirectDiff(); - - /*--- Store the multigrid level. ---*/ - MGLevel = iMesh; - - /*--- Check for a restart file to evaluate if there is a change in the angle of attack - before computing all the non-dimesional quantities. ---*/ - - if (!(!restart || (iMesh != MESH_0) || nZone > 1)) { - - /*--- Multizone problems require the number of the zone to be appended. ---*/ - - if (nZone > 1) filename_ = config->GetMultizone_FileName(filename_, iZone, ".dat"); - - /*--- Modify file name for a dual-time unsteady restart ---*/ - - if (dual_time) { - if (adjoint) Unst_RestartIter = SU2_TYPE::Int(config->GetUnst_AdjointIter())-1; - else if (config->GetTime_Marching() == DT_STEPPING_1ST) - Unst_RestartIter = SU2_TYPE::Int(config->GetRestart_Iter())-1; - else Unst_RestartIter = SU2_TYPE::Int(config->GetRestart_Iter())-2; - filename_ = config->GetUnsteady_FileName(filename_, Unst_RestartIter, ".dat"); - } - - /*--- Modify file name for a time stepping unsteady restart ---*/ - - if (time_stepping) { - if (adjoint) Unst_RestartIter = SU2_TYPE::Int(config->GetUnst_AdjointIter())-1; - else Unst_RestartIter = SU2_TYPE::Int(config->GetRestart_Iter())-1; - filename_ = config->GetUnsteady_FileName(filename_, Unst_RestartIter, ".dat"); - } - - /*--- Read and store the restart metadata. ---*/ - -// Read_SU2_Restart_Metadata(geometry, config, false, filename_); - - } - - /*--- Array initialization ---*/ - - CD_Visc = nullptr; CL_Visc = nullptr; CSF_Visc = nullptr; CEff_Visc = nullptr; - CMx_Visc = nullptr; CMy_Visc = nullptr; CMz_Visc = nullptr; - CFx_Visc = nullptr; CFy_Visc = nullptr; CFz_Visc = nullptr; - CoPx_Visc = nullptr; CoPy_Visc = nullptr; CoPz_Visc = nullptr; - - Surface_CL_Visc = nullptr; Surface_CD_Visc = nullptr; Surface_CSF_Visc = nullptr; Surface_CEff_Visc = nullptr; - Surface_CFx_Visc = nullptr; Surface_CFy_Visc = nullptr; Surface_CFz_Visc = nullptr; - Surface_CMx_Visc = nullptr; Surface_CMy_Visc = nullptr; Surface_CMz_Visc = nullptr; - Surface_HF_Visc = nullptr; Surface_MaxHF_Visc = nullptr; - - CMerit_Visc = nullptr; CT_Visc = nullptr; CQ_Visc = nullptr; - MaxHF_Visc = nullptr; ForceViscous = nullptr; MomentViscous = nullptr; - CSkinFriction = nullptr; HF_Visc = nullptr; - - /*--- Set the gamma value ---*/ - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - /*--- Define geometry constants in the solver structure - * Incompressible flow, primitive variables (P, vx, vy, vz, T, rho, beta, lamMu, EddyMu, Kt_eff, Cp, Cv) --- */ - - nDim = geometry->GetnDim(); - - nVar = nDim+2; nPrimVar = nDim+9; nPrimVarGrad = nDim+4; - - /*--- Initialize nVarGrad for deallocation ---*/ - - nVarGrad = nPrimVarGrad; - - nMarker = config->GetnMarker_All(); - nPoint = geometry->GetnPoint(); - nPointDomain = geometry->GetnPointDomain(); - - /*--- Store the number of vertices on each marker for deallocation later ---*/ - - nVertex = new unsigned long[nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) - nVertex[iMarker] = geometry->nVertex[iMarker]; - - /*--- Fluid model intialization. ---*/ - - FluidModel = nullptr; - - /*--- Perform the non-dimensionalization for the flow equations using the - specified reference values. ---*/ - - SetNondimensionalization(config, iMesh); - - /*--- Check if we are executing a verification case. If so, the - VerificationSolution object will be instantiated for a particular - option from the available library of verification solutions. Note - that this is done after SetNondim(), as problem-specific initial - parameters are needed by the solution constructors. ---*/ - - SetVerificationSolution(nDim, nVar, config); - - /*--- Define some auxiliar vector related with the residual ---*/ - - Residual = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual[iVar] = 0.0; - Residual_RMS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_RMS[iVar] = 0.0; - Residual_Max = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max[iVar] = 0.0; - Res_Conv = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Res_Conv[iVar] = 0.0; - Res_Visc = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Res_Visc[iVar] = 0.0; - Res_Sour = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Res_Sour[iVar] = 0.0; - - /*--- Define some structures for locating max residuals ---*/ - - Point_Max = new unsigned long[nVar]; for (iVar = 0; iVar < nVar; iVar++) Point_Max[iVar] = 0; - Point_Max_Coord = new su2double*[nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - Point_Max_Coord[iVar] = new su2double[nDim]; - for (iDim = 0; iDim < nDim; iDim++) Point_Max_Coord[iVar][iDim] = 0.0; - } - - /*--- Define some auxiliary vectors related to the solution ---*/ - - Solution = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 0.0; - Solution_i = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Solution_i[iVar] = 0.0; - Solution_j = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Solution_j[iVar] = 0.0; - - /*--- Define some auxiliary vectors related to the geometry ---*/ - - Vector = new su2double[nDim]; for (iDim = 0; iDim < nDim; iDim++) Vector[iDim] = 0.0; - Vector_i = new su2double[nDim]; for (iDim = 0; iDim < nDim; iDim++) Vector_i[iDim] = 0.0; - Vector_j = new su2double[nDim]; for (iDim = 0; iDim < nDim; iDim++) Vector_j[iDim] = 0.0; - - /*--- Define some auxiliary vectors related to the primitive solution ---*/ - - Primitive = new su2double[nPrimVar]; for (iVar = 0; iVar < nPrimVar; iVar++) Primitive[iVar] = 0.0; - Primitive_i = new su2double[nPrimVar]; for (iVar = 0; iVar < nPrimVar; iVar++) Primitive_i[iVar] = 0.0; - Primitive_j = new su2double[nPrimVar]; for (iVar = 0; iVar < nPrimVar; iVar++) Primitive_j[iVar] = 0.0; - - /*--- Define some auxiliar vector related with the undivided lapalacian computation ---*/ - - if (config->GetKind_ConvNumScheme_Flow() == SPACE_CENTERED) { - iPoint_UndLapl = new su2double [nPoint]; - jPoint_UndLapl = new su2double [nPoint]; - } - - Preconditioner = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar ++) - Preconditioner[iVar] = new su2double[nVar]; - - /*--- Initialize the solution and right hand side vectors for storing - the residuals and updating the solution (always needed even for - explicit schemes). ---*/ - - LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0); - LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0); - - /*--- Jacobians and vector structures for implicit computations ---*/ - - if (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT) { - - Jacobian_i = new su2double* [nVar]; - Jacobian_j = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - Jacobian_i[iVar] = new su2double [nVar]; - Jacobian_j[iVar] = new su2double [nVar]; - } - - if (rank == MASTER_NODE) cout << "Initialize Jacobian structure (Navier-Stokes). MG level: " << iMesh <<"." << endl; - Jacobian.Initialize(nPoint, nPointDomain, nVar, nVar, true, geometry, config); - - if (config->GetKind_Linear_Solver_Prec() == LINELET) { - nLineLets = Jacobian.BuildLineletPreconditioner(geometry, config); - if (rank == MASTER_NODE) cout << "Compute linelet structure. " << nLineLets << " elements in each line (average)." << endl; - } - - } - - else { - if (rank == MASTER_NODE) - cout << "Explicit scheme. No Jacobian structure (Navier-Stokes). MG level: " << iMesh <<"." << endl; - } - - /*--- Store the value of the characteristic primitive variables at the boundaries ---*/ - - CharacPrimVar = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - CharacPrimVar[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - CharacPrimVar[iMarker][iVertex] = new su2double [nPrimVar]; - for (iVar = 0; iVar < nPrimVar; iVar++) { - CharacPrimVar[iMarker][iVertex][iVar] = 0.0; - } - } - } - - /*--- Store the values of the temperature and the heat flux density at the boundaries, - used for coupling with a solid donor cell ---*/ - unsigned short nHeatConjugateVar = 4; - - HeatConjugateVar = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - HeatConjugateVar[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - - HeatConjugateVar[iMarker][iVertex] = new su2double [nHeatConjugateVar]; - for (iVar = 1; iVar < nHeatConjugateVar ; iVar++) { - HeatConjugateVar[iMarker][iVertex][iVar] = 0.0; - } - HeatConjugateVar[iMarker][iVertex][0] = config->GetTemperature_FreeStreamND(); - } - } - - /*--- Inviscid force definition and coefficient in all the markers ---*/ - - CPressure = new su2double* [nMarker]; - CPressureTarget = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - CPressure[iMarker] = new su2double [geometry->nVertex[iMarker]]; - CPressureTarget[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - CPressure[iMarker][iVertex] = 0.0; - CPressureTarget[iMarker][iVertex] = 0.0; - } - } - - /*--- Heat flux in all the markers ---*/ - - HeatFlux = new su2double* [nMarker]; - HeatFluxTarget = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - HeatFlux[iMarker] = new su2double [geometry->nVertex[iMarker]]; - HeatFluxTarget[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - HeatFlux[iMarker][iVertex] = 0.0; - HeatFluxTarget[iMarker][iVertex] = 0.0; - } - } - - /*--- Y plus in all the markers ---*/ - - YPlus = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - YPlus[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - YPlus[iMarker][iVertex] = 0.0; - } - } - - /*--- Skin friction in all the markers ---*/ - - CSkinFriction = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - CSkinFriction[iMarker] = new su2double*[nDim]; - for (iDim = 0; iDim < nDim; iDim++) { - CSkinFriction[iMarker][iDim] = new su2double[geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - CSkinFriction[iMarker][iDim][iVertex] = 0.0; - } - } - } +/*--- Explicit instantiation of the parent class of CIncEulerSolver, + * to spread the compilation over two cpp files. ---*/ +template class CFVMFlowSolverBase; - /*--- Store the value of the Total Pressure at the inlet BC ---*/ - Inlet_Ttotal = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_Ttotal[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - Inlet_Ttotal[iMarker][iVertex] = 0; - } - } - - /*--- Store the value of the Total Temperature at the inlet BC ---*/ - - Inlet_Ptotal = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_Ptotal[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - Inlet_Ptotal[iMarker][iVertex] = 0; - } - } - - /*--- Store the value of the Flow direction at the inlet BC ---*/ - - Inlet_FlowDir = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_FlowDir[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - Inlet_FlowDir[iMarker][iVertex] = new su2double [nDim]; - for (iDim = 0; iDim < nDim; iDim++) { - Inlet_FlowDir[iMarker][iVertex][iDim] = 0; - } - } - } - - /*--- Non dimensional coefficients ---*/ - - ForceInviscid = new su2double[3]; - MomentInviscid = new su2double[3]; - CD_Inv = new su2double[nMarker]; - CL_Inv = new su2double[nMarker]; - CSF_Inv = new su2double[nMarker]; - CMx_Inv = new su2double[nMarker]; - CMy_Inv = new su2double[nMarker]; - CMz_Inv = new su2double[nMarker]; - CEff_Inv = new su2double[nMarker]; - CFx_Inv = new su2double[nMarker]; - CFy_Inv = new su2double[nMarker]; - CFz_Inv = new su2double[nMarker]; - CoPx_Inv = new su2double[nMarker]; - CoPy_Inv = new su2double[nMarker]; - CoPz_Inv = new su2double[nMarker]; - - ForceMomentum = new su2double[3]; - MomentMomentum = new su2double[3]; - CD_Mnt = new su2double[nMarker]; - CL_Mnt = new su2double[nMarker]; - CSF_Mnt = new su2double[nMarker]; - CMx_Mnt = new su2double[nMarker]; - CMy_Mnt = new su2double[nMarker]; - CMz_Mnt = new su2double[nMarker]; - CEff_Mnt = new su2double[nMarker]; - CFx_Mnt = new su2double[nMarker]; - CFy_Mnt = new su2double[nMarker]; - CFz_Mnt = new su2double[nMarker]; - CoPx_Mnt = new su2double[nMarker]; - CoPy_Mnt = new su2double[nMarker]; - CoPz_Mnt = new su2double[nMarker]; - - ForceViscous = new su2double[3]; - MomentViscous = new su2double[3]; - CD_Visc = new su2double[nMarker]; - CL_Visc = new su2double[nMarker]; - CSF_Visc = new su2double[nMarker]; - CMx_Visc = new su2double[nMarker]; - CMy_Visc = new su2double[nMarker]; - CMz_Visc = new su2double[nMarker]; - CEff_Visc = new su2double[nMarker]; - CFx_Visc = new su2double[nMarker]; - CFy_Visc = new su2double[nMarker]; - CFz_Visc = new su2double[nMarker]; - CoPx_Visc = new su2double[nMarker]; - CoPy_Visc = new su2double[nMarker]; - CoPz_Visc = new su2double[nMarker]; - - Surface_CL_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CD_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CSF_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CEff_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFx_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFy_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFz_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMx_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMy_Inv = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMz_Inv = new su2double[config->GetnMarker_Monitoring()]; - - Surface_CL_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CD_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CSF_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CEff_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFx_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFy_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFz_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMx_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMy_Mnt = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMz_Mnt = new su2double[config->GetnMarker_Monitoring()]; - - Surface_CL = new su2double[config->GetnMarker_Monitoring()]; - Surface_CD = new su2double[config->GetnMarker_Monitoring()]; - Surface_CSF = new su2double[config->GetnMarker_Monitoring()]; - Surface_CEff = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFx = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFy = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFz = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMx = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMy = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMz = new su2double[config->GetnMarker_Monitoring()]; - - Surface_CL_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CD_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CSF_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CEff_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFx_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFy_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CFz_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMx_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMy_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_CMz_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_HF_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_MaxHF_Visc = new su2double[config->GetnMarker_Monitoring()]; - - /*--- Rotorcraft coefficients ---*/ - - CT_Inv = new su2double[nMarker]; - CQ_Inv = new su2double[nMarker]; - CMerit_Inv = new su2double[nMarker]; - - CT_Mnt = new su2double[nMarker]; - CQ_Mnt = new su2double[nMarker]; - CMerit_Mnt = new su2double[nMarker]; - - CMerit_Visc = new su2double[nMarker]; - CT_Visc = new su2double[nMarker]; - CQ_Visc = new su2double[nMarker]; - - /*--- Heat based coefficients ---*/ - - HF_Visc = new su2double[nMarker]; - MaxHF_Visc = new su2double[nMarker]; - - /*--- Init total coefficients ---*/ - - Total_CD = 0.0; Total_CL = 0.0; Total_CSF = 0.0; - Total_CMx = 0.0; Total_CMy = 0.0; Total_CMz = 0.0; - Total_CoPx = 0.0; Total_CoPy = 0.0; Total_CoPz = 0.0; - Total_CEff = 0.0; - Total_CFx = 0.0; Total_CFy = 0.0; Total_CFz = 0.0; - Total_CT = 0.0; Total_CQ = 0.0; Total_CMerit = 0.0; - Total_MaxHeat = 0.0; Total_Heat = 0.0; Total_ComboObj = 0.0; - Total_CpDiff = 0.0; Total_HeatFluxDiff = 0.0; Total_Custom_ObjFunc = 0.0; +CIncNSSolver::CIncNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : + CIncEulerSolver(geometry, config, iMesh, true) { /*--- Read farfield conditions from config ---*/ - Density_Inf = config->GetDensity_FreeStreamND(); - Pressure_Inf = config->GetPressure_FreeStreamND(); - Temperature_Inf = config->GetTemperature_FreeStreamND(); - Velocity_Inf = config->GetVelocity_FreeStreamND(); Viscosity_Inf = config->GetViscosity_FreeStreamND(); Tke_Inf = config->GetTke_FreeStreamND(); /*--- Initialize the secondary values for direct derivative approxiations ---*/ - switch(direct_diff){ - case NO_DERIVATIVE: - break; - case D_DENSITY: - SU2_TYPE::SetDerivative(Density_Inf, 1.0); - break; - case D_PRESSURE: - SU2_TYPE::SetDerivative(Pressure_Inf, 1.0); - break; - case D_TEMPERATURE: - SU2_TYPE::SetDerivative(Temperature_Inf, 1.0); - break; + switch (config->GetDirectDiff()) { case D_VISCOSITY: SU2_TYPE::SetDerivative(Viscosity_Inf, 1.0); break; - case D_MACH: case D_AOA: - case D_SIDESLIP: case D_REYNOLDS: - case D_TURB2LAM: case D_DESIGN: - /*--- Already done in postprocessing of config ---*/ - break; default: break; } - - /*--- Initializate quantities for SlidingMesh Interface ---*/ - - SlidingState = new su2double*** [nMarker]; - SlidingStateNodes = new int* [nMarker]; - - for (iMarker = 0; iMarker < nMarker; iMarker++){ - - SlidingState[iMarker] = nullptr; - SlidingStateNodes[iMarker] = nullptr; - - if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE){ - - SlidingState[iMarker] = new su2double**[geometry->GetnVertex(iMarker)]; - SlidingStateNodes[iMarker] = new int [geometry->GetnVertex(iMarker)]; - - for (iPoint = 0; iPoint < geometry->GetnVertex(iMarker); iPoint++){ - SlidingState[iMarker][iPoint] = new su2double*[nPrimVar+1]; - - SlidingStateNodes[iMarker][iPoint] = 0; - for (iVar = 0; iVar < nPrimVar+1; iVar++) - SlidingState[iMarker][iPoint][iVar] = nullptr; - } - - } - } - - /*--- Only initialize when there is a Marker_Fluid_Load defined - *--- (this avoids overhead in all other cases while a more permanent structure is being developed) ---*/ - if((config->GetnMarker_Fluid_Load() > 0) && (MGLevel == MESH_0)){ - - InitVertexTractionContainer(geometry, config); - - if (config->GetDiscrete_Adjoint()) - InitVertexTractionAdjointContainer(geometry, config); - - } - - /*--- Initialize the solution to the far-field state everywhere. ---*/ - - nodes = new CIncNSVariable(Pressure_Inf, Velocity_Inf, Temperature_Inf, nPoint, nDim, nVar, config); - SetBaseClassPointerToNodes(); - - /*--- Initialize the BGS residuals in FSI problems. ---*/ - if (config->GetMultizone_Residual()){ - Residual_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_RMS[iVar] = 0.0; - Residual_Max_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max_BGS[iVar] = 0.0; - - /*--- Define some structures for locating max residuals ---*/ - - Point_Max_BGS = new unsigned long[nVar]; for (iVar = 0; iVar < nVar; iVar++) Point_Max_BGS[iVar] = 0; - Point_Max_Coord_BGS = new su2double*[nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - Point_Max_Coord_BGS[iVar] = new su2double[nDim]; - for (iDim = 0; iDim < nDim; iDim++) Point_Max_Coord_BGS[iVar][iDim] = 0.0; - } - } - - /*--- Define solver parameters needed for execution of destructor ---*/ - - if (config->GetKind_ConvNumScheme_Flow() == SPACE_CENTERED) space_centered = true; - else space_centered = false; - - if (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT) euler_implicit = true; - else euler_implicit = false; - - if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) least_squares = true; - else least_squares = false; - - /*--- Communicate and store volume and the number of neighbors for - any dual CVs that lie on on periodic markers. ---*/ - - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME); - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS); - } - SetImplicitPeriodic(euler_implicit); - if (iMesh == MESH_0) SetRotatePeriodic(true); - - /*--- Perform the MPI communication of the solution ---*/ - - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); - - /* Store the initial CFL number for all grid points. */ - - const su2double CFL = config->GetCFL(MGLevel); - for (iPoint = 0; iPoint < nPoint; iPoint++) { - nodes->SetLocalCFL(iPoint, CFL); - } - Min_CFL_Local = CFL; - Max_CFL_Local = CFL; - Avg_CFL_Local = CFL; - - /*--- Add the solver name (max 8 characters) ---*/ - SolverName = "INC.FLOW"; - -} - -CIncNSSolver::~CIncNSSolver(void) { - - unsigned short iMarker, iDim; - - unsigned long iVertex; - - delete [] CD_Visc; - delete [] CL_Visc; - delete [] CSF_Visc; - delete [] CMx_Visc; - delete [] CMy_Visc; - delete [] CMz_Visc; - delete [] CoPx_Visc; - delete [] CoPy_Visc; - delete [] CoPz_Visc; - delete [] CFx_Visc; - delete [] CFy_Visc; - delete [] CFz_Visc; - delete [] CEff_Visc; - delete [] CMerit_Visc; - delete [] CT_Visc; - delete [] CQ_Visc; - delete [] HF_Visc; - delete [] MaxHF_Visc; - delete [] ForceViscous; - delete [] MomentViscous; - - delete [] Surface_CL_Visc; - delete [] Surface_CD_Visc; - delete [] Surface_CSF_Visc; - delete [] Surface_CEff_Visc; - delete [] Surface_CFx_Visc; - delete [] Surface_CFy_Visc; - delete [] Surface_CFz_Visc; - delete [] Surface_CMx_Visc; - delete [] Surface_CMy_Visc; - delete [] Surface_CMz_Visc; - delete [] Surface_HF_Visc; - delete [] Surface_MaxHF_Visc; - - if (CSkinFriction != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - for (iDim = 0; iDim < nDim; iDim++) { - delete [] CSkinFriction[iMarker][iDim]; - } - delete [] CSkinFriction[iMarker]; - } - delete [] CSkinFriction; - } - - if (HeatConjugateVar != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { - delete [] HeatConjugateVar[iMarker][iVertex]; - } - delete [] HeatConjugateVar[iMarker]; - } - delete [] HeatConjugateVar; - } - } void CIncNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { @@ -1121,468 +488,6 @@ void CIncNSSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_contai } -void CIncNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { - - unsigned long iVertex, iPoint, iPointNormal; - unsigned short Boundary, Monitoring, iMarker, iMarker_Monitoring, iDim, jDim; - su2double Viscosity = 0.0, div_vel, *Normal, MomentDist[3] = {0.0, 0.0, 0.0}, WallDist[3] = {0.0, 0.0, 0.0}, - *Coord, *Coord_Normal, Area, WallShearStress, TauNormal, factor, RefVel2 = 0.0, - RefDensity = 0.0, Density = 0.0, WallDistMod, FrictionVel, UnitNormal[3] = {0.0, 0.0, 0.0}, TauElem[3] = {0.0, 0.0, 0.0}, TauTangent[3] = {0.0, 0.0, 0.0}, - Tau[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}}, Force[3] = {0.0, 0.0, 0.0}, - Grad_Vel[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}}, - delta[3][3] = {{1.0, 0.0, 0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}}, - Grad_Temp[3] = {0.0, 0.0, 0.0}, GradTemperature, thermal_conductivity, MaxNorm = 8.0; - su2double MomentX_Force[3] = {0.0,0.0,0.0}, MomentY_Force[3] = {0.0,0.0,0.0}, MomentZ_Force[3] = {0.0,0.0,0.0}; - su2double AxiFactor; - -#ifdef HAVE_MPI - su2double MyAllBound_CD_Visc, MyAllBound_CL_Visc, MyAllBound_CSF_Visc, MyAllBound_CMx_Visc, MyAllBound_CMy_Visc, MyAllBound_CMz_Visc, MyAllBound_CoPx_Visc, MyAllBound_CoPy_Visc, MyAllBound_CoPz_Visc, MyAllBound_CFx_Visc, MyAllBound_CFy_Visc, MyAllBound_CFz_Visc, MyAllBound_CT_Visc, MyAllBound_CQ_Visc, MyAllBound_HF_Visc, MyAllBound_MaxHF_Visc, *MySurface_CL_Visc = NULL, *MySurface_CD_Visc = NULL, *MySurface_CSF_Visc = NULL, *MySurface_CEff_Visc = NULL, *MySurface_CFx_Visc = NULL, *MySurface_CFy_Visc = NULL, *MySurface_CFz_Visc = NULL, *MySurface_CMx_Visc = NULL, *MySurface_CMy_Visc = NULL, *MySurface_CMz_Visc = NULL, *MySurface_HF_Visc = NULL, *MySurface_MaxHF_Visc = NULL; -#endif - - string Marker_Tag, Monitoring_Tag; - - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - su2double RefArea = config->GetRefArea(); - su2double RefLength = config->GetRefLength(); - su2double RefHeatFlux = config->GetHeat_Flux_Ref(); - su2double *Origin = nullptr; - - if (config->GetnMarker_Monitoring() != 0) { Origin = config->GetRefOriginMoment(0); } - - bool axisymmetric = config->GetAxisymmetric(); - bool energy = config->GetEnergy_Equation(); - - /*--- Evaluate reference values for non-dimensionalization. - For dimensional or non-dim based on initial values, use - the far-field state (inf). For a custom non-dim based - on user-provided reference values, use the ref values - to compute the forces. ---*/ - - if ((config->GetRef_Inc_NonDim() == DIMENSIONAL) || - (config->GetRef_Inc_NonDim() == INITIAL_VALUES)) { - RefDensity = Density_Inf; - RefVel2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - RefVel2 += Velocity_Inf[iDim]*Velocity_Inf[iDim]; - } - else if (config->GetRef_Inc_NonDim() == REFERENCE_VALUES) { - RefDensity = config->GetInc_Density_Ref(); - RefVel2 = config->GetInc_Velocity_Ref()*config->GetInc_Velocity_Ref(); - } - - /*--- Compute factor for force coefficients. ---*/ - - factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2); - - /*--- Variables initialization ---*/ - - AllBound_CD_Visc = 0.0; AllBound_CL_Visc = 0.0; AllBound_CSF_Visc = 0.0; - AllBound_CMx_Visc = 0.0; AllBound_CMy_Visc = 0.0; AllBound_CMz_Visc = 0.0; - AllBound_CFx_Visc = 0.0; AllBound_CFy_Visc = 0.0; AllBound_CFz_Visc = 0.0; - AllBound_CoPx_Visc = 0.0; AllBound_CoPy_Visc = 0.0; AllBound_CoPz_Visc = 0.0; - AllBound_CT_Visc = 0.0; AllBound_CQ_Visc = 0.0; AllBound_CMerit_Visc = 0.0; - AllBound_HF_Visc = 0.0; AllBound_MaxHF_Visc = 0.0; AllBound_CEff_Visc = 0.0; - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Surface_CL_Visc[iMarker_Monitoring] = 0.0; Surface_CD_Visc[iMarker_Monitoring] = 0.0; - Surface_CSF_Visc[iMarker_Monitoring] = 0.0; Surface_CEff_Visc[iMarker_Monitoring] = 0.0; - Surface_CFx_Visc[iMarker_Monitoring] = 0.0; Surface_CFy_Visc[iMarker_Monitoring] = 0.0; - Surface_CFz_Visc[iMarker_Monitoring] = 0.0; Surface_CMx_Visc[iMarker_Monitoring] = 0.0; - Surface_CMy_Visc[iMarker_Monitoring] = 0.0; Surface_CMz_Visc[iMarker_Monitoring] = 0.0; - Surface_HF_Visc[iMarker_Monitoring] = 0.0; Surface_MaxHF_Visc[iMarker_Monitoring] = 0.0; - } - - /*--- Loop over the Navier-Stokes markers ---*/ - - for (iMarker = 0; iMarker < nMarker; iMarker++) { - - Boundary = config->GetMarker_All_KindBC(iMarker); - Monitoring = config->GetMarker_All_Monitoring(iMarker); - - /*--- Obtain the origin for the moment computation for a particular marker ---*/ - - if (Monitoring == YES) { - 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); - if (Marker_Tag == Monitoring_Tag) - Origin = config->GetRefOriginMoment(iMarker_Monitoring); - } - } - - if ((Boundary == HEAT_FLUX) || (Boundary == ISOTHERMAL) || (Boundary == CHT_WALL_INTERFACE)) { - - /*--- Forces initialization at each Marker ---*/ - - CD_Visc[iMarker] = 0.0; CL_Visc[iMarker] = 0.0; CSF_Visc[iMarker] = 0.0; - CMx_Visc[iMarker] = 0.0; CMy_Visc[iMarker] = 0.0; CMz_Visc[iMarker] = 0.0; - CFx_Visc[iMarker] = 0.0; CFy_Visc[iMarker] = 0.0; CFz_Visc[iMarker] = 0.0; - CoPx_Visc[iMarker] = 0.0; CoPy_Visc[iMarker] = 0.0; CoPz_Visc[iMarker] = 0.0; - CT_Visc[iMarker] = 0.0; CQ_Visc[iMarker] = 0.0; CMerit_Visc[iMarker] = 0.0; - HF_Visc[iMarker] = 0.0; MaxHF_Visc[iMarker] = 0.0; CEff_Visc[iMarker] = 0.0; - - for (iDim = 0; iDim < nDim; iDim++) ForceViscous[iDim] = 0.0; - MomentViscous[0] = 0.0; MomentViscous[1] = 0.0; MomentViscous[2] = 0.0; - MomentX_Force[0] = 0.0; MomentX_Force[1] = 0.0; MomentX_Force[2] = 0.0; - MomentY_Force[0] = 0.0; MomentY_Force[1] = 0.0; MomentY_Force[2] = 0.0; - MomentZ_Force[0] = 0.0; MomentZ_Force[1] = 0.0; MomentZ_Force[2] = 0.0; - - /*--- Loop over the vertices to compute the forces ---*/ - - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - iPointNormal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); - - Coord = geometry->nodes->GetCoord(iPoint); - Coord_Normal = geometry->nodes->GetCoord(iPointNormal); - - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - - for (iDim = 0; iDim < nDim; iDim++) { - for (jDim = 0 ; jDim < nDim; jDim++) { - Grad_Vel[iDim][jDim] = nodes->GetGradient_Primitive(iPoint,iDim+1, jDim); - } - Grad_Temp[iDim] = nodes->GetGradient_Primitive(iPoint,nDim+1, iDim); - } - - Viscosity = nodes->GetLaminarViscosity(iPoint); - Density = nodes->GetDensity(iPoint); - - Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); - for (iDim = 0; iDim < nDim; iDim++) { - UnitNormal[iDim] = Normal[iDim]/Area; - } - - /*--- Evaluate Tau ---*/ - - div_vel = 0.0; for (iDim = 0; iDim < nDim; iDim++) div_vel += Grad_Vel[iDim][iDim]; - - for (iDim = 0; iDim < nDim; iDim++) { - for (jDim = 0 ; jDim < nDim; jDim++) { - Tau[iDim][jDim] = Viscosity*(Grad_Vel[jDim][iDim] + Grad_Vel[iDim][jDim]) - TWO3*Viscosity*div_vel*delta[iDim][jDim]; - } - } - - /*--- Project Tau in each surface element ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - TauElem[iDim] = 0.0; - for (jDim = 0; jDim < nDim; jDim++) { - TauElem[iDim] += Tau[iDim][jDim]*UnitNormal[jDim]; - } - } - - /*--- Compute wall shear stress (using the stress tensor). Compute wall skin friction coefficient, and heat flux on the wall ---*/ - - TauNormal = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - TauNormal += TauElem[iDim] * UnitNormal[iDim]; - - WallShearStress = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - TauTangent[iDim] = TauElem[iDim] - TauNormal * UnitNormal[iDim]; - CSkinFriction[iMarker][iDim][iVertex] = TauTangent[iDim] / (0.5*RefDensity*RefVel2); - WallShearStress += TauTangent[iDim] * TauTangent[iDim]; - } - WallShearStress = sqrt(WallShearStress); - - for (iDim = 0; iDim < nDim; iDim++) WallDist[iDim] = (Coord[iDim] - Coord_Normal[iDim]); - WallDistMod = 0.0; for (iDim = 0; iDim < nDim; iDim++) WallDistMod += WallDist[iDim]*WallDist[iDim]; WallDistMod = sqrt(WallDistMod); - - /*--- Compute y+ and non-dimensional velocity ---*/ - - FrictionVel = sqrt(fabs(WallShearStress)/Density); - YPlus[iMarker][iVertex] = WallDistMod*FrictionVel/(Viscosity/Density); - - /*--- Compute total and maximum heat flux on the wall ---*/ - - GradTemperature = 0.0; - if (energy) { - for (iDim = 0; iDim < nDim; iDim++) - GradTemperature -= Grad_Temp[iDim]*UnitNormal[iDim]; - } - - thermal_conductivity = nodes->GetThermalConductivity(iPoint); - HeatFlux[iMarker][iVertex] = -thermal_conductivity*GradTemperature*RefHeatFlux; - - /*--- Note that y+, and heat are computed at the - halo cells (for visualization purposes), but not the forces ---*/ - - if ((geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES)) { - - /*--- Axisymmetric simulations ---*/ - - if (axisymmetric) AxiFactor = 2.0*PI_NUMBER*geometry->nodes->GetCoord(iPoint, 1); - else AxiFactor = 1.0; - - /*--- Force computation ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Force[iDim] = TauElem[iDim] * Area * factor * AxiFactor; - ForceViscous[iDim] += Force[iDim]; - MomentDist[iDim] = Coord[iDim] - Origin[iDim]; - } - - /*--- Moment with respect to the reference axis ---*/ - - if (iDim == 3) { - MomentViscous[0] += (Force[2]*MomentDist[1] - Force[1]*MomentDist[2])/RefLength; - MomentX_Force[1] += (-Force[1]*Coord[2]); - MomentX_Force[2] += (Force[2]*Coord[1]); - - MomentViscous[1] += (Force[0]*MomentDist[2] - Force[2]*MomentDist[0])/RefLength; - MomentY_Force[2] += (-Force[2]*Coord[0]); - MomentY_Force[0] += (Force[0]*Coord[2]); - } - MomentViscous[2] += (Force[1]*MomentDist[0] - Force[0]*MomentDist[1])/RefLength; - MomentZ_Force[0] += (-Force[0]*Coord[1]); - MomentZ_Force[1] += (Force[1]*Coord[0]); - - HF_Visc[iMarker] += HeatFlux[iMarker][iVertex]*Area; - MaxHF_Visc[iMarker] += pow(HeatFlux[iMarker][iVertex], MaxNorm); - - } - - } - - /*--- Project forces and store the non-dimensional coefficients ---*/ - - if (Monitoring == YES) { - if (nDim == 2) { - CD_Visc[iMarker] = ForceViscous[0]*cos(Alpha) + ForceViscous[1]*sin(Alpha); - CL_Visc[iMarker] = -ForceViscous[0]*sin(Alpha) + ForceViscous[1]*cos(Alpha); - CEff_Visc[iMarker] = CL_Visc[iMarker] / (CD_Visc[iMarker]+EPS); - CMz_Visc[iMarker] = MomentViscous[2]; - CFx_Visc[iMarker] = ForceViscous[0]; - CFy_Visc[iMarker] = ForceViscous[1]; - CoPx_Visc[iMarker] = MomentZ_Force[1]; - CoPy_Visc[iMarker] = -MomentZ_Force[0]; - CT_Visc[iMarker] = -CFx_Visc[iMarker]; - CQ_Visc[iMarker] = -CMz_Visc[iMarker]; - CMerit_Visc[iMarker] = CT_Visc[iMarker] / (CQ_Visc[iMarker]+EPS); - MaxHF_Visc[iMarker] = pow(MaxHF_Visc[iMarker], 1.0/MaxNorm); - } - if (nDim == 3) { - CD_Visc[iMarker] = ForceViscous[0]*cos(Alpha)*cos(Beta) + ForceViscous[1]*sin(Beta) + ForceViscous[2]*sin(Alpha)*cos(Beta); - CL_Visc[iMarker] = -ForceViscous[0]*sin(Alpha) + ForceViscous[2]*cos(Alpha); - CSF_Visc[iMarker] = -ForceViscous[0]*sin(Beta)*cos(Alpha) + ForceViscous[1]*cos(Beta) - ForceViscous[2]*sin(Beta)*sin(Alpha); - CEff_Visc[iMarker] = CL_Visc[iMarker]/(CD_Visc[iMarker] + EPS); - CMx_Visc[iMarker] = MomentViscous[0]; - CMy_Visc[iMarker] = MomentViscous[1]; - CMz_Visc[iMarker] = MomentViscous[2]; - CFx_Visc[iMarker] = ForceViscous[0]; - CFy_Visc[iMarker] = ForceViscous[1]; - CFz_Visc[iMarker] = ForceViscous[2]; - CoPx_Visc[iMarker] = -MomentY_Force[0]; - CoPz_Visc[iMarker] = MomentY_Force[2]; - CT_Visc[iMarker] = -CFz_Visc[iMarker]; - CQ_Visc[iMarker] = -CMz_Visc[iMarker]; - CMerit_Visc[iMarker] = CT_Visc[iMarker] / (CQ_Visc[iMarker] + EPS); - MaxHF_Visc[iMarker] = pow(MaxHF_Visc[iMarker], 1.0/MaxNorm); - } - - AllBound_CD_Visc += CD_Visc[iMarker]; - AllBound_CL_Visc += CL_Visc[iMarker]; - AllBound_CSF_Visc += CSF_Visc[iMarker]; - AllBound_CMx_Visc += CMx_Visc[iMarker]; - AllBound_CMy_Visc += CMy_Visc[iMarker]; - AllBound_CMz_Visc += CMz_Visc[iMarker]; - AllBound_CFx_Visc += CFx_Visc[iMarker]; - AllBound_CFy_Visc += CFy_Visc[iMarker]; - AllBound_CFz_Visc += CFz_Visc[iMarker]; - AllBound_CoPx_Visc += CoPx_Visc[iMarker]; - AllBound_CoPy_Visc += CoPy_Visc[iMarker]; - AllBound_CoPz_Visc += CoPz_Visc[iMarker]; - AllBound_CT_Visc += CT_Visc[iMarker]; - AllBound_CQ_Visc += CQ_Visc[iMarker]; - AllBound_HF_Visc += HF_Visc[iMarker]; - AllBound_MaxHF_Visc += pow(MaxHF_Visc[iMarker], MaxNorm); - - /*--- 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); - if (Marker_Tag == Monitoring_Tag) { - Surface_CL_Visc[iMarker_Monitoring] += CL_Visc[iMarker]; - Surface_CD_Visc[iMarker_Monitoring] += CD_Visc[iMarker]; - Surface_CSF_Visc[iMarker_Monitoring] += CSF_Visc[iMarker]; - Surface_CEff_Visc[iMarker_Monitoring] += CEff_Visc[iMarker]; - Surface_CFx_Visc[iMarker_Monitoring] += CFx_Visc[iMarker]; - Surface_CFy_Visc[iMarker_Monitoring] += CFy_Visc[iMarker]; - Surface_CFz_Visc[iMarker_Monitoring] += CFz_Visc[iMarker]; - Surface_CMx_Visc[iMarker_Monitoring] += CMx_Visc[iMarker]; - Surface_CMy_Visc[iMarker_Monitoring] += CMy_Visc[iMarker]; - Surface_CMz_Visc[iMarker_Monitoring] += CMz_Visc[iMarker]; - Surface_HF_Visc[iMarker_Monitoring] += HF_Visc[iMarker]; - Surface_MaxHF_Visc[iMarker_Monitoring] += pow(MaxHF_Visc[iMarker],MaxNorm); - } - } - - } - - } - } - - /*--- Update some global coeffients ---*/ - - AllBound_CEff_Visc = AllBound_CL_Visc / (AllBound_CD_Visc + EPS); - AllBound_CMerit_Visc = AllBound_CT_Visc / (AllBound_CQ_Visc + EPS); - AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0/MaxNorm); - - -#ifdef HAVE_MPI - - /*--- Add AllBound information using all the nodes ---*/ - - MyAllBound_CD_Visc = AllBound_CD_Visc; AllBound_CD_Visc = 0.0; - MyAllBound_CL_Visc = AllBound_CL_Visc; AllBound_CL_Visc = 0.0; - MyAllBound_CSF_Visc = AllBound_CSF_Visc; AllBound_CSF_Visc = 0.0; - AllBound_CEff_Visc = 0.0; - MyAllBound_CMx_Visc = AllBound_CMx_Visc; AllBound_CMx_Visc = 0.0; - MyAllBound_CMy_Visc = AllBound_CMy_Visc; AllBound_CMy_Visc = 0.0; - MyAllBound_CMz_Visc = AllBound_CMz_Visc; AllBound_CMz_Visc = 0.0; - MyAllBound_CFx_Visc = AllBound_CFx_Visc; AllBound_CFx_Visc = 0.0; - MyAllBound_CFy_Visc = AllBound_CFy_Visc; AllBound_CFy_Visc = 0.0; - MyAllBound_CFz_Visc = AllBound_CFz_Visc; AllBound_CFz_Visc = 0.0; - MyAllBound_CoPx_Visc = AllBound_CoPx_Visc; AllBound_CoPx_Visc = 0.0; - MyAllBound_CoPy_Visc = AllBound_CoPy_Visc; AllBound_CoPy_Visc = 0.0; - MyAllBound_CoPz_Visc = AllBound_CoPz_Visc; AllBound_CoPz_Visc = 0.0; - MyAllBound_CT_Visc = AllBound_CT_Visc; AllBound_CT_Visc = 0.0; - MyAllBound_CQ_Visc = AllBound_CQ_Visc; AllBound_CQ_Visc = 0.0; - AllBound_CMerit_Visc = 0.0; - MyAllBound_HF_Visc = AllBound_HF_Visc; AllBound_HF_Visc = 0.0; - MyAllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, MaxNorm); AllBound_MaxHF_Visc = 0.0; - - if (config->GetComm_Level() == COMM_FULL) { - SU2_MPI::Allreduce(&MyAllBound_CD_Visc, &AllBound_CD_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CL_Visc, &AllBound_CL_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CSF_Visc, &AllBound_CSF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - AllBound_CEff_Visc = AllBound_CL_Visc / (AllBound_CD_Visc + EPS); - SU2_MPI::Allreduce(&MyAllBound_CMx_Visc, &AllBound_CMx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CMy_Visc, &AllBound_CMy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CMz_Visc, &AllBound_CMz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFx_Visc, &AllBound_CFx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFy_Visc, &AllBound_CFy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CFz_Visc, &AllBound_CFz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPx_Visc, &AllBound_CoPx_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPy_Visc, &AllBound_CoPy_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CoPz_Visc, &AllBound_CoPz_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CT_Visc, &AllBound_CT_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_CQ_Visc, &AllBound_CQ_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - AllBound_CMerit_Visc = AllBound_CT_Visc / (AllBound_CQ_Visc + EPS); - SU2_MPI::Allreduce(&MyAllBound_HF_Visc, &AllBound_HF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyAllBound_MaxHF_Visc, &AllBound_MaxHF_Visc, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0/MaxNorm); - } - - /*--- Add the forces on the surfaces using all the nodes ---*/ - - MySurface_CL_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CD_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CSF_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CEff_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFx_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFy_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CFz_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMx_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMy_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_CMz_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_HF_Visc = new su2double[config->GetnMarker_Monitoring()]; - MySurface_MaxHF_Visc = new su2double[config->GetnMarker_Monitoring()]; - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - - MySurface_CL_Visc[iMarker_Monitoring] = Surface_CL_Visc[iMarker_Monitoring]; - MySurface_CD_Visc[iMarker_Monitoring] = Surface_CD_Visc[iMarker_Monitoring]; - MySurface_CSF_Visc[iMarker_Monitoring] = Surface_CSF_Visc[iMarker_Monitoring]; - MySurface_CEff_Visc[iMarker_Monitoring] = Surface_CEff_Visc[iMarker_Monitoring]; - MySurface_CFx_Visc[iMarker_Monitoring] = Surface_CFx_Visc[iMarker_Monitoring]; - MySurface_CFy_Visc[iMarker_Monitoring] = Surface_CFy_Visc[iMarker_Monitoring]; - MySurface_CFz_Visc[iMarker_Monitoring] = Surface_CFz_Visc[iMarker_Monitoring]; - MySurface_CMx_Visc[iMarker_Monitoring] = Surface_CMx_Visc[iMarker_Monitoring]; - MySurface_CMy_Visc[iMarker_Monitoring] = Surface_CMy_Visc[iMarker_Monitoring]; - MySurface_CMz_Visc[iMarker_Monitoring] = Surface_CMz_Visc[iMarker_Monitoring]; - MySurface_HF_Visc[iMarker_Monitoring] = Surface_HF_Visc[iMarker_Monitoring]; - MySurface_MaxHF_Visc[iMarker_Monitoring] = Surface_MaxHF_Visc[iMarker_Monitoring]; - - Surface_CL_Visc[iMarker_Monitoring] = 0.0; - Surface_CD_Visc[iMarker_Monitoring] = 0.0; - Surface_CSF_Visc[iMarker_Monitoring] = 0.0; - Surface_CEff_Visc[iMarker_Monitoring] = 0.0; - Surface_CFx_Visc[iMarker_Monitoring] = 0.0; - Surface_CFy_Visc[iMarker_Monitoring] = 0.0; - Surface_CFz_Visc[iMarker_Monitoring] = 0.0; - Surface_CMx_Visc[iMarker_Monitoring] = 0.0; - Surface_CMy_Visc[iMarker_Monitoring] = 0.0; - Surface_CMz_Visc[iMarker_Monitoring] = 0.0; - Surface_HF_Visc[iMarker_Monitoring] = 0.0; - Surface_MaxHF_Visc[iMarker_Monitoring] = 0.0; - } - - if (config->GetComm_Level() == COMM_FULL) { - SU2_MPI::Allreduce(MySurface_CL_Visc, Surface_CL_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CD_Visc, Surface_CD_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CSF_Visc, Surface_CSF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) - Surface_CEff_Visc[iMarker_Monitoring] = Surface_CL_Visc[iMarker_Monitoring] / (Surface_CD_Visc[iMarker_Monitoring] + EPS); - SU2_MPI::Allreduce(MySurface_CFx_Visc, Surface_CFx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CFy_Visc, Surface_CFy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CFz_Visc, Surface_CFz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMx_Visc, Surface_CMx_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMy_Visc, Surface_CMy_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_CMz_Visc, Surface_CMz_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_HF_Visc, Surface_HF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MySurface_MaxHF_Visc, Surface_MaxHF_Visc, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - } - - delete [] MySurface_CL_Visc; delete [] MySurface_CD_Visc; delete [] MySurface_CSF_Visc; - delete [] MySurface_CEff_Visc; delete [] MySurface_CFx_Visc; delete [] MySurface_CFy_Visc; - delete [] MySurface_CFz_Visc; delete [] MySurface_CMx_Visc; delete [] MySurface_CMy_Visc; - delete [] MySurface_CMz_Visc; delete [] MySurface_HF_Visc; delete [] MySurface_MaxHF_Visc; - -#endif - - /*--- Update the total coefficients (note that all the nodes have the same value)---*/ - - Total_CD += AllBound_CD_Visc; - Total_CL += AllBound_CL_Visc; - Total_CSF += AllBound_CSF_Visc; - Total_CEff = Total_CL / (Total_CD + EPS); - Total_CMx += AllBound_CMx_Visc; - Total_CMy += AllBound_CMy_Visc; - Total_CMz += AllBound_CMz_Visc; - Total_CFx += AllBound_CFx_Visc; - Total_CFy += AllBound_CFy_Visc; - Total_CFz += AllBound_CFz_Visc; - Total_CoPx += AllBound_CoPx_Visc; - Total_CoPy += AllBound_CoPy_Visc; - Total_CoPz += AllBound_CoPz_Visc; - Total_CT += AllBound_CT_Visc; - Total_CQ += AllBound_CQ_Visc; - Total_CMerit = AllBound_CT_Visc / (AllBound_CQ_Visc + EPS); - Total_Heat = AllBound_HF_Visc; - Total_MaxHeat = AllBound_MaxHF_Visc; - - /*--- Update the total coefficients per surface (note that all the nodes have the same value)---*/ - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Surface_CL[iMarker_Monitoring] += Surface_CL_Visc[iMarker_Monitoring]; - Surface_CD[iMarker_Monitoring] += Surface_CD_Visc[iMarker_Monitoring]; - Surface_CSF[iMarker_Monitoring] += Surface_CSF_Visc[iMarker_Monitoring]; - Surface_CEff[iMarker_Monitoring] = Surface_CL[iMarker_Monitoring] / (Surface_CD[iMarker_Monitoring] + EPS); - Surface_CFx[iMarker_Monitoring] += Surface_CFx_Visc[iMarker_Monitoring]; - Surface_CFy[iMarker_Monitoring] += Surface_CFy_Visc[iMarker_Monitoring]; - Surface_CFz[iMarker_Monitoring] += Surface_CFz_Visc[iMarker_Monitoring]; - Surface_CMx[iMarker_Monitoring] += Surface_CMx_Visc[iMarker_Monitoring]; - Surface_CMy[iMarker_Monitoring] += Surface_CMy_Visc[iMarker_Monitoring]; - Surface_CMz[iMarker_Monitoring] += Surface_CMz_Visc[iMarker_Monitoring]; - } - -} - void CIncNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { diff --git a/SU2_CFD/src/solvers/CNSSolver.cpp b/SU2_CFD/src/solvers/CNSSolver.cpp index 93014f3285ec..345ce3404699 100644 --- a/SU2_CFD/src/solvers/CNSSolver.cpp +++ b/SU2_CFD/src/solvers/CNSSolver.cpp @@ -29,31 +29,18 @@ #include "../../include/variables/CNSVariable.hpp" #include "../../../Common/include/toolboxes/printing_toolbox.hpp" #include "../../../Common/include/toolboxes/geometry_toolbox.hpp" +#include "../../include/solvers/CFVMFlowSolverBase.inl" +/*--- Explicit instantiation of the parent class of CEulerSolver, + * to spread the compilation over two cpp files. ---*/ +template class CFVMFlowSolverBase; -CNSSolver::CNSSolver(void) : CEulerSolver() { } CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : CEulerSolver(geometry, config, iMesh, true) { /*--- This constructor only allocates/inits what is extra to CEulerSolver. ---*/ - unsigned short iMarker, iDim; - unsigned long iVertex; - - /*--- Store the values of the temperature and the heat flux density at the boundaries, - used for coupling with a solid donor cell ---*/ - unsigned short nHeatConjugateVar = 4; - - HeatConjugateVar = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - HeatConjugateVar[iMarker] = new su2double* [nVertex[iMarker]]; - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { - HeatConjugateVar[iMarker][iVertex] = new su2double [nHeatConjugateVar](); - HeatConjugateVar[iMarker][iVertex][0] = config->GetTemperature_FreeStreamND(); - } - } - /*--- Allocates a 2D array with variable "outer" sizes and init to 0. ---*/ auto Alloc2D = [](unsigned long M, const unsigned long* N, su2double**& X) { @@ -62,41 +49,9 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) X[i] = new su2double [N[i]] (); }; - /*--- Heat flux in all the markers ---*/ - - Alloc2D(nMarker, nVertex, HeatFlux); - Alloc2D(nMarker, nVertex, HeatFluxTarget); - - /*--- Y plus in all the markers ---*/ - - Alloc2D(nMarker, nVertex, YPlus); - - /*--- Skin friction in all the markers ---*/ - - CSkinFriction = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - CSkinFriction[iMarker] = new su2double*[nDim]; - for (iDim = 0; iDim < nDim; iDim++) { - CSkinFriction[iMarker][iDim] = new su2double[nVertex[iMarker]] (); - } - } - - /*--- Non dimensional aerodynamic coefficients ---*/ - - ViscCoeff.allocate(nMarker); - SurfaceViscCoeff.allocate(config->GetnMarker_Monitoring()); - - /*--- Heat flux and buffet coefficients ---*/ - - HF_Visc = new su2double[nMarker]; - MaxHF_Visc = new su2double[nMarker]; - - Surface_HF_Visc = new su2double[config->GetnMarker_Monitoring()]; - Surface_MaxHF_Visc = new su2double[config->GetnMarker_Monitoring()]; - /*--- Buffet sensor in all the markers and coefficients ---*/ - if(config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){ + if (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){ Alloc2D(nMarker, nVertex, Buffet_Sensor); Buffet_Metric = new su2double[nMarker]; @@ -126,38 +81,11 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) CNSSolver::~CNSSolver(void) { - unsigned short iMarker, iDim; - - unsigned long iVertex; + unsigned short iMarker; delete [] Buffet_Metric; - delete [] HF_Visc; - delete [] MaxHF_Visc; - - delete [] Surface_HF_Visc; - delete [] Surface_MaxHF_Visc; delete [] Surface_Buffet_Metric; - if (CSkinFriction != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - for (iDim = 0; iDim < nDim; iDim++) { - delete [] CSkinFriction[iMarker][iDim]; - } - delete [] CSkinFriction[iMarker]; - } - delete [] CSkinFriction; - } - - if (HeatConjugateVar != nullptr) { - for (iMarker = 0; iMarker < nMarker; iMarker++) { - for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { - delete [] HeatConjugateVar[iMarker][iVertex]; - } - delete [] HeatConjugateVar[iMarker]; - } - delete [] HeatConjugateVar; - } - if (Buffet_Sensor != nullptr) { for (iMarker = 0; iMarker < nMarker; iMarker++){ delete [] Buffet_Sensor[iMarker]; @@ -365,442 +293,6 @@ void CNSSolver::Viscous_Residual(unsigned long iEdge, CGeometry *geometry, CSolv } -void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { - - unsigned long iVertex, iPoint, iPointNormal; - unsigned short Boundary, Monitoring, iMarker, iMarker_Monitoring, iDim, jDim; - su2double Viscosity = 0.0, div_vel, WallDist[3] = {0.0, 0.0, 0.0}, - Area, WallShearStress, TauNormal, factor, RefTemp, RefVel2, RefDensity, GradTemperature, Density = 0.0, WallDistMod, FrictionVel, - Mach2Vel, Mach_Motion, UnitNormal[3] = {0.0, 0.0, 0.0}, TauElem[3] = {0.0, 0.0, 0.0}, TauTangent[3] = {0.0, 0.0, 0.0}, - Tau[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}}, Cp, thermal_conductivity, MaxNorm = 8.0, - Grad_Vel[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.0, 0.0}}, Grad_Temp[3] = {0.0, 0.0, 0.0}, - delta[3][3] = {{1.0, 0.0, 0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}}; - su2double AxiFactor; - const su2double *Coord = nullptr, *Coord_Normal = nullptr, *Normal = nullptr; - - string Marker_Tag, Monitoring_Tag; - - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - su2double RefArea = config->GetRefArea(); - su2double RefLength = config->GetRefLength(); - su2double RefHeatFlux = config->GetHeat_Flux_Ref(); - su2double Gas_Constant = config->GetGas_ConstantND(); - const su2double *Origin = nullptr; - - if (config->GetnMarker_Monitoring() != 0) { Origin = config->GetRefOriginMoment(0); } - - su2double Prandtl_Lam = config->GetPrandtl_Lam(); - bool QCR = config->GetQCR(); - bool axisymmetric = config->GetAxisymmetric(); - - /*--- Evaluate reference values for non-dimensionalization. - For dynamic meshes, use the motion Mach number as a reference value - for computing the force coefficients. Otherwise, use the freestream values, - which is the standard convention. ---*/ - - RefTemp = Temperature_Inf; - RefDensity = Density_Inf; - if (dynamic_grid) { - Mach2Vel = sqrt(Gamma*Gas_Constant*RefTemp); - Mach_Motion = config->GetMach_Motion(); - RefVel2 = (Mach_Motion*Mach2Vel)*(Mach_Motion*Mach2Vel); - } else { - RefVel2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - RefVel2 += Velocity_Inf[iDim]*Velocity_Inf[iDim]; - } - - factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2); - - /*--- Variables initialization ---*/ - - AllBoundViscCoeff.setZero(); - SurfaceViscCoeff.setZero(); - - AllBound_HF_Visc = 0.0; AllBound_MaxHF_Visc = 0.0; - - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - Surface_HF_Visc[iMarker_Monitoring] = 0.0; Surface_MaxHF_Visc[iMarker_Monitoring] = 0.0; - } - - /*--- Loop over the Navier-Stokes markers ---*/ - - for (iMarker = 0; iMarker < nMarker; iMarker++) { - - Boundary = config->GetMarker_All_KindBC(iMarker); - Monitoring = config->GetMarker_All_Monitoring(iMarker); - - /*--- Obtain the origin for the moment computation for a particular marker ---*/ - - if (Monitoring == YES) { - 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); - if (Marker_Tag == Monitoring_Tag) - Origin = config->GetRefOriginMoment(iMarker_Monitoring); - } - } - - if ((Boundary == HEAT_FLUX) || (Boundary == ISOTHERMAL) || (Boundary == HEAT_FLUX) || (Boundary == CHT_WALL_INTERFACE)) { - - /*--- Forces initialization at each Marker ---*/ - - ViscCoeff.setZero(iMarker); - - HF_Visc[iMarker] = 0.0; MaxHF_Visc[iMarker] = 0.0; - - su2double ForceViscous[MAXNDIM] = {0.0}, MomentViscous[MAXNDIM] = {0.0}; - su2double MomentX_Force[MAXNDIM] = {0.0}, MomentY_Force[MAXNDIM] = {0.0}, MomentZ_Force[MAXNDIM] = {0.0}; - - /*--- Loop over the vertices to compute the forces ---*/ - - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - iPointNormal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); - - Coord = geometry->nodes->GetCoord(iPoint); - Coord_Normal = geometry->nodes->GetCoord(iPointNormal); - - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - - for (iDim = 0; iDim < nDim; iDim++) { - for (jDim = 0 ; jDim < nDim; jDim++) { - Grad_Vel[iDim][jDim] = nodes->GetGradient_Primitive(iPoint,iDim+1, jDim); - } - Grad_Temp[iDim] = nodes->GetGradient_Primitive(iPoint,0, iDim); - } - - Viscosity = nodes->GetLaminarViscosity(iPoint); - Density = nodes->GetDensity(iPoint); - - Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); - - - for (iDim = 0; iDim < nDim; iDim++) { - UnitNormal[iDim] = Normal[iDim]/Area; - } - - /*--- Evaluate Tau ---*/ - - div_vel = 0.0; for (iDim = 0; iDim < nDim; iDim++) div_vel += Grad_Vel[iDim][iDim]; - - for (iDim = 0; iDim < nDim; iDim++) { - for (jDim = 0 ; jDim < nDim; jDim++) { - Tau[iDim][jDim] = Viscosity*(Grad_Vel[jDim][iDim] + Grad_Vel[iDim][jDim]) - TWO3*Viscosity*div_vel*delta[iDim][jDim]; - } - } - - /*--- If necessary evaluate the QCR contribution to Tau ---*/ - - if (QCR) { - su2double den_aux, c_cr1=0.3, O_ik, O_jk; - unsigned short kDim; - - /*--- Denominator Antisymmetric normalized rotation tensor ---*/ - - den_aux = 0.0; - for (iDim = 0 ; iDim < nDim; iDim++) - for (jDim = 0 ; jDim < nDim; jDim++) - den_aux += Grad_Vel[iDim][jDim] * Grad_Vel[iDim][jDim]; - den_aux = sqrt(max(den_aux,1E-10)); - - /*--- Adding the QCR contribution ---*/ - - for (iDim = 0 ; iDim < nDim; iDim++){ - for (jDim = 0 ; jDim < nDim; jDim++){ - for (kDim = 0 ; kDim < nDim; kDim++){ - O_ik = (Grad_Vel[iDim][kDim] - Grad_Vel[kDim][iDim])/ den_aux; - O_jk = (Grad_Vel[jDim][kDim] - Grad_Vel[kDim][jDim])/ den_aux; - Tau[iDim][jDim] -= c_cr1 * (O_ik * Tau[jDim][kDim] + O_jk * Tau[iDim][kDim]); - } - } - } - } - - /*--- Project Tau in each surface element ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - TauElem[iDim] = 0.0; - for (jDim = 0; jDim < nDim; jDim++) { - TauElem[iDim] += Tau[iDim][jDim]*UnitNormal[jDim]; - } - } - - /*--- Compute wall shear stress (using the stress tensor). Compute wall skin friction coefficient, and heat flux on the wall ---*/ - - TauNormal = 0.0; for (iDim = 0; iDim < nDim; iDim++) TauNormal += TauElem[iDim] * UnitNormal[iDim]; - - WallShearStress = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - TauTangent[iDim] = TauElem[iDim] - TauNormal * UnitNormal[iDim]; - CSkinFriction[iMarker][iDim][iVertex] = TauTangent[iDim] / (0.5*RefDensity*RefVel2); - WallShearStress += TauTangent[iDim] * TauTangent[iDim]; - } - WallShearStress = sqrt(WallShearStress); - - for (iDim = 0; iDim < nDim; iDim++) WallDist[iDim] = (Coord[iDim] - Coord_Normal[iDim]); - WallDistMod = 0.0; for (iDim = 0; iDim < nDim; iDim++) WallDistMod += WallDist[iDim]*WallDist[iDim]; WallDistMod = sqrt(WallDistMod); - - /*--- Compute y+ and non-dimensional velocity ---*/ - - FrictionVel = sqrt(fabs(WallShearStress)/Density); - YPlus[iMarker][iVertex] = WallDistMod*FrictionVel/(Viscosity/Density); - - /*--- Compute total and maximum heat flux on the wall ---*/ - - GradTemperature = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - GradTemperature -= Grad_Temp[iDim]*UnitNormal[iDim]; - - Cp = (Gamma / Gamma_Minus_One) * Gas_Constant; - thermal_conductivity = Cp * Viscosity/Prandtl_Lam; - HeatFlux[iMarker][iVertex] = -thermal_conductivity*GradTemperature*RefHeatFlux; - - /*--- Note that y+, and heat are computed at the - halo cells (for visualization purposes), but not the forces ---*/ - - if ((geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES)) { - - /*--- Axisymmetric simulations ---*/ - - if (axisymmetric) AxiFactor = 2.0*PI_NUMBER*geometry->nodes->GetCoord(iPoint, 1); - else AxiFactor = 1.0; - - /*--- Force computation ---*/ - - su2double Force[MAXNDIM] = {0.0}, MomentDist[MAXNDIM] = {0.0}; - for (iDim = 0; iDim < nDim; iDim++) { - Force[iDim] = TauElem[iDim] * Area * factor * AxiFactor; - ForceViscous[iDim] += Force[iDim]; - MomentDist[iDim] = Coord[iDim] - Origin[iDim]; - } - - /*--- Moment with respect to the reference axis ---*/ - - if (iDim == 3) { - MomentViscous[0] += (Force[2]*MomentDist[1] - Force[1]*MomentDist[2])/RefLength; - MomentX_Force[1] += (-Force[1]*Coord[2]); - MomentX_Force[2] += (Force[2]*Coord[1]); - - MomentViscous[1] += (Force[0]*MomentDist[2] - Force[2]*MomentDist[0])/RefLength; - MomentY_Force[2] += (-Force[2]*Coord[0]); - MomentY_Force[0] += (Force[0]*Coord[2]); - } - MomentViscous[2] += (Force[1]*MomentDist[0] - Force[0]*MomentDist[1])/RefLength; - MomentZ_Force[0] += (-Force[0]*Coord[1]); - MomentZ_Force[1] += (Force[1]*Coord[0]); - - } - - HF_Visc[iMarker] += HeatFlux[iMarker][iVertex]*Area; - MaxHF_Visc[iMarker] += pow(HeatFlux[iMarker][iVertex], MaxNorm); - - } - - /*--- Project forces and store the non-dimensional coefficients ---*/ - - if (Monitoring == YES) { - if (nDim == 2) { - ViscCoeff.CD[iMarker] = ForceViscous[0]*cos(Alpha) + ForceViscous[1]*sin(Alpha); - ViscCoeff.CL[iMarker] = -ForceViscous[0]*sin(Alpha) + ForceViscous[1]*cos(Alpha); - ViscCoeff.CEff[iMarker] = ViscCoeff.CL[iMarker] / (ViscCoeff.CD[iMarker]+EPS); - ViscCoeff.CFx[iMarker] = ForceViscous[0]; - ViscCoeff.CFy[iMarker] = ForceViscous[1]; - ViscCoeff.CMz[iMarker] = MomentViscous[2]; - ViscCoeff.CoPx[iMarker] = MomentZ_Force[1]; - ViscCoeff.CoPy[iMarker] = -MomentZ_Force[0]; - ViscCoeff.CT[iMarker] = -ViscCoeff.CFx[iMarker]; - ViscCoeff.CQ[iMarker] = -ViscCoeff.CMz[iMarker]; - ViscCoeff.CMerit[iMarker] = ViscCoeff.CT[iMarker] / (ViscCoeff.CQ[iMarker]+EPS); - MaxHF_Visc[iMarker] = pow(MaxHF_Visc[iMarker], 1.0/MaxNorm); - } - if (nDim == 3) { - ViscCoeff.CD[iMarker] = ForceViscous[0]*cos(Alpha)*cos(Beta) + ForceViscous[1]*sin(Beta) + ForceViscous[2]*sin(Alpha)*cos(Beta); - ViscCoeff.CL[iMarker] = -ForceViscous[0]*sin(Alpha) + ForceViscous[2]*cos(Alpha); - ViscCoeff.CSF[iMarker] = -ForceViscous[0]*sin(Beta)*cos(Alpha) + ForceViscous[1]*cos(Beta) - ForceViscous[2]*sin(Beta)*sin(Alpha); - ViscCoeff.CEff[iMarker] = ViscCoeff.CL[iMarker]/(ViscCoeff.CD[iMarker] + EPS); - ViscCoeff.CFx[iMarker] = ForceViscous[0]; - ViscCoeff.CFy[iMarker] = ForceViscous[1]; - ViscCoeff.CFz[iMarker] = ForceViscous[2]; - ViscCoeff.CMx[iMarker] = MomentViscous[0]; - ViscCoeff.CMy[iMarker] = MomentViscous[1]; - ViscCoeff.CMz[iMarker] = MomentViscous[2]; - ViscCoeff.CoPx[iMarker] = -MomentY_Force[0]; - ViscCoeff.CoPz[iMarker] = MomentY_Force[2]; - ViscCoeff.CT[iMarker] = -ViscCoeff.CFz[iMarker]; - ViscCoeff.CQ[iMarker] = -ViscCoeff.CMz[iMarker]; - ViscCoeff.CMerit[iMarker] = ViscCoeff.CT[iMarker] / (ViscCoeff.CQ[iMarker] + EPS); - MaxHF_Visc[iMarker] = pow(MaxHF_Visc[iMarker], 1.0/MaxNorm); - } - - AllBoundViscCoeff.CD += ViscCoeff.CD[iMarker]; - AllBoundViscCoeff.CL += ViscCoeff.CL[iMarker]; - AllBoundViscCoeff.CSF += ViscCoeff.CSF[iMarker]; - AllBoundViscCoeff.CFx += ViscCoeff.CFx[iMarker]; - AllBoundViscCoeff.CFy += ViscCoeff.CFy[iMarker]; - AllBoundViscCoeff.CFz += ViscCoeff.CFz[iMarker]; - AllBoundViscCoeff.CMx += ViscCoeff.CMx[iMarker]; - AllBoundViscCoeff.CMy += ViscCoeff.CMy[iMarker]; - AllBoundViscCoeff.CMz += ViscCoeff.CMz[iMarker]; - AllBoundViscCoeff.CoPx += ViscCoeff.CoPx[iMarker]; - AllBoundViscCoeff.CoPy += ViscCoeff.CoPy[iMarker]; - AllBoundViscCoeff.CoPz += ViscCoeff.CoPz[iMarker]; - AllBoundViscCoeff.CT += ViscCoeff.CT[iMarker]; - AllBoundViscCoeff.CQ += ViscCoeff.CQ[iMarker]; - AllBound_HF_Visc += HF_Visc[iMarker]; - AllBound_MaxHF_Visc += pow(MaxHF_Visc[iMarker], MaxNorm); - - /*--- 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); - if (Marker_Tag == Monitoring_Tag) { - SurfaceViscCoeff.CL[iMarker_Monitoring] += ViscCoeff.CL[iMarker]; - SurfaceViscCoeff.CD[iMarker_Monitoring] += ViscCoeff.CD[iMarker]; - SurfaceViscCoeff.CSF[iMarker_Monitoring] += ViscCoeff.CSF[iMarker]; - SurfaceViscCoeff.CEff[iMarker_Monitoring] += ViscCoeff.CEff[iMarker]; - SurfaceViscCoeff.CFx[iMarker_Monitoring] += ViscCoeff.CFx[iMarker]; - SurfaceViscCoeff.CFy[iMarker_Monitoring] += ViscCoeff.CFy[iMarker]; - SurfaceViscCoeff.CFz[iMarker_Monitoring] += ViscCoeff.CFz[iMarker]; - SurfaceViscCoeff.CMx[iMarker_Monitoring] += ViscCoeff.CMx[iMarker]; - SurfaceViscCoeff.CMy[iMarker_Monitoring] += ViscCoeff.CMy[iMarker]; - SurfaceViscCoeff.CMz[iMarker_Monitoring] += ViscCoeff.CMz[iMarker]; - Surface_HF_Visc[iMarker_Monitoring] += HF_Visc[iMarker]; - Surface_MaxHF_Visc[iMarker_Monitoring] += pow(MaxHF_Visc[iMarker],MaxNorm); - } - } - - } - - } - } - - /*--- Update some global coeffients ---*/ - - AllBoundViscCoeff.CEff = AllBoundViscCoeff.CL / (AllBoundViscCoeff.CD + EPS); - AllBoundViscCoeff.CMerit = AllBoundViscCoeff.CT / (AllBoundViscCoeff.CQ + EPS); - AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0/MaxNorm); - - -#ifdef HAVE_MPI - - /*--- Add AllBound information using all the nodes ---*/ - - if (config->GetComm_Level() == COMM_FULL) { - - auto Allreduce = [](su2double x) { - su2double tmp = x; x = 0.0; - SU2_MPI::Allreduce(&tmp, &x, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - return x; - }; - AllBoundViscCoeff.CD = Allreduce(AllBoundViscCoeff.CD); - AllBoundViscCoeff.CL = Allreduce(AllBoundViscCoeff.CL); - AllBoundViscCoeff.CSF = Allreduce(AllBoundViscCoeff.CSF); - AllBoundViscCoeff.CEff = AllBoundViscCoeff.CL / (AllBoundViscCoeff.CD + EPS); - - AllBoundViscCoeff.CMx = Allreduce(AllBoundViscCoeff.CMx); - AllBoundViscCoeff.CMy = Allreduce(AllBoundViscCoeff.CMy); - AllBoundViscCoeff.CMz = Allreduce(AllBoundViscCoeff.CMz); - - AllBoundViscCoeff.CFx = Allreduce(AllBoundViscCoeff.CFx); - AllBoundViscCoeff.CFy = Allreduce(AllBoundViscCoeff.CFy); - AllBoundViscCoeff.CFz = Allreduce(AllBoundViscCoeff.CFz); - - AllBoundViscCoeff.CoPx = Allreduce(AllBoundViscCoeff.CoPx); - AllBoundViscCoeff.CoPy = Allreduce(AllBoundViscCoeff.CoPy); - AllBoundViscCoeff.CoPz = Allreduce(AllBoundViscCoeff.CoPz); - - AllBoundViscCoeff.CT = Allreduce(AllBoundViscCoeff.CT); - AllBoundViscCoeff.CQ = Allreduce(AllBoundViscCoeff.CQ); - AllBoundViscCoeff.CMerit = AllBoundViscCoeff.CT / (AllBoundViscCoeff.CQ + EPS); - - AllBound_HF_Visc = Allreduce(AllBound_HF_Visc); - AllBound_MaxHF_Visc = pow(Allreduce(pow(AllBound_MaxHF_Visc, MaxNorm)), 1.0/MaxNorm); - - } - - /*--- Add the forces on the surfaces using all the nodes ---*/ - - if (config->GetComm_Level() == COMM_FULL) { - - int nMarkerMon = config->GetnMarker_Monitoring(); - - /*--- Use the same buffer for all reductions. We could avoid the copy back into - * the original variable by swaping pointers, but it is safer this way... ---*/ - - su2double* buffer = new su2double [nMarkerMon]; - - auto Allreduce_inplace = [buffer](int size, su2double* x) { - SU2_MPI::Allreduce(x, buffer, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - for(int i=0; iGetnMarker_Monitoring(); iMarker_Monitoring++) { - SurfaceCoeff.CL[iMarker_Monitoring] += SurfaceViscCoeff.CL[iMarker_Monitoring]; - SurfaceCoeff.CD[iMarker_Monitoring] += SurfaceViscCoeff.CD[iMarker_Monitoring]; - SurfaceCoeff.CSF[iMarker_Monitoring] += SurfaceViscCoeff.CSF[iMarker_Monitoring]; - SurfaceCoeff.CEff[iMarker_Monitoring] = SurfaceViscCoeff.CL[iMarker_Monitoring] / (SurfaceCoeff.CD[iMarker_Monitoring] + EPS); - SurfaceCoeff.CFx[iMarker_Monitoring] += SurfaceViscCoeff.CFx[iMarker_Monitoring]; - SurfaceCoeff.CFy[iMarker_Monitoring] += SurfaceViscCoeff.CFy[iMarker_Monitoring]; - SurfaceCoeff.CFz[iMarker_Monitoring] += SurfaceViscCoeff.CFz[iMarker_Monitoring]; - SurfaceCoeff.CMx[iMarker_Monitoring] += SurfaceViscCoeff.CMx[iMarker_Monitoring]; - SurfaceCoeff.CMy[iMarker_Monitoring] += SurfaceViscCoeff.CMy[iMarker_Monitoring]; - SurfaceCoeff.CMz[iMarker_Monitoring] += SurfaceViscCoeff.CMz[iMarker_Monitoring]; - } - -} - void CNSSolver::Buffet_Monitoring(CGeometry *geometry, CConfig *config) { unsigned long iVertex; diff --git a/SU2_CFD/src/solvers/CSolver.cpp b/SU2_CFD/src/solvers/CSolver.cpp index d73bf4c8f5eb..e44238421d78 100644 --- a/SU2_CFD/src/solvers/CSolver.cpp +++ b/SU2_CFD/src/solvers/CSolver.cpp @@ -3196,7 +3196,7 @@ void CSolver::Restart_OldGeometry(CGeometry *geometry, CConfig *config) { } -void CSolver::Read_SU2_Restart_ASCII(CGeometry *geometry, CConfig *config, string val_filename) { +void CSolver::Read_SU2_Restart_ASCII(CGeometry *geometry, const CConfig *config, string val_filename) { ifstream restart_file; string text_line, Tag; @@ -3355,7 +3355,7 @@ void CSolver::Read_SU2_Restart_ASCII(CGeometry *geometry, CConfig *config, strin } -void CSolver::Read_SU2_Restart_Binary(CGeometry *geometry, CConfig *config, string val_filename) { +void CSolver::Read_SU2_Restart_Binary(CGeometry *geometry, const CConfig *config, string val_filename) { char str_buf[CGNS_STRING_SIZE], fname[100]; unsigned short iVar; diff --git a/SU2_CFD/src/solvers/CTurbSASolver.cpp b/SU2_CFD/src/solvers/CTurbSASolver.cpp index b7c98777119f..050867370b9a 100644 --- a/SU2_CFD/src/solvers/CTurbSASolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSASolver.cpp @@ -1850,7 +1850,7 @@ void CTurbSASolver::SetDES_LengthScale(CSolver **solver, CGeometry *geometry, CC } } -void CTurbSASolver::SetInletAtVertex(su2double *val_inlet, +void CTurbSASolver::SetInletAtVertex(const su2double *val_inlet, unsigned short iMarker, unsigned long iVertex) { @@ -1862,9 +1862,8 @@ su2double CTurbSASolver::GetInletAtVertex(su2double *val_inlet, unsigned long val_inlet_point, unsigned short val_kind_marker, string val_marker, - CGeometry *geometry, - CConfig *config) const { - + const CGeometry *geometry, + const CConfig *config) const { /*--- Local variables ---*/ unsigned short iMarker, iDim; @@ -1919,7 +1918,7 @@ su2double CTurbSASolver::GetInletAtVertex(su2double *val_inlet, } -void CTurbSASolver::SetUniformInlet(CConfig* config, unsigned short iMarker) { +void CTurbSASolver::SetUniformInlet(const CConfig* config, unsigned short iMarker) { for(unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ Inlet_TurbVars[iMarker][iVertex][0] = nu_tilde_Inf; diff --git a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp index 8d4ac0c3a727..b17bdef9b1ef 100644 --- a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp @@ -856,7 +856,7 @@ void CTurbSSTSolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_contai } -void CTurbSSTSolver::SetInletAtVertex(su2double *val_inlet, +void CTurbSSTSolver::SetInletAtVertex(const su2double *val_inlet, unsigned short iMarker, unsigned long iVertex) { @@ -869,9 +869,8 @@ su2double CTurbSSTSolver::GetInletAtVertex(su2double *val_inlet, unsigned long val_inlet_point, unsigned short val_kind_marker, string val_marker, - CGeometry *geometry, - CConfig *config) const { - + const CGeometry *geometry, + const CConfig *config) const { /*--- Local variables ---*/ unsigned short iMarker, iDim; @@ -928,7 +927,7 @@ su2double CTurbSSTSolver::GetInletAtVertex(su2double *val_inlet, } -void CTurbSSTSolver::SetUniformInlet(CConfig* config, unsigned short iMarker) { +void CTurbSSTSolver::SetUniformInlet(const CConfig* config, unsigned short iMarker) { for(unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ Inlet_TurbVars[iMarker][iVertex][0] = kine_Inf; diff --git a/SU2_CFD/src/solvers/CTurbSolver.cpp b/SU2_CFD/src/solvers/CTurbSolver.cpp index 457f16cc1a74..4c418f48e33a 100644 --- a/SU2_CFD/src/solvers/CTurbSolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSolver.cpp @@ -646,7 +646,7 @@ void CTurbSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_ } -void CTurbSolver::ComputeUnderRelaxationFactor(CSolver **solver_container, CConfig *config) { +void CTurbSolver::ComputeUnderRelaxationFactor(CSolver **solver_container, const CConfig *config) { /* Only apply the turbulent under-relaxation to the SA variants. The SA_NEG model is more robust due to allowing for negative nu_tilde,